This adds several relationships into the resource package that are then
made use of to improve the grant validation that runs during Parse. By
understanding mappings between ID and resource type the validation
checks can far better align with actual allowed grant formats so we can
find several common misunderstandings before they simply result in an
authorization failure.
In the future some of these functions could be used in the logic in the
actual ACL checks but it's not currently necessary and I don't want to
lump that change in with this.
Note that the tests have not meaningfully changed, but they _have_ had
to be updated because the stricter validation is actually catching
issues.
// First up, an ID is given, no type, and actions contains "create" or
// "list". Note wildcard for actions is still okay.
ifgrant.id!=""&&grant.typ==resource.Unknown{
ifgrant.actions[action.Create]||
grant.actions[action.List]{
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,"parsed grant string contains create or list action in a format that does not allow these")
switch{
casegrant.id=="*":
// Matches
// id=*;type=sometype;actions=foo,bar
// or
// id=*;type=*;actions=foo,bar
// This can be a non-unknown type or wildcard
ifgrant.typ==resource.Unknown{
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains wildcard id and no specified type",grant.CanonicalString()))
}
casegrant.id!="":
// Non-wildcard but specified ID. This can match
// id=foo_bar;actions=foo,bar
// or
// id=foo_bar;type=sometype;actions=foo,bar
// or
// id=foo_bar;type=*;actions=foo,bar
// but notably the specified types have to actually make sense: in
// the second example the type corresponding to the ID must have the
// specified type as a child type; in the third the ID must be a
// type that has child types.
idType:=globals.ResourceTypeFromPrefix(grant.id)
ifidType==resource.Unknown{
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains an id %q of an unknown resource type",grant.CanonicalString(),grant.id))
}
}
// If no ID is given...
ifgrant.id==""{
// Check the type
switchgrant.typ{
caseresource.Unknown:
// This is fine as-is but we do not support collection actions
// without a type (either directly specified or wildcard) so
// check that
ifgrant.actions[action.Create]||
grant.actions[action.List]{
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains create or list action in a format that does not allow these",grant.CanonicalString()))
}
caseresource.All:
// Verify that the ID is a type that has child types
if!resource.HasChildTypes(idType){
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains an id that does not support child types",grant.CanonicalString()))
}
default:
// Specified resource type, verify it's a child
ifresource.Parent(grant.typ)!=idType{
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains type %s that is not a child type of the type (%s) of the specified id",grant.CanonicalString(),grant.typ.String(),idType.String()))
}
}
default:// no specified id
switchgrant.typ{
caseresource.Unknown:
// Error -- no ID or type isn't valid (although we should never
// get to this point because original parsing should error)
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,"parsed grant string contains no id or type")
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains no id or type",grant.CanonicalString()))
caseresource.All:
// "type=*;actions=..." is not supported -- we require you to
// explicitly set a pin or set the ID to *
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,"parsed grant string contains wildcard type with no id value")
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains wildcard type with no id value",grant.CanonicalString()))
default:
// Here we have type=something,actions=<something else>. This
// means we're operating on collections. Note that wildcard
// actions are not okay here; that uses the format
// id=*;type=<something>;actions=*
// means we're operating on collections and support only create
// or list. Note that wildcard actions are not okay here; that
// uses the format id=*;type=<something>;actions=*
switchlen(grant.actions){
case0:
// It's okay to have no actions if only output fields are being defined
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,"parsed grant string contains no actions or output fields")
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains no actions or output fields",grant.CanonicalString()))
}
case1:
if!grant.hasActionOrSubaction(action.Create)&&
!grant.hasActionOrSubaction(action.List){
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,"parsed grant string contains non-create or non-list action in a format that only allows these")
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains non-create or non-list action in a format that only allows these",grant.CanonicalString()))
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,"parsed grant string contains non-create or non-list action in a format that only allows these")
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains non-create or non-list action in a format that only allows these",grant.CanonicalString()))
}
default:
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,"parsed grant string contains non-create or non-list action in a format that only allows these")
returnGrant{},errors.NewDeprecated(errors.InvalidParameter,op,fmt.Sprintf("parsed grant string %q contains non-create or non-list action in a format that only allows these",grant.CanonicalString()))
err:`perms.Parse: parsed grant string contains create or list action in a format that does not allow these: parameter violation: error #100`,
err:`perms.Parse: parsed grant string "id=foobar;actions=create" contains an id "foobar" of an unknown resource type: parameter violation: error #100`,
},
{
name:"bad create action for id",
input:"id=u_foobar;actions=create",
err:`perms.Parse: parsed grant string "id=u_foobar;actions=create" contains create or list action in a format that does not allow these: parameter violation: error #100`,
},
{
name:"bad create action for id with other perms",
input:"id=foobar;actions=read,create",
err:`perms.Parse: parsed grant string contains create or list action in a format that does not allow these: parameter violation: error #100`,
input:"id=u_foobar;actions=read,create",
err:`perms.Parse: parsed grant string "id=u_foobar;actions=create,read" contains create or list action in a format that does not allow these: parameter violation: error #100`,
},
{
name:"bad list action for id",
input:"id=foobar;actions=list",
err:`perms.Parse: parsed grant string contains create or list action in a format that does not allow these: parameter violation: error #100`,
input:"id=u_foobar;actions=list",
err:`perms.Parse: parsed grant string "id=u_foobar;actions=list" contains create or list action in a format that does not allow these: parameter violation: error #100`,
},
{
name:"bad list action for id with other perms",
input:"type=host-catalog;actions=list,read",
err:`perms.Parse: parsed grant string contains non-create or non-list action in a format that only allows these: parameter violation: error #100`,
err:`perms.Parse: parsed grant string "type=host-catalog;actions=list,read" contains non-create or non-list action in a format that only allows these: parameter violation: error #100`,
},
{
name:"wildcard id and actions without collection",
input:"id=*;actions=read",
err:`perms.Parse: parsed grant string would not result in any action being authorized: parameter violation: error #100`,
err:`perms.Parse: parsed grant string "id=*;actions=read" contains wildcard id and no specified type: parameter violation: error #100`,
},
{
name:"wildcard id and actions with list",
input:"id=*;actions=read,list",
err:`perms.Parse: parsed grant string contains create or list action in a format that does not allow these: parameter violation: error #100`,
err:`perms.Parse: parsed grant string "id=*;actions=list,read" contains wildcard id and no specified type: parameter violation: error #100`,
},
{
name:"wildcard type with no id",
input:"type=*;actions=read,list",
err:`perms.Parse: parsed grant string contains wildcard type with no id value: parameter violation: error #100`,
err:`perms.Parse: parsed grant string "type=*;actions=list,read" contains wildcard type with no id value: parameter violation: error #100`,
},
{
name:"empty id and type",
input:"actions=create",
err:`perms.Parse: parsed grant string contains no id or type: parameter violation: error #100`,
err:`perms.Parse: parsed grant string "actions=create" contains no id or type: parameter violation: error #100`,
},
{
name:"wildcard type non child id",
input:"id=ttcp_1234567890;type=*;actions=create",
err:`perms.Parse: parsed grant string "id=ttcp_1234567890;type=*;actions=create" contains an id that does not support child types: parameter violation: error #100`,
err:`perms.Parse: parsed grant string "id=hcst_1234567890;type=account;actions=read" contains type account that is not a child type of the type (host-catalog) of the specified id: parameter violation: error #100`,
},
{
name:"no id with one bad action",
input:"type=host-set;actions=read",
err:`perms.Parse: parsed grant string "type=host-set;actions=read" contains non-create or non-list action in a format that only allows these: parameter violation: error #100`,
},
{
name:"no id with two bad action",
input:"type=host-set;actions=read,create",
err:`perms.Parse: parsed grant string "type=host-set;actions=create,read" contains non-create or non-list action in a format that only allows these: parameter violation: error #100`,
},
{
name:"no id with three bad action",
input:"type=host-set;actions=list,read,create",
err:`perms.Parse: parsed grant string "type=host-set;actions=create,list,read" contains non-create or non-list action in a format that only allows these: parameter violation: error #100`,