Files
threshold/internal/perms/output_fields_test.go
T
Todd a4ea99047f Remove Prefix Id and Plugin Name fields (#1563)
* Remove Prefix Id and Plugin Name fields.  Creating catalogs now require either the plugin id or the name of the plugin resource (but not both).  Host Catalogs and Host Sets API resources now have a read only plugin field populated with plugin info.  Host Catalogs have a plugin id field as a top level field.
2021-09-24 13:16:13 -07:00

280 lines
7.6 KiB
Go

package perms
import (
"testing"
"github.com/hashicorp/boundary/globals"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_OutputFields(t *testing.T) {
t.Parallel()
type input struct {
name string
fields []string
startMap OutputFieldsMap
resMap OutputFieldsMap
resStar bool
}
tests := []input{
{
name: "nil map, add nil",
},
{
name: "nil map, add fields",
fields: []string{"id", "version"},
resMap: OutputFieldsMap{"id": true, "version": true},
},
{
name: "existing map, add nil",
startMap: OutputFieldsMap{"id": true, "version": true},
resMap: OutputFieldsMap{"id": true, "version": true},
},
{
name: "existing with star, add nil",
startMap: OutputFieldsMap{"*": true},
resMap: OutputFieldsMap{"*": true},
resStar: true,
},
{
name: "existing with star, add new",
fields: []string{"id", "version"},
startMap: OutputFieldsMap{"*": true},
resMap: OutputFieldsMap{"*": true},
resStar: true,
},
{
name: "existing without star, add new",
fields: []string{"id", "version"},
startMap: OutputFieldsMap{"name": true},
resMap: OutputFieldsMap{"id": true, "version": true, "name": true},
},
{
name: "existing without star, add star",
fields: []string{"id", "*"},
startMap: OutputFieldsMap{"name": true},
resMap: OutputFieldsMap{"*": true},
resStar: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert := assert.New(t)
out := test.startMap.AddFields(test.fields)
assert.True(out.HasAll() == test.resStar)
assert.Equal(test.resMap, out)
})
}
}
func Test_ACLOutputFields(t *testing.T) {
t.Parallel()
type input struct {
name string
grants []string
resource Resource
action action.Type
fields []string
authorized bool
}
tests := []input{
{
name: "default",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
action: action.Read,
grants: []string{"id=bar;actions=read,update"},
authorized: true,
},
{
name: "single value",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{"id=bar;actions=read,update;output_fields=id"},
action: action.Read,
fields: []string{"id"},
authorized: true,
},
{
name: "compound no overlap",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;actions=read,update;output_fields=id",
"id=*;type=host-catalog;actions=read,update;output_fields=version",
},
action: action.Read,
fields: []string{"id"},
authorized: true,
},
{
name: "compound",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;actions=read,update;output_fields=id",
"id=*;type=role;output_fields=version",
},
action: action.Read,
fields: []string{"id", "version"},
authorized: true,
},
{
name: "wildcard with type",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;actions=read,update;output_fields=read",
"id=*;type=role;output_fields=*",
},
action: action.Read,
fields: []string{"*"},
authorized: true,
},
{
name: "wildcard with wildcard type",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;actions=read,update;output_fields=read",
"id=*;type=*;output_fields=*",
},
action: action.Read,
fields: []string{"*"},
authorized: true,
},
{
name: "subaction exact",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;actions=read:self,update;output_fields=version",
},
action: action.ReadSelf,
fields: []string{"version"},
authorized: true,
},
{
// If the action is a subaction, parent output fields will apply, in
// addition to subaction. This matches authorization.
name: "subaction parent action",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;actions=read,update;output_fields=version",
"id=bar;actions=read:self;output_fields=id",
},
action: action.ReadSelf,
fields: []string{"id", "version"},
authorized: true,
},
{
// The inverse isn't true. Similarly to authorization, if you have
// specific output fields on a self action, they don't apply to
// non-self actions. This is useful to allow more visibility to self
// actions and less in the general case.
name: "subaction child action",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;actions=read:self,update;output_fields=version",
"id=bar;actions=read;output_fields=id",
},
action: action.Read,
fields: []string{"id"},
authorized: true,
},
{
name: "initial grant unauthorized with star",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;output_fields=*",
"id=bar;actions=delete;output_fields=id",
},
action: action.Delete,
fields: []string{"*"},
authorized: true,
},
{
name: "unauthorized id only",
resource: Resource{ScopeId: "o_myorg", Id: "bar", Type: resource.Role},
grants: []string{
"id=bar;output_fields=name",
},
action: action.Delete,
fields: []string{"name"},
},
{
name: "unauthorized type only",
resource: Resource{ScopeId: "o_myorg", Type: resource.Role},
grants: []string{
"type=role;output_fields=name",
},
action: action.List,
fields: []string{"name"},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var grants []Grant
for _, g := range test.grants {
grant, err := Parse("o_myorg", g)
require.NoError(t, err)
grants = append(grants, grant)
}
acl := NewACL(grants...)
results := acl.Allowed(test.resource, test.action)
assert.ElementsMatch(t, results.OutputFields.Fields(), test.fields)
assert.True(t, test.authorized == results.Authorized)
})
}
}
func Test_ACLSelfOrDefault(t *testing.T) {
t.Parallel()
type input struct {
name string
input OutputFieldsMap
output OutputFieldsMap
userId string
}
tests := []input{
{
name: "nil, no user ID",
output: OutputFieldsMap{},
},
{
name: "nil, non anon id",
output: OutputFieldsMap{"*": true},
userId: "u_abc123",
},
{
name: "nil, anon id",
output: OutputFieldsMap{
globals.IdField: true,
globals.ScopeField: true,
globals.ScopeIdField: true,
globals.PluginField: true,
globals.PluginIdField: true,
globals.NameField: true,
globals.DescriptionField: true,
globals.TypeField: true,
globals.IsPrimaryField: true,
globals.PrimaryAuthMethodIdField: true,
globals.AuthorizedActionsField: true,
globals.AuthorizedCollectionActionsField: true,
},
userId: AnonymousUserId,
},
{
name: "not nil",
input: OutputFieldsMap{"foo": true},
output: OutputFieldsMap{"foo": true},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, test.output, test.input.SelfOrDefaults(test.userId))
})
}
}