From dcb15cffbddf5b9c141ec0e8387fea51d4cc50f5 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Wed, 20 Jan 2021 10:53:01 -0500 Subject: [PATCH] Add authorized actions output on resources (#870) --- CHANGELOG.md | 5 +- Makefile | 2 +- api/accounts/account.gen.go | 21 +- api/authmethods/authmethods.gen.go | 22 +- api/authtokens/authtokens.gen.go | 1 + api/groups/group.gen.go | 21 +- api/hostcatalogs/host_catalog.gen.go | 22 +- api/hosts/host.gen.go | 23 +- api/hostsets/host_set.gen.go | 23 +- api/roles/role.gen.go | 27 +- api/scopes/scope.gen.go | 20 +- api/sessions/session.gen.go | 1 + api/targets/target.gen.go | 2 +- api/users/user.gen.go | 21 +- internal/api/genapi/parse.go | 7 +- internal/auth/additional_verification_test.go | 18 +- internal/auth/auth.go | 25 +- internal/cmd/commands/accounts/account.go | 16 +- internal/cmd/commands/accounts/funcs.go | 8 + .../cmd/commands/authmethods/authmethod.go | 16 +- internal/cmd/commands/authmethods/funcs.go | 28 ++ .../cmd/commands/authtokens/authtokens.go | 6 + internal/cmd/commands/authtokens/funcs.go | 8 + internal/cmd/commands/groups/funcs.go | 9 + internal/cmd/commands/groups/group.go | 14 +- internal/cmd/commands/hostcatalogs/funcs.go | 27 ++ .../cmd/commands/hostcatalogs/hostcatalog.go | 16 +- internal/cmd/commands/hosts/funcs.go | 8 + internal/cmd/commands/hosts/host.go | 16 +- internal/cmd/commands/hostsets/funcs.go | 8 + internal/cmd/commands/hostsets/hostset.go | 16 +- internal/cmd/commands/roles/funcs.go | 8 + internal/cmd/commands/roles/role.go | 14 +- internal/cmd/commands/scopes/funcs.go | 26 ++ internal/cmd/commands/scopes/scope.go | 14 +- internal/cmd/commands/sessions/funcs.go | 8 + internal/cmd/commands/sessions/session.go | 20 +- internal/cmd/commands/targets/funcs.go | 16 +- internal/cmd/commands/targets/target.go | 16 +- internal/cmd/commands/users/funcs.go | 8 + internal/cmd/commands/users/user.go | 14 +- internal/gen/controller.swagger.json | 129 +++++++- .../api/resources/accounts/account.pb.go | 50 +-- .../resources/authmethods/auth_method.pb.go | 123 ++++--- .../api/resources/authtokens/authtoken.pb.go | 28 +- .../api/resources/groups/group.pb.go | 28 +- .../resources/hostcatalogs/host_catalog.pb.go | 94 ++++-- .../controller/api/resources/hosts/host.pb.go | 42 ++- .../api/resources/hostsets/host_set.pb.go | 28 +- .../controller/api/resources/roles/role.pb.go | 28 +- .../api/resources/scopes/scope.pb.go | 164 ++++++---- .../api/resources/sessions/session.pb.go | 28 +- .../api/resources/targets/target.pb.go | 26 +- .../controller/api/resources/users/user.pb.go | 28 +- .../api/resources/accounts/v1/account.proto | 5 +- .../authmethods/v1/auth_method.proto | 8 +- .../resources/authtokens/v1/authtoken.proto | 3 + .../api/resources/groups/v1/group.proto | 5 +- .../hostcatalogs/v1/host_catalog.proto | 8 +- .../api/resources/hosts/v1/host.proto | 5 +- .../api/resources/hostsets/v1/host_set.proto | 5 +- .../api/resources/roles/v1/role.proto | 5 +- .../api/resources/scopes/v1/scope.proto | 9 +- .../api/resources/sessions/v1/session.proto | 5 +- .../api/resources/targets/v1/target.proto | 6 +- .../api/resources/users/v1/user.proto | 5 +- .../handlers/accounts/account_service.go | 39 ++- .../handlers/accounts/account_service_test.go | 168 +++++----- .../authmethods/authmethod_service.go | 87 ++++- .../authmethods/authmethod_service_test.go | 47 ++- .../handlers/authtokens/authtoken_service.go | 28 +- .../authtokens/authtoken_service_test.go | 3 + .../handlers/groups/group_service.go | 40 ++- .../handlers/groups/group_service_test.go | 68 ++-- .../host_catalogs/host_catalog_service.go | 82 ++++- .../host_catalog_service_test.go | 170 ++++++---- .../handlers/host_sets/host_set_service.go | 41 ++- .../host_sets/host_set_service_test.go | 150 +++++---- .../controller/handlers/hosts/host_service.go | 35 +- .../handlers/hosts/host_service_test.go | 10 + .../controller/handlers/roles/role_service.go | 45 ++- .../handlers/roles/role_service_test.go | 266 ++++++++------- .../handlers/scopes/scope_service.go | 109 ++++++- .../handlers/scopes/scope_service_test.go | 307 ++++++++++++------ .../handlers/sessions/session_service.go | 29 +- .../handlers/sessions/session_service_test.go | 101 +++--- .../handlers/targets/target_service.go | 29 +- .../handlers/targets/target_service_test.go | 16 +- .../controller/handlers/users/user_service.go | 40 ++- .../handlers/users/user_service_test.go | 115 ++++--- internal/types/action/action.go | 6 +- internal/types/action/action_test.go | 8 +- sdk/strutil/strutil.go | 8 + 93 files changed, 2475 insertions(+), 1038 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbafca0fd..34ec119f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,9 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. ### New and Improved -* controller: Improved error handling in kms, oplog and perms repos - ([PR1](https://github.com/hashicorp/boundary/pull/848), [PR2](https://github.com/hashicorp/boundary/pull/854)) +* api/cli: On listing/reading, return a list of actions the user is authorized + to perform on the identified resources + ([PR](https://github.com/hashicorp/boundary/pull/870)) ### Bug Fixes diff --git a/Makefile b/Makefile index ec2bc419f..50aa400b4 100644 --- a/Makefile +++ b/Makefile @@ -134,7 +134,7 @@ protobuild: protolint: @buf check lint - @buf check breaking --against 'https://github.com/hashicorp/boundary.git' + @buf check breaking --against 'https://github.com/hashicorp/boundary.git#branch=stable-website' # must have nodejs and npm installed website: website-install website-start diff --git a/api/accounts/account.gen.go b/api/accounts/account.gen.go index b644417d9..f0eddbfc3 100644 --- a/api/accounts/account.gen.go +++ b/api/accounts/account.gen.go @@ -14,16 +14,17 @@ import ( ) type Account struct { - Id string `json:"id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Type string `json:"type,omitempty"` - AuthMethodId string `json:"auth_method_id,omitempty"` - Attributes map[string]interface{} `json:"attributes,omitempty"` + Id string `json:"id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Type string `json:"type,omitempty"` + AuthMethodId string `json:"auth_method_id,omitempty"` + Attributes map[string]interface{} `json:"attributes,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/authmethods/authmethods.gen.go b/api/authmethods/authmethods.gen.go index b8ee11c99..325c7744d 100644 --- a/api/authmethods/authmethods.gen.go +++ b/api/authmethods/authmethods.gen.go @@ -14,16 +14,18 @@ import ( ) type AuthMethod struct { - Id string `json:"id,omitempty"` - ScopeId string `json:"scope_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Type string `json:"type,omitempty"` - Attributes map[string]interface{} `json:"attributes,omitempty"` + Id string `json:"id,omitempty"` + ScopeId string `json:"scope_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Type string `json:"type,omitempty"` + Attributes map[string]interface{} `json:"attributes,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` + AuthorizedCollectionActions map[string][]string `json:"authorized_collection_actions,omitempty"` response *api.Response } diff --git a/api/authtokens/authtokens.gen.go b/api/authtokens/authtokens.gen.go index cd1930955..1425219ca 100644 --- a/api/authtokens/authtokens.gen.go +++ b/api/authtokens/authtokens.gen.go @@ -24,6 +24,7 @@ type AuthToken struct { UpdatedTime time.Time `json:"updated_time,omitempty"` ApproximateLastUsedTime time.Time `json:"approximate_last_used_time,omitempty"` ExpirationTime time.Time `json:"expiration_time,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/groups/group.gen.go b/api/groups/group.gen.go index e051ee388..c04179b3f 100644 --- a/api/groups/group.gen.go +++ b/api/groups/group.gen.go @@ -14,16 +14,17 @@ import ( ) type Group struct { - Id string `json:"id,omitempty"` - ScopeId string `json:"scope_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - MemberIds []string `json:"member_ids,omitempty"` - Members []*Member `json:"members,omitempty"` + Id string `json:"id,omitempty"` + ScopeId string `json:"scope_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + MemberIds []string `json:"member_ids,omitempty"` + Members []*Member `json:"members,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/hostcatalogs/host_catalog.gen.go b/api/hostcatalogs/host_catalog.gen.go index bbaaf3857..7a0fe8ea7 100644 --- a/api/hostcatalogs/host_catalog.gen.go +++ b/api/hostcatalogs/host_catalog.gen.go @@ -14,16 +14,18 @@ import ( ) type HostCatalog struct { - Id string `json:"id,omitempty"` - ScopeId string `json:"scope_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Type string `json:"type,omitempty"` - Attributes map[string]interface{} `json:"attributes,omitempty"` + Id string `json:"id,omitempty"` + ScopeId string `json:"scope_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Type string `json:"type,omitempty"` + Attributes map[string]interface{} `json:"attributes,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` + AuthorizedCollectionActions map[string][]string `json:"authorized_collection_actions,omitempty"` response *api.Response } diff --git a/api/hosts/host.gen.go b/api/hosts/host.gen.go index 27a5f117f..32dd78fb0 100644 --- a/api/hosts/host.gen.go +++ b/api/hosts/host.gen.go @@ -14,17 +14,18 @@ import ( ) type Host struct { - Id string `json:"id,omitempty"` - HostCatalogId string `json:"host_catalog_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Type string `json:"type,omitempty"` - HostSetIds []string `json:"host_set_ids,omitempty"` - Attributes map[string]interface{} `json:"attributes,omitempty"` + Id string `json:"id,omitempty"` + HostCatalogId string `json:"host_catalog_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Type string `json:"type,omitempty"` + HostSetIds []string `json:"host_set_ids,omitempty"` + Attributes map[string]interface{} `json:"attributes,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/hostsets/host_set.gen.go b/api/hostsets/host_set.gen.go index 2f4b639d3..d721ae6ae 100644 --- a/api/hostsets/host_set.gen.go +++ b/api/hostsets/host_set.gen.go @@ -14,17 +14,18 @@ import ( ) type HostSet struct { - Id string `json:"id,omitempty"` - HostCatalogId string `json:"host_catalog_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Type string `json:"type,omitempty"` - HostIds []string `json:"host_ids,omitempty"` - Attributes map[string]interface{} `json:"attributes,omitempty"` + Id string `json:"id,omitempty"` + HostCatalogId string `json:"host_catalog_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Type string `json:"type,omitempty"` + HostIds []string `json:"host_ids,omitempty"` + Attributes map[string]interface{} `json:"attributes,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/roles/role.gen.go b/api/roles/role.gen.go index 51db5f7a3..0bebd58ea 100644 --- a/api/roles/role.gen.go +++ b/api/roles/role.gen.go @@ -14,19 +14,20 @@ import ( ) type Role struct { - Id string `json:"id,omitempty"` - ScopeId string `json:"scope_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - GrantScopeId string `json:"grant_scope_id,omitempty"` - PrincipalIds []string `json:"principal_ids,omitempty"` - Principals []*Principal `json:"principals,omitempty"` - GrantStrings []string `json:"grant_strings,omitempty"` - Grants []*Grant `json:"grants,omitempty"` + Id string `json:"id,omitempty"` + ScopeId string `json:"scope_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + GrantScopeId string `json:"grant_scope_id,omitempty"` + PrincipalIds []string `json:"principal_ids,omitempty"` + Principals []*Principal `json:"principals,omitempty"` + GrantStrings []string `json:"grant_strings,omitempty"` + Grants []*Grant `json:"grants,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/scopes/scope.gen.go b/api/scopes/scope.gen.go index 6ff81c340..b04c603bc 100644 --- a/api/scopes/scope.gen.go +++ b/api/scopes/scope.gen.go @@ -13,15 +13,17 @@ import ( ) type Scope struct { - Id string `json:"id,omitempty"` - ScopeId string `json:"scope_id,omitempty"` - Scope *ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Type string `json:"type,omitempty"` + Id string `json:"id,omitempty"` + ScopeId string `json:"scope_id,omitempty"` + Scope *ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Type string `json:"type,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` + AuthorizedCollectionActions map[string][]string `json:"authorized_collection_actions,omitempty"` response *api.Response } diff --git a/api/sessions/session.gen.go b/api/sessions/session.gen.go index 3bb30ac86..99d956b56 100644 --- a/api/sessions/session.gen.go +++ b/api/sessions/session.gen.go @@ -32,6 +32,7 @@ type Session struct { WorkerInfo []*WorkerInfo `json:"worker_info,omitempty"` Certificate []byte `json:"certificate,omitempty"` TerminationReason string `json:"termination_reason,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/targets/target.gen.go b/api/targets/target.gen.go index b358118d3..3bc18de76 100644 --- a/api/targets/target.gen.go +++ b/api/targets/target.gen.go @@ -27,8 +27,8 @@ type Target struct { HostSets []*HostSet `json:"host_sets,omitempty"` SessionMaxSeconds uint32 `json:"session_max_seconds,omitempty"` SessionConnectionLimit int32 `json:"session_connection_limit,omitempty"` - AuthorizedActions []string `json:"authorized_actions,omitempty"` Attributes map[string]interface{} `json:"attributes,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/users/user.gen.go b/api/users/user.gen.go index 7cf461da4..6bf8d9852 100644 --- a/api/users/user.gen.go +++ b/api/users/user.gen.go @@ -14,16 +14,17 @@ import ( ) type User struct { - Id string `json:"id,omitempty"` - ScopeId string `json:"scope_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - AccountIds []string `json:"account_ids,omitempty"` - Accounts []*Account `json:"accounts,omitempty"` + Id string `json:"id,omitempty"` + ScopeId string `json:"scope_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + AccountIds []string `json:"account_ids,omitempty"` + Accounts []*Account `json:"accounts,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/internal/api/genapi/parse.go b/internal/api/genapi/parse.go index 257b8d214..6df15f5fb 100644 --- a/internal/api/genapi/parse.go +++ b/internal/api/genapi/parse.go @@ -65,7 +65,12 @@ func parsePBs() { if pkg != "" && pkg != in.generatedStructure.pkg { name = fmt.Sprintf("%s.%s", pkg, name) } - fi.FieldType = sliceText + ptr + name + switch name { + case "v1.AuthorizedCollectionActionsEntry": + fi.FieldType = "map[string][]string" + default: + fi.FieldType = sliceText + ptr + name + } case protoreflect.BytesKind: fi.FieldType = "[]byte" default: diff --git a/internal/auth/additional_verification_test.go b/internal/auth/additional_verification_test.go index be8df0c62..5e7868cd8 100644 --- a/internal/auth/additional_verification_test.go +++ b/internal/auth/additional_verification_test.go @@ -153,7 +153,7 @@ func TestAdditionalVerification(t *testing.T) { } } -func TestFetchActionsForId(t *testing.T) { +func TestFetchActionSetForId(t *testing.T) { tc := controller.NewTestController(t, nil) defer tc.Shutdown() @@ -182,8 +182,8 @@ func TestFetchActionsForId(t *testing.T) { cases := []struct { name string id string - avail action.Actions - allowed action.Actions + avail action.ActionSet + allowed action.ActionSet typeOverride resource.Type }{ { @@ -192,13 +192,13 @@ func TestFetchActionsForId(t *testing.T) { { name: "no match", id: "zip", - avail: action.Actions{action.Read, action.Update}, + avail: action.ActionSet{action.Read, action.Update}, }, { name: "disjoint match", id: "bar", - avail: action.Actions{action.Delete, action.AddGrants, action.Read, action.RemoveHostSets}, - allowed: action.Actions{action.Delete, action.Read}, + avail: action.ActionSet{action.Delete, action.AddGrants, action.Read, action.RemoveHostSets}, + allowed: action.ActionSet{action.Delete, action.Read}, }, { name: "different type", @@ -209,8 +209,8 @@ func TestFetchActionsForId(t *testing.T) { name: "type match", id: "anything", typeOverride: resource.Role, - avail: action.Actions{action.Read, action.AddGrants}, - allowed: action.Actions{action.AddGrants}, + avail: action.ActionSet{action.Read, action.AddGrants}, + allowed: action.ActionSet{action.AddGrants}, }, } for _, tt := range cases { @@ -239,7 +239,7 @@ func TestFetchActionsForId(t *testing.T) { auth.WithType(typ), }...) req.NoError(res.Error) - assert.Equal(t, tt.allowed, res.FetchActionsForId(ctx, tt.id, tt.avail)) + assert.Equal(t, tt.allowed, res.FetchActionSetForId(ctx, tt.id, tt.avail)) }) } } diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 88e1b3385..75d5dc7d0 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -554,9 +554,19 @@ func (r *VerifyResults) AdditionalVerification(ctx context.Context, opt ...Optio return } -// FetchActionsForId returns the allowed actions for a given ID using the -// current set of ACLs and all other parameters the same (user, scope, etc.) -func (r *VerifyResults) FetchActionsForId(ctx context.Context, id string, availableActions action.Actions, opt ...Option) action.Actions { +// FetchActionSetForId returns the allowed actions for a given ID using the +// current set of ACLs and all other parameters the same (user, etc.) +func (r *VerifyResults) FetchActionSetForId(ctx context.Context, id string, availableActions action.ActionSet, opt ...Option) action.ActionSet { + return r.fetchActions(ctx, id, resource.Unknown, availableActions, opt...) +} + +// FetchActionSetForType returns the allowed actions for a given collection type +// using the current set of ACLs and all other parameters the same (user, etc.) +func (r *VerifyResults) FetchActionSetForType(ctx context.Context, typ resource.Type, availableActions action.ActionSet, opt ...Option) action.ActionSet { + return r.fetchActions(ctx, "", typ, availableActions, opt...) +} + +func (r *VerifyResults) fetchActions(ctx context.Context, id string, typ resource.Type, availableActions action.ActionSet, opt ...Option) action.ActionSet { switch { case r.v.requestInfo.DisableAuthEntirely, r.v.requestInfo.TokenFormat == AuthTokenTypeRecoveryKms: @@ -573,9 +583,14 @@ func (r *VerifyResults) FetchActionsForId(ctx context.Context, id string, availa if res == nil { res = new(perms.Resource) } - res.Id = id + if id != "" { + res.Id = id + } + if typ != resource.Unknown { + res.Type = typ + } - ret := make(action.Actions, 0, len(availableActions)) + ret := make(action.ActionSet, 0, len(availableActions)) for _, act := range availableActions { if r.v.acl.Allowed(*res, act).Allowed { ret = append(ret, act) diff --git a/internal/cmd/commands/accounts/account.go b/internal/cmd/commands/accounts/account.go index ffa20069a..17378ae99 100644 --- a/internal/cmd/commands/accounts/account.go +++ b/internal/cmd/commands/accounts/account.go @@ -341,19 +341,25 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", m.Id), - fmt.Sprintf(" Version: %d", m.Version), - fmt.Sprintf(" Type: %s", m.Type), + fmt.Sprintf(" ID: %s", m.Id), + fmt.Sprintf(" Version: %d", m.Version), + fmt.Sprintf(" Type: %s", m.Type), ) } if m.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", m.Name), + fmt.Sprintf(" Name: %s", m.Name), ) } if m.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", m.Description), + fmt.Sprintf(" Description: %s", m.Description), + ) + } + if len(m.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, m.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/accounts/funcs.go b/internal/cmd/commands/accounts/funcs.go index 9586b3c4f..3716477ab 100644 --- a/internal/cmd/commands/accounts/funcs.go +++ b/internal/cmd/commands/accounts/funcs.go @@ -35,6 +35,14 @@ func generateAccountTableOutput(in *accounts.Account) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.Attributes) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/authmethods/authmethod.go b/internal/cmd/commands/authmethods/authmethod.go index b1810b128..181fb5425 100644 --- a/internal/cmd/commands/authmethods/authmethod.go +++ b/internal/cmd/commands/authmethods/authmethod.go @@ -227,23 +227,29 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", m.Id), + fmt.Sprintf(" ID: %s", m.Id), ) } if m.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", m.Description), + fmt.Sprintf(" Description: %s", m.Description), ) } if m.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", m.Name), + fmt.Sprintf(" Name: %s", m.Name), ) } if true { output = append(output, - fmt.Sprintf(" Type: %s", m.Type), - fmt.Sprintf(" Version: %d", m.Version), + fmt.Sprintf(" Type: %s", m.Type), + fmt.Sprintf(" Version: %d", m.Version), + ) + } + if len(m.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, m.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/authmethods/funcs.go b/internal/cmd/commands/authmethods/funcs.go index 7255bf64e..aa1351a91 100644 --- a/internal/cmd/commands/authmethods/funcs.go +++ b/internal/cmd/commands/authmethods/funcs.go @@ -1,6 +1,8 @@ package authmethods import ( + "fmt" + "sort" "time" "github.com/hashicorp/boundary/api/authmethods" @@ -47,6 +49,32 @@ func generateAuthMethodTableOutput(in *authmethods.AuthMethod) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + + if len(in.AuthorizedCollectionActions) > 0 { + keys := make([]string, 0, len(in.AuthorizedCollectionActions)) + for k := range in.AuthorizedCollectionActions { + keys = append(keys, k) + } + sort.Strings(keys) + ret = append(ret, + "", + " Authorized Actions on Auth Method's Collections:", + ) + for _, key := range keys { + ret = append(ret, + fmt.Sprintf(" %ss:", key), + base.WrapSlice(6, in.AuthorizedCollectionActions[key]), + ) + } + } + if len(in.Attributes) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/authtokens/authtokens.go b/internal/cmd/commands/authtokens/authtokens.go index a9f88d0ea..8986e9592 100644 --- a/internal/cmd/commands/authtokens/authtokens.go +++ b/internal/cmd/commands/authtokens/authtokens.go @@ -177,6 +177,12 @@ func (c *Command) Run(args []string) int { fmt.Sprintf(" Updated Time: %s", t.UpdatedTime.Local().Format(time.RFC1123)), fmt.Sprintf(" User ID: %s", t.UserId), ) + if len(t.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, t.AuthorizedActions), + ) + } } c.UI.Output(base.WrapForHelpText(output)) } diff --git a/internal/cmd/commands/authtokens/funcs.go b/internal/cmd/commands/authtokens/funcs.go index d4069b165..d79dc9b55 100644 --- a/internal/cmd/commands/authtokens/funcs.go +++ b/internal/cmd/commands/authtokens/funcs.go @@ -29,5 +29,13 @@ func generateAuthTokenTableOutput(in *authtokens.AuthToken) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + return base.WrapForHelpText(ret) } diff --git a/internal/cmd/commands/groups/funcs.go b/internal/cmd/commands/groups/funcs.go index 8f0e20e5e..b27cebaa0 100644 --- a/internal/cmd/commands/groups/funcs.go +++ b/internal/cmd/commands/groups/funcs.go @@ -111,10 +111,19 @@ func generateGroupTableOutput(in *groups.Group) string { "", "Group information:", base.WrapMap(2, maxLength+2, nonAttributeMap), + "", " Scope:", base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.Members) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/groups/group.go b/internal/cmd/commands/groups/group.go index 7d0e34216..1f8ab323b 100644 --- a/internal/cmd/commands/groups/group.go +++ b/internal/cmd/commands/groups/group.go @@ -247,18 +247,24 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", g.Id), - fmt.Sprintf(" Version: %d", g.Version), + fmt.Sprintf(" ID: %s", g.Id), + fmt.Sprintf(" Version: %d", g.Version), ) } if g.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", g.Name), + fmt.Sprintf(" Name: %s", g.Name), ) } if g.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", g.Description), + fmt.Sprintf(" Description: %s", g.Description), + ) + } + if len(g.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, g.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/hostcatalogs/funcs.go b/internal/cmd/commands/hostcatalogs/funcs.go index b095c0c1e..6d1953b34 100644 --- a/internal/cmd/commands/hostcatalogs/funcs.go +++ b/internal/cmd/commands/hostcatalogs/funcs.go @@ -1,6 +1,8 @@ package hostcatalogs import ( + "fmt" + "sort" "time" "github.com/hashicorp/boundary/api/hostcatalogs" @@ -34,6 +36,31 @@ func generateHostCatalogTableOutput(in *hostcatalogs.HostCatalog) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + + if len(in.AuthorizedCollectionActions) > 0 { + keys := make([]string, 0, len(in.AuthorizedCollectionActions)) + for k := range in.AuthorizedCollectionActions { + keys = append(keys, k) + } + sort.Strings(keys) + ret = append(ret, "", + " Authorized Actions on Host Catalog's Collections:", + ) + for _, key := range keys { + ret = append(ret, + fmt.Sprintf(" %ss:", key), + base.WrapSlice(6, in.AuthorizedCollectionActions[key]), + ) + } + } + if len(in.Attributes) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/hostcatalogs/hostcatalog.go b/internal/cmd/commands/hostcatalogs/hostcatalog.go index 15838c987..14a91609b 100644 --- a/internal/cmd/commands/hostcatalogs/hostcatalog.go +++ b/internal/cmd/commands/hostcatalogs/hostcatalog.go @@ -228,19 +228,25 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", m.Id), - fmt.Sprintf(" Version: %d", m.Version), - fmt.Sprintf(" Type: %s", m.Type), + fmt.Sprintf(" ID: %s", m.Id), + fmt.Sprintf(" Version: %d", m.Version), + fmt.Sprintf(" Type: %s", m.Type), ) } if m.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", m.Name), + fmt.Sprintf(" Name: %s", m.Name), ) } if m.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", m.Description), + fmt.Sprintf(" Description: %s", m.Description), + ) + } + if len(m.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, m.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/hosts/funcs.go b/internal/cmd/commands/hosts/funcs.go index 9130cd673..40bae759c 100644 --- a/internal/cmd/commands/hosts/funcs.go +++ b/internal/cmd/commands/hosts/funcs.go @@ -35,6 +35,14 @@ func generateHostTableOutput(in *hosts.Host) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.HostSetIds) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/hosts/host.go b/internal/cmd/commands/hosts/host.go index 0117bd3ba..d7c2be14d 100644 --- a/internal/cmd/commands/hosts/host.go +++ b/internal/cmd/commands/hosts/host.go @@ -227,19 +227,25 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", m.Id), - fmt.Sprintf(" Version: %d", m.Version), - fmt.Sprintf(" Type: %s", m.Type), + fmt.Sprintf(" ID: %s", m.Id), + fmt.Sprintf(" Version: %d", m.Version), + fmt.Sprintf(" Type: %s", m.Type), ) } if m.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", m.Name), + fmt.Sprintf(" Name: %s", m.Name), ) } if m.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", m.Description), + fmt.Sprintf(" Description: %s", m.Description), + ) + } + if len(m.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, m.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/hostsets/funcs.go b/internal/cmd/commands/hostsets/funcs.go index 47d3bb5d8..4d9577a54 100644 --- a/internal/cmd/commands/hostsets/funcs.go +++ b/internal/cmd/commands/hostsets/funcs.go @@ -35,6 +35,14 @@ func generateHostSetTableOutput(in *hostsets.HostSet) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.HostIds) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/hostsets/hostset.go b/internal/cmd/commands/hostsets/hostset.go index 27fe902c3..74cb249b5 100644 --- a/internal/cmd/commands/hostsets/hostset.go +++ b/internal/cmd/commands/hostsets/hostset.go @@ -322,19 +322,25 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", m.Id), - fmt.Sprintf(" Version: %d", m.Version), - fmt.Sprintf(" Type: %s", m.Type), + fmt.Sprintf(" ID: %s", m.Id), + fmt.Sprintf(" Version: %d", m.Version), + fmt.Sprintf(" Type: %s", m.Type), ) } if m.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", m.Name), + fmt.Sprintf(" Name: %s", m.Name), ) } if m.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", m.Description), + fmt.Sprintf(" Description: %s", m.Description), + ) + } + if len(m.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, m.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/roles/funcs.go b/internal/cmd/commands/roles/funcs.go index 90db514f3..dad1b623e 100644 --- a/internal/cmd/commands/roles/funcs.go +++ b/internal/cmd/commands/roles/funcs.go @@ -115,6 +115,14 @@ func generateRoleTableOutput(in *roles.Role) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.Principals) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/roles/role.go b/internal/cmd/commands/roles/role.go index 862278403..56639cef9 100644 --- a/internal/cmd/commands/roles/role.go +++ b/internal/cmd/commands/roles/role.go @@ -300,18 +300,24 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", r.Id), - fmt.Sprintf(" Version: %d", r.Version), + fmt.Sprintf(" ID: %s", r.Id), + fmt.Sprintf(" Version: %d", r.Version), ) } if r.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", r.Name), + fmt.Sprintf(" Name: %s", r.Name), ) } if r.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", r.Description), + fmt.Sprintf(" Description: %s", r.Description), + ) + } + if len(r.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, r.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/scopes/funcs.go b/internal/cmd/commands/scopes/funcs.go index 09fac7b15..1f7cd3418 100644 --- a/internal/cmd/commands/scopes/funcs.go +++ b/internal/cmd/commands/scopes/funcs.go @@ -1,6 +1,8 @@ package scopes import ( + "fmt" + "sort" "time" "github.com/hashicorp/boundary/api/scopes" @@ -33,5 +35,29 @@ func generateScopeTableOutput(in *scopes.Scope) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + "", + ) + } + + if len(in.AuthorizedCollectionActions) > 0 { + keys := make([]string, 0, len(in.AuthorizedCollectionActions)) + for k := range in.AuthorizedCollectionActions { + keys = append(keys, k) + } + sort.Strings(keys) + ret = append(ret, " Authorized Actions on Scope's Collections:") + for _, key := range keys { + ret = append(ret, + fmt.Sprintf(" %ss:", key), + base.WrapSlice(6, in.AuthorizedCollectionActions[key]), + ) + } + } + return base.WrapForHelpText(ret) } diff --git a/internal/cmd/commands/scopes/scope.go b/internal/cmd/commands/scopes/scope.go index 9c106fe4b..a5a485804 100644 --- a/internal/cmd/commands/scopes/scope.go +++ b/internal/cmd/commands/scopes/scope.go @@ -227,18 +227,24 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", s.Id), - fmt.Sprintf(" Version: %d", s.Version), + fmt.Sprintf(" ID: %s", s.Id), + fmt.Sprintf(" Version: %d", s.Version), ) } if s.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", s.Name), + fmt.Sprintf(" Name: %s", s.Name), ) } if s.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", s.Description), + fmt.Sprintf(" Description: %s", s.Description), + ) + } + if len(s.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, s.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/sessions/funcs.go b/internal/cmd/commands/sessions/funcs.go index f195ebb2e..3d4aac507 100644 --- a/internal/cmd/commands/sessions/funcs.go +++ b/internal/cmd/commands/sessions/funcs.go @@ -70,6 +70,14 @@ func generateSessionTableOutput(in *sessions.Session) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.States) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/sessions/session.go b/internal/cmd/commands/sessions/session.go index 444dd89b8..7e9e98cb0 100644 --- a/internal/cmd/commands/sessions/session.go +++ b/internal/cmd/commands/sessions/session.go @@ -168,14 +168,20 @@ func (c *Command) Run(args []string) int { output = append(output, "") } output = append(output, - fmt.Sprintf(" ID: %s", t.Id), - fmt.Sprintf(" Status: %s", t.Status), - fmt.Sprintf(" Created Time: %s", t.CreatedTime.Local().Format(time.RFC1123)), - fmt.Sprintf(" Expiration Time: %s", t.ExpirationTime.Local().Format(time.RFC1123)), - fmt.Sprintf(" Updated Time: %s", t.UpdatedTime.Local().Format(time.RFC1123)), - fmt.Sprintf(" User ID: %s", t.UserId), - fmt.Sprintf(" Target ID: %s", t.TargetId), + fmt.Sprintf(" ID: %s", t.Id), + fmt.Sprintf(" Status: %s", t.Status), + fmt.Sprintf(" Created Time: %s", t.CreatedTime.Local().Format(time.RFC1123)), + fmt.Sprintf(" Expiration Time: %s", t.ExpirationTime.Local().Format(time.RFC1123)), + fmt.Sprintf(" Updated Time: %s", t.UpdatedTime.Local().Format(time.RFC1123)), + fmt.Sprintf(" User ID: %s", t.UserId), + fmt.Sprintf(" Target ID: %s", t.TargetId), ) + if len(t.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, t.AuthorizedActions), + ) + } } c.UI.Output(base.WrapForHelpText(output)) } diff --git a/internal/cmd/commands/targets/funcs.go b/internal/cmd/commands/targets/funcs.go index 4b5a11aff..f2f806088 100644 --- a/internal/cmd/commands/targets/funcs.go +++ b/internal/cmd/commands/targets/funcs.go @@ -67,6 +67,14 @@ func generateTargetTableOutput(in *targets.Target) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.HostSets) > 0 { ret = append(ret, "", @@ -80,14 +88,6 @@ func generateTargetTableOutput(in *targets.Target) string { } } - if len(in.AuthorizedActions) > 0 { - ret = append(ret, - " Authorized Actions:", - base.WrapSlice(4, in.AuthorizedActions), - "", - ) - } - if len(in.Attributes) > 0 { ret = append(ret, " Attributes:", diff --git a/internal/cmd/commands/targets/target.go b/internal/cmd/commands/targets/target.go index a1c618775..22b6f92fa 100644 --- a/internal/cmd/commands/targets/target.go +++ b/internal/cmd/commands/targets/target.go @@ -427,19 +427,25 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", m.Id), - fmt.Sprintf(" Version: %d", m.Version), - fmt.Sprintf(" Type: %s", m.Type), + fmt.Sprintf(" ID: %s", m.Id), + fmt.Sprintf(" Version: %d", m.Version), + fmt.Sprintf(" Type: %s", m.Type), ) } if m.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", m.Name), + fmt.Sprintf(" Name: %s", m.Name), ) } if m.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", m.Description), + fmt.Sprintf(" Description: %s", m.Description), + ) + } + if len(m.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, m.AuthorizedActions), ) } } diff --git a/internal/cmd/commands/users/funcs.go b/internal/cmd/commands/users/funcs.go index 01c1b338d..73257937d 100644 --- a/internal/cmd/commands/users/funcs.go +++ b/internal/cmd/commands/users/funcs.go @@ -110,6 +110,14 @@ func generateUserTableOutput(in *users.User) string { base.ScopeInfoForOutput(in.Scope, maxLength), } + if len(in.AuthorizedActions) > 0 { + ret = append(ret, + "", + " Authorized Actions:", + base.WrapSlice(4, in.AuthorizedActions), + ) + } + if len(in.Accounts) > 0 { ret = append(ret, "", diff --git a/internal/cmd/commands/users/user.go b/internal/cmd/commands/users/user.go index fd9424ddc..79453070c 100644 --- a/internal/cmd/commands/users/user.go +++ b/internal/cmd/commands/users/user.go @@ -247,18 +247,24 @@ func (c *Command) Run(args []string) int { } if true { output = append(output, - fmt.Sprintf(" ID: %s", u.Id), - fmt.Sprintf(" Version: %d", u.Version), + fmt.Sprintf(" ID: %s", u.Id), + fmt.Sprintf(" Version: %d", u.Version), ) } if u.Name != "" { output = append(output, - fmt.Sprintf(" Name: %s", u.Name), + fmt.Sprintf(" Name: %s", u.Name), ) } if u.Description != "" { output = append(output, - fmt.Sprintf(" Description: %s", u.Description), + fmt.Sprintf(" Description: %s", u.Description), + ) + } + if len(u.AuthorizedActions) > 0 { + output = append(output, + " Authorized Actions:", + base.WrapSlice(6, u.AuthorizedActions), ) } } diff --git a/internal/gen/controller.swagger.json b/internal/gen/controller.swagger.json index 03fbc8570..1cdb02065 100644 --- a/internal/gen/controller.swagger.json +++ b/internal/gen/controller.swagger.json @@ -2352,6 +2352,14 @@ "attributes": { "type": "object", "description": "The attributes that are applicable for the specific Account type." + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "Account contains all fields related to an Account resource" @@ -2405,6 +2413,25 @@ "attributes": { "type": "object", "description": "The attributes that are applicable for the specific Auth Method type." + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true + }, + "authorized_collection_actions": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "object" + } + }, + "description": "Output only. The authorized actions for the scope's collections.", + "readOnly": true } }, "title": "AuthMethod contains all fields related to an Auth Method resource" @@ -2469,6 +2496,14 @@ "format": "date-time", "description": "Output only. The time this Auth Token expires.", "readOnly": true + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "AuthToken contains all fields related to an Auth Token resource" @@ -2530,6 +2565,14 @@ }, "description": "Output only. The members of this Group.", "readOnly": true + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "Group contains all fields related to a Group resource" @@ -2598,6 +2641,25 @@ "attributes": { "type": "object", "description": "Attributes specific to the catalog type." + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true + }, + "authorized_collection_actions": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "object" + } + }, + "description": "Output only. The authorized actions for the scope's collections.", + "readOnly": true } }, "title": "HostCatalog manages Hosts and Host Sets" @@ -2659,6 +2721,14 @@ "attributes": { "type": "object", "description": "The attributes that are applicable to the specific Host type." + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "Host contains all fields related to a Host resource" @@ -2720,6 +2790,14 @@ "attributes": { "type": "object", "description": "The attributes that are applicable for the specific Host Set type." + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "HostSet is a collection of Hosts created and managed by a Host Catalog" @@ -2864,6 +2942,14 @@ }, "description": "Output only. The parsed grant information.", "readOnly": true + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "Role contains all fields related to a Role resource" @@ -2913,6 +2999,25 @@ "type": { "type": "string", "description": "The type of the resource." + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true + }, + "authorized_collection_actions": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "object" + } + }, + "description": "Output only. The authorized actions for the scope's collections.", + "readOnly": true } }, "title": "Scope contains all fields related to a Scope resource" @@ -3054,6 +3159,14 @@ "type": "string", "description": "Output only. If the session is terminated, this provides a short description as to why.", "readOnly": true + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "Session contains all fields related to a Session resource" @@ -3231,6 +3344,10 @@ "format": "int32", "description": "Maximum number of connections allowed in a Session. Unlimited is indicated by the value -1." }, + "attributes": { + "type": "object", + "description": "The attributes that are applicable for the specific Target." + }, "authorized_actions": { "type": "array", "items": { @@ -3238,10 +3355,6 @@ }, "description": "Output only. The available actions on this resource for this user.", "readOnly": true - }, - "attributes": { - "type": "object", - "description": "The attributes that are applicable for the specific Target." } }, "title": "Target contains all fields related to a Target resource" @@ -3318,6 +3431,14 @@ }, "description": "Output only. The Accounts linked to this User.", "readOnly": true + }, + "authorized_actions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The available actions on this resource for this user.", + "readOnly": true } }, "title": "User contains all fields related to a User resource" diff --git a/internal/gen/controller/api/resources/accounts/account.pb.go b/internal/gen/controller/api/resources/accounts/account.pb.go index dec56112e..792caeb8d 100644 --- a/internal/gen/controller/api/resources/accounts/account.pb.go +++ b/internal/gen/controller/api/resources/accounts/account.pb.go @@ -52,6 +52,8 @@ type Account struct { AuthMethodId string `protobuf:"bytes,90,opt,name=auth_method_id,proto3" json:"auth_method_id,omitempty"` // The attributes that are applicable for the specific Account type. Attributes *_struct.Struct `protobuf:"bytes,100,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *Account) Reset() { @@ -156,6 +158,13 @@ func (x *Account) GetAttributes() *_struct.Struct { return nil } +func (x *Account) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + type PasswordAccountAttributes struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -233,7 +242,7 @@ var file_controller_api_resources_accounts_v1_account_proto_rawDesc = []byte{ 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x04, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd0, 0x04, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, @@ -267,24 +276,27 @@ var file_controller_api_resources_accounts_v1_account_proto_rawDesc = []byte{ 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x19, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xa0, 0xda, 0x29, 0x01, 0xc2, - 0xdd, 0x29, 0x22, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, - 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x09, 0x4c, 0x6f, 0x67, 0x69, - 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x3e, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x14, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, - 0x64, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, - 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x73, 0x3b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, + 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x19, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2a, 0xa0, 0xda, 0x29, 0x01, + 0xc2, 0xdd, 0x29, 0x22, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x2e, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x09, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x14, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x73, 0x3b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/resources/authmethods/auth_method.pb.go b/internal/gen/controller/api/resources/authmethods/auth_method.pb.go index e32e3aad0..0357cd6f5 100644 --- a/internal/gen/controller/api/resources/authmethods/auth_method.pb.go +++ b/internal/gen/controller/api/resources/authmethods/auth_method.pb.go @@ -52,6 +52,10 @@ type AuthMethod struct { Type string `protobuf:"bytes,90,opt,name=type,proto3" json:"type,omitempty"` // The attributes that are applicable for the specific Auth Method type. Attributes *_struct.Struct `protobuf:"bytes,100,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` + // Output only. The authorized actions for the scope's collections. + AuthorizedCollectionActions map[string]*_struct.ListValue `protobuf:"bytes,310,rep,name=authorized_collection_actions,proto3" json:"authorized_collection_actions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *AuthMethod) Reset() { @@ -156,6 +160,20 @@ func (x *AuthMethod) GetAttributes() *_struct.Struct { return nil } +func (x *AuthMethod) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + +func (x *AuthMethod) GetAuthorizedCollectionActions() map[string]*_struct.ListValue { + if x != nil { + return x.AuthorizedCollectionActions + } + return nil +} + type PasswordAuthMethodAttributes struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -234,7 +252,7 @@ var file_controller_api_resources_authmethods_v1_auth_method_proto_rawDesc = []b 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x96, 0x04, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0e, + 0xd1, 0x06, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, @@ -267,30 +285,49 @@ var file_controller_api_resources_authmethods_v1_auth_method_proto_rawDesc = []b 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x83, 0x02, 0x0a, 0x1c, 0x50, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x74, 0x0a, 0x15, 0x6d, 0x69, 0x6e, - 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x3e, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, - 0x29, 0x36, 0x0a, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, - 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x12, 0x12, 0x4d, 0x69, 0x6e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x4e, 0x61, - 0x6d, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x52, 0x15, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, + 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x9b, 0x01, 0x0a, 0x1d, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb6, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x54, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x75, + 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, + 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, + 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x83, 0x02, 0x0a, 0x1c, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x12, 0x74, 0x0a, 0x15, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, + 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0d, 0x42, 0x3e, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x36, 0x0a, 0x20, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, - 0x6d, 0x0a, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x3b, 0xa0, 0xda, - 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x33, 0x0a, 0x1e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x2e, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x11, 0x4d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x52, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x70, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x42, 0x5d, - 0x5a, 0x5b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x73, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x12, 0x4d, 0x69, 0x6e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x52, 0x15, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x6d, 0x0a, 0x13, 0x6d, 0x69, + 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x3b, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, + 0x33, 0x0a, 0x1e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x69, + 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x12, 0x11, 0x4d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x52, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x42, 0x5d, 0x5a, 0x5b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x2f, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x3b, 0x61, 0x75, 0x74, + 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -305,27 +342,31 @@ func file_controller_api_resources_authmethods_v1_auth_method_proto_rawDescGZIP( return file_controller_api_resources_authmethods_v1_auth_method_proto_rawDescData } -var file_controller_api_resources_authmethods_v1_auth_method_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_controller_api_resources_authmethods_v1_auth_method_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_controller_api_resources_authmethods_v1_auth_method_proto_goTypes = []interface{}{ (*AuthMethod)(nil), // 0: controller.api.resources.authmethods.v1.AuthMethod (*PasswordAuthMethodAttributes)(nil), // 1: controller.api.resources.authmethods.v1.PasswordAuthMethodAttributes - (*scopes.ScopeInfo)(nil), // 2: controller.api.resources.scopes.v1.ScopeInfo - (*wrappers.StringValue)(nil), // 3: google.protobuf.StringValue - (*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp - (*_struct.Struct)(nil), // 5: google.protobuf.Struct + nil, // 2: controller.api.resources.authmethods.v1.AuthMethod.AuthorizedCollectionActionsEntry + (*scopes.ScopeInfo)(nil), // 3: controller.api.resources.scopes.v1.ScopeInfo + (*wrappers.StringValue)(nil), // 4: google.protobuf.StringValue + (*timestamp.Timestamp)(nil), // 5: google.protobuf.Timestamp + (*_struct.Struct)(nil), // 6: google.protobuf.Struct + (*_struct.ListValue)(nil), // 7: google.protobuf.ListValue } var file_controller_api_resources_authmethods_v1_auth_method_proto_depIdxs = []int32{ - 2, // 0: controller.api.resources.authmethods.v1.AuthMethod.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 3, // 1: controller.api.resources.authmethods.v1.AuthMethod.name:type_name -> google.protobuf.StringValue - 3, // 2: controller.api.resources.authmethods.v1.AuthMethod.description:type_name -> google.protobuf.StringValue - 4, // 3: controller.api.resources.authmethods.v1.AuthMethod.created_time:type_name -> google.protobuf.Timestamp - 4, // 4: controller.api.resources.authmethods.v1.AuthMethod.updated_time:type_name -> google.protobuf.Timestamp - 5, // 5: controller.api.resources.authmethods.v1.AuthMethod.attributes:type_name -> google.protobuf.Struct - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 3, // 0: controller.api.resources.authmethods.v1.AuthMethod.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo + 4, // 1: controller.api.resources.authmethods.v1.AuthMethod.name:type_name -> google.protobuf.StringValue + 4, // 2: controller.api.resources.authmethods.v1.AuthMethod.description:type_name -> google.protobuf.StringValue + 5, // 3: controller.api.resources.authmethods.v1.AuthMethod.created_time:type_name -> google.protobuf.Timestamp + 5, // 4: controller.api.resources.authmethods.v1.AuthMethod.updated_time:type_name -> google.protobuf.Timestamp + 6, // 5: controller.api.resources.authmethods.v1.AuthMethod.attributes:type_name -> google.protobuf.Struct + 2, // 6: controller.api.resources.authmethods.v1.AuthMethod.authorized_collection_actions:type_name -> controller.api.resources.authmethods.v1.AuthMethod.AuthorizedCollectionActionsEntry + 7, // 7: controller.api.resources.authmethods.v1.AuthMethod.AuthorizedCollectionActionsEntry.value:type_name -> google.protobuf.ListValue + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_controller_api_resources_authmethods_v1_auth_method_proto_init() } @@ -365,7 +406,7 @@ func file_controller_api_resources_authmethods_v1_auth_method_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_api_resources_authmethods_v1_auth_method_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 3, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/gen/controller/api/resources/authtokens/authtoken.pb.go b/internal/gen/controller/api/resources/authtokens/authtoken.pb.go index acbb50383..fc2ed0194 100644 --- a/internal/gen/controller/api/resources/authtokens/authtoken.pb.go +++ b/internal/gen/controller/api/resources/authtokens/authtoken.pb.go @@ -51,6 +51,8 @@ type AuthToken struct { ApproximateLastUsedTime *timestamp.Timestamp `protobuf:"bytes,100,opt,name=approximate_last_used_time,proto3" json:"approximate_last_used_time,omitempty"` // Output only. The time this Auth Token expires. ExpirationTime *timestamp.Timestamp `protobuf:"bytes,110,opt,name=expiration_time,proto3" json:"expiration_time,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *AuthToken) Reset() { @@ -162,6 +164,13 @@ func (x *AuthToken) GetExpirationTime() *timestamp.Timestamp { return nil } +func (x *AuthToken) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + var File_controller_api_resources_authtokens_v1_authtoken_proto protoreflect.FileDescriptor var file_controller_api_resources_authtokens_v1_authtoken_proto_rawDesc = []byte{ @@ -178,7 +187,7 @@ var file_controller_api_resources_authtokens_v1_authtoken_proto_rawDesc = []byte 0x6f, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x96, 0x04, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, + 0x6f, 0x22, 0xc7, 0x04, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, @@ -211,13 +220,16 @@ var file_controller_api_resources_authtokens_v1_authtoken_proto_rawDesc = []byte 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x42, 0x5b, 0x5a, 0x59, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x3b, 0x61, 0x75, 0x74, - 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x5b, 0x5a, 0x59, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x3b, 0x61, 0x75, + 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/resources/groups/group.pb.go b/internal/gen/controller/api/resources/groups/group.pb.go index 9a7a327e7..c7431ff68 100644 --- a/internal/gen/controller/api/resources/groups/group.pb.go +++ b/internal/gen/controller/api/resources/groups/group.pb.go @@ -108,6 +108,8 @@ type Group struct { MemberIds []string `protobuf:"bytes,90,rep,name=member_ids,proto3" json:"member_ids,omitempty"` // Output only. The members of this Group. Members []*Member `protobuf:"bytes,100,rep,name=members,proto3" json:"members,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *Group) Reset() { @@ -212,6 +214,13 @@ func (x *Group) GetMembers() []*Member { return nil } +func (x *Group) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + var File_controller_api_resources_groups_v1_group_proto protoreflect.FileDescriptor var file_controller_api_resources_groups_v1_group_proto_rawDesc = []byte{ @@ -233,7 +242,7 @@ var file_controller_api_resources_groups_v1_group_proto_rawDesc = []byte{ 0x6f, 0x22, 0x34, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, - 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x22, 0xa4, 0x04, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, + 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x22, 0xd5, 0x04, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, @@ -267,13 +276,16 @@ var file_controller_api_resources_groups_v1_group_proto_rawDesc = []byte{ 0x65, 0x72, 0x73, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x42, 0x53, - 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x3b, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x2f, + 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, + 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x3b, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/resources/hostcatalogs/host_catalog.pb.go b/internal/gen/controller/api/resources/hostcatalogs/host_catalog.pb.go index 0b136b7c2..715c8d2c5 100644 --- a/internal/gen/controller/api/resources/hostcatalogs/host_catalog.pb.go +++ b/internal/gen/controller/api/resources/hostcatalogs/host_catalog.pb.go @@ -52,6 +52,10 @@ type HostCatalog struct { Type string `protobuf:"bytes,90,opt,name=type,proto3" json:"type,omitempty"` // Attributes specific to the catalog type. Attributes *_struct.Struct `protobuf:"bytes,100,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` + // Output only. The authorized actions for the scope's collections. + AuthorizedCollectionActions map[string]*_struct.ListValue `protobuf:"bytes,310,rep,name=authorized_collection_actions,proto3" json:"authorized_collection_actions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *HostCatalog) Reset() { @@ -156,6 +160,20 @@ func (x *HostCatalog) GetAttributes() *_struct.Struct { return nil } +func (x *HostCatalog) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + +func (x *HostCatalog) GetAuthorizedCollectionActions() map[string]*_struct.ListValue { + if x != nil { + return x.AuthorizedCollectionActions + } + return nil +} + var File_controller_api_resources_hostcatalogs_v1_host_catalog_proto protoreflect.FileDescriptor var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc = []byte{ @@ -177,7 +195,7 @@ var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc = [ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x97, 0x04, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, + 0x74, 0x6f, 0x22, 0xd4, 0x06, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, @@ -210,14 +228,34 @@ var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc = [ 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, - 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x5f, 0x5a, 0x5d, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, - 0x3b, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x12, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x9d, 0x01, + 0x0a, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0xb6, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x56, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x5f, 0x5a, 0x5d, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x3b, 0x68, 0x6f, + 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -232,26 +270,30 @@ func file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDescGZI return file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDescData } -var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_goTypes = []interface{}{ (*HostCatalog)(nil), // 0: controller.api.resources.hostcatalogs.v1.HostCatalog - (*scopes.ScopeInfo)(nil), // 1: controller.api.resources.scopes.v1.ScopeInfo - (*wrappers.StringValue)(nil), // 2: google.protobuf.StringValue - (*timestamp.Timestamp)(nil), // 3: google.protobuf.Timestamp - (*_struct.Struct)(nil), // 4: google.protobuf.Struct + nil, // 1: controller.api.resources.hostcatalogs.v1.HostCatalog.AuthorizedCollectionActionsEntry + (*scopes.ScopeInfo)(nil), // 2: controller.api.resources.scopes.v1.ScopeInfo + (*wrappers.StringValue)(nil), // 3: google.protobuf.StringValue + (*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp + (*_struct.Struct)(nil), // 5: google.protobuf.Struct + (*_struct.ListValue)(nil), // 6: google.protobuf.ListValue } var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_depIdxs = []int32{ - 1, // 0: controller.api.resources.hostcatalogs.v1.HostCatalog.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 2, // 1: controller.api.resources.hostcatalogs.v1.HostCatalog.name:type_name -> google.protobuf.StringValue - 2, // 2: controller.api.resources.hostcatalogs.v1.HostCatalog.description:type_name -> google.protobuf.StringValue - 3, // 3: controller.api.resources.hostcatalogs.v1.HostCatalog.created_time:type_name -> google.protobuf.Timestamp - 3, // 4: controller.api.resources.hostcatalogs.v1.HostCatalog.updated_time:type_name -> google.protobuf.Timestamp - 4, // 5: controller.api.resources.hostcatalogs.v1.HostCatalog.attributes:type_name -> google.protobuf.Struct - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 2, // 0: controller.api.resources.hostcatalogs.v1.HostCatalog.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo + 3, // 1: controller.api.resources.hostcatalogs.v1.HostCatalog.name:type_name -> google.protobuf.StringValue + 3, // 2: controller.api.resources.hostcatalogs.v1.HostCatalog.description:type_name -> google.protobuf.StringValue + 4, // 3: controller.api.resources.hostcatalogs.v1.HostCatalog.created_time:type_name -> google.protobuf.Timestamp + 4, // 4: controller.api.resources.hostcatalogs.v1.HostCatalog.updated_time:type_name -> google.protobuf.Timestamp + 5, // 5: controller.api.resources.hostcatalogs.v1.HostCatalog.attributes:type_name -> google.protobuf.Struct + 1, // 6: controller.api.resources.hostcatalogs.v1.HostCatalog.authorized_collection_actions:type_name -> controller.api.resources.hostcatalogs.v1.HostCatalog.AuthorizedCollectionActionsEntry + 6, // 7: controller.api.resources.hostcatalogs.v1.HostCatalog.AuthorizedCollectionActionsEntry.value:type_name -> google.protobuf.ListValue + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_init() } @@ -279,7 +321,7 @@ func file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/gen/controller/api/resources/hosts/host.pb.go b/internal/gen/controller/api/resources/hosts/host.pb.go index 9f66e5ae4..3f8395cbe 100644 --- a/internal/gen/controller/api/resources/hosts/host.pb.go +++ b/internal/gen/controller/api/resources/hosts/host.pb.go @@ -54,6 +54,8 @@ type Host struct { HostSetIds []string `protobuf:"bytes,100,rep,name=host_set_ids,proto3" json:"host_set_ids,omitempty"` // The attributes that are applicable to the specific Host type. Attributes *_struct.Struct `protobuf:"bytes,110,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *Host) Reset() { @@ -165,6 +167,13 @@ func (x *Host) GetAttributes() *_struct.Struct { return nil } +func (x *Host) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + type StaticHostAttributes struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -232,7 +241,7 @@ var file_controller_api_resources_hosts_v1_host_proto_rawDesc = []byte{ 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc2, 0x04, 0x0a, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf3, 0x04, 0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, @@ -269,20 +278,23 @@ var file_controller_api_resources_hosts_v1_host_proto_rawDesc = []byte{ 0x18, 0x6e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x22, 0x75, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x25, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, - 0x29, 0x1d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, - 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3b, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x73, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x22, 0x75, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x25, 0xa0, 0xda, 0x29, 0x01, 0xc2, + 0xdd, 0x29, 0x1d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3b, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/resources/hostsets/host_set.pb.go b/internal/gen/controller/api/resources/hostsets/host_set.pb.go index fe7f276f5..00960847e 100644 --- a/internal/gen/controller/api/resources/hostsets/host_set.pb.go +++ b/internal/gen/controller/api/resources/hostsets/host_set.pb.go @@ -55,6 +55,8 @@ type HostSet struct { HostIds []string `protobuf:"bytes,100,rep,name=host_ids,proto3" json:"host_ids,omitempty"` // The attributes that are applicable for the specific Host Set type. Attributes *_struct.Struct `protobuf:"bytes,110,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *HostSet) Reset() { @@ -166,6 +168,13 @@ func (x *HostSet) GetAttributes() *_struct.Struct { return nil } +func (x *HostSet) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + var File_controller_api_resources_hostsets_v1_host_set_proto protoreflect.FileDescriptor var file_controller_api_resources_hostsets_v1_host_set_proto_rawDesc = []byte{ @@ -189,7 +198,7 @@ var file_controller_api_resources_hostsets_v1_host_set_proto_rawDesc = []byte{ 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb7, 0x04, 0x0a, 0x07, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe8, 0x04, 0x0a, 0x07, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x6f, 0x73, 0x74, 0x5f, @@ -224,13 +233,16 @@ var file_controller_api_resources_hostsets_v1_host_set_proto_rawDesc = []byte{ 0x74, 0x5f, 0x69, 0x64, 0x73, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x57, - 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x65, 0x74, 0x73, 0x3b, 0x68, - 0x6f, 0x73, 0x74, 0x73, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, + 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, + 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x65, 0x74, 0x73, 0x3b, + 0x68, 0x6f, 0x73, 0x74, 0x73, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/resources/roles/role.pb.go b/internal/gen/controller/api/resources/roles/role.pb.go index 365c90be3..34ace82a6 100644 --- a/internal/gen/controller/api/resources/roles/role.pb.go +++ b/internal/gen/controller/api/resources/roles/role.pb.go @@ -255,6 +255,8 @@ type Role struct { GrantStrings []string `protobuf:"bytes,120,rep,name=grant_strings,proto3" json:"grant_strings,omitempty"` // Output only. The parsed grant information. Grants []*Grant `protobuf:"bytes,130,rep,name=grants,proto3" json:"grants,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *Role) Reset() { @@ -380,6 +382,13 @@ func (x *Role) GetGrants() []*Grant { return nil } +func (x *Role) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + var File_controller_api_resources_roles_v1_role_proto protoreflect.FileDescriptor var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{ @@ -415,7 +424,7 @@ var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x4a, 0x73, 0x6f, 0x6e, 0x52, 0x04, 0x6a, 0x73, 0x6f, - 0x6e, 0x22, 0x88, 0x06, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x6e, 0x22, 0xb9, 0x06, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, @@ -463,13 +472,16 @@ var file_controller_api_resources_roles_v1_role_proto_rawDesc = []byte{ 0x6e, 0x74, 0x73, 0x18, 0x82, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x72, 0x61, 0x6e, 0x74, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x42, 0x51, 0x5a, 0x4f, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x61, 0x6e, 0x74, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x12, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x51, 0x5a, + 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x72, 0x6f, 0x6c, 0x65, 0x73, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/resources/scopes/scope.pb.go b/internal/gen/controller/api/resources/scopes/scope.pb.go index 938a8806a..d8f7cf3ef 100644 --- a/internal/gen/controller/api/resources/scopes/scope.pb.go +++ b/internal/gen/controller/api/resources/scopes/scope.pb.go @@ -7,6 +7,7 @@ package scopes import ( + _struct "github.com/golang/protobuf/ptypes/struct" timestamp "github.com/golang/protobuf/ptypes/timestamp" wrappers "github.com/golang/protobuf/ptypes/wrappers" _ "github.com/hashicorp/boundary/internal/gen/controller/protooptions" @@ -132,6 +133,10 @@ type Scope struct { Version uint32 `protobuf:"varint,80,opt,name=version,proto3" json:"version,omitempty"` // The type of the resource. Type string `protobuf:"bytes,90,opt,name=type,proto3" json:"type,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` + // Output only. The authorized actions for the scope's collections. + AuthorizedCollectionActions map[string]*_struct.ListValue `protobuf:"bytes,310,rep,name=authorized_collection_actions,proto3" json:"authorized_collection_actions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Scope) Reset() { @@ -229,6 +234,20 @@ func (x *Scope) GetType() string { return "" } +func (x *Scope) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + +func (x *Scope) GetAuthorizedCollectionActions() map[string]*_struct.ListValue { + if x != nil { + return x.AuthorizedCollectionActions + } + return nil +} + var File_controller_api_resources_scopes_v1_scope_proto protoreflect.FileDescriptor var file_controller_api_resources_scopes_v1_scope_proto_rawDesc = []byte{ @@ -241,54 +260,75 @@ var file_controller_api_resources_scopes_v1_scope_proto_rawDesc = []byte{ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x8f, 0x01, 0x0a, 0x09, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, - 0x5f, 0x69, 0x64, 0x22, 0xd2, 0x03, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, - 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, - 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x46, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, 0xda, 0x29, 0x01, - 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, 0x29, 0x01, 0xc2, - 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, + 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, + 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x8f, 0x01, 0x0a, 0x09, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, + 0x64, 0x22, 0x83, 0x06, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x46, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, + 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, + 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x91, 0x01, 0x0a, 0x1d, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb6, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x4a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x5a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x3b, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x53, 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x73, 0x3b, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -303,24 +343,28 @@ func file_controller_api_resources_scopes_v1_scope_proto_rawDescGZIP() []byte { return file_controller_api_resources_scopes_v1_scope_proto_rawDescData } -var file_controller_api_resources_scopes_v1_scope_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_controller_api_resources_scopes_v1_scope_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_controller_api_resources_scopes_v1_scope_proto_goTypes = []interface{}{ (*ScopeInfo)(nil), // 0: controller.api.resources.scopes.v1.ScopeInfo (*Scope)(nil), // 1: controller.api.resources.scopes.v1.Scope - (*wrappers.StringValue)(nil), // 2: google.protobuf.StringValue - (*timestamp.Timestamp)(nil), // 3: google.protobuf.Timestamp + nil, // 2: controller.api.resources.scopes.v1.Scope.AuthorizedCollectionActionsEntry + (*wrappers.StringValue)(nil), // 3: google.protobuf.StringValue + (*timestamp.Timestamp)(nil), // 4: google.protobuf.Timestamp + (*_struct.ListValue)(nil), // 5: google.protobuf.ListValue } var file_controller_api_resources_scopes_v1_scope_proto_depIdxs = []int32{ 0, // 0: controller.api.resources.scopes.v1.Scope.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 2, // 1: controller.api.resources.scopes.v1.Scope.name:type_name -> google.protobuf.StringValue - 2, // 2: controller.api.resources.scopes.v1.Scope.description:type_name -> google.protobuf.StringValue - 3, // 3: controller.api.resources.scopes.v1.Scope.created_time:type_name -> google.protobuf.Timestamp - 3, // 4: controller.api.resources.scopes.v1.Scope.updated_time:type_name -> google.protobuf.Timestamp - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 3, // 1: controller.api.resources.scopes.v1.Scope.name:type_name -> google.protobuf.StringValue + 3, // 2: controller.api.resources.scopes.v1.Scope.description:type_name -> google.protobuf.StringValue + 4, // 3: controller.api.resources.scopes.v1.Scope.created_time:type_name -> google.protobuf.Timestamp + 4, // 4: controller.api.resources.scopes.v1.Scope.updated_time:type_name -> google.protobuf.Timestamp + 2, // 5: controller.api.resources.scopes.v1.Scope.authorized_collection_actions:type_name -> controller.api.resources.scopes.v1.Scope.AuthorizedCollectionActionsEntry + 5, // 6: controller.api.resources.scopes.v1.Scope.AuthorizedCollectionActionsEntry.value:type_name -> google.protobuf.ListValue + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_controller_api_resources_scopes_v1_scope_proto_init() } @@ -360,7 +404,7 @@ func file_controller_api_resources_scopes_v1_scope_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_api_resources_scopes_v1_scope_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 3, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/gen/controller/api/resources/sessions/session.pb.go b/internal/gen/controller/api/resources/sessions/session.pb.go index ddc6f14ec..9890fa7ae 100644 --- a/internal/gen/controller/api/resources/sessions/session.pb.go +++ b/internal/gen/controller/api/resources/sessions/session.pb.go @@ -184,6 +184,8 @@ type Session struct { Certificate []byte `protobuf:"bytes,200,opt,name=certificate,proto3" json:"certificate,omitempty"` // Output only. If the session is terminated, this provides a short description as to why. TerminationReason string `protobuf:"bytes,210,opt,name=termination_reason,proto3" json:"termination_reason,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *Session) Reset() { @@ -351,6 +353,13 @@ func (x *Session) GetTerminationReason() string { return "" } +func (x *Session) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + var File_controller_api_resources_sessions_v1_session_proto protoreflect.FileDescriptor var file_controller_api_resources_sessions_v1_session_proto_rawDesc = []byte{ @@ -386,7 +395,7 @@ var file_controller_api_resources_sessions_v1_session_proto_rawDesc = []byte{ 0x74, 0x69, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0xb7, 0x06, 0x0a, + 0x6d, 0x70, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0xe8, 0x06, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x72, @@ -438,13 +447,16 @@ var file_controller_api_resources_sessions_v1_session_proto_rawDesc = []byte{ 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x12, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0xd2, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/gen/controller/api/resources/targets/target.pb.go b/internal/gen/controller/api/resources/targets/target.pb.go index 04fe1ddcf..692248287 100644 --- a/internal/gen/controller/api/resources/targets/target.pb.go +++ b/internal/gen/controller/api/resources/targets/target.pb.go @@ -115,10 +115,10 @@ type Target struct { SessionMaxSeconds *wrappers.UInt32Value `protobuf:"bytes,120,opt,name=session_max_seconds,proto3" json:"session_max_seconds,omitempty"` // Maximum number of connections allowed in a Session. Unlimited is indicated by the value -1. SessionConnectionLimit *wrappers.Int32Value `protobuf:"bytes,130,opt,name=session_connection_limit,proto3" json:"session_connection_limit,omitempty"` - // Output only. The available actions on this resource for this user. - AuthorizedActions []string `protobuf:"bytes,140,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` // The attributes that are applicable for the specific Target. Attributes *_struct.Struct `protobuf:"bytes,200,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *Target) Reset() { @@ -244,16 +244,16 @@ func (x *Target) GetSessionConnectionLimit() *wrappers.Int32Value { return nil } -func (x *Target) GetAuthorizedActions() []string { +func (x *Target) GetAttributes() *_struct.Struct { if x != nil { - return x.AuthorizedActions + return x.Attributes } return nil } -func (x *Target) GetAttributes() *_struct.Struct { +func (x *Target) GetAuthorizedActions() []string { if x != nil { - return x.Attributes + return x.AuthorizedActions } return nil } @@ -703,14 +703,14 @@ var file_controller_api_resources_targets_v1_target_proto_rawDesc = []byte{ 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x8c, 0x01, + 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0xc8, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, - 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0xc8, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x87, 0x01, 0x0a, 0x13, 0x54, 0x63, 0x70, + 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x87, 0x01, 0x0a, 0x13, 0x54, 0x63, 0x70, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x70, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, diff --git a/internal/gen/controller/api/resources/users/user.pb.go b/internal/gen/controller/api/resources/users/user.pb.go index c485cfe3c..a82144ce4 100644 --- a/internal/gen/controller/api/resources/users/user.pb.go +++ b/internal/gen/controller/api/resources/users/user.pb.go @@ -108,6 +108,8 @@ type User struct { AccountIds []string `protobuf:"bytes,90,rep,name=account_ids,proto3" json:"account_ids,omitempty"` // Output only. The Accounts linked to this User. Accounts []*Account `protobuf:"bytes,100,rep,name=accounts,proto3" json:"accounts,omitempty"` + // Output only. The available actions on this resource for this user. + AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty"` } func (x *User) Reset() { @@ -212,6 +214,13 @@ func (x *User) GetAccounts() []*Account { return nil } +func (x *User) GetAuthorizedActions() []string { + if x != nil { + return x.AuthorizedActions + } + return nil +} + var File_controller_api_resources_users_v1_user_proto protoreflect.FileDescriptor var file_controller_api_resources_users_v1_user_proto_rawDesc = []byte{ @@ -233,7 +242,7 @@ var file_controller_api_resources_users_v1_user_proto_rawDesc = []byte{ 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x5f, 0x69, 0x64, 0x22, 0xa7, 0x04, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, + 0x70, 0x65, 0x5f, 0x69, 0x64, 0x22, 0xd8, 0x04, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, @@ -267,13 +276,16 @@ var file_controller_api_resources_users_v1_user_proto_rawDesc = []byte{ 0x6e, 0x74, 0x73, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x42, - 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, - 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3b, 0x75, 0x73, 0x65, - 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, + 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3b, 0x75, 0x73, + 0x65, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/proto/local/controller/api/resources/accounts/v1/account.proto b/internal/proto/local/controller/api/resources/accounts/v1/account.proto index 3e21b4619..65e0a600d 100644 --- a/internal/proto/local/controller/api/resources/accounts/v1/account.proto +++ b/internal/proto/local/controller/api/resources/accounts/v1/account.proto @@ -31,7 +31,7 @@ message Account { google.protobuf.Timestamp updated_time = 60 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 70; // The type of this Account. @@ -42,6 +42,9 @@ message Account { // The attributes that are applicable for the specific Account type. google.protobuf.Struct attributes = 100 [(custom_options.v1.generate_sdk_option) = true]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } message PasswordAccountAttributes { diff --git a/internal/proto/local/controller/api/resources/authmethods/v1/auth_method.proto b/internal/proto/local/controller/api/resources/authmethods/v1/auth_method.proto index 88773db37..ab4133fdd 100644 --- a/internal/proto/local/controller/api/resources/authmethods/v1/auth_method.proto +++ b/internal/proto/local/controller/api/resources/authmethods/v1/auth_method.proto @@ -34,7 +34,7 @@ message AuthMethod { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // The Auth Method type. @@ -42,6 +42,12 @@ message AuthMethod { // The attributes that are applicable for the specific Auth Method type. google.protobuf.Struct attributes = 100 [(custom_options.v1.generate_sdk_option) = true]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; + + // Output only. The authorized actions for the scope's collections. + map authorized_collection_actions = 310 [json_name="authorized_collection_actions"]; } message PasswordAuthMethodAttributes { diff --git a/internal/proto/local/controller/api/resources/authtokens/v1/authtoken.proto b/internal/proto/local/controller/api/resources/authtokens/v1/authtoken.proto index 3cad11689..3d3698728 100644 --- a/internal/proto/local/controller/api/resources/authtokens/v1/authtoken.proto +++ b/internal/proto/local/controller/api/resources/authtokens/v1/authtoken.proto @@ -42,4 +42,7 @@ message AuthToken { // Output only. The time this Auth Token expires. google.protobuf.Timestamp expiration_time = 110 [json_name="expiration_time"]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } diff --git a/internal/proto/local/controller/api/resources/groups/v1/group.proto b/internal/proto/local/controller/api/resources/groups/v1/group.proto index d53e8b9c5..9688fd72c 100644 --- a/internal/proto/local/controller/api/resources/groups/v1/group.proto +++ b/internal/proto/local/controller/api/resources/groups/v1/group.proto @@ -41,7 +41,7 @@ message Group { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // Output only. Contains the list of member IDs in this Group. @@ -49,4 +49,7 @@ message Group { // Output only. The members of this Group. repeated Member members = 100; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } diff --git a/internal/proto/local/controller/api/resources/hostcatalogs/v1/host_catalog.proto b/internal/proto/local/controller/api/resources/hostcatalogs/v1/host_catalog.proto index fc0048397..d7b06b959 100644 --- a/internal/proto/local/controller/api/resources/hostcatalogs/v1/host_catalog.proto +++ b/internal/proto/local/controller/api/resources/hostcatalogs/v1/host_catalog.proto @@ -34,7 +34,7 @@ message HostCatalog { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // The type of Host Catalog. @@ -42,4 +42,10 @@ message HostCatalog { // Attributes specific to the catalog type. google.protobuf.Struct attributes = 100 [(custom_options.v1.generate_sdk_option) = true]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; + + // Output only. The authorized actions for the scope's collections. + map authorized_collection_actions = 310 [json_name="authorized_collection_actions"]; } diff --git a/internal/proto/local/controller/api/resources/hosts/v1/host.proto b/internal/proto/local/controller/api/resources/hosts/v1/host.proto index 8716d9110..b14661fdc 100644 --- a/internal/proto/local/controller/api/resources/hosts/v1/host.proto +++ b/internal/proto/local/controller/api/resources/hosts/v1/host.proto @@ -34,7 +34,7 @@ message Host { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // The type of the resource. @@ -45,6 +45,9 @@ message Host { // The attributes that are applicable to the specific Host type. google.protobuf.Struct attributes = 110 [(custom_options.v1.generate_sdk_option) = true]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } message StaticHostAttributes { diff --git a/internal/proto/local/controller/api/resources/hostsets/v1/host_set.proto b/internal/proto/local/controller/api/resources/hostsets/v1/host_set.proto index 2f5295ff5..6b7384e55 100644 --- a/internal/proto/local/controller/api/resources/hostsets/v1/host_set.proto +++ b/internal/proto/local/controller/api/resources/hostsets/v1/host_set.proto @@ -35,7 +35,7 @@ message HostSet { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // The type of the Host Set. @@ -46,4 +46,7 @@ message HostSet { // The attributes that are applicable for the specific Host Set type. google.protobuf.Struct attributes = 110; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } diff --git a/internal/proto/local/controller/api/resources/roles/v1/role.proto b/internal/proto/local/controller/api/resources/roles/v1/role.proto index c2b3c983b..93c5a624c 100644 --- a/internal/proto/local/controller/api/resources/roles/v1/role.proto +++ b/internal/proto/local/controller/api/resources/roles/v1/role.proto @@ -66,7 +66,7 @@ message Role { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // The Scope the grants will apply to. If the Role is at the global scope, this can be an org or project. If the Role is at an org scope, this can be a project within the org. It is invalid for this to be anything other than the Role's scope when the Role's scope is a project. @@ -83,4 +83,7 @@ message Role { // Output only. The parsed grant information. repeated Grant grants = 130; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } diff --git a/internal/proto/local/controller/api/resources/scopes/v1/scope.proto b/internal/proto/local/controller/api/resources/scopes/v1/scope.proto index 3d1a96b07..393762cf3 100644 --- a/internal/proto/local/controller/api/resources/scopes/v1/scope.proto +++ b/internal/proto/local/controller/api/resources/scopes/v1/scope.proto @@ -6,6 +6,7 @@ option go_package = "github.com/hashicorp/boundary/internal/gen/controller/api/r import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; +import "google/protobuf/struct.proto"; import "controller/custom_options/v1/options.proto"; message ScopeInfo { @@ -49,9 +50,15 @@ message Scope { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // The type of the resource. string type = 90; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; + + // Output only. The authorized actions for the scope's collections. + map authorized_collection_actions = 310 [json_name="authorized_collection_actions"]; } diff --git a/internal/proto/local/controller/api/resources/sessions/v1/session.proto b/internal/proto/local/controller/api/resources/sessions/v1/session.proto index c5be644f3..f1e001034 100644 --- a/internal/proto/local/controller/api/resources/sessions/v1/session.proto +++ b/internal/proto/local/controller/api/resources/sessions/v1/session.proto @@ -52,7 +52,7 @@ message Session { // Output only. After this time the connection will be expired, e.g. forcefully terminated. google.protobuf.Timestamp expiration_time = 100 [json_name = "expiration_time"]; - + // Output only. The ID of the Auth Token used to authenticate. string auth_token_id = 110 [json_name = "auth_token_id"]; @@ -85,4 +85,7 @@ message Session { // Output only. If the session is terminated, this provides a short description as to why. string termination_reason = 210 [json_name = "termination_reason"]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } diff --git a/internal/proto/local/controller/api/resources/targets/v1/target.proto b/internal/proto/local/controller/api/resources/targets/v1/target.proto index d62970e7d..8ec11e1c9 100644 --- a/internal/proto/local/controller/api/resources/targets/v1/target.proto +++ b/internal/proto/local/controller/api/resources/targets/v1/target.proto @@ -60,11 +60,11 @@ message Target { // Maximum number of connections allowed in a Session. Unlimited is indicated by the value -1. google.protobuf.Int32Value session_connection_limit = 130 [json_name="session_connection_limit", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this:"session_connection_limit" that: "SessionConnectionLimit"}]; - // Output only. The available actions on this resource for this user. - repeated string authorized_actions = 140 [json_name="authorized_actions"]; - // The attributes that are applicable for the specific Target. google.protobuf.Struct attributes = 200 [(custom_options.v1.generate_sdk_option) = true]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } // TcpTargetAttributes contains attributes relevant to Targets of type "tcp" diff --git a/internal/proto/local/controller/api/resources/users/v1/user.proto b/internal/proto/local/controller/api/resources/users/v1/user.proto index 184581881..68d324018 100644 --- a/internal/proto/local/controller/api/resources/users/v1/user.proto +++ b/internal/proto/local/controller/api/resources/users/v1/user.proto @@ -41,7 +41,7 @@ message User { google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. + // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // Output only. Contains the list of Account IDs linked to this User. @@ -49,4 +49,7 @@ message User { // Output only. The Accounts linked to this User. repeated Account accounts = 100; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name="authorized_actions"]; } diff --git a/internal/servers/controller/handlers/accounts/account_service.go b/internal/servers/controller/handlers/accounts/account_service.go index de5e0125e..c9b0a7498 100644 --- a/internal/servers/controller/handlers/accounts/account_service.go +++ b/internal/servers/controller/handlers/accounts/account_service.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/boundary/internal/errors" pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/accounts" pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/types/action" @@ -18,7 +19,26 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + action.SetPassword, + action.ChangePassword, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } +) func init() { var err error @@ -57,10 +77,20 @@ func (s Service) ListAccounts(ctx context.Context, req *pbs.ListAccountsRequest) if err != nil { return nil, err } + finalItems := make([]*pb.Account, 0, len(ul)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.Account, + Pin: req.GetAuthMethodId(), + } for _, item := range ul { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListAccountsResponse{Items: ul}, nil + return &pbs.ListAccountsResponse{Items: finalItems}, nil } // GetAccount implements the interface pbs.AccountServiceServer. @@ -77,6 +107,7 @@ func (s Service) GetAccount(ctx context.Context, req *pbs.GetAccountRequest) (*p return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.GetAccountResponse{Item: u}, nil } @@ -94,6 +125,7 @@ func (s Service) CreateAccount(ctx context.Context, req *pbs.CreateAccountReques return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.CreateAccountResponse{Item: u, Uri: fmt.Sprintf("accounts/%s", u.GetId())}, nil } @@ -111,6 +143,7 @@ func (s Service) UpdateAccount(ctx context.Context, req *pbs.UpdateAccountReques return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.UpdateAccountResponse{Item: u}, nil } @@ -144,6 +177,7 @@ func (s Service) ChangePassword(ctx context.Context, req *pbs.ChangePasswordRequ return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.ChangePasswordResponse{Item: u}, nil } @@ -161,6 +195,7 @@ func (s Service) SetPassword(ctx context.Context, req *pbs.SetPasswordRequest) ( return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.SetPasswordResponse{Item: u}, nil } diff --git a/internal/servers/controller/handlers/accounts/account_service_test.go b/internal/servers/controller/handlers/accounts/account_service_test.go index 36eab9f28..32fbfce8d 100644 --- a/internal/servers/controller/handlers/accounts/account_service_test.go +++ b/internal/servers/controller/handlers/accounts/account_service_test.go @@ -46,14 +46,15 @@ func TestGet(t *testing.T) { aa := password.TestAccounts(t, conn, am.GetPublicId(), 1)[0] wireAccount := pb.Account{ - Id: aa.GetPublicId(), - AuthMethodId: aa.GetAuthMethodId(), - CreatedTime: aa.GetCreateTime().GetTimestamp(), - UpdatedTime: aa.GetUpdateTime().GetTimestamp(), - Scope: &scopepb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, - Version: 1, - Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"login_name": structpb.NewStringValue(aa.GetLoginName())}}, + Id: aa.GetPublicId(), + AuthMethodId: aa.GetAuthMethodId(), + CreatedTime: aa.GetCreateTime().GetTimestamp(), + UpdatedTime: aa.GetUpdateTime().GetTimestamp(), + Scope: &scopepb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + Version: 1, + Type: "password", + Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"login_name": structpb.NewStringValue(aa.GetLoginName())}}, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, } cases := []struct { @@ -115,28 +116,30 @@ func TestList(t *testing.T) { var wantSomeAccounts []*pb.Account for _, aa := range password.TestAccounts(t, conn, amSomeAccounts.GetPublicId(), 3) { wantSomeAccounts = append(wantSomeAccounts, &pb.Account{ - Id: aa.GetPublicId(), - AuthMethodId: aa.GetAuthMethodId(), - CreatedTime: aa.GetCreateTime().GetTimestamp(), - UpdatedTime: aa.GetUpdateTime().GetTimestamp(), - Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, - Version: 1, - Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"login_name": structpb.NewStringValue(aa.GetLoginName())}}, + Id: aa.GetPublicId(), + AuthMethodId: aa.GetAuthMethodId(), + CreatedTime: aa.GetCreateTime().GetTimestamp(), + UpdatedTime: aa.GetUpdateTime().GetTimestamp(), + Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, + Version: 1, + Type: "password", + Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"login_name": structpb.NewStringValue(aa.GetLoginName())}}, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }) } var wantOtherAccounts []*pb.Account for _, aa := range password.TestAccounts(t, conn, amOtherAccounts.GetPublicId(), 3) { wantOtherAccounts = append(wantOtherAccounts, &pb.Account{ - Id: aa.GetPublicId(), - AuthMethodId: aa.GetAuthMethodId(), - CreatedTime: aa.GetCreateTime().GetTimestamp(), - UpdatedTime: aa.GetUpdateTime().GetTimestamp(), - Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, - Version: 1, - Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"login_name": structpb.NewStringValue(aa.GetLoginName())}}, + Id: aa.GetPublicId(), + AuthMethodId: aa.GetAuthMethodId(), + CreatedTime: aa.GetCreateTime().GetTimestamp(), + UpdatedTime: aa.GetUpdateTime().GetTimestamp(), + Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, + Version: 1, + Type: "password", + Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{"login_name": structpb.NewStringValue(aa.GetLoginName())}}, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }) } @@ -315,13 +318,14 @@ func TestCreate(t *testing.T) { res: &pbs.CreateAccountResponse{ Uri: fmt.Sprintf("accounts/%s_", password.AccountPrefix), Item: &pb.Account{ - AuthMethodId: defaultAccount.GetAuthMethodId(), - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, - Version: 1, - Type: "password", - Attributes: createAttr("validaccount", ""), + AuthMethodId: defaultAccount.GetAuthMethodId(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, + Version: 1, + Type: "password", + Attributes: createAttr("validaccount", ""), + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -336,11 +340,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateAccountResponse{ Uri: fmt.Sprintf("accounts/%s_", password.AccountPrefix), Item: &pb.Account{ - AuthMethodId: defaultAccount.GetAuthMethodId(), - Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, - Version: 1, - Type: "password", - Attributes: createAttr("notypedefined", ""), + AuthMethodId: defaultAccount.GetAuthMethodId(), + Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, + Version: 1, + Type: "password", + Attributes: createAttr("notypedefined", ""), + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -357,13 +362,14 @@ func TestCreate(t *testing.T) { res: &pbs.CreateAccountResponse{ Uri: fmt.Sprintf("accounts/%s_", password.AccountPrefix), Item: &pb.Account{ - AuthMethodId: defaultAccount.GetAuthMethodId(), - Name: &wrapperspb.StringValue{Value: "name_with_password"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, - Version: 1, - Type: "password", - Attributes: createAttr("haspassword", ""), + AuthMethodId: defaultAccount.GetAuthMethodId(), + Name: &wrapperspb.StringValue{Value: "name_with_password"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: scope.Org.String()}, + Version: 1, + Type: "password", + Attributes: createAttr("haspassword", ""), + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -525,12 +531,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateAccountResponse{ Item: &pb.Account{ - AuthMethodId: am.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Type: "password", - Attributes: defaultAttributes, - Scope: defaultScopeInfo, + AuthMethodId: am.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Type: "password", + Attributes: defaultAttributes, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -548,12 +555,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateAccountResponse{ Item: &pb.Account{ - AuthMethodId: am.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Type: "password", - Attributes: defaultAttributes, - Scope: defaultScopeInfo, + AuthMethodId: am.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Type: "password", + Attributes: defaultAttributes, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -618,11 +626,12 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateAccountResponse{ Item: &pb.Account{ - AuthMethodId: am.GetPublicId(), - Description: &wrapperspb.StringValue{Value: "default"}, - Type: "password", - Attributes: defaultAttributes, - Scope: defaultScopeInfo, + AuthMethodId: am.GetPublicId(), + Description: &wrapperspb.StringValue{Value: "default"}, + Type: "password", + Attributes: defaultAttributes, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -640,12 +649,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateAccountResponse{ Item: &pb.Account{ - AuthMethodId: am.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "updated"}, - Description: &wrapperspb.StringValue{Value: "default"}, - Type: "password", - Attributes: defaultAttributes, - Scope: defaultScopeInfo, + AuthMethodId: am.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "updated"}, + Description: &wrapperspb.StringValue{Value: "default"}, + Type: "password", + Attributes: defaultAttributes, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -663,12 +673,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateAccountResponse{ Item: &pb.Account{ - AuthMethodId: am.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "default"}, - Description: &wrapperspb.StringValue{Value: "notignored"}, - Type: "password", - Attributes: defaultAttributes, - Scope: defaultScopeInfo, + AuthMethodId: am.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "default"}, + Description: &wrapperspb.StringValue{Value: "notignored"}, + Type: "password", + Attributes: defaultAttributes, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, @@ -686,12 +697,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateAccountResponse{ Item: &pb.Account{ - AuthMethodId: am.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "default"}, - Description: &wrapperspb.StringValue{Value: "default"}, - Type: "password", - Attributes: modifiedAttributes, - Scope: defaultScopeInfo, + AuthMethodId: am.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "default"}, + Description: &wrapperspb.StringValue{Value: "default"}, + Type: "password", + Attributes: modifiedAttributes, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "set-password", "change-password"}, }, }, }, diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service.go b/internal/servers/controller/handlers/authmethods/authmethod_service.go index f9f796a4f..56153211b 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service.go @@ -17,12 +17,17 @@ import ( pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/accounts" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/authtokens" "github.com/hashicorp/boundary/internal/types/action" "github.com/hashicorp/boundary/internal/types/resource" "github.com/hashicorp/boundary/internal/types/scope" + "github.com/hashicorp/boundary/sdk/strutil" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -31,7 +36,29 @@ const ( pwKey = "password" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + action.Authenticate, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } + + collectionTypeMap = map[resource.Type]action.ActionSet{ + resource.Account: accounts.CollectionActions, + } +) func init() { var err error @@ -40,6 +67,33 @@ func init() { } } +func populateCollectionAuthorizedActions(ctx context.Context, + authResults auth.VerifyResults, + item *pb.AuthMethod) error { + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Pin: item.Id, + } + // Range over the defined collections and check permissions against those + // collections. We use the ID of this scope being returned, not its parent, + // hence passing in a resource here. + for k, v := range collectionTypeMap { + res.Type = k + acts := authResults.FetchActionSetForType(ctx, k, v, auth.WithResource(res)).Strings() + if len(acts) > 0 { + if item.AuthorizedCollectionActions == nil { + item.AuthorizedCollectionActions = make(map[string]*structpb.ListValue) + } + lv, err := structpb.NewList(strutil.StringListToInterfaceList(acts)) + if err != nil { + return err + } + item.AuthorizedCollectionActions[k.String()+"s"] = lv + } + } + return nil +} + // Service handles request as described by the pbs.AuthMethodServiceServer interface. type Service struct { pbs.UnimplementedAuthMethodServiceServer @@ -79,10 +133,22 @@ func (s Service) ListAuthMethods(ctx context.Context, req *pbs.ListAuthMethodsRe if err != nil { return nil, err } + finalItems := make([]*pb.AuthMethod, 0, len(ul)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.AuthMethod, + } for _, item := range ul { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + if err := populateCollectionAuthorizedActions(ctx, authResults, item); err != nil { + return nil, err + } + } } - return &pbs.ListAuthMethodsResponse{Items: ul}, nil + return &pbs.ListAuthMethodsResponse{Items: finalItems}, nil } // GetAuthMethod implements the interface pbs.AuthMethodServiceServer. @@ -99,6 +165,10 @@ func (s Service) GetAuthMethod(ctx context.Context, req *pbs.GetAuthMethodReques return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, u); err != nil { + return nil, err + } return &pbs.GetAuthMethodResponse{Item: u}, nil } @@ -116,6 +186,10 @@ func (s Service) CreateAuthMethod(ctx context.Context, req *pbs.CreateAuthMethod return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, u); err != nil { + return nil, err + } return &pbs.CreateAuthMethodResponse{Item: u, Uri: fmt.Sprintf("auth-methods/%s", u.GetId())}, nil } @@ -133,6 +207,10 @@ func (s Service) UpdateAuthMethod(ctx context.Context, req *pbs.UpdateAuthMethod return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, u); err != nil { + return nil, err + } return &pbs.UpdateAuthMethodResponse{Item: u}, nil } @@ -166,6 +244,11 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) if err != nil { return nil, err } + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.AuthToken, + } + tok.AuthorizedActions = authResults.FetchActionSetForId(ctx, tok.Id, authtokens.IdActions, auth.WithResource(res)).Strings() return &pbs.AuthenticateResponse{Item: tok, TokenType: req.GetTokenType()}, nil } diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go index 95c64cefa..c4495419f 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go @@ -36,6 +36,15 @@ const ( testLoginName = "default" ) +var authorizedCollectionActions = map[string]*structpb.ListValue{ + "accounts": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, +} + func TestGet(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) @@ -70,6 +79,8 @@ func TestGet(t *testing.T) { Id: o.GetPublicId(), Type: o.GetType(), }, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, } cases := []struct { @@ -158,6 +169,8 @@ func TestList(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }) } @@ -175,6 +188,8 @@ func TestList(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }) } @@ -368,6 +383,8 @@ func TestCreate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -395,6 +412,8 @@ func TestCreate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -568,7 +587,9 @@ func TestUpdate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, - Scope: defaultScopeInfo, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -594,7 +615,9 @@ func TestUpdate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, - Scope: defaultScopeInfo, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -660,7 +683,9 @@ func TestUpdate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, - Scope: defaultScopeInfo, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -685,7 +710,9 @@ func TestUpdate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, - Scope: defaultScopeInfo, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -710,7 +737,9 @@ func TestUpdate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(3), }}, - Scope: defaultScopeInfo, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -807,7 +836,9 @@ func TestUpdate(t *testing.T) { "min_password_length": structpb.NewNumberValue(8), "min_login_name_length": structpb.NewNumberValue(42), }}, - Scope: defaultScopeInfo, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -836,7 +867,9 @@ func TestUpdate(t *testing.T) { "min_password_length": structpb.NewNumberValue(42), "min_login_name_length": structpb.NewNumberValue(3), }}, - Scope: defaultScopeInfo, + Scope: defaultScopeInfo, + AuthorizedActions: []string{"read", "update", "delete", "authenticate"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, diff --git a/internal/servers/controller/handlers/authtokens/authtoken_service.go b/internal/servers/controller/handlers/authtokens/authtoken_service.go index 2dba75a9c..18a41619b 100644 --- a/internal/servers/controller/handlers/authtokens/authtoken_service.go +++ b/internal/servers/controller/handlers/authtokens/authtoken_service.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/boundary/internal/errors" pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/authtokens" pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/types/action" @@ -16,6 +17,21 @@ import ( "github.com/hashicorp/boundary/internal/types/scope" ) +var ( + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Delete, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.List, + } +) + // Service handles request as described by the pbs.AuthTokenServiceServer interface. type Service struct { pbs.UnimplementedAuthTokenServiceServer @@ -50,10 +66,19 @@ func (s Service) ListAuthTokens(ctx context.Context, req *pbs.ListAuthTokensRequ if err != nil { return nil, err } + finalItems := make([]*pb.AuthToken, 0, len(ul)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.AuthToken, + } for _, item := range ul { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListAuthTokensResponse{Items: ul}, nil + return &pbs.ListAuthTokensResponse{Items: finalItems}, nil } // GetAuthToken implements the interface pbs.AuthTokenServiceServer. @@ -70,6 +95,7 @@ func (s Service) GetAuthToken(ctx context.Context, req *pbs.GetAuthTokenRequest) return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.GetAuthTokenResponse{Item: u}, nil } diff --git a/internal/servers/controller/handlers/authtokens/authtoken_service_test.go b/internal/servers/controller/handlers/authtokens/authtoken_service_test.go index c84e36330..42c7f130a 100644 --- a/internal/servers/controller/handlers/authtokens/authtoken_service_test.go +++ b/internal/servers/controller/handlers/authtokens/authtoken_service_test.go @@ -52,6 +52,7 @@ func TestGet(t *testing.T) { ApproximateLastUsedTime: at.GetApproximateLastAccessTime().GetTimestamp(), ExpirationTime: at.GetExpirationTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + AuthorizedActions: []string{"read", "delete"}, } cases := []struct { @@ -127,6 +128,7 @@ func TestList(t *testing.T) { ApproximateLastUsedTime: at.GetApproximateLastAccessTime().GetTimestamp(), ExpirationTime: at.GetExpirationTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: orgWithSomeTokens.GetPublicId(), Type: scope.Org.String()}, + AuthorizedActions: []string{"read", "delete"}, }) } @@ -145,6 +147,7 @@ func TestList(t *testing.T) { ApproximateLastUsedTime: at.GetApproximateLastAccessTime().GetTimestamp(), ExpirationTime: at.GetExpirationTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: orgWithOtherTokens.GetPublicId(), Type: scope.Org.String()}, + AuthorizedActions: []string{"read", "delete"}, }) } diff --git a/internal/servers/controller/handlers/groups/group_service.go b/internal/servers/controller/handlers/groups/group_service.go index a9dc8064f..e6b19417d 100644 --- a/internal/servers/controller/handlers/groups/group_service.go +++ b/internal/servers/controller/handlers/groups/group_service.go @@ -10,6 +10,7 @@ import ( pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/iam/store" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/types/action" @@ -20,7 +21,27 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + action.AddMembers, + action.SetMembers, + action.RemoveMembers, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } +) func init() { var err error @@ -59,10 +80,19 @@ func (s Service) ListGroups(ctx context.Context, req *pbs.ListGroupsRequest) (*p if err != nil { return nil, err } + finalItems := make([]*pb.Group, 0, len(gl)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.Group, + } for _, item := range gl { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListGroupsResponse{Items: gl}, nil + return &pbs.ListGroupsResponse{Items: finalItems}, nil } // GetGroups implements the interface pbs.GroupServiceServer. @@ -79,6 +109,7 @@ func (s Service) GetGroup(ctx context.Context, req *pbs.GetGroupRequest) (*pbs.G return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.GetGroupResponse{Item: u}, nil } @@ -96,6 +127,7 @@ func (s Service) CreateGroup(ctx context.Context, req *pbs.CreateGroupRequest) ( return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.CreateGroupResponse{Item: u, Uri: fmt.Sprintf("groups/%s", u.GetId())}, nil } @@ -113,6 +145,7 @@ func (s Service) UpdateGroup(ctx context.Context, req *pbs.UpdateGroupRequest) ( return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.UpdateGroupResponse{Item: u}, nil } @@ -146,6 +179,7 @@ func (s Service) AddGroupMembers(ctx context.Context, req *pbs.AddGroupMembersRe return nil, err } g.Scope = authResults.Scope + g.AuthorizedActions = authResults.FetchActionSetForId(ctx, g.Id, IdActions).Strings() return &pbs.AddGroupMembersResponse{Item: g}, nil } @@ -163,6 +197,7 @@ func (s Service) SetGroupMembers(ctx context.Context, req *pbs.SetGroupMembersRe return nil, err } g.Scope = authResults.Scope + g.AuthorizedActions = authResults.FetchActionSetForId(ctx, g.Id, IdActions).Strings() return &pbs.SetGroupMembersResponse{Item: g}, nil } @@ -180,6 +215,7 @@ func (s Service) RemoveGroupMembers(ctx context.Context, req *pbs.RemoveGroupMem return nil, err } g.Scope = authResults.Scope + g.AuthorizedActions = authResults.FetchActionSetForId(ctx, g.Id, IdActions).Strings() return &pbs.RemoveGroupMembersResponse{Item: g}, nil } diff --git a/internal/servers/controller/handlers/groups/group_service_test.go b/internal/servers/controller/handlers/groups/group_service_test.go index 02cb29b5c..275528831 100644 --- a/internal/servers/controller/handlers/groups/group_service_test.go +++ b/internal/servers/controller/handlers/groups/group_service_test.go @@ -106,6 +106,7 @@ func TestGet(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, } wantProjGroup := &pb.Group{ @@ -124,6 +125,7 @@ func TestGet(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, } cases := []struct { @@ -218,21 +220,23 @@ func TestList(t *testing.T) { for i := 0; i < 10; i++ { og := iam.TestGroup(t, conn, oWithGroups.GetPublicId()) wantOrgGroups = append(wantOrgGroups, &pb.Group{ - Id: og.GetPublicId(), - ScopeId: og.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: oWithGroups.GetPublicId(), Type: scope.Org.String()}, - CreatedTime: og.GetCreateTime().GetTimestamp(), - UpdatedTime: og.GetUpdateTime().GetTimestamp(), - Version: 1, + Id: og.GetPublicId(), + ScopeId: og.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: oWithGroups.GetPublicId(), Type: scope.Org.String()}, + CreatedTime: og.GetCreateTime().GetTimestamp(), + UpdatedTime: og.GetUpdateTime().GetTimestamp(), + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }) pg := iam.TestGroup(t, conn, pWithGroups.GetPublicId()) wantProjGroups = append(wantProjGroups, &pb.Group{ - Id: pg.GetPublicId(), - ScopeId: pg.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: pWithGroups.GetPublicId(), Type: scope.Project.String()}, - CreatedTime: pg.GetCreateTime().GetTimestamp(), - UpdatedTime: pg.GetUpdateTime().GetTimestamp(), - Version: 1, + Id: pg.GetPublicId(), + ScopeId: pg.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: pWithGroups.GetPublicId(), Type: scope.Project.String()}, + CreatedTime: pg.GetCreateTime().GetTimestamp(), + UpdatedTime: pg.GetUpdateTime().GetTimestamp(), + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }) } @@ -397,11 +401,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateGroupResponse{ Uri: fmt.Sprintf("groups/%s_", iam.GroupPrefix), Item: &pb.Group{ - ScopeId: defaultOGroup.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: defaultOGroup.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, + ScopeId: defaultOGroup.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: defaultOGroup.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -415,11 +420,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateGroupResponse{ Uri: fmt.Sprintf("groups/%s_", iam.GroupPrefix), Item: &pb.Group{ - ScopeId: scope.Global.String(), - Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, + ScopeId: scope.Global.String(), + Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -435,11 +441,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateGroupResponse{ Uri: fmt.Sprintf("groups/%s_", iam.GroupPrefix), Item: &pb.Group{ - ScopeId: defaultPGroup.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: defaultPGroup.GetScopeId(), Type: scope.Project.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, + ScopeId: defaultPGroup.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: defaultPGroup.GetScopeId(), Type: scope.Project.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -581,6 +588,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -611,6 +619,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -642,6 +651,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -673,6 +683,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -735,6 +746,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -765,6 +777,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, @@ -795,6 +808,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, + AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, }, }, }, diff --git a/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go b/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go index b95c2db7a..dff96de69 100644 --- a/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go +++ b/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go @@ -11,16 +11,43 @@ import ( "github.com/hashicorp/boundary/internal/host" "github.com/hashicorp/boundary/internal/host/static" "github.com/hashicorp/boundary/internal/host/static/store" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/host_sets" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/hosts" "github.com/hashicorp/boundary/internal/types/action" "github.com/hashicorp/boundary/internal/types/resource" "github.com/hashicorp/boundary/internal/types/scope" + "github.com/hashicorp/boundary/sdk/strutil" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } + + collectionTypeMap = map[resource.Type]action.ActionSet{ + resource.HostSet: host_sets.CollectionActions, + resource.Host: hosts.CollectionActions, + } +) func init() { var err error @@ -38,6 +65,33 @@ type Service struct { var _ pbs.HostCatalogServiceServer = Service{} +func populateCollectionAuthorizedActions(ctx context.Context, + authResults auth.VerifyResults, + item *pb.HostCatalog) error { + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Pin: item.Id, + } + // Range over the defined collections and check permissions against those + // collections. We use the ID of this scope being returned, not its parent, + // hence passing in a resource here. + for k, v := range collectionTypeMap { + res.Type = k + acts := authResults.FetchActionSetForType(ctx, k, v, auth.WithResource(res)).Strings() + if len(acts) > 0 { + if item.AuthorizedCollectionActions == nil { + item.AuthorizedCollectionActions = make(map[string]*structpb.ListValue) + } + lv, err := structpb.NewList(strutil.StringListToInterfaceList(acts)) + if err != nil { + return err + } + item.AuthorizedCollectionActions[k.String()+"s"] = lv + } + } + return nil +} + // NewService returns a host catalog Service which handles host catalog related requests to boundary and uses the provided // repositories for storage and retrieval. func NewService(repoFn common.StaticRepoFactory, iamRepoFn common.IamRepoFactory) (Service, error) { @@ -62,10 +116,22 @@ func (s Service) ListHostCatalogs(ctx context.Context, req *pbs.ListHostCatalogs if err != nil { return nil, err } + finalItems := make([]*pb.HostCatalog, 0, len(ul)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.HostCatalog, + } for _, item := range ul { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + if err := populateCollectionAuthorizedActions(ctx, authResults, item); err != nil { + return nil, err + } + } } - return &pbs.ListHostCatalogsResponse{Items: ul}, nil + return &pbs.ListHostCatalogsResponse{Items: finalItems}, nil } // GetHostCatalog implements the interface pbs.HostCatalogServiceServer. @@ -82,6 +148,10 @@ func (s Service) GetHostCatalog(ctx context.Context, req *pbs.GetHostCatalogRequ return nil, err } hc.Scope = authResults.Scope + hc.AuthorizedActions = authResults.FetchActionSetForId(ctx, hc.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, hc); err != nil { + return nil, err + } return &pbs.GetHostCatalogResponse{Item: hc}, nil } @@ -99,6 +169,10 @@ func (s Service) CreateHostCatalog(ctx context.Context, req *pbs.CreateHostCatal return nil, err } hc.Scope = authResults.Scope + hc.AuthorizedActions = authResults.FetchActionSetForId(ctx, hc.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, hc); err != nil { + return nil, err + } return &pbs.CreateHostCatalogResponse{ Item: hc, Uri: fmt.Sprintf("host-catalogs/%s", hc.GetId()), @@ -119,6 +193,10 @@ func (s Service) UpdateHostCatalog(ctx context.Context, req *pbs.UpdateHostCatal return nil, err } hc.Scope = authResults.Scope + hc.AuthorizedActions = authResults.FetchActionSetForId(ctx, hc.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, hc); err != nil { + return nil, err + } return &pbs.UpdateHostCatalogResponse{Item: hc}, nil } diff --git a/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go b/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go index 28d5073a2..f905af14f 100644 --- a/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go +++ b/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go @@ -26,11 +26,27 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/structpb" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +var authorizedCollectionActions = map[string]*structpb.ListValue{ + "host-sets": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "hosts": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, +} + func createDefaultHostCatalogAndRepo(t *testing.T) (*static.HostCatalog, *iam.Scope, common.StaticRepoFactory, common.IamRepoFactory) { t.Helper() require := require.New(t) @@ -66,14 +82,16 @@ func TestGet(t *testing.T) { } pHostCatalog := &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: hc.GetName()}, - Description: &wrappers.StringValue{Value: hc.GetDescription()}, - CreatedTime: hc.CreateTime.GetTimestamp(), - UpdatedTime: hc.UpdateTime.GetTimestamp(), - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: hc.GetName()}, + Description: &wrappers.StringValue{Value: hc.GetDescription()}, + CreatedTime: hc.CreateTime.GetTimestamp(), + UpdatedTime: hc.UpdateTime.GetTimestamp(), + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, } cases := []struct { @@ -149,26 +167,30 @@ func TestList(t *testing.T) { var wantSomeCatalogs []*pb.HostCatalog for _, hc := range static.TestCatalogs(t, conn, pWithCatalogs.GetPublicId(), 3) { wantSomeCatalogs = append(wantSomeCatalogs, &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - CreatedTime: hc.GetCreateTime().GetTimestamp(), - UpdatedTime: hc.GetUpdateTime().GetTimestamp(), - Scope: &scopepb.ScopeInfo{Id: pWithCatalogs.GetPublicId(), Type: scope.Project.String()}, - Version: 1, - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + CreatedTime: hc.GetCreateTime().GetTimestamp(), + UpdatedTime: hc.GetUpdateTime().GetTimestamp(), + Scope: &scopepb.ScopeInfo{Id: pWithCatalogs.GetPublicId(), Type: scope.Project.String()}, + Version: 1, + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }) } var wantOtherCatalogs []*pb.HostCatalog for _, hc := range static.TestCatalogs(t, conn, pWithOtherCatalogs.GetPublicId(), 3) { wantOtherCatalogs = append(wantOtherCatalogs, &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - CreatedTime: hc.GetCreateTime().GetTimestamp(), - UpdatedTime: hc.GetUpdateTime().GetTimestamp(), - Scope: &scopepb.ScopeInfo{Id: pWithOtherCatalogs.GetPublicId(), Type: scope.Project.String()}, - Version: 1, - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + CreatedTime: hc.GetCreateTime().GetTimestamp(), + UpdatedTime: hc.GetUpdateTime().GetTimestamp(), + Scope: &scopepb.ScopeInfo{Id: pWithOtherCatalogs.GetPublicId(), Type: scope.Project.String()}, + Version: 1, + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }) } @@ -314,11 +336,13 @@ func TestCreate(t *testing.T) { res: &pbs.CreateHostCatalogResponse{ Uri: fmt.Sprintf("host-catalogs/%s_", static.HostCatalogPrefix), Item: &pb.HostCatalog{ - ScopeId: proj.GetPublicId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "name"}, - Description: &wrappers.StringValue{Value: "desc"}, - Type: "static", + ScopeId: proj.GetPublicId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "name"}, + Description: &wrappers.StringValue{Value: "desc"}, + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -465,13 +489,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostCatalogResponse{ Item: &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "new"}, - Description: &wrappers.StringValue{Value: "desc"}, - CreatedTime: hc.GetCreateTime().GetTimestamp(), - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + CreatedTime: hc.GetCreateTime().GetTimestamp(), + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -489,13 +515,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostCatalogResponse{ Item: &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "new"}, - Description: &wrappers.StringValue{Value: "desc"}, - CreatedTime: hc.GetCreateTime().GetTimestamp(), - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + CreatedTime: hc.GetCreateTime().GetTimestamp(), + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -543,12 +571,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostCatalogResponse{ Item: &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Description: &wrappers.StringValue{Value: "default"}, - CreatedTime: hc.GetCreateTime().GetTimestamp(), - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Description: &wrappers.StringValue{Value: "default"}, + CreatedTime: hc.GetCreateTime().GetTimestamp(), + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -564,12 +594,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostCatalogResponse{ Item: &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "default"}, - CreatedTime: hc.GetCreateTime().GetTimestamp(), - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "default"}, + CreatedTime: hc.GetCreateTime().GetTimestamp(), + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -586,13 +618,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostCatalogResponse{ Item: &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "updated"}, - Description: &wrappers.StringValue{Value: "default"}, - CreatedTime: hc.GetCreateTime().GetTimestamp(), - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "updated"}, + Description: &wrappers.StringValue{Value: "default"}, + CreatedTime: hc.GetCreateTime().GetTimestamp(), + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, @@ -609,13 +643,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostCatalogResponse{ Item: &pb.HostCatalog{ - Id: hc.GetPublicId(), - ScopeId: hc.GetScopeId(), - Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "default"}, - Description: &wrappers.StringValue{Value: "notignored"}, - CreatedTime: hc.GetCreateTime().GetTimestamp(), - Type: "static", + Id: hc.GetPublicId(), + ScopeId: hc.GetScopeId(), + Scope: &scopepb.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "default"}, + Description: &wrappers.StringValue{Value: "notignored"}, + CreatedTime: hc.GetCreateTime().GetTimestamp(), + Type: "static", + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: authorizedCollectionActions, }, }, }, diff --git a/internal/servers/controller/handlers/host_sets/host_set_service.go b/internal/servers/controller/handlers/host_sets/host_set_service.go index 57614e652..7da479060 100644 --- a/internal/servers/controller/handlers/host_sets/host_set_service.go +++ b/internal/servers/controller/handlers/host_sets/host_set_service.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/boundary/internal/host" "github.com/hashicorp/boundary/internal/host/static" "github.com/hashicorp/boundary/internal/host/static/store" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/types/action" @@ -20,7 +21,27 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + action.AddHosts, + action.SetHosts, + action.RemoveHosts, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } +) func init() { var err error @@ -58,10 +79,20 @@ func (s Service) ListHostSets(ctx context.Context, req *pbs.ListHostSetsRequest) if err != nil { return nil, err } + finalItems := make([]*pb.HostSet, 0, len(hl)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.HostSet, + Pin: req.GetHostCatalogId(), + } for _, item := range hl { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListHostSetsResponse{Items: hl}, nil + return &pbs.ListHostSetsResponse{Items: finalItems}, nil } // GetHostSet implements the interface pbs.HostSetServiceServer. @@ -78,6 +109,7 @@ func (s Service) GetHostSet(ctx context.Context, req *pbs.GetHostSetRequest) (*p return nil, err } hc.Scope = authResults.Scope + hc.AuthorizedActions = authResults.FetchActionSetForId(ctx, hc.Id, IdActions).Strings() return &pbs.GetHostSetResponse{Item: hc}, nil } @@ -95,6 +127,7 @@ func (s Service) CreateHostSet(ctx context.Context, req *pbs.CreateHostSetReques return nil, err } h.Scope = authResults.Scope + h.AuthorizedActions = authResults.FetchActionSetForId(ctx, h.Id, IdActions).Strings() return &pbs.CreateHostSetResponse{ Item: h, Uri: fmt.Sprintf("host-sets/%s", h.GetId()), @@ -115,6 +148,7 @@ func (s Service) UpdateHostSet(ctx context.Context, req *pbs.UpdateHostSetReques return nil, err } hc.Scope = authResults.Scope + hc.AuthorizedActions = authResults.FetchActionSetForId(ctx, hc.Id, IdActions).Strings() return &pbs.UpdateHostSetResponse{Item: hc}, nil } @@ -148,6 +182,7 @@ func (s Service) AddHostSetHosts(ctx context.Context, req *pbs.AddHostSetHostsRe return nil, err } g.Scope = authResults.Scope + g.AuthorizedActions = authResults.FetchActionSetForId(ctx, g.Id, IdActions).Strings() return &pbs.AddHostSetHostsResponse{Item: g}, nil } @@ -165,6 +200,7 @@ func (s Service) SetHostSetHosts(ctx context.Context, req *pbs.SetHostSetHostsRe return nil, err } g.Scope = authResults.Scope + g.AuthorizedActions = authResults.FetchActionSetForId(ctx, g.Id, IdActions).Strings() return &pbs.SetHostSetHostsResponse{Item: g}, nil } @@ -182,6 +218,7 @@ func (s Service) RemoveHostSetHosts(ctx context.Context, req *pbs.RemoveHostSetH return nil, err } g.Scope = authResults.Scope + g.AuthorizedActions = authResults.FetchActionSetForId(ctx, g.Id, IdActions).Strings() return &pbs.RemoveHostSetHostsResponse{Item: g}, nil } diff --git a/internal/servers/controller/handlers/host_sets/host_set_service_test.go b/internal/servers/controller/handlers/host_sets/host_set_service_test.go index 95f372f9a..cab470492 100644 --- a/internal/servers/controller/handlers/host_sets/host_set_service_test.go +++ b/internal/servers/controller/handlers/host_sets/host_set_service_test.go @@ -53,13 +53,14 @@ func TestGet(t *testing.T) { toMerge := &pbs.GetHostSetRequest{} pHost := &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Id: hs.GetPublicId(), - CreatedTime: hs.CreateTime.GetTimestamp(), - UpdatedTime: hs.UpdateTime.GetTimestamp(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Type: "static", - HostIds: hIds, + HostCatalogId: hc.GetPublicId(), + Id: hs.GetPublicId(), + CreatedTime: hs.CreateTime.GetTimestamp(), + UpdatedTime: hs.UpdateTime.GetTimestamp(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Type: "static", + HostIds: hIds, + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, } cases := []struct { @@ -132,13 +133,14 @@ func TestList(t *testing.T) { var wantHs []*pb.HostSet for _, h := range static.TestSets(t, conn, hc.GetPublicId(), 10) { wantHs = append(wantHs, &pb.HostSet{ - Id: h.GetPublicId(), - HostCatalogId: h.GetCatalogId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - CreatedTime: h.GetCreateTime().GetTimestamp(), - UpdatedTime: h.GetUpdateTime().GetTimestamp(), - Version: h.GetVersion(), - Type: host.StaticSubtype.String(), + Id: h.GetPublicId(), + HostCatalogId: h.GetCatalogId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + CreatedTime: h.GetCreateTime().GetTimestamp(), + UpdatedTime: h.GetUpdateTime().GetTimestamp(), + Version: h.GetVersion(), + Type: host.StaticSubtype.String(), + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }) } @@ -309,11 +311,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateHostSetResponse{ Uri: fmt.Sprintf("host-sets/%s_", static.HostSetPrefix), Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "name"}, - Description: &wrappers.StringValue{Value: "desc"}, - Type: "static", + HostCatalogId: hc.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "name"}, + Description: &wrappers.StringValue{Value: "desc"}, + Type: "static", + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, @@ -337,11 +340,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateHostSetResponse{ Uri: fmt.Sprintf("host-sets/%s_", static.HostSetPrefix), Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "no type name"}, - Description: &wrappers.StringValue{Value: "no type desc"}, - Type: "static", + HostCatalogId: hc.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "no type name"}, + Description: &wrappers.StringValue{Value: "no type desc"}, + Type: "static", + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, @@ -474,14 +478,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostSetResponse{ Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Id: hs.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "new"}, - Description: &wrappers.StringValue{Value: "desc"}, - CreatedTime: hs.GetCreateTime().GetTimestamp(), - Type: "static", - HostIds: hIds, + HostCatalogId: hc.GetPublicId(), + Id: hs.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + CreatedTime: hs.GetCreateTime().GetTimestamp(), + Type: "static", + HostIds: hIds, + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, @@ -499,14 +504,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostSetResponse{ Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Id: hs.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "new"}, - Description: &wrappers.StringValue{Value: "desc"}, - CreatedTime: hs.GetCreateTime().GetTimestamp(), - Type: "static", - HostIds: hIds, + HostCatalogId: hc.GetPublicId(), + Id: hs.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "new"}, + Description: &wrappers.StringValue{Value: "desc"}, + CreatedTime: hs.GetCreateTime().GetTimestamp(), + Type: "static", + HostIds: hIds, + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, @@ -568,13 +574,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostSetResponse{ Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Id: hs.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Description: &wrappers.StringValue{Value: "default"}, - CreatedTime: hs.GetCreateTime().GetTimestamp(), - Type: "static", - HostIds: hIds, + HostCatalogId: hc.GetPublicId(), + Id: hs.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Description: &wrappers.StringValue{Value: "default"}, + CreatedTime: hs.GetCreateTime().GetTimestamp(), + Type: "static", + HostIds: hIds, + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, @@ -590,13 +597,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostSetResponse{ Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Id: hs.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "default"}, - CreatedTime: hs.GetCreateTime().GetTimestamp(), - Type: "static", - HostIds: hIds, + HostCatalogId: hc.GetPublicId(), + Id: hs.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "default"}, + CreatedTime: hs.GetCreateTime().GetTimestamp(), + Type: "static", + HostIds: hIds, + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, @@ -613,14 +621,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostSetResponse{ Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Id: hs.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "updated"}, - Description: &wrappers.StringValue{Value: "default"}, - CreatedTime: hs.GetCreateTime().GetTimestamp(), - Type: "static", - HostIds: hIds, + HostCatalogId: hc.GetPublicId(), + Id: hs.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "updated"}, + Description: &wrappers.StringValue{Value: "default"}, + CreatedTime: hs.GetCreateTime().GetTimestamp(), + Type: "static", + HostIds: hIds, + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, @@ -637,14 +646,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateHostSetResponse{ Item: &pb.HostSet{ - HostCatalogId: hc.GetPublicId(), - Id: hs.GetPublicId(), - Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, - Name: &wrappers.StringValue{Value: "default"}, - Description: &wrappers.StringValue{Value: "notignored"}, - CreatedTime: hs.GetCreateTime().GetTimestamp(), - Type: "static", - HostIds: hIds, + HostCatalogId: hc.GetPublicId(), + Id: hs.GetPublicId(), + Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String()}, + Name: &wrappers.StringValue{Value: "default"}, + Description: &wrappers.StringValue{Value: "notignored"}, + CreatedTime: hs.GetCreateTime().GetTimestamp(), + Type: "static", + HostIds: hIds, + AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, }, }, }, diff --git a/internal/servers/controller/handlers/hosts/host_service.go b/internal/servers/controller/handlers/hosts/host_service.go index 4a5f8e025..d6b748223 100644 --- a/internal/servers/controller/handlers/hosts/host_service.go +++ b/internal/servers/controller/handlers/hosts/host_service.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/boundary/internal/host" "github.com/hashicorp/boundary/internal/host/static" "github.com/hashicorp/boundary/internal/host/static/store" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/types/action" @@ -21,7 +22,24 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } +) func init() { var err error @@ -59,10 +77,20 @@ func (s Service) ListHosts(ctx context.Context, req *pbs.ListHostsRequest) (*pbs if err != nil { return nil, err } + finalItems := make([]*pb.Host, 0, len(hl)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.Host, + Pin: req.GetHostCatalogId(), + } for _, item := range hl { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListHostsResponse{Items: hl}, nil + return &pbs.ListHostsResponse{Items: finalItems}, nil } // GetHost implements the interface pbs.HostServiceServer. @@ -79,6 +107,7 @@ func (s Service) GetHost(ctx context.Context, req *pbs.GetHostRequest) (*pbs.Get return nil, err } hc.Scope = authResults.Scope + hc.AuthorizedActions = authResults.FetchActionSetForId(ctx, hc.Id, IdActions).Strings() return &pbs.GetHostResponse{Item: hc}, nil } @@ -96,6 +125,7 @@ func (s Service) CreateHost(ctx context.Context, req *pbs.CreateHostRequest) (*p return nil, err } h.Scope = authResults.Scope + h.AuthorizedActions = authResults.FetchActionSetForId(ctx, h.Id, IdActions).Strings() return &pbs.CreateHostResponse{ Item: h, Uri: fmt.Sprintf("hosts/%s", h.GetId()), @@ -116,6 +146,7 @@ func (s Service) UpdateHost(ctx context.Context, req *pbs.UpdateHostRequest) (*p return nil, err } hc.Scope = authResults.Scope + hc.AuthorizedActions = authResults.FetchActionSetForId(ctx, hc.Id, IdActions).Strings() return &pbs.UpdateHostResponse{Item: hc}, nil } diff --git a/internal/servers/controller/handlers/hosts/host_service_test.go b/internal/servers/controller/handlers/hosts/host_service_test.go index 1c4420b57..b8b215661 100644 --- a/internal/servers/controller/handlers/hosts/host_service_test.go +++ b/internal/servers/controller/handlers/hosts/host_service_test.go @@ -56,6 +56,7 @@ func TestGet(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue(h.GetAddress()), }}, + AuthorizedActions: []string{"read", "update", "delete"}, } cases := []struct { @@ -134,6 +135,7 @@ func TestList(t *testing.T) { Type: host.StaticSubtype.String(), Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue(h.GetAddress()), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }) } @@ -307,6 +309,7 @@ func TestCreate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("123.456.789"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, @@ -365,6 +368,7 @@ func TestCreate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("123.456.789"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, @@ -500,6 +504,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, @@ -527,6 +532,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, @@ -596,6 +602,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, @@ -620,6 +627,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, @@ -646,6 +654,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, @@ -672,6 +681,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, + AuthorizedActions: []string{"read", "update", "delete"}, }, }, }, diff --git a/internal/servers/controller/handlers/roles/role_service.go b/internal/servers/controller/handlers/roles/role_service.go index b63a858bd..cdf85ccd9 100644 --- a/internal/servers/controller/handlers/roles/role_service.go +++ b/internal/servers/controller/handlers/roles/role_service.go @@ -21,7 +21,30 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + action.AddPrincipals, + action.SetPrincipals, + action.RemovePrincipals, + action.AddGrants, + action.SetGrants, + action.RemoveGrants, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } +) func init() { var err error @@ -60,10 +83,19 @@ func (s Service) ListRoles(ctx context.Context, req *pbs.ListRolesRequest) (*pbs if err != nil { return nil, err } + finalItems := make([]*pb.Role, 0, len(gl)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.Role, + } for _, item := range gl { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListRolesResponse{Items: gl}, nil + return &pbs.ListRolesResponse{Items: finalItems}, nil } // GetRoles implements the interface pbs.RoleServiceServer. @@ -80,6 +112,7 @@ func (s Service) GetRole(ctx context.Context, req *pbs.GetRoleRequest) (*pbs.Get return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.GetRoleResponse{Item: u}, nil } @@ -97,6 +130,7 @@ func (s Service) CreateRole(ctx context.Context, req *pbs.CreateRoleRequest) (*p return nil, err } r.Scope = authResults.Scope + r.AuthorizedActions = authResults.FetchActionSetForId(ctx, r.Id, IdActions).Strings() return &pbs.CreateRoleResponse{Item: r, Uri: fmt.Sprintf("roles/%s", r.GetId())}, nil } @@ -114,6 +148,7 @@ func (s Service) UpdateRole(ctx context.Context, req *pbs.UpdateRoleRequest) (*p return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.UpdateRoleResponse{Item: u}, nil } @@ -147,6 +182,7 @@ func (s Service) AddRolePrincipals(ctx context.Context, req *pbs.AddRolePrincipa return nil, err } r.Scope = authResults.Scope + r.AuthorizedActions = authResults.FetchActionSetForId(ctx, r.Id, IdActions).Strings() return &pbs.AddRolePrincipalsResponse{Item: r}, nil } @@ -164,6 +200,7 @@ func (s Service) SetRolePrincipals(ctx context.Context, req *pbs.SetRolePrincipa return nil, err } r.Scope = authResults.Scope + r.AuthorizedActions = authResults.FetchActionSetForId(ctx, r.Id, IdActions).Strings() return &pbs.SetRolePrincipalsResponse{Item: r}, nil } @@ -181,6 +218,7 @@ func (s Service) RemoveRolePrincipals(ctx context.Context, req *pbs.RemoveRolePr return nil, err } r.Scope = authResults.Scope + r.AuthorizedActions = authResults.FetchActionSetForId(ctx, r.Id, IdActions).Strings() return &pbs.RemoveRolePrincipalsResponse{Item: r}, nil } @@ -198,6 +236,7 @@ func (s Service) AddRoleGrants(ctx context.Context, req *pbs.AddRoleGrantsReques return nil, err } r.Scope = authResults.Scope + r.AuthorizedActions = authResults.FetchActionSetForId(ctx, r.Id, IdActions).Strings() return &pbs.AddRoleGrantsResponse{Item: r}, nil } @@ -215,6 +254,7 @@ func (s Service) SetRoleGrants(ctx context.Context, req *pbs.SetRoleGrantsReques return nil, err } r.Scope = authResults.Scope + r.AuthorizedActions = authResults.FetchActionSetForId(ctx, r.Id, IdActions).Strings() return &pbs.SetRoleGrantsResponse{Item: r}, nil } @@ -232,6 +272,7 @@ func (s Service) RemoveRoleGrants(ctx context.Context, req *pbs.RemoveRoleGrants return nil, err } r.Scope = authResults.Scope + r.AuthorizedActions = authResults.FetchActionSetForId(ctx, r.Id, IdActions).Strings() return &pbs.RemoveRoleGrantsResponse{Item: r}, nil } diff --git a/internal/servers/controller/handlers/roles/role_service_test.go b/internal/servers/controller/handlers/roles/role_service_test.go index d24abac0c..ed2e92837 100644 --- a/internal/servers/controller/handlers/roles/role_service_test.go +++ b/internal/servers/controller/handlers/roles/role_service_test.go @@ -77,27 +77,29 @@ func TestGet(t *testing.T) { } wantOrgRole := &pb.Role{ - Id: or.GetPublicId(), - ScopeId: or.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: or.GetName()}, - Description: &wrapperspb.StringValue{Value: or.GetDescription()}, - GrantScopeId: &wrapperspb.StringValue{Value: pr.GetGrantScopeId()}, - CreatedTime: or.CreateTime.GetTimestamp(), - UpdatedTime: or.UpdateTime.GetTimestamp(), - Version: or.GetVersion(), + Id: or.GetPublicId(), + ScopeId: or.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: or.GetName()}, + Description: &wrapperspb.StringValue{Value: or.GetDescription()}, + GrantScopeId: &wrapperspb.StringValue{Value: pr.GetGrantScopeId()}, + CreatedTime: or.CreateTime.GetTimestamp(), + UpdatedTime: or.UpdateTime.GetTimestamp(), + Version: or.GetVersion(), + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, } wantProjRole := &pb.Role{ - Id: pr.GetPublicId(), - ScopeId: pr.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, - Name: &wrapperspb.StringValue{Value: pr.GetName()}, - Description: &wrapperspb.StringValue{Value: pr.GetDescription()}, - GrantScopeId: &wrapperspb.StringValue{Value: pr.GetGrantScopeId()}, - CreatedTime: pr.CreateTime.GetTimestamp(), - UpdatedTime: pr.UpdateTime.GetTimestamp(), - Version: pr.GetVersion(), + Id: pr.GetPublicId(), + ScopeId: pr.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, + Name: &wrapperspb.StringValue{Value: pr.GetName()}, + Description: &wrapperspb.StringValue{Value: pr.GetDescription()}, + GrantScopeId: &wrapperspb.StringValue{Value: pr.GetGrantScopeId()}, + CreatedTime: pr.CreateTime.GetTimestamp(), + UpdatedTime: pr.UpdateTime.GetTimestamp(), + Version: pr.GetVersion(), + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, } cases := []struct { @@ -192,23 +194,25 @@ func TestList(t *testing.T) { for i := 0; i < 10; i++ { or := iam.TestRole(t, conn, oWithRoles.GetPublicId()) wantOrgRoles = append(wantOrgRoles, &pb.Role{ - Id: or.GetPublicId(), - ScopeId: or.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, - CreatedTime: or.GetCreateTime().GetTimestamp(), - UpdatedTime: or.GetUpdateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: or.GetGrantScopeId()}, - Version: or.GetVersion(), + Id: or.GetPublicId(), + ScopeId: or.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, + CreatedTime: or.GetCreateTime().GetTimestamp(), + UpdatedTime: or.GetUpdateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: or.GetGrantScopeId()}, + Version: or.GetVersion(), + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }) pr := iam.TestRole(t, conn, pWithRoles.GetPublicId()) wantProjRoles = append(wantProjRoles, &pb.Role{ - Id: pr.GetPublicId(), - ScopeId: pr.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, - CreatedTime: pr.GetCreateTime().GetTimestamp(), - UpdatedTime: pr.GetUpdateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: pr.GetGrantScopeId()}, - Version: pr.GetVersion(), + Id: pr.GetPublicId(), + ScopeId: pr.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, + CreatedTime: pr.GetCreateTime().GetTimestamp(), + UpdatedTime: pr.GetUpdateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: pr.GetGrantScopeId()}, + Version: pr.GetVersion(), + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }) } @@ -367,12 +371,13 @@ func TestCreate(t *testing.T) { res: &pbs.CreateRoleResponse{ Uri: fmt.Sprintf("roles/%s_", iam.RolePrefix), Item: &pb.Role{ - ScopeId: defaultOrgRole.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: defaultOrgRole.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, - Version: 1, + ScopeId: defaultOrgRole.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: defaultOrgRole.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -387,12 +392,13 @@ func TestCreate(t *testing.T) { res: &pbs.CreateRoleResponse{ Uri: fmt.Sprintf("roles/%s_", iam.RolePrefix), Item: &pb.Role{ - ScopeId: scope.Global.String(), - Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, - Version: 1, + ScopeId: scope.Global.String(), + Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -408,12 +414,13 @@ func TestCreate(t *testing.T) { res: &pbs.CreateRoleResponse{ Uri: fmt.Sprintf("roles/%s_", iam.RolePrefix), Item: &pb.Role{ - ScopeId: defaultProjRole.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: defaultProjRole.GetScopeId(), Type: scope.Project.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, - Version: 1, + ScopeId: defaultProjRole.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: defaultProjRole.GetScopeId(), Type: scope.Project.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + GrantScopeId: &wrapperspb.StringValue{Value: defaultProjRole.ScopeId}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -581,17 +588,18 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateRoleResponse{ Item: &pb.Role{ - Id: or.GetPublicId(), - ScopeId: or.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: or.GetCreateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, - GrantStrings: []string{grant.GetRaw()}, - Grants: []*pb.Grant{grant}, - PrincipalIds: []string{u.GetPublicId()}, - Principals: []*pb.Principal{principal}, + Id: or.GetPublicId(), + ScopeId: or.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: or.GetCreateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, + GrantStrings: []string{grant.GetRaw()}, + Grants: []*pb.Grant{grant}, + PrincipalIds: []string{u.GetPublicId()}, + Principals: []*pb.Principal{principal}, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -609,17 +617,18 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateRoleResponse{ Item: &pb.Role{ - Id: or.GetPublicId(), - ScopeId: or.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: or.GetCreateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, - GrantStrings: []string{grant.GetRaw()}, - Grants: []*pb.Grant{grant}, - PrincipalIds: []string{u.GetPublicId()}, - Principals: []*pb.Principal{principal}, + Id: or.GetPublicId(), + ScopeId: or.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: or.GetCreateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, + GrantStrings: []string{grant.GetRaw()}, + Grants: []*pb.Grant{grant}, + PrincipalIds: []string{u.GetPublicId()}, + Principals: []*pb.Principal{principal}, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -638,17 +647,18 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateRoleResponse{ Item: &pb.Role{ - Id: pr.GetPublicId(), - ScopeId: pr.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: pr.GetCreateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: pr.GetScopeId()}, - GrantStrings: []string{grant.GetRaw()}, - Grants: []*pb.Grant{grant}, - PrincipalIds: []string{u.GetPublicId()}, - Principals: []*pb.Principal{principal}, + Id: pr.GetPublicId(), + ScopeId: pr.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: pr.GetCreateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: pr.GetScopeId()}, + GrantStrings: []string{grant.GetRaw()}, + Grants: []*pb.Grant{grant}, + PrincipalIds: []string{u.GetPublicId()}, + Principals: []*pb.Principal{principal}, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -667,17 +677,18 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateRoleResponse{ Item: &pb.Role{ - Id: pr.GetPublicId(), - ScopeId: pr.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: pr.GetCreateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: pr.GetScopeId()}, - GrantStrings: []string{grant.GetRaw()}, - Grants: []*pb.Grant{grant}, - PrincipalIds: []string{u.GetPublicId()}, - Principals: []*pb.Principal{principal}, + Id: pr.GetPublicId(), + ScopeId: pr.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: pr.GetScopeId(), Type: scope.Project.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: pr.GetCreateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: pr.GetScopeId()}, + GrantStrings: []string{grant.GetRaw()}, + Grants: []*pb.Grant{grant}, + PrincipalIds: []string{u.GetPublicId()}, + Principals: []*pb.Principal{principal}, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -728,16 +739,17 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateRoleResponse{ Item: &pb.Role{ - Id: or.GetPublicId(), - ScopeId: or.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, - Description: &wrapperspb.StringValue{Value: "default"}, - CreatedTime: or.GetCreateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, - GrantStrings: []string{grant.GetRaw()}, - Grants: []*pb.Grant{grant}, - PrincipalIds: []string{u.GetPublicId()}, - Principals: []*pb.Principal{principal}, + Id: or.GetPublicId(), + ScopeId: or.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, + Description: &wrapperspb.StringValue{Value: "default"}, + CreatedTime: or.GetCreateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, + GrantStrings: []string{grant.GetRaw()}, + Grants: []*pb.Grant{grant}, + PrincipalIds: []string{u.GetPublicId()}, + Principals: []*pb.Principal{principal}, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -755,17 +767,18 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateRoleResponse{ Item: &pb.Role{ - Id: or.GetPublicId(), - ScopeId: or.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "updated"}, - Description: &wrapperspb.StringValue{Value: "default"}, - CreatedTime: or.GetCreateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, - GrantStrings: []string{grant.GetRaw()}, - Grants: []*pb.Grant{grant}, - PrincipalIds: []string{u.GetPublicId()}, - Principals: []*pb.Principal{principal}, + Id: or.GetPublicId(), + ScopeId: or.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "updated"}, + Description: &wrapperspb.StringValue{Value: "default"}, + CreatedTime: or.GetCreateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, + GrantStrings: []string{grant.GetRaw()}, + Grants: []*pb.Grant{grant}, + PrincipalIds: []string{u.GetPublicId()}, + Principals: []*pb.Principal{principal}, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, @@ -783,17 +796,18 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateRoleResponse{ Item: &pb.Role{ - Id: or.GetPublicId(), - ScopeId: or.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "default"}, - Description: &wrapperspb.StringValue{Value: "notignored"}, - CreatedTime: or.GetCreateTime().GetTimestamp(), - GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, - GrantStrings: []string{grant.GetRaw()}, - Grants: []*pb.Grant{grant}, - PrincipalIds: []string{u.GetPublicId()}, - Principals: []*pb.Principal{principal}, + Id: or.GetPublicId(), + ScopeId: or.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: or.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "default"}, + Description: &wrapperspb.StringValue{Value: "notignored"}, + CreatedTime: or.GetCreateTime().GetTimestamp(), + GrantScopeId: &wrapperspb.StringValue{Value: or.GetScopeId()}, + GrantStrings: []string{grant.GetRaw()}, + Grants: []*pb.Grant{grant}, + PrincipalIds: []string{u.GetPublicId()}, + Principals: []*pb.Principal{principal}, + AuthorizedActions: []string{"read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"}, }, }, }, diff --git a/internal/servers/controller/handlers/scopes/scope_service.go b/internal/servers/controller/handlers/scopes/scope_service.go index 5279588df..ed5ad2bdf 100644 --- a/internal/servers/controller/handlers/scopes/scope_service.go +++ b/internal/servers/controller/handlers/scopes/scope_service.go @@ -12,16 +12,61 @@ import ( pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/iam/store" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/authmethods" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/authtokens" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/groups" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/host_catalogs" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/roles" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/sessions" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/targets" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/users" "github.com/hashicorp/boundary/internal/types/action" "github.com/hashicorp/boundary/internal/types/resource" "github.com/hashicorp/boundary/internal/types/scope" + "github.com/hashicorp/boundary/sdk/strutil" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } + + orgCollectionTypeMap = map[resource.Type]action.ActionSet{ + resource.AuthMethod: authmethods.CollectionActions, + resource.AuthToken: authtokens.CollectionActions, + resource.Group: groups.CollectionActions, + resource.Role: roles.CollectionActions, + resource.Scope: CollectionActions, + resource.Session: sessions.CollectionActions, + resource.User: users.CollectionActions, + } + + projectCollectionTypeMap = map[resource.Type]action.ActionSet{ + resource.Group: groups.CollectionActions, + resource.HostCatalog: host_catalogs.CollectionActions, + resource.Role: roles.CollectionActions, + resource.Target: targets.CollectionActions, + } +) func init() { var err error @@ -47,6 +92,36 @@ func NewService(repo common.IamRepoFactory) (Service, error) { var _ pbs.ScopeServiceServer = Service{} +func populateCollectionAuthorizedActions(ctx context.Context, + authResults auth.VerifyResults, + item *pb.Scope) error { + res := &perms.Resource{ + ScopeId: item.Id, + } + mapToRange := orgCollectionTypeMap + if item.Type == "project" { + mapToRange = projectCollectionTypeMap + } + // Range over the defined collections and check permissions against those + // collections. We use the ID of this scope being returned, not its parent, + // hence passing in a resource here. + for k, v := range mapToRange { + res.Type = k + acts := authResults.FetchActionSetForType(ctx, k, v, auth.WithResource(res)).Strings() + if len(acts) > 0 { + if item.AuthorizedCollectionActions == nil { + item.AuthorizedCollectionActions = make(map[string]*structpb.ListValue) + } + lv, err := structpb.NewList(strutil.StringListToInterfaceList(acts)) + if err != nil { + return err + } + item.AuthorizedCollectionActions[k.String()+"s"] = lv + } + } + return nil +} + // ListScopes implements the interface pbs.ScopeServiceServer. func (s Service) ListScopes(ctx context.Context, req *pbs.ListScopesRequest) (*pbs.ListScopesResponse, error) { if req.GetScopeId() == "" { @@ -63,12 +138,23 @@ func (s Service) ListScopes(ctx context.Context, req *pbs.ListScopesRequest) (*p if err != nil { return nil, err } - + finalItems := make([]*pb.Scope, 0, len(pl)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.Scope, + } for _, item := range pl { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + if err := populateCollectionAuthorizedActions(ctx, authResults, item); err != nil { + return nil, err + } + } } - return &pbs.ListScopesResponse{Items: pl}, nil + return &pbs.ListScopesResponse{Items: finalItems}, nil } // GetScopes implements the interface pbs.ScopeServiceServer. @@ -85,6 +171,15 @@ func (s Service) GetScope(ctx context.Context, req *pbs.GetScopeRequest) (*pbs.G return nil, err } p.Scope = authResults.Scope + act := IdActions + // Can't delete global so elide it + if p.Id == "global" { + act = act[0:2] + } + p.AuthorizedActions = authResults.FetchActionSetForId(ctx, p.Id, act).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, p); err != nil { + return nil, err + } return &pbs.GetScopeResponse{Item: p}, nil } @@ -102,6 +197,10 @@ func (s Service) CreateScope(ctx context.Context, req *pbs.CreateScopeRequest) ( return nil, err } p.Scope = authResults.Scope + p.AuthorizedActions = authResults.FetchActionSetForId(ctx, p.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, p); err != nil { + return nil, err + } return &pbs.CreateScopeResponse{Item: p, Uri: fmt.Sprintf("scopes/%s", p.GetId())}, nil } @@ -119,6 +218,10 @@ func (s Service) UpdateScope(ctx context.Context, req *pbs.UpdateScopeRequest) ( return nil, err } p.Scope = authResults.Scope + p.AuthorizedActions = authResults.FetchActionSetForId(ctx, p.Id, IdActions).Strings() + if err := populateCollectionAuthorizedActions(ctx, authResults, p); err != nil { + return nil, err + } return &pbs.UpdateScopeResponse{Item: p}, nil } diff --git a/internal/servers/controller/handlers/scopes/scope_service_test.go b/internal/servers/controller/handlers/scopes/scope_service_test.go index ca57e8364..70a073d9f 100644 --- a/internal/servers/controller/handlers/scopes/scope_service_test.go +++ b/internal/servers/controller/handlers/scopes/scope_service_test.go @@ -22,6 +22,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/wrapperspb" "github.com/stretchr/testify/assert" @@ -55,6 +56,76 @@ func createDefaultScopesAndRepo(t *testing.T) (*iam.Scope, *iam.Scope, func() (* return oRes, pRes, repoFn } +var orgAuthorizedCollectionActions = map[string]*structpb.ListValue{ + "auth-methods": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "auth-tokens": { + Values: []*structpb.Value{ + structpb.NewStringValue("list"), + }, + }, + "groups": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "roles": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "scopes": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "sessions": { + Values: []*structpb.Value{ + structpb.NewStringValue("list"), + }, + }, + "users": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, +} + +var projectAuthorizedCollectionActions = map[string]*structpb.ListValue{ + "groups": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "host-catalogs": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "roles": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, + "targets": { + Values: []*structpb.Value{ + structpb.NewStringValue("create"), + structpb.NewStringValue("list"), + }, + }, +} + func TestGet(t *testing.T) { org, proj, repo := createDefaultScopesAndRepo(t) toMerge := &pbs.GetScopeRequest{ @@ -62,27 +133,31 @@ func TestGet(t *testing.T) { } oScope := &pb.Scope{ - Id: org.GetPublicId(), - ScopeId: org.GetParentId(), - Scope: &pb.ScopeInfo{Id: "global", Type: scope.Global.String()}, - Name: &wrapperspb.StringValue{Value: org.GetName()}, - Description: &wrapperspb.StringValue{Value: org.GetDescription()}, - CreatedTime: org.CreateTime.GetTimestamp(), - UpdatedTime: org.UpdateTime.GetTimestamp(), - Version: 2, - Type: scope.Org.String(), + Id: org.GetPublicId(), + ScopeId: org.GetParentId(), + Scope: &pb.ScopeInfo{Id: "global", Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: org.GetName()}, + Description: &wrapperspb.StringValue{Value: org.GetDescription()}, + CreatedTime: org.CreateTime.GetTimestamp(), + UpdatedTime: org.UpdateTime.GetTimestamp(), + Version: 2, + Type: scope.Org.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: orgAuthorizedCollectionActions, } pScope := &pb.Scope{ - Id: proj.GetPublicId(), - ScopeId: proj.GetParentId(), - Scope: &pb.ScopeInfo{Id: oScope.Id, Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: proj.GetName()}, - Description: &wrapperspb.StringValue{Value: proj.GetDescription()}, - CreatedTime: proj.CreateTime.GetTimestamp(), - UpdatedTime: proj.UpdateTime.GetTimestamp(), - Version: 2, - Type: scope.Project.String(), + Id: proj.GetPublicId(), + ScopeId: proj.GetParentId(), + Scope: &pb.ScopeInfo{Id: oScope.Id, Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: proj.GetName()}, + Description: &wrapperspb.StringValue{Value: proj.GetDescription()}, + CreatedTime: proj.CreateTime.GetTimestamp(), + UpdatedTime: proj.UpdateTime.GetTimestamp(), + Version: 2, + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, } cases := []struct { @@ -174,8 +249,12 @@ func TestList(t *testing.T) { globalScope := &pb.ScopeInfo{Id: "global", Type: scope.Global.String()} oNoProjectsProto := scopes.ToProto(oNoProjects) oNoProjectsProto.Scope = globalScope + oNoProjectsProto.AuthorizedActions = []string{"read", "update", "delete"} + oNoProjectsProto.AuthorizedCollectionActions = orgAuthorizedCollectionActions oWithProjectsProto := scopes.ToProto(oWithProjects) oWithProjectsProto.Scope = globalScope + oWithProjectsProto.AuthorizedActions = []string{"read", "update", "delete"} + oWithProjectsProto.AuthorizedCollectionActions = orgAuthorizedCollectionActions initialOrgs = append(initialOrgs, oNoProjectsProto, oWithProjectsProto) scopes.SortScopes(initialOrgs) @@ -227,13 +306,15 @@ func TestList(t *testing.T) { o, err := repo.CreateScope(context.Background(), newO, "") require.NoError(t, err) wantOrgs = append(wantOrgs, &pb.Scope{ - Id: o.GetPublicId(), - ScopeId: globalScope.GetId(), - Scope: globalScope, - CreatedTime: o.GetCreateTime().GetTimestamp(), - UpdatedTime: o.GetUpdateTime().GetTimestamp(), - Version: 1, - Type: scope.Org.String(), + Id: o.GetPublicId(), + ScopeId: globalScope.GetId(), + Scope: globalScope, + CreatedTime: o.GetCreateTime().GetTimestamp(), + UpdatedTime: o.GetUpdateTime().GetTimestamp(), + Version: 1, + Type: scope.Org.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: orgAuthorizedCollectionActions, }) } wantOrgs = append(wantOrgs, initialOrgs...) @@ -246,13 +327,15 @@ func TestList(t *testing.T) { p, err := repo.CreateScope(context.Background(), newP, "") require.NoError(t, err) wantProjects = append(wantProjects, &pb.Scope{ - Id: p.GetPublicId(), - ScopeId: oWithProjects.GetPublicId(), - Scope: &pb.ScopeInfo{Id: oWithProjects.GetPublicId(), Type: scope.Org.String()}, - CreatedTime: p.GetCreateTime().GetTimestamp(), - UpdatedTime: p.GetUpdateTime().GetTimestamp(), - Version: 1, - Type: scope.Project.String(), + Id: p.GetPublicId(), + ScopeId: oWithProjects.GetPublicId(), + Scope: &pb.ScopeInfo{Id: oWithProjects.GetPublicId(), Type: scope.Org.String()}, + CreatedTime: p.GetCreateTime().GetTimestamp(), + UpdatedTime: p.GetUpdateTime().GetTimestamp(), + Version: 1, + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }) } scopes.SortScopes(wantProjects) @@ -433,12 +516,14 @@ func TestCreate(t *testing.T) { res: &pbs.CreateScopeResponse{ Uri: "scopes/p_", Item: &pb.Scope{ - ScopeId: defaultOrg.GetPublicId(), - Scope: &pb.ScopeInfo{Id: defaultOrg.GetPublicId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, - Type: scope.Project.String(), + ScopeId: defaultOrg.GetPublicId(), + Scope: &pb.ScopeInfo{Id: defaultOrg.GetPublicId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, @@ -455,12 +540,14 @@ func TestCreate(t *testing.T) { res: &pbs.CreateScopeResponse{ Uri: "scopes/o_", Item: &pb.Scope{ - ScopeId: scope.Global.String(), - Scope: &pb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, - Type: scope.Org.String(), + ScopeId: scope.Global.String(), + Scope: &pb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + Type: scope.Org.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: orgAuthorizedCollectionActions, }, }, }, @@ -477,11 +564,13 @@ func TestCreate(t *testing.T) { res: &pbs.CreateScopeResponse{ Uri: "scopes/p_", Item: &pb.Scope{ - ScopeId: defaultOrg.GetPublicId(), - Scope: &pb.ScopeInfo{Id: defaultOrg.GetPublicId(), Type: scope.Org.String()}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, - Type: scope.Project.String(), + ScopeId: defaultOrg.GetPublicId(), + Scope: &pb.ScopeInfo{Id: defaultOrg.GetPublicId(), Type: scope.Org.String()}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, @@ -498,11 +587,13 @@ func TestCreate(t *testing.T) { res: &pbs.CreateScopeResponse{ Uri: "scopes/o_", Item: &pb.Scope{ - ScopeId: scope.Global.String(), - Scope: &pb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, - Type: scope.Org.String(), + ScopeId: scope.Global.String(), + Scope: &pb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + Type: scope.Org.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: orgAuthorizedCollectionActions, }, }, }, @@ -704,13 +795,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateScopeResponse{ Item: &pb.Scope{ - Id: proj.GetPublicId(), - ScopeId: org.GetPublicId(), - Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: proj.GetCreateTime().GetTimestamp(), - Type: scope.Project.String(), + Id: proj.GetPublicId(), + ScopeId: org.GetPublicId(), + Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: proj.GetCreateTime().GetTimestamp(), + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, @@ -729,13 +822,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateScopeResponse{ Item: &pb.Scope{ - Id: org.GetPublicId(), - ScopeId: scope.Global.String(), - Scope: &pb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: org.GetCreateTime().GetTimestamp(), - Type: scope.Org.String(), + Id: org.GetPublicId(), + ScopeId: scope.Global.String(), + Scope: &pb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: org.GetCreateTime().GetTimestamp(), + Type: scope.Org.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: orgAuthorizedCollectionActions, }, }, }, @@ -753,13 +848,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateScopeResponse{ Item: &pb.Scope{ - Id: proj.GetPublicId(), - ScopeId: org.GetPublicId(), - Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: proj.GetCreateTime().GetTimestamp(), - Type: scope.Project.String(), + Id: proj.GetPublicId(), + ScopeId: org.GetPublicId(), + Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: proj.GetCreateTime().GetTimestamp(), + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, @@ -825,12 +922,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateScopeResponse{ Item: &pb.Scope{ - Id: proj.GetPublicId(), - ScopeId: org.GetPublicId(), - Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, - Description: &wrapperspb.StringValue{Value: "defaultProj"}, - CreatedTime: proj.GetCreateTime().GetTimestamp(), - Type: scope.Project.String(), + Id: proj.GetPublicId(), + ScopeId: org.GetPublicId(), + Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + Description: &wrapperspb.StringValue{Value: "defaultProj"}, + CreatedTime: proj.GetCreateTime().GetTimestamp(), + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, @@ -847,12 +946,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateScopeResponse{ Item: &pb.Scope{ - Id: proj.GetPublicId(), - ScopeId: org.GetPublicId(), - Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, - Name: &wrappers.StringValue{Value: "defaultProj"}, - CreatedTime: proj.GetCreateTime().GetTimestamp(), - Type: scope.Project.String(), + Id: proj.GetPublicId(), + ScopeId: org.GetPublicId(), + Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + Name: &wrappers.StringValue{Value: "defaultProj"}, + CreatedTime: proj.GetCreateTime().GetTimestamp(), + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, @@ -870,13 +971,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateScopeResponse{ Item: &pb.Scope{ - Id: proj.GetPublicId(), - ScopeId: org.GetPublicId(), - Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "updated"}, - Description: &wrapperspb.StringValue{Value: "defaultProj"}, - CreatedTime: proj.GetCreateTime().GetTimestamp(), - Type: scope.Project.String(), + Id: proj.GetPublicId(), + ScopeId: org.GetPublicId(), + Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "updated"}, + Description: &wrapperspb.StringValue{Value: "defaultProj"}, + CreatedTime: proj.GetCreateTime().GetTimestamp(), + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, @@ -894,13 +997,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateScopeResponse{ Item: &pb.Scope{ - Id: proj.GetPublicId(), - ScopeId: org.GetPublicId(), - Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "defaultProj"}, - Description: &wrapperspb.StringValue{Value: "notignored"}, - CreatedTime: proj.GetCreateTime().GetTimestamp(), - Type: scope.Project.String(), + Id: proj.GetPublicId(), + ScopeId: org.GetPublicId(), + Scope: &pb.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "defaultProj"}, + Description: &wrapperspb.StringValue{Value: "notignored"}, + CreatedTime: proj.GetCreateTime().GetTimestamp(), + Type: scope.Project.String(), + AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, }, diff --git a/internal/servers/controller/handlers/sessions/session_service.go b/internal/servers/controller/handlers/sessions/session_service.go index d2c76fcba..5bf9a6911 100644 --- a/internal/servers/controller/handlers/sessions/session_service.go +++ b/internal/servers/controller/handlers/sessions/session_service.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/boundary/internal/errors" pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/sessions" pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/session" @@ -18,6 +19,21 @@ import ( "github.com/hashicorp/boundary/internal/types/scope" ) +var ( + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Cancel, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.List, + } +) + // Service handles request as described by the pbs.SessionServiceServer interface. type Service struct { pbs.UnimplementedSessionServiceServer @@ -53,6 +69,7 @@ func (s Service) GetSession(ctx context.Context, req *pbs.GetSessionRequest) (*p return nil, err } ses.Scope = authResults.Scope + ses.AuthorizedActions = authResults.FetchActionSetForId(ctx, ses.Id, IdActions).Strings() return &pbs.GetSessionResponse{Item: ses}, nil } @@ -69,10 +86,19 @@ func (s Service) ListSessions(ctx context.Context, req *pbs.ListSessionsRequest) if err != nil { return nil, err } + finalItems := make([]*pb.Session, 0, len(seslist)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.Session, + } for _, item := range seslist { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListSessionsResponse{Items: seslist}, nil + return &pbs.ListSessionsResponse{Items: finalItems}, nil } // CancelSession implements the interface pbs.SessionServiceServer. @@ -89,6 +115,7 @@ func (s Service) CancelSession(ctx context.Context, req *pbs.CancelSessionReques return nil, err } ses.Scope = authResults.Scope + ses.AuthorizedActions = authResults.FetchActionSetForId(ctx, ses.Id, IdActions).Strings() return &pbs.CancelSessionResponse{Item: ses}, nil } diff --git a/internal/servers/controller/handlers/sessions/session_service_test.go b/internal/servers/controller/handlers/sessions/session_service_test.go index b185212ae..ef775dbae 100644 --- a/internal/servers/controller/handlers/sessions/session_service_test.go +++ b/internal/servers/controller/handlers/sessions/session_service_test.go @@ -64,23 +64,24 @@ func TestGetSession(t *testing.T) { }) wireSess := &pb.Session{ - Id: sess.GetPublicId(), - ScopeId: p.GetPublicId(), - AuthTokenId: at.GetPublicId(), - Endpoint: sess.Endpoint, - UserId: at.GetIamUserId(), - TargetId: sess.TargetId, - HostSetId: sess.HostSetId, - HostId: sess.HostId, - Version: sess.Version, - Status: session.StatusPending.String(), - UpdatedTime: sess.UpdateTime.GetTimestamp(), - CreatedTime: sess.CreateTime.GetTimestamp(), - ExpirationTime: sess.ExpirationTime.GetTimestamp(), - Scope: &scopes.ScopeInfo{Id: p.GetPublicId(), Type: scope.Project.String()}, - States: []*pb.SessionState{{Status: session.StatusPending.String(), StartTime: sess.CreateTime.GetTimestamp()}}, - Certificate: sess.Certificate, - Type: target.TcpSubType.String(), + Id: sess.GetPublicId(), + ScopeId: p.GetPublicId(), + AuthTokenId: at.GetPublicId(), + Endpoint: sess.Endpoint, + UserId: at.GetIamUserId(), + TargetId: sess.TargetId, + HostSetId: sess.HostSetId, + HostId: sess.HostId, + Version: sess.Version, + Status: session.StatusPending.String(), + UpdatedTime: sess.UpdateTime.GetTimestamp(), + CreatedTime: sess.CreateTime.GetTimestamp(), + ExpirationTime: sess.ExpirationTime.GetTimestamp(), + Scope: &scopes.ScopeInfo{Id: p.GetPublicId(), Type: scope.Project.String()}, + States: []*pb.SessionState{{Status: session.StatusPending.String(), StartTime: sess.CreateTime.GetTimestamp()}}, + Certificate: sess.Certificate, + Type: target.TcpSubType.String(), + AuthorizedActions: []string{"read", "cancel"}, } cases := []struct { @@ -180,23 +181,24 @@ func TestList(t *testing.T) { status, states := convertStates(sess.States) wantSession = append(wantSession, &pb.Session{ - Id: sess.GetPublicId(), - ScopeId: pWithSessions.GetPublicId(), - AuthTokenId: at.GetPublicId(), - UserId: at.GetIamUserId(), - TargetId: sess.TargetId, - Endpoint: sess.Endpoint, - HostSetId: sess.HostSetId, - HostId: sess.HostId, - Version: sess.Version, - UpdatedTime: sess.UpdateTime.GetTimestamp(), - CreatedTime: sess.CreateTime.GetTimestamp(), - ExpirationTime: sess.ExpirationTime.GetTimestamp(), - Scope: &scopes.ScopeInfo{Id: pWithSessions.GetPublicId(), Type: scope.Project.String()}, - Status: status, - States: states, - Certificate: sess.Certificate, - Type: target.TcpSubType.String(), + Id: sess.GetPublicId(), + ScopeId: pWithSessions.GetPublicId(), + AuthTokenId: at.GetPublicId(), + UserId: at.GetIamUserId(), + TargetId: sess.TargetId, + Endpoint: sess.Endpoint, + HostSetId: sess.HostSetId, + HostId: sess.HostId, + Version: sess.Version, + UpdatedTime: sess.UpdateTime.GetTimestamp(), + CreatedTime: sess.CreateTime.GetTimestamp(), + ExpirationTime: sess.ExpirationTime.GetTimestamp(), + Scope: &scopes.ScopeInfo{Id: pWithSessions.GetPublicId(), Type: scope.Project.String()}, + Status: status, + States: states, + Certificate: sess.Certificate, + Type: target.TcpSubType.String(), + AuthorizedActions: []string{"read", "cancel"}, }) } @@ -293,21 +295,22 @@ func TestCancel(t *testing.T) { }) wireSess := &pb.Session{ - Id: sess.GetPublicId(), - ScopeId: p.GetPublicId(), - AuthTokenId: at.GetPublicId(), - UserId: at.GetIamUserId(), - TargetId: sess.TargetId, - HostSetId: sess.HostSetId, - HostId: sess.HostId, - Version: sess.Version, - Endpoint: sess.Endpoint, - CreatedTime: sess.CreateTime.GetTimestamp(), - ExpirationTime: sess.ExpirationTime.GetTimestamp(), - Scope: &scopes.ScopeInfo{Id: p.GetPublicId(), Type: scope.Project.String()}, - Status: session.StatusCanceling.String(), - Certificate: sess.Certificate, - Type: target.TcpSubType.String(), + Id: sess.GetPublicId(), + ScopeId: p.GetPublicId(), + AuthTokenId: at.GetPublicId(), + UserId: at.GetIamUserId(), + TargetId: sess.TargetId, + HostSetId: sess.HostSetId, + HostId: sess.HostId, + Version: sess.Version, + Endpoint: sess.Endpoint, + CreatedTime: sess.CreateTime.GetTimestamp(), + ExpirationTime: sess.ExpirationTime.GetTimestamp(), + Scope: &scopes.ScopeInfo{Id: p.GetPublicId(), Type: scope.Project.String()}, + Status: session.StatusCanceling.String(), + Certificate: sess.Certificate, + Type: target.TcpSubType.String(), + AuthorizedActions: []string{"read", "cancel"}, } version := wireSess.GetVersion() diff --git a/internal/servers/controller/handlers/targets/target_service.go b/internal/servers/controller/handlers/targets/target_service.go index 82650ba2e..0c9466766 100644 --- a/internal/servers/controller/handlers/targets/target_service.go +++ b/internal/servers/controller/handlers/targets/target_service.go @@ -38,9 +38,9 @@ import ( var ( maskManager handlers.MaskManager - // TargetIdActions contains the set of actions that can be performed on - // individual target resources - TargetIdActions = action.Actions{ + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ action.Read, action.Update, action.Delete, @@ -49,6 +49,13 @@ var ( action.RemoveHostSets, action.AuthorizeSession, } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } ) func init() { @@ -119,13 +126,13 @@ func (s Service) ListTargets(ctx context.Context, req *pbs.ListTargetsRequest) ( return nil, err } finalItems := make([]*pb.Target, 0, len(ul)) - resource := &perms.Resource{ + res := &perms.Resource{ ScopeId: authResults.Scope.Id, Type: resource.Target, } for _, item := range ul { item.Scope = authResults.Scope - item.AuthorizedActions = authResults.FetchActionsForId(ctx, item.Id, TargetIdActions, auth.WithResource(resource)).Strings() + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() if len(item.AuthorizedActions) > 0 { finalItems = append(finalItems, item) } @@ -147,7 +154,7 @@ func (s Service) GetTarget(ctx context.Context, req *pbs.GetTargetRequest) (*pbs return nil, err } u.Scope = authResults.Scope - u.AuthorizedActions = authResults.FetchActionsForId(ctx, u.Id, TargetIdActions).Strings() + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.GetTargetResponse{Item: u}, nil } @@ -165,7 +172,7 @@ func (s Service) CreateTarget(ctx context.Context, req *pbs.CreateTargetRequest) return nil, err } u.Scope = authResults.Scope - u.AuthorizedActions = authResults.FetchActionsForId(ctx, u.Id, TargetIdActions).Strings() + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.CreateTargetResponse{Item: u, Uri: fmt.Sprintf("targets/%s", u.GetId())}, nil } @@ -183,7 +190,7 @@ func (s Service) UpdateTarget(ctx context.Context, req *pbs.UpdateTargetRequest) return nil, err } u.Scope = authResults.Scope - u.AuthorizedActions = authResults.FetchActionsForId(ctx, u.Id, TargetIdActions).Strings() + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.UpdateTargetResponse{Item: u}, nil } @@ -217,7 +224,7 @@ func (s Service) AddTargetHostSets(ctx context.Context, req *pbs.AddTargetHostSe return nil, err } u.Scope = authResults.Scope - u.AuthorizedActions = authResults.FetchActionsForId(ctx, u.Id, TargetIdActions).Strings() + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.AddTargetHostSetsResponse{Item: u}, nil } @@ -235,7 +242,7 @@ func (s Service) SetTargetHostSets(ctx context.Context, req *pbs.SetTargetHostSe return nil, err } u.Scope = authResults.Scope - u.AuthorizedActions = authResults.FetchActionsForId(ctx, u.Id, TargetIdActions).Strings() + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.SetTargetHostSetsResponse{Item: u}, nil } @@ -253,7 +260,7 @@ func (s Service) RemoveTargetHostSets(ctx context.Context, req *pbs.RemoveTarget return nil, err } u.Scope = authResults.Scope - u.AuthorizedActions = authResults.FetchActionsForId(ctx, u.Id, TargetIdActions).Strings() + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.RemoveTargetHostSetsResponse{Item: u}, nil } diff --git a/internal/servers/controller/handlers/targets/target_service_test.go b/internal/servers/controller/handlers/targets/target_service_test.go index 6a475ed94..d15e08853 100644 --- a/internal/servers/controller/handlers/targets/target_service_test.go +++ b/internal/servers/controller/handlers/targets/target_service_test.go @@ -81,7 +81,7 @@ func TestGet(t *testing.T) { Attributes: new(structpb.Struct), SessionMaxSeconds: wrapperspb.UInt32(28800), SessionConnectionLimit: wrapperspb.Int32(1), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), } for _, ihs := range hs { pTar.HostSets = append(pTar.HostSets, &pb.HostSet{Id: ihs.GetPublicId(), HostCatalogId: ihs.GetCatalogId()}) @@ -164,7 +164,7 @@ func TestList(t *testing.T) { Attributes: new(structpb.Struct), SessionMaxSeconds: wrapperspb.UInt32(28800), SessionConnectionLimit: wrapperspb.Int32(1), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), }) } @@ -320,7 +320,7 @@ func TestCreate(t *testing.T) { }}, SessionMaxSeconds: wrapperspb.UInt32(28800), SessionConnectionLimit: wrapperspb.Int32(1), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), }, }, }, @@ -491,7 +491,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), }, }, }, @@ -523,7 +523,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), }, }, }, @@ -608,7 +608,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), }, }, }, @@ -639,7 +639,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), }, }, }, @@ -670,7 +670,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.TargetIdActions.Strings(), + AuthorizedActions: targets.IdActions.Strings(), }, }, }, diff --git a/internal/servers/controller/handlers/users/user_service.go b/internal/servers/controller/handlers/users/user_service.go index ad2be85ea..db75cbd42 100644 --- a/internal/servers/controller/handlers/users/user_service.go +++ b/internal/servers/controller/handlers/users/user_service.go @@ -11,6 +11,7 @@ import ( pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/iam/store" + "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/types/action" @@ -21,7 +22,27 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var maskManager handlers.MaskManager +var ( + maskManager handlers.MaskManager + + // IdActions contains the set of actions that can be performed on + // individual resources + IdActions = action.ActionSet{ + action.Read, + action.Update, + action.Delete, + action.AddAccounts, + action.SetAccounts, + action.RemoveAccounts, + } + + // CollectionActions contains the set of actions that can be performed on + // this collection + CollectionActions = action.ActionSet{ + action.Create, + action.List, + } +) func init() { var err error @@ -60,10 +81,19 @@ func (s Service) ListUsers(ctx context.Context, req *pbs.ListUsersRequest) (*pbs if err != nil { return nil, err } + finalItems := make([]*pb.User, 0, len(ul)) + res := &perms.Resource{ + ScopeId: authResults.Scope.Id, + Type: resource.User, + } for _, item := range ul { item.Scope = authResults.Scope + item.AuthorizedActions = authResults.FetchActionSetForId(ctx, item.Id, IdActions, auth.WithResource(res)).Strings() + if len(item.AuthorizedActions) > 0 { + finalItems = append(finalItems, item) + } } - return &pbs.ListUsersResponse{Items: ul}, nil + return &pbs.ListUsersResponse{Items: finalItems}, nil } // GetUsers implements the interface pbs.UserServiceServer. @@ -80,6 +110,7 @@ func (s Service) GetUser(ctx context.Context, req *pbs.GetUserRequest) (*pbs.Get return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.GetUserResponse{Item: u}, nil } @@ -97,6 +128,7 @@ func (s Service) CreateUser(ctx context.Context, req *pbs.CreateUserRequest) (*p return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.CreateUserResponse{Item: u, Uri: fmt.Sprintf("users/%s", u.GetId())}, nil } @@ -114,6 +146,7 @@ func (s Service) UpdateUser(ctx context.Context, req *pbs.UpdateUserRequest) (*p return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.UpdateUserResponse{Item: u}, nil } @@ -147,6 +180,7 @@ func (s Service) AddUserAccounts(ctx context.Context, req *pbs.AddUserAccountsRe return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.AddUserAccountsResponse{Item: u}, nil } @@ -164,6 +198,7 @@ func (s Service) SetUserAccounts(ctx context.Context, req *pbs.SetUserAccountsRe return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.SetUserAccountsResponse{Item: u}, nil } @@ -181,6 +216,7 @@ func (s Service) RemoveUserAccounts(ctx context.Context, req *pbs.RemoveUserAcco return nil, err } u.Scope = authResults.Scope + u.AuthorizedActions = authResults.FetchActionSetForId(ctx, u.Id, IdActions).Strings() return &pbs.RemoveUserAccountsResponse{Item: u}, nil } diff --git a/internal/servers/controller/handlers/users/user_service_test.go b/internal/servers/controller/handlers/users/user_service_test.go index 3bedd07fa..13f1ccddd 100644 --- a/internal/servers/controller/handlers/users/user_service_test.go +++ b/internal/servers/controller/handlers/users/user_service_test.go @@ -49,14 +49,15 @@ func TestGet(t *testing.T) { } wantU := &pb.User{ - Id: u.GetPublicId(), - ScopeId: u.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: u.ScopeId, Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: u.GetName()}, - Description: &wrapperspb.StringValue{Value: u.GetDescription()}, - CreatedTime: u.CreateTime.GetTimestamp(), - UpdatedTime: u.UpdateTime.GetTimestamp(), - Version: 1, + Id: u.GetPublicId(), + ScopeId: u.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: u.ScopeId, Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: u.GetName()}, + Description: &wrapperspb.StringValue{Value: u.GetDescription()}, + CreatedTime: u.CreateTime.GetTimestamp(), + UpdatedTime: u.UpdateTime.GetTimestamp(), + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, } cases := []struct { @@ -128,12 +129,13 @@ func TestList(t *testing.T) { u, err := repo.CreateUser(context.Background(), newU) require.NoError(t, err) wantUsers = append(wantUsers, &pb.User{ - Id: u.GetPublicId(), - ScopeId: u.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, - CreatedTime: u.GetCreateTime().GetTimestamp(), - UpdatedTime: u.GetUpdateTime().GetTimestamp(), - Version: 1, + Id: u.GetPublicId(), + ScopeId: u.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, + CreatedTime: u.GetCreateTime().GetTimestamp(), + UpdatedTime: u.GetUpdateTime().GetTimestamp(), + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }) } @@ -254,11 +256,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateUserResponse{ Uri: fmt.Sprintf("users/%s_", iam.UserPrefix), Item: &pb.User{ - ScopeId: defaultUser.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: defaultUser.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, + ScopeId: defaultUser.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: defaultUser.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }, }, }, @@ -272,11 +275,12 @@ func TestCreate(t *testing.T) { res: &pbs.CreateUserResponse{ Uri: fmt.Sprintf("users/%s_", iam.UserPrefix), Item: &pb.User{ - ScopeId: scope.Global.String(), - Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, - Name: &wrapperspb.StringValue{Value: "name"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Version: 1, + ScopeId: scope.Global.String(), + Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String()}, + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Version: 1, + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }, }, }, @@ -381,12 +385,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateUserResponse{ Item: &pb.User{ - Id: u.GetPublicId(), - ScopeId: u.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: u.GetCreateTime().GetTimestamp(), + Id: u.GetPublicId(), + ScopeId: u.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: u.GetCreateTime().GetTimestamp(), + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }, }, }, @@ -403,12 +408,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateUserResponse{ Item: &pb.User{ - Id: u.GetPublicId(), - ScopeId: u.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - CreatedTime: u.GetCreateTime().GetTimestamp(), + Id: u.GetPublicId(), + ScopeId: u.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + CreatedTime: u.GetCreateTime().GetTimestamp(), + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }, }, }, @@ -456,11 +462,12 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateUserResponse{ Item: &pb.User{ - Id: u.GetPublicId(), - ScopeId: u.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, - Description: &wrapperspb.StringValue{Value: "default"}, - CreatedTime: u.GetCreateTime().GetTimestamp(), + Id: u.GetPublicId(), + ScopeId: u.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, + Description: &wrapperspb.StringValue{Value: "default"}, + CreatedTime: u.GetCreateTime().GetTimestamp(), + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }, }, }, @@ -477,12 +484,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateUserResponse{ Item: &pb.User{ - Id: u.GetPublicId(), - ScopeId: u.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "updated"}, - Description: &wrapperspb.StringValue{Value: "default"}, - CreatedTime: u.GetCreateTime().GetTimestamp(), + Id: u.GetPublicId(), + ScopeId: u.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "updated"}, + Description: &wrapperspb.StringValue{Value: "default"}, + CreatedTime: u.GetCreateTime().GetTimestamp(), + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }, }, }, @@ -499,12 +507,13 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateUserResponse{ Item: &pb.User{ - Id: u.GetPublicId(), - ScopeId: u.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, - Name: &wrapperspb.StringValue{Value: "default"}, - Description: &wrapperspb.StringValue{Value: "notignored"}, - CreatedTime: u.GetCreateTime().GetTimestamp(), + Id: u.GetPublicId(), + ScopeId: u.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String()}, + Name: &wrapperspb.StringValue{Value: "default"}, + Description: &wrapperspb.StringValue{Value: "notignored"}, + CreatedTime: u.GetCreateTime().GetTimestamp(), + AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, }, }, }, diff --git a/internal/types/action/action.go b/internal/types/action/action.go index 353ec14f4..327a8d6a4 100644 --- a/internal/types/action/action.go +++ b/internal/types/action/action.go @@ -108,11 +108,11 @@ func (a Type) String() string { }[a] } -// Actions stores a slice of action types -type Actions []Type +// ActionSet stores a slice of action types +type ActionSet []Type // Strings converts Actions into a slice of the actions' string equivalents -func (a Actions) Strings() []string { +func (a ActionSet) Strings() []string { if a == nil { return nil } diff --git a/internal/types/action/action_test.go b/internal/types/action/action_test.go index f8ccb8228..40f5f688e 100644 --- a/internal/types/action/action_test.go +++ b/internal/types/action/action_test.go @@ -87,22 +87,22 @@ func TestAction(t *testing.T) { func TestActionStrings(t *testing.T) { tests := []struct { name string - actions Actions + actions ActionSet want []string }{ { name: "basic test", - actions: Actions{Read, AuthorizeSession}, + actions: ActionSet{Read, AuthorizeSession}, want: []string{"read", "authorize-session"}, }, { name: "reverse test to check ordering", - actions: Actions{AuthorizeSession, Read}, + actions: ActionSet{AuthorizeSession, Read}, want: []string{"authorize-session", "read"}, }, { name: "another test", - actions: Actions{Delete, AddGrants}, + actions: ActionSet{Delete, AddGrants}, want: []string{"delete", "add-grants"}, }, } diff --git a/sdk/strutil/strutil.go b/sdk/strutil/strutil.go index 6a3be0451..9688bbe9a 100644 --- a/sdk/strutil/strutil.go +++ b/sdk/strutil/strutil.go @@ -445,3 +445,11 @@ func Difference(a, b []string, lowercase bool) []string { sort.Strings(items) return items } + +func StringListToInterfaceList(in []string) []interface{} { + ret := make([]interface{}, len(in)) + for i, v := range in { + ret[i] = v + } + return ret +}