From 727d1c7085637208c948936166efd7b12e84e67b Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 23 Apr 2021 09:13:37 -0500 Subject: [PATCH] Add "no-op" action and use it as default for scope permissions (#1138) Because of listing visibility, if no actions are assigned to a user for an individual resource, it's excluded from the list. This is fine and good. However, when we made a change in 0.2.0 to restrict the information returned from listing for the anonymous user for scopes and auth methods, it exposed the fact that because of the way this visibility works we had to add `read` to scopes by default -- thereby rather defeating the purpose of restricting what goes back to `u_anon` requests. The purpose of "no-op" is to never be used for real actions within the API, but as something that can be granted to specifically enable visibility for the targeted user. This makes the controls over list visibility much more granular. --- CHANGELOG.md | 17 ++++-- internal/cmd/base/initial_resources.go | 2 +- internal/iam/repository_scope.go | 2 +- .../common/scopeids/scope_ids_test.go | 28 +++++----- .../handlers/accounts/account_service.go | 2 + .../handlers/accounts/account_service_test.go | 2 + .../authmethods/authmethod_service_test.go | 2 + .../controller/handlers/authmethods/oidc.go | 1 + .../handlers/authmethods/password.go | 1 + .../handlers/authtokens/authtoken_service.go | 1 + .../authtokens/authtoken_service_test.go | 10 ++-- .../handlers/groups/group_service.go | 1 + .../handlers/groups/group_service_test.go | 55 +++++++++---------- .../host_catalogs/host_catalog_service.go | 1 + .../host_catalog_service_test.go | 44 +++++++-------- .../handlers/host_sets/host_set_service.go | 1 + .../host_sets/host_set_service_test.go | 45 ++++++++------- .../controller/handlers/hosts/host_service.go | 1 + .../handlers/hosts/host_service_test.go | 47 ++++++++-------- .../controller/handlers/roles/role_service.go | 1 + .../handlers/roles/role_service_test.go | 54 +++++++++--------- .../handlers/scopes/scope_service.go | 1 + .../handlers/scopes/scope_service_test.go | 38 +++++++------ .../handlers/sessions/session_service.go | 1 + .../handlers/sessions/session_service_test.go | 10 ++-- .../handlers/targets/target_service.go | 1 + .../handlers/targets/target_service_test.go | 36 ++++++------ .../controller/handlers/users/user_service.go | 1 + .../handlers/users/user_service_test.go | 27 +++++---- internal/types/action/action.go | 3 + internal/types/action/action_test.go | 4 ++ .../docs/common-workflows/manage-roles.mdx | 4 +- .../docs/concepts/security/permissions.mdx | 15 +++++ 33 files changed, 253 insertions(+), 206 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1ab0eea00..ccafe151ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,23 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. ### New and Improved -* cli/api/sdk: New User's attributes for: +* actions: The new `no-op` action allows a grant to be given to a principals + without conveying any actionable result. Since resources do not appear in list + results if the principal has no actions granted on that resource, this can be + used to allow principals to see values in list results without also giving + `read` or other capabilities on the resources. The default scope permissions + have been updated to convey `no-op,list` instead of `read,list`. + [PR](https://github.com/hashicorp/boundary/pull/1138) +* cli/api/sdk: User resources have new attributes for: * Primary Account ID * Login Name * Full Name * Email - These new user attributes correspond to attributes - from the user's primary auth method account. These attributes will be empty - when the user has no account in the primary auth method for their scope, or - there is no designated primary auth method for their scope. + These new user attributes correspond to attributes from the user's primary + auth method account. These attributes will be empty when the user has no + account in the primary auth method for their scope, or there is no designated + primary auth method for their scope. ### Bug Fixes diff --git a/internal/cmd/base/initial_resources.go b/internal/cmd/base/initial_resources.go index b2f2adc1fc..a951f307fa 100644 --- a/internal/cmd/base/initial_resources.go +++ b/internal/cmd/base/initial_resources.go @@ -59,7 +59,7 @@ func (b *Server) CreateInitialLoginRole(ctx context.Context) (*iam.Role, error) return nil, fmt.Errorf("error creating role for default generated grants: %w", err) } if _, err := iamRepo.AddRoleGrants(cancelCtx, role.PublicId, role.Version, []string{ - "id=*;type=scope;actions=list,read", + "id=*;type=scope;actions=list,no-op", "id=*;type=auth-method;actions=authenticate,list", "id={{account.id}};actions=read,change-password", }); err != nil { diff --git a/internal/iam/repository_scope.go b/internal/iam/repository_scope.go index b4ce107fce..7711b7e6da 100644 --- a/internal/iam/repository_scope.go +++ b/internal/iam/repository_scope.go @@ -296,7 +296,7 @@ func (r *Repository) CreateScope(ctx context.Context, s *Scope, userId string, o grants = append(grants, roleGrant) default: - roleGrant, err := NewRoleGrant(defaultRolePublicId, "id=*;type=scope;actions=list,read") + roleGrant, err := NewRoleGrant(defaultRolePublicId, "id=*;type=scope;actions=list,no-op") if err != nil { return errors.Wrap(err, op, errors.WithMsg("unable to create in memory role grant")) } diff --git a/internal/servers/controller/common/scopeids/scope_ids_test.go b/internal/servers/controller/common/scopeids/scope_ids_test.go index 71a9b940b3..cc01904a95 100644 --- a/internal/servers/controller/common/scopeids/scope_ids_test.go +++ b/internal/servers/controller/common/scopeids/scope_ids_test.go @@ -79,24 +79,24 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on global, no groups", - globalGrants: []string{"id=*;type=group;actions=list,read"}, + globalGrants: []string{"id=*;type=group;actions=list,no-op"}, projGrants: []string{"id=*;type=group;actions=read"}, recurseFrom: "global", }, { name: "perms on org, no groups", - orgGrants: []string{"id=*;type=group;actions=list,read"}, + orgGrants: []string{"id=*;type=group;actions=list,no-op"}, projGrants: []string{"id=*;type=group;actions=read"}, recurseFrom: "org", }, { name: "perms on project, no groups", - projGrants: []string{"id=*;type=group;actions=list,read"}, + projGrants: []string{"id=*;type=group;actions=list,no-op"}, recurseFrom: "project", }, { name: "perms on global, none in org", - globalGrants: []string{"id=*;type=group;actions=list,read"}, + globalGrants: []string{"id=*;type=group;actions=list,no-op"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, orgGroups: 3, @@ -106,7 +106,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on global, none in org, start at org", - globalGrants: []string{"id=*;type=group;actions=list,read"}, + globalGrants: []string{"id=*;type=group;actions=list,no-op"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, orgGroups: 3, @@ -116,7 +116,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on global, with org", - globalGrants: []string{"id=*;type=group;actions=list,read"}, + globalGrants: []string{"id=*;type=group;actions=list,no-op"}, orgGrants: []string{"id=*;type=group;actions=read"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, @@ -127,7 +127,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on global, with org, start at org", - globalGrants: []string{"id=*;type=group;actions=list,read"}, + globalGrants: []string{"id=*;type=group;actions=list,no-op"}, orgGrants: []string{"id=*;type=group;actions=read"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, @@ -138,7 +138,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on global, start at project", - globalGrants: []string{"id=*;type=group;actions=list,read"}, + globalGrants: []string{"id=*;type=group;actions=list,no-op"}, orgGrants: []string{"id=*;type=group;actions=read"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, @@ -159,7 +159,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on org, start at global, read on org", - orgGrants: []string{"id=*;type=group;actions=list,read"}, + orgGrants: []string{"id=*;type=group;actions=list,no-op"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, orgGroups: 3, @@ -169,7 +169,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on org, start at org", - orgGrants: []string{"id=*;type=group;actions=list,read"}, + orgGrants: []string{"id=*;type=group;actions=list,no-op"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, orgGroups: 3, @@ -179,7 +179,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on org, start at project", - orgGrants: []string{"id=*;type=group;actions=list,read"}, + orgGrants: []string{"id=*;type=group;actions=list,no-op"}, projGrants: []string{"id=*;type=group;actions=read"}, globalGroups: 1, orgGroups: 3, @@ -189,7 +189,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on proj", - projGrants: []string{"id=*;type=group;actions=list,read"}, + projGrants: []string{"id=*;type=group;actions=list,no-op"}, globalGroups: 1, orgGroups: 3, projGroups: 5, @@ -198,7 +198,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on proj, start at org", - projGrants: []string{"id=*;type=group;actions=list,read"}, + projGrants: []string{"id=*;type=group;actions=list,no-op"}, globalGroups: 1, orgGroups: 3, projGroups: 5, @@ -207,7 +207,7 @@ func TestListingScopeIds(t *testing.T) { }, { name: "perms on proj, start at global", - projGrants: []string{"id=*;type=group;actions=list,read"}, + projGrants: []string{"id=*;type=group;actions=list,no-op"}, globalGroups: 1, orgGroups: 3, projGroups: 5, diff --git a/internal/servers/controller/handlers/accounts/account_service.go b/internal/servers/controller/handlers/accounts/account_service.go index 97a4ee252b..8f0444e906 100644 --- a/internal/servers/controller/handlers/accounts/account_service.go +++ b/internal/servers/controller/handlers/accounts/account_service.go @@ -52,6 +52,7 @@ var ( // individual resources IdActions = map[auth.SubType]action.ActionSet{ auth.PasswordSubtype: { + action.NoOp, action.Read, action.Update, action.Delete, @@ -59,6 +60,7 @@ var ( action.ChangePassword, }, auth.OidcSubtype: { + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/accounts/account_service_test.go b/internal/servers/controller/handlers/accounts/account_service_test.go index 12f87e811a..2c1221f3ad 100644 --- a/internal/servers/controller/handlers/accounts/account_service_test.go +++ b/internal/servers/controller/handlers/accounts/account_service_test.go @@ -36,6 +36,7 @@ import ( var ( pwAuthorizedActions = []string{ + action.NoOp.String(), action.Read.String(), action.Update.String(), action.Delete.String(), @@ -43,6 +44,7 @@ var ( action.ChangePassword.String(), } oidcAuthorizedActions = []string{ + action.NoOp.String(), action.Read.String(), action.Update.String(), action.Delete.String(), diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go index 863d236e1b..076bb625f2 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go @@ -40,12 +40,14 @@ const ( var ( pwAuthorizedActions = []string{ + action.NoOp.String(), action.Read.String(), action.Update.String(), action.Delete.String(), action.Authenticate.String(), } oidcAuthorizedActions = []string{ + action.NoOp.String(), action.Read.String(), action.Update.String(), action.Delete.String(), diff --git a/internal/servers/controller/handlers/authmethods/oidc.go b/internal/servers/controller/handlers/authmethods/oidc.go index 45b08de683..6c96a94a8c 100644 --- a/internal/servers/controller/handlers/authmethods/oidc.go +++ b/internal/servers/controller/handlers/authmethods/oidc.go @@ -52,6 +52,7 @@ func init() { } IdActions[auth.OidcSubtype] = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/authmethods/password.go b/internal/servers/controller/handlers/authmethods/password.go index ef6253061c..56309c137b 100644 --- a/internal/servers/controller/handlers/authmethods/password.go +++ b/internal/servers/controller/handlers/authmethods/password.go @@ -33,6 +33,7 @@ func init() { } IdActions[auth.PasswordSubtype] = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/authtokens/authtoken_service.go b/internal/servers/controller/handlers/authtokens/authtoken_service.go index 632b9636d6..e08bff06d8 100644 --- a/internal/servers/controller/handlers/authtokens/authtoken_service.go +++ b/internal/servers/controller/handlers/authtokens/authtoken_service.go @@ -22,6 +22,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Delete, } diff --git a/internal/servers/controller/handlers/authtokens/authtoken_service_test.go b/internal/servers/controller/handlers/authtokens/authtoken_service_test.go index 26ca95805f..ad4f76c025 100644 --- a/internal/servers/controller/handlers/authtokens/authtoken_service_test.go +++ b/internal/servers/controller/handlers/authtokens/authtoken_service_test.go @@ -24,6 +24,8 @@ import ( "github.com/stretchr/testify/require" ) +var testAuthorizedActions = []string{"no-op", "read", "delete"} + func TestGet(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) @@ -53,7 +55,7 @@ func TestGet(t *testing.T) { ApproximateLastUsedTime: at.GetApproximateLastAccessTime().GetTimestamp(), ExpirationTime: at.GetExpirationTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: org.GetPublicId(), Type: scope.Org.String(), ParentScopeId: scope.Global.String()}, - AuthorizedActions: []string{"read", "delete"}, + AuthorizedActions: testAuthorizedActions, } cases := []struct { @@ -128,7 +130,7 @@ func TestList(t *testing.T) { ApproximateLastUsedTime: at.GetApproximateLastAccessTime().GetTimestamp(), ExpirationTime: at.GetExpirationTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, - AuthorizedActions: []string{"read", "delete"}, + AuthorizedActions: testAuthorizedActions, }) } @@ -147,7 +149,7 @@ func TestList(t *testing.T) { ApproximateLastUsedTime: at.GetApproximateLastAccessTime().GetTimestamp(), ExpirationTime: at.GetExpirationTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: orgWithSomeTokens.GetPublicId(), Type: scope.Org.String(), ParentScopeId: scope.Global.String()}, - AuthorizedActions: []string{"read", "delete"}, + AuthorizedActions: testAuthorizedActions, }) } @@ -166,7 +168,7 @@ func TestList(t *testing.T) { ApproximateLastUsedTime: at.GetApproximateLastAccessTime().GetTimestamp(), ExpirationTime: at.GetExpirationTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: orgWithOtherTokens.GetPublicId(), Type: scope.Org.String(), ParentScopeId: scope.Global.String()}, - AuthorizedActions: []string{"read", "delete"}, + AuthorizedActions: testAuthorizedActions, }) } diff --git a/internal/servers/controller/handlers/groups/group_service.go b/internal/servers/controller/handlers/groups/group_service.go index a41b0f4053..45153e772f 100644 --- a/internal/servers/controller/handlers/groups/group_service.go +++ b/internal/servers/controller/handlers/groups/group_service.go @@ -28,6 +28,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/groups/group_service_test.go b/internal/servers/controller/handlers/groups/group_service_test.go index 88a4fc740e..333b4163b5 100644 --- a/internal/servers/controller/handlers/groups/group_service_test.go +++ b/internal/servers/controller/handlers/groups/group_service_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/golang/protobuf/ptypes" "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" @@ -23,12 +22,15 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +var testAuthorizedActions = []string{"no-op", "read", "update", "delete", "add-members", "set-members", "remove-members"} + // Creates an org scoped group and a project scoped group. func createDefaultGroupsAndRepo(t *testing.T) (*iam.Group, *iam.Group, func() (*iam.Repository, error)) { t.Helper() @@ -106,7 +108,7 @@ func TestGet(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, } wantProjGroup := &pb.Group{ @@ -125,7 +127,7 @@ func TestGet(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, } cases := []struct { @@ -227,7 +229,7 @@ func TestList(t *testing.T) { CreatedTime: og.GetCreateTime().GetTimestamp(), UpdatedTime: og.GetUpdateTime().GetTimestamp(), Version: 1, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }) totalGroups = append(totalGroups, wantOrgGroups[i]) pg := iam.TestGroup(t, conn, pWithGroups.GetPublicId()) @@ -238,7 +240,7 @@ func TestList(t *testing.T) { CreatedTime: pg.GetCreateTime().GetTimestamp(), UpdatedTime: pg.GetUpdateTime().GetTimestamp(), Version: 1, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }) totalGroups = append(totalGroups, wantProjGroups[i]) } @@ -425,8 +427,7 @@ func TestDelete_twice(t *testing.T) { func TestCreate(t *testing.T) { defaultOGroup, defaultPGroup, repoFn := createDefaultGroupsAndRepo(t) - defaultCreated, err := ptypes.Timestamp(defaultOGroup.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Error converting proto to timestamp.") + defaultCreated := defaultOGroup.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.CreateGroupRequest{} cases := []struct { @@ -450,7 +451,7 @@ func TestCreate(t *testing.T) { Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -469,7 +470,7 @@ func TestCreate(t *testing.T) { Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -490,7 +491,7 @@ func TestCreate(t *testing.T) { Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -505,7 +506,7 @@ func TestCreate(t *testing.T) { { name: "Can't specify Created Time", req: &pbs.CreateGroupRequest{Item: &pb.Group{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -513,7 +514,7 @@ func TestCreate(t *testing.T) { { name: "Can't specify Update Time", req: &pbs.CreateGroupRequest{Item: &pb.Group{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -536,10 +537,8 @@ func TestCreate(t *testing.T) { if got != nil { assert.Contains(got.GetUri(), tc.res.Uri) assert.True(strings.HasPrefix(got.GetItem().GetId(), iam.GroupPrefix+"_")) - gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime()) - require.NoError(err, "Error converting proto to timestamp.") - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) - require.NoError(err, "Error converting proto to timestamp.") + gotCreateTime := got.GetItem().GetCreatedTime().AsTime() + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() // Verify it is a group created after the test setup's default group assert.True(gotCreateTime.After(defaultCreated), "New group should have been created after default group. Was created %v, which is after %v", gotCreateTime, defaultCreated) assert.True(gotUpdateTime.After(defaultCreated), "New group should have been updated after default group. Was updated %v, which is after %v", gotUpdateTime, defaultCreated) @@ -590,8 +589,7 @@ func TestUpdate(t *testing.T) { } } - created, err := ptypes.Timestamp(og.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Error converting proto to timestamp") + created := og.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.UpdateGroupRequest{ Id: og.GetPublicId(), } @@ -632,7 +630,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -663,7 +661,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -695,7 +693,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -727,7 +725,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -790,7 +788,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -821,7 +819,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -852,7 +850,7 @@ func TestUpdate(t *testing.T) { ScopeId: u.GetScopeId(), }, }, - AuthorizedActions: []string{"read", "update", "delete", "add-members", "set-members", "remove-members"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -893,7 +891,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"created_time"}, }, Item: &pb.Group{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }, }, res: nil, @@ -906,7 +904,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"updated_time"}, }, Item: &pb.Group{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }, }, res: nil, @@ -946,8 +944,7 @@ func TestUpdate(t *testing.T) { if got != nil { assert.NotNilf(tc.res, "Expected UpdateGroup response to be nil, but was %v", got) - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) - require.NoError(err, "Error converting proto to timestamp") + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() // Verify it is a group updated after it was created assert.True(gotUpdateTime.After(created), "Updated group should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, created) 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 f58c37a49a..e0b176331c 100644 --- a/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go +++ b/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go @@ -32,6 +32,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, 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 9760050972..54062e8e69 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 @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/wrappers" "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/auth" @@ -27,6 +26,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/structpb" + "google.golang.org/protobuf/types/known/timestamppb" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -47,6 +47,8 @@ var authorizedCollectionActions = map[string]*structpb.ListValue{ }, } +var testAuthorizedActions = []string{"no-op", "read", "update", "delete"} + func createDefaultHostCatalogAndRepo(t *testing.T) (*static.HostCatalog, *iam.Scope, common.StaticRepoFactory, common.IamRepoFactory) { t.Helper() require := require.New(t) @@ -90,7 +92,7 @@ func TestGet(t *testing.T) { CreatedTime: hc.CreateTime.GetTimestamp(), UpdatedTime: hc.UpdateTime.GetTimestamp(), Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, } @@ -174,7 +176,7 @@ func TestList(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: pWithCatalogs.GetPublicId(), Type: scope.Project.String(), ParentScopeId: oWithCatalogs.GetPublicId()}, Version: 1, Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }) } @@ -189,7 +191,7 @@ func TestList(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: pWithOtherCatalogs.GetPublicId(), Type: scope.Project.String(), ParentScopeId: oWithOtherCatalogs.GetPublicId()}, Version: 1, Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }) } @@ -340,8 +342,7 @@ func TestDelete_twice(t *testing.T) { func TestCreate(t *testing.T) { t.Parallel() defaultHc, proj, repo, iamRepoFn := createDefaultHostCatalogAndRepo(t) - defaultHcCreated, err := ptypes.Timestamp(defaultHc.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Error converting proto to timestamp.") + defaultHcCreated := defaultHc.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.CreateHostCatalogRequest{} cases := []struct { @@ -366,7 +367,7 @@ func TestCreate(t *testing.T) { Name: &wrappers.StringValue{Value: "name"}, Description: &wrappers.StringValue{Value: "desc"}, Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, }, @@ -419,7 +420,7 @@ func TestCreate(t *testing.T) { { name: "Can't specify Created Time", req: &pbs.CreateHostCatalogRequest{Item: &pb.HostCatalog{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -427,7 +428,7 @@ func TestCreate(t *testing.T) { { name: "Can't specify Update Time", req: &pbs.CreateHostCatalogRequest{Item: &pb.HostCatalog{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -450,9 +451,9 @@ func TestCreate(t *testing.T) { if got != nil { assert.Contains(got.GetUri(), tc.res.GetUri()) assert.True(strings.HasPrefix(got.GetItem().GetId(), static.HostCatalogPrefix)) - gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime()) + gotCreateTime := got.GetItem().GetCreatedTime().AsTime() require.NoError(err, "Error converting proto to timestamp.") - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() require.NoError(err, "Error converting proto to timestamp") // Verify it is a catalog created after the test setup's default catalog assert.True(gotCreateTime.After(defaultHcCreated), "New catalog should have been created after default catalog. Was created %v, which is after %v", gotCreateTime, defaultHcCreated) @@ -488,8 +489,7 @@ func TestUpdate(t *testing.T) { version++ } - hcCreated, err := ptypes.Timestamp(hc.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Failed to convert proto to timestamp") + hcCreated := hc.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.UpdateHostCatalogRequest{ Id: hc.GetPublicId(), } @@ -521,7 +521,7 @@ func TestUpdate(t *testing.T) { Description: &wrappers.StringValue{Value: "desc"}, CreatedTime: hc.GetCreateTime().GetTimestamp(), Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, }, @@ -547,7 +547,7 @@ func TestUpdate(t *testing.T) { Description: &wrappers.StringValue{Value: "desc"}, CreatedTime: hc.GetCreateTime().GetTimestamp(), Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, }, @@ -602,7 +602,7 @@ func TestUpdate(t *testing.T) { Description: &wrappers.StringValue{Value: "default"}, CreatedTime: hc.GetCreateTime().GetTimestamp(), Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, }, @@ -625,7 +625,7 @@ func TestUpdate(t *testing.T) { Name: &wrappers.StringValue{Value: "default"}, CreatedTime: hc.GetCreateTime().GetTimestamp(), Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, }, @@ -650,7 +650,7 @@ func TestUpdate(t *testing.T) { Description: &wrappers.StringValue{Value: "default"}, CreatedTime: hc.GetCreateTime().GetTimestamp(), Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, }, @@ -675,7 +675,7 @@ func TestUpdate(t *testing.T) { Description: &wrappers.StringValue{Value: "notignored"}, CreatedTime: hc.GetCreateTime().GetTimestamp(), Type: "static", - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, }, @@ -732,7 +732,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"created_time"}, }, Item: &pb.HostCatalog{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }, }, res: nil, @@ -745,7 +745,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"updated_time"}, }, Item: &pb.HostCatalog{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }, }, res: nil, @@ -794,7 +794,7 @@ func TestUpdate(t *testing.T) { if got != nil { assert.NotNilf(tc.res, "Expected UpdateHostCatalog response to be nil, but was %v", got) - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() require.NoError(err, "Failed to convert proto to timestamp") // Verify it is a catalog updated after it was created // TODO: This is currently failing. 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 b8240fa175..f3a32e7edc 100644 --- a/internal/servers/controller/handlers/host_sets/host_set_service.go +++ b/internal/servers/controller/handlers/host_sets/host_set_service.go @@ -27,6 +27,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, 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 88e7985d32..6eeaf1a8c2 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 @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/wrappers" "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/auth" @@ -29,8 +28,11 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/timestamppb" ) +var testAuthorizedActions = []string{"no-op", "read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"} + func TestGet(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") @@ -65,7 +67,7 @@ func TestGet(t *testing.T) { Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String(), ParentScopeId: org.GetPublicId()}, Type: "static", HostIds: hIds, - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, } cases := []struct { @@ -150,7 +152,7 @@ func TestList(t *testing.T) { UpdatedTime: h.GetUpdateTime().GetTimestamp(), Version: h.GetVersion(), Type: host.StaticSubtype.String(), - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }) } @@ -333,8 +335,7 @@ func TestCreate(t *testing.T) { } hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] - defaultHcCreated, err := ptypes.Timestamp(hc.GetCreateTime().GetTimestamp()) - require.NoError(t, err) + defaultHcCreated := hc.GetCreateTime().GetTimestamp().AsTime() cases := []struct { name string @@ -358,7 +359,7 @@ func TestCreate(t *testing.T) { Name: &wrappers.StringValue{Value: "name"}, Description: &wrappers.StringValue{Value: "desc"}, Type: "static", - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -387,7 +388,7 @@ func TestCreate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -404,7 +405,7 @@ func TestCreate(t *testing.T) { name: "Can't specify Created Time", req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ HostCatalogId: hc.GetPublicId(), - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -413,7 +414,7 @@ func TestCreate(t *testing.T) { name: "Can't specify Update Time", req: &pbs.CreateHostSetRequest{Item: &pb.HostSet{ HostCatalogId: hc.GetPublicId(), - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -434,9 +435,9 @@ func TestCreate(t *testing.T) { if got != nil { assert.Contains(got.GetUri(), tc.res.GetUri()) assert.True(strings.HasPrefix(got.GetItem().GetId(), static.HostSetPrefix), got.GetItem().GetId()) - gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime()) + gotCreateTime := got.GetItem().GetCreatedTime().AsTime() require.NoError(err, "Error converting proto to timestamp.") - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() require.NoError(err, "Error converting proto to timestamp") // Verify it is a set created after the test setup's default set assert.True(gotCreateTime.After(defaultHcCreated), "New set should have been created after default set. Was created %v, which is after %v", gotCreateTime, defaultHcCreated) @@ -496,8 +497,7 @@ func TestUpdate(t *testing.T) { version++ } - hCreated, err := ptypes.Timestamp(hs.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Failed to convert proto to timestamp") + hCreated := hs.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.UpdateHostSetRequest{ Id: hs.GetPublicId(), } @@ -533,7 +533,7 @@ func TestUpdate(t *testing.T) { CreatedTime: hs.GetCreateTime().GetTimestamp(), Type: "static", HostIds: hIds, - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -559,7 +559,7 @@ func TestUpdate(t *testing.T) { CreatedTime: hs.GetCreateTime().GetTimestamp(), Type: "static", HostIds: hIds, - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -628,7 +628,7 @@ func TestUpdate(t *testing.T) { CreatedTime: hs.GetCreateTime().GetTimestamp(), Type: "static", HostIds: hIds, - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -651,7 +651,7 @@ func TestUpdate(t *testing.T) { CreatedTime: hs.GetCreateTime().GetTimestamp(), Type: "static", HostIds: hIds, - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -676,7 +676,7 @@ func TestUpdate(t *testing.T) { CreatedTime: hs.GetCreateTime().GetTimestamp(), Type: "static", HostIds: hIds, - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -701,7 +701,7 @@ func TestUpdate(t *testing.T) { CreatedTime: hs.GetCreateTime().GetTimestamp(), Type: "static", HostIds: hIds, - AuthorizedActions: []string{"read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -744,7 +744,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"created_time"}, }, Item: &pb.HostSet{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }, }, res: nil, @@ -757,7 +757,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"updated_time"}, }, Item: &pb.HostSet{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }, }, res: nil, @@ -806,8 +806,7 @@ func TestUpdate(t *testing.T) { if got != nil { assert.NotNilf(tc.res, "Expected UpdateHost response to be nil, but was %v", got) - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) - require.NoError(err, "Failed to convert proto to timestamp") + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() // Verify it is a set updated after it was created // TODO: This is currently failing. assert.True(gotUpdateTime.After(hCreated), "Updated set should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, hCreated) diff --git a/internal/servers/controller/handlers/hosts/host_service.go b/internal/servers/controller/handlers/hosts/host_service.go index 49052ec65d..a5521e5ac9 100644 --- a/internal/servers/controller/handlers/hosts/host_service.go +++ b/internal/servers/controller/handlers/hosts/host_service.go @@ -28,6 +28,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/hosts/host_service_test.go b/internal/servers/controller/handlers/hosts/host_service_test.go index 328ec00e34..2a35d40147 100644 --- a/internal/servers/controller/handlers/hosts/host_service_test.go +++ b/internal/servers/controller/handlers/hosts/host_service_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/wrappers" "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/auth" @@ -29,8 +28,11 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/structpb" + "google.golang.org/protobuf/types/known/timestamppb" ) +var testAuthorizedActions = []string{"no-op", "read", "update", "delete"} + func TestGet(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") @@ -61,7 +63,7 @@ func TestGet(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue(h.GetAddress()), }}, - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, } cases := []struct { @@ -145,7 +147,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"}, + AuthorizedActions: testAuthorizedActions, }) } @@ -320,8 +322,7 @@ func TestCreate(t *testing.T) { } hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] - defaultHcCreated, err := ptypes.Timestamp(hc.GetCreateTime().GetTimestamp()) - require.NoError(t, err) + defaultHcCreated := hc.GetCreateTime().GetTimestamp().AsTime() cases := []struct { name string @@ -351,7 +352,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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -410,7 +411,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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -427,7 +428,7 @@ func TestCreate(t *testing.T) { name: "Can't specify Created Time", req: &pbs.CreateHostRequest{Item: &pb.Host{ HostCatalogId: hc.GetPublicId(), - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -435,7 +436,7 @@ func TestCreate(t *testing.T) { { name: "Can't specify Update Time", req: &pbs.CreateHostRequest{Item: &pb.Host{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -455,10 +456,8 @@ func TestCreate(t *testing.T) { if got != nil { assert.Contains(got.GetUri(), tc.res.GetUri()) assert.True(strings.HasPrefix(got.GetItem().GetId(), static.HostPrefix)) - gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime()) - require.NoError(err, "Error converting proto to timestamp.") - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) - require.NoError(err, "Error converting proto to timestamp") + gotCreateTime := got.GetItem().GetCreatedTime().AsTime() + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() // Verify it is a set created after the test setup's default set assert.True(gotCreateTime.After(defaultHcCreated), "New host should have been created after default host. Was created %v, which is after %v", gotCreateTime, defaultHcCreated) assert.True(gotUpdateTime.After(defaultHcCreated), "New host should have been updated after default host. Was updated %v, which is after %v", gotUpdateTime, defaultHcCreated) @@ -512,8 +511,7 @@ func TestUpdate(t *testing.T) { version++ } - hCreated, err := ptypes.Timestamp(h.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Failed to convert proto to timestamp") + hCreated := h.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.UpdateHostRequest{ Id: h.GetPublicId(), } @@ -551,7 +549,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -579,7 +577,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -649,7 +647,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -674,7 +672,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -701,7 +699,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -728,7 +726,7 @@ func TestUpdate(t *testing.T) { Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ "address": structpb.NewStringValue("defaultaddress"), }}, - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -803,7 +801,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"created_time"}, }, Item: &pb.Host{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }, }, res: nil, @@ -816,7 +814,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"updated_time"}, }, Item: &pb.Host{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }, }, res: nil, @@ -865,8 +863,7 @@ func TestUpdate(t *testing.T) { if got != nil { assert.NotNilf(tc.res, "Expected UpdateHost response to be nil, but was %v", got) - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) - require.NoError(err, "Failed to convert proto to timestamp") + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() // Verify it is a set updated after it was created // TODO: This is currently failing. assert.True(gotUpdateTime.After(hCreated), "Updated set should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, hCreated) diff --git a/internal/servers/controller/handlers/roles/role_service.go b/internal/servers/controller/handlers/roles/role_service.go index 0451eb6897..a11deffbd0 100644 --- a/internal/servers/controller/handlers/roles/role_service.go +++ b/internal/servers/controller/handlers/roles/role_service.go @@ -28,6 +28,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/roles/role_service_test.go b/internal/servers/controller/handlers/roles/role_service_test.go index 1d736e244f..b04f532944 100644 --- a/internal/servers/controller/handlers/roles/role_service_test.go +++ b/internal/servers/controller/handlers/roles/role_service_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/golang/protobuf/ptypes" "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" @@ -24,12 +23,15 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +var testAuthorizedActions = []string{"no-op", "read", "update", "delete", "add-principals", "set-principals", "remove-principals", "add-grants", "set-grants", "remove-grants"} + func createDefaultRolesAndRepo(t *testing.T) (*iam.Role, *iam.Role, func() (*iam.Repository, error)) { t.Helper() conn, _ := db.TestSetup(t, "postgres") @@ -86,7 +88,7 @@ func TestGet(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, } wantProjRole := &pb.Role{ @@ -99,7 +101,7 @@ func TestGet(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, } cases := []struct { @@ -201,7 +203,7 @@ func TestList(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }) totalRoles = append(totalRoles, wantOrgRoles[i]) pr := iam.TestRole(t, conn, pWithRoles.GetPublicId()) @@ -213,7 +215,7 @@ func TestList(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }) totalRoles = append(totalRoles, wantProjRoles[i]) } @@ -400,8 +402,7 @@ func TestDelete_twice(t *testing.T) { func TestCreate(t *testing.T) { defaultOrgRole, defaultProjRole, repoFn := createDefaultRolesAndRepo(t) - defaultCreated, err := ptypes.Timestamp(defaultOrgRole.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Error converting proto to timestamp.") + defaultCreated := defaultOrgRole.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.CreateRoleRequest{} cases := []struct { @@ -427,7 +428,7 @@ func TestCreate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -448,7 +449,7 @@ func TestCreate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -470,7 +471,7 @@ func TestCreate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -500,7 +501,7 @@ func TestCreate(t *testing.T) { name: "Can't specify Created Time", req: &pbs.CreateRoleRequest{Item: &pb.Role{ ScopeId: defaultProjRole.GetScopeId(), - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -509,7 +510,7 @@ func TestCreate(t *testing.T) { name: "Can't specify Update Time", req: &pbs.CreateRoleRequest{Item: &pb.Role{ ScopeId: defaultProjRole.GetScopeId(), - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -532,10 +533,8 @@ func TestCreate(t *testing.T) { if got != nil { assert.Contains(got.GetUri(), tc.res.Uri) assert.True(strings.HasPrefix(got.GetItem().GetId(), iam.RolePrefix+"_"), "Expected %q to have the prefix %q", got.GetItem().GetId(), iam.RolePrefix+"_") - gotCreateTime, err := ptypes.Timestamp(got.GetItem().GetCreatedTime()) - require.NoError(err, "Error converting proto to timestamp.") - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) - require.NoError(err, "Error converting proto to timestamp.") + gotCreateTime := got.GetItem().GetCreatedTime().AsTime() + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() // Verify it is a role created after the test setup's default role assert.True(gotCreateTime.After(defaultCreated), "New role should have been created after default role. Was created %v, which is after %v", gotCreateTime, defaultCreated) assert.True(gotUpdateTime.After(defaultCreated), "New role should have been updated after default role. Was updated %v, which is after %v", gotUpdateTime, defaultCreated) @@ -610,8 +609,7 @@ func TestUpdate(t *testing.T) { } } - created, err := ptypes.Timestamp(or.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Error converting proto to timestamp") + created := or.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.UpdateRoleRequest{ Id: or.GetPublicId(), } @@ -649,7 +647,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -678,7 +676,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -708,7 +706,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -738,7 +736,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -799,7 +797,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -828,7 +826,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -857,7 +855,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -897,7 +895,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"created_time"}, }, Item: &pb.Role{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }, }, res: nil, @@ -910,7 +908,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"updated_time"}, }, Item: &pb.Role{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }, }, res: nil, @@ -976,7 +974,7 @@ func TestUpdate(t *testing.T) { if got != nil { assert.NotNilf(tc.res, "Expected UpdateRole response to be nil, but was %v", got) - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() require.NoError(err, "Error converting proto to timestamp") // Verify it is a role updated after it was created assert.True(gotUpdateTime.After(created), "Updated role should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, created) diff --git a/internal/servers/controller/handlers/scopes/scope_service.go b/internal/servers/controller/handlers/scopes/scope_service.go index 5547011c5a..3e4af80998 100644 --- a/internal/servers/controller/handlers/scopes/scope_service.go +++ b/internal/servers/controller/handlers/scopes/scope_service.go @@ -41,6 +41,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/scopes/scope_service_test.go b/internal/servers/controller/handlers/scopes/scope_service_test.go index 3e78c86e3d..da546bb30b 100644 --- a/internal/servers/controller/handlers/scopes/scope_service_test.go +++ b/internal/servers/controller/handlers/scopes/scope_service_test.go @@ -29,6 +29,8 @@ import ( "github.com/stretchr/testify/require" ) +var testAuthorizedActions = []string{"no-op", "read", "update", "delete"} + func createDefaultScopesAndRepo(t *testing.T) (*iam.Scope, *iam.Scope, func() (*iam.Repository, error)) { t.Helper() conn, _ := db.TestSetup(t, "postgres") @@ -185,7 +187,7 @@ func TestGet(t *testing.T) { UpdatedTime: org.UpdateTime.GetTimestamp(), Version: 2, Type: scope.Org.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: orgAuthorizedCollectionActions, } @@ -199,7 +201,7 @@ func TestGet(t *testing.T) { UpdatedTime: proj.UpdateTime.GetTimestamp(), Version: 2, Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, } @@ -292,11 +294,11 @@ func TestList(t *testing.T) { globalScope := &pb.ScopeInfo{Id: "global", Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"} oNoProjectsProto := scopes.ToProto(oNoProjects) oNoProjectsProto.Scope = globalScope - oNoProjectsProto.AuthorizedActions = []string{"read", "update", "delete"} + oNoProjectsProto.AuthorizedActions = testAuthorizedActions oNoProjectsProto.AuthorizedCollectionActions = orgAuthorizedCollectionActions oWithProjectsProto := scopes.ToProto(oWithProjects) oWithProjectsProto.Scope = globalScope - oWithProjectsProto.AuthorizedActions = []string{"read", "update", "delete"} + oWithProjectsProto.AuthorizedActions = testAuthorizedActions oWithProjectsProto.AuthorizedCollectionActions = orgAuthorizedCollectionActions initialOrgs = append(initialOrgs, oNoProjectsProto, oWithProjectsProto) scopes.SortScopes(initialOrgs) @@ -373,7 +375,7 @@ func TestList(t *testing.T) { UpdatedTime: o.GetUpdateTime().GetTimestamp(), Version: 1, Type: scope.Org.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: orgAuthorizedCollectionActions, }) } @@ -394,7 +396,7 @@ func TestList(t *testing.T) { UpdatedTime: p.GetUpdateTime().GetTimestamp(), Version: 1, Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }) } @@ -619,7 +621,7 @@ func TestCreate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, @@ -643,7 +645,7 @@ func TestCreate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, Type: scope.Org.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: orgAuthorizedCollectionActions, }, }, @@ -666,7 +668,7 @@ func TestCreate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, @@ -689,7 +691,7 @@ func TestCreate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, Type: scope.Org.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: orgAuthorizedCollectionActions, }, }, @@ -918,7 +920,7 @@ func TestUpdate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, CreatedTime: proj.GetCreateTime().GetTimestamp(), Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, @@ -945,7 +947,7 @@ func TestUpdate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, CreatedTime: org.GetCreateTime().GetTimestamp(), Type: scope.Org.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: orgAuthorizedCollectionActions, }, }, @@ -971,7 +973,7 @@ func TestUpdate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, CreatedTime: global.GetCreateTime().GetTimestamp(), Type: scope.Global.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: globalAuthorizedCollectionActions, }, }, @@ -997,7 +999,7 @@ func TestUpdate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "desc"}, CreatedTime: proj.GetCreateTime().GetTimestamp(), Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, @@ -1070,7 +1072,7 @@ func TestUpdate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "defaultProj"}, CreatedTime: proj.GetCreateTime().GetTimestamp(), Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, @@ -1094,7 +1096,7 @@ func TestUpdate(t *testing.T) { Name: &wrappers.StringValue{Value: "defaultProj"}, CreatedTime: proj.GetCreateTime().GetTimestamp(), Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, @@ -1120,7 +1122,7 @@ func TestUpdate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "defaultProj"}, CreatedTime: proj.GetCreateTime().GetTimestamp(), Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, @@ -1146,7 +1148,7 @@ func TestUpdate(t *testing.T) { Description: &wrapperspb.StringValue{Value: "notignored"}, CreatedTime: proj.GetCreateTime().GetTimestamp(), Type: scope.Project.String(), - AuthorizedActions: []string{"read", "update", "delete"}, + AuthorizedActions: testAuthorizedActions, AuthorizedCollectionActions: projectAuthorizedCollectionActions, }, }, diff --git a/internal/servers/controller/handlers/sessions/session_service.go b/internal/servers/controller/handlers/sessions/session_service.go index 88692d4bf5..97e12f9cc7 100644 --- a/internal/servers/controller/handlers/sessions/session_service.go +++ b/internal/servers/controller/handlers/sessions/session_service.go @@ -24,6 +24,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.ReadSelf, action.Cancel, diff --git a/internal/servers/controller/handlers/sessions/session_service_test.go b/internal/servers/controller/handlers/sessions/session_service_test.go index a5421882cb..d4c330a3d7 100644 --- a/internal/servers/controller/handlers/sessions/session_service_test.go +++ b/internal/servers/controller/handlers/sessions/session_service_test.go @@ -31,6 +31,8 @@ import ( "google.golang.org/protobuf/testing/protocmp" ) +var testAuthorizedActions = []string{"no-op", "read", "read:self", "cancel", "cancel:self"} + func TestGetSession(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrap := db.TestWrapper(t) @@ -86,7 +88,7 @@ func TestGetSession(t *testing.T) { States: []*pb.SessionState{{Status: session.StatusPending.String(), StartTime: sess.CreateTime.GetTimestamp()}}, Certificate: sess.Certificate, Type: target.TcpSubType.String(), - AuthorizedActions: []string{"read", "read:self", "cancel", "cancel:self"}, + AuthorizedActions: testAuthorizedActions, } cases := []struct { @@ -299,7 +301,7 @@ func TestList(t *testing.T) { States: states, Certificate: sess.Certificate, Type: target.TcpSubType.String(), - AuthorizedActions: []string{"read", "read:self", "cancel", "cancel:self"}, + AuthorizedActions: testAuthorizedActions, }) totalSession = append(totalSession, wantSession[i]) @@ -334,7 +336,7 @@ func TestList(t *testing.T) { States: states, Certificate: sess.Certificate, Type: target.TcpSubType.String(), - AuthorizedActions: []string{"read", "read:self", "cancel", "cancel:self"}, + AuthorizedActions: testAuthorizedActions, }) } @@ -477,7 +479,7 @@ func TestCancel(t *testing.T) { Status: session.StatusCanceling.String(), Certificate: sess.Certificate, Type: target.TcpSubType.String(), - AuthorizedActions: []string{"read", "read:self", "cancel", "cancel:self"}, + AuthorizedActions: testAuthorizedActions, } version := wireSess.GetVersion() diff --git a/internal/servers/controller/handlers/targets/target_service.go b/internal/servers/controller/handlers/targets/target_service.go index de3d6e4bcd..8407119c7c 100644 --- a/internal/servers/controller/handlers/targets/target_service.go +++ b/internal/servers/controller/handlers/targets/target_service.go @@ -44,6 +44,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/targets/target_service_test.go b/internal/servers/controller/handlers/targets/target_service_test.go index 07e8cff43f..67b79df6fe 100644 --- a/internal/servers/controller/handlers/targets/target_service_test.go +++ b/internal/servers/controller/handlers/targets/target_service_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "github.com/golang/protobuf/ptypes" "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" @@ -33,9 +32,12 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/structpb" + "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" ) +var testAuthorizedActions = []string{"no-op", "read", "update", "delete", "add-host-sets", "set-host-sets", "remove-host-sets", "authorize-session"} + func testService(t *testing.T, conn *gorm.DB, kms *kms.Kms, wrapper wrapping.Wrapper) (targets.Service, error) { rw := db.New(conn) repoFn := func() (*target.Repository, error) { @@ -86,7 +88,7 @@ func TestGet(t *testing.T) { Attributes: new(structpb.Struct), SessionMaxSeconds: wrapperspb.UInt32(28800), SessionConnectionLimit: wrapperspb.Int32(1), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, } for _, ihs := range hs { pTar.HostSets = append(pTar.HostSets, &pb.HostSet{Id: ihs.GetPublicId(), HostCatalogId: ihs.GetCatalogId()}) @@ -178,7 +180,7 @@ func TestList(t *testing.T) { Attributes: new(structpb.Struct), SessionMaxSeconds: wrapperspb.UInt32(28800), SessionConnectionLimit: wrapperspb.Int32(1), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, }) totalTars = append(totalTars, wantTars[i]) tar = target.TestTcpTarget(t, conn, otherProj.GetPublicId(), name, target.WithHostSets([]string{otherHss[0].GetPublicId(), otherHss[1].GetPublicId()})) @@ -194,7 +196,7 @@ func TestList(t *testing.T) { Attributes: new(structpb.Struct), SessionMaxSeconds: wrapperspb.UInt32(28800), SessionConnectionLimit: wrapperspb.Int32(1), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, }) } @@ -388,7 +390,7 @@ func TestCreate(t *testing.T) { }}, SessionMaxSeconds: wrapperspb.UInt32(28800), SessionConnectionLimit: wrapperspb.Int32(1), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, WorkerFilter: wrapperspb.String(`type == "bar"`), }, }, @@ -433,7 +435,7 @@ func TestCreate(t *testing.T) { { name: "Can't specify Created Time", req: &pbs.CreateTargetRequest{Item: &pb.Target{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -441,7 +443,7 @@ func TestCreate(t *testing.T) { { name: "Can't specify Update Time", req: &pbs.CreateTargetRequest{Item: &pb.Target{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }}, res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -531,8 +533,7 @@ func TestUpdate(t *testing.T) { version++ } - hCreated, err := ptypes.Timestamp(tar.GetCreateTime().GetTimestamp()) - require.NoError(t, err, "Failed to convert proto to timestamp") + hCreated := tar.GetCreateTime().GetTimestamp().AsTime() toMerge := &pbs.UpdateTargetRequest{ Id: tar.GetPublicId(), } @@ -576,7 +577,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -608,7 +609,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -693,7 +694,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -724,7 +725,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -755,7 +756,7 @@ func TestUpdate(t *testing.T) { HostSets: hostSets, SessionMaxSeconds: wrapperspb.UInt32(3600), SessionConnectionLimit: wrapperspb.Int32(5), - AuthorizedActions: targets.IdActions.Strings(), + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -798,7 +799,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"created_time"}, }, Item: &pb.Target{ - CreatedTime: ptypes.TimestampNow(), + CreatedTime: timestamppb.Now(), }, }, res: nil, @@ -811,7 +812,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"updated_time"}, }, Item: &pb.Target{ - UpdatedTime: ptypes.TimestampNow(), + UpdatedTime: timestamppb.Now(), }, }, res: nil, @@ -838,8 +839,7 @@ func TestUpdate(t *testing.T) { if got != nil { assert.NotNilf(tc.res, "Expected UpdateHost response to be nil, but was %v", got) - gotUpdateTime, err := ptypes.Timestamp(got.GetItem().GetUpdatedTime()) - require.NoError(err, "Failed to convert proto to timestamp") + gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() // Verify it is a set updated after it was created // TODO: This is currently failing. assert.True(gotUpdateTime.After(hCreated), "Updated target should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, hCreated) diff --git a/internal/servers/controller/handlers/users/user_service.go b/internal/servers/controller/handlers/users/user_service.go index f6eef1c4ca..9b4d816232 100644 --- a/internal/servers/controller/handlers/users/user_service.go +++ b/internal/servers/controller/handlers/users/user_service.go @@ -30,6 +30,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ + action.NoOp, action.Read, action.Update, action.Delete, diff --git a/internal/servers/controller/handlers/users/user_service_test.go b/internal/servers/controller/handlers/users/user_service_test.go index 0ce9700206..fd07293a44 100644 --- a/internal/servers/controller/handlers/users/user_service_test.go +++ b/internal/servers/controller/handlers/users/user_service_test.go @@ -32,6 +32,8 @@ import ( "github.com/stretchr/testify/require" ) +var testAuthorizedActions = []string{"no-op", "read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"} + func createDefaultUserAndRepo(t *testing.T, withAccts bool) (*iam.User, []string, func() (*iam.Repository, error)) { t.Helper() conn, _ := db.TestSetup(t, "postgres") @@ -92,7 +94,7 @@ func TestGet(t *testing.T) { CreatedTime: u.CreateTime.GetTimestamp(), UpdatedTime: u.UpdateTime.GetTimestamp(), Version: u.Version, - AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, + AuthorizedActions: testAuthorizedActions, LoginName: u.LoginName, FullName: u.GetFullName(), Email: u.GetEmail(), @@ -216,7 +218,7 @@ func TestList(t *testing.T) { CreatedTime: u.GetCreateTime().GetTimestamp(), UpdatedTime: u.GetUpdateTime().GetTimestamp(), Version: 2, - AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, + AuthorizedActions: testAuthorizedActions, LoginName: oidcAcct.GetSubject(), FullName: oidcAcct.GetFullName(), Email: oidcAcct.GetEmail(), @@ -396,7 +398,7 @@ func TestCreate(t *testing.T) { Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, - AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -415,7 +417,7 @@ func TestCreate(t *testing.T) { Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "desc"}, Version: 1, - AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -523,7 +525,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -546,7 +548,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -599,7 +601,7 @@ func TestUpdate(t *testing.T) { Scope: &scopes.ScopeInfo{Id: u.GetScopeId(), Type: scope.Org.String(), ParentScopeId: scope.Global.String()}, Description: &wrapperspb.StringValue{Value: "default"}, CreatedTime: u.GetCreateTime().GetTimestamp(), - AuthorizedActions: []string{"read", "update", "delete", "add-accounts", "set-accounts", "remove-accounts"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -622,7 +624,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -645,7 +647,7 @@ func TestUpdate(t *testing.T) { 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"}, + AuthorizedActions: testAuthorizedActions, }, }, }, @@ -981,7 +983,8 @@ func TestSetAccount(t *testing.T) { t.Run(tc.name, func(t *testing.T) { usr := iam.TestUser(t, iamRepo, o.GetPublicId()) defer func() { - _, _ = iamRepo.DeleteUser(context.Background(), usr.GetPublicId()) + _, err := iamRepo.DeleteUser(context.Background(), usr.GetPublicId()) + require.NoError(t, err) }() tc.setup(usr) @@ -1060,7 +1063,6 @@ func TestRemoveAccount(t *testing.T) { databaseWrapper, err := kmsCache.GetWrapper(context.Background(), o.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) - oidcAm := oidc.TestAuthMethod( t, conn, databaseWrapper, o.PublicId, oidc.ActivePrivateState, "alice-rp", "fido", @@ -1143,7 +1145,8 @@ func TestRemoveAccount(t *testing.T) { t.Run(tc.name, func(t *testing.T) { usr := iam.TestUser(t, iamRepo, o.GetPublicId()) defer func() { - _, _ = iamRepo.DeleteUser(context.Background(), usr.GetPublicId()) + _, err := iamRepo.DeleteUser(context.Background(), usr.GetPublicId()) + require.NoError(t, err) }() tc.setup(usr) req := &pbs.RemoveUserAccountsRequest{ diff --git a/internal/types/action/action.go b/internal/types/action/action.go index 1869627d5f..b6edf97f19 100644 --- a/internal/types/action/action.go +++ b/internal/types/action/action.go @@ -40,6 +40,7 @@ const ( ReadSelf Type = 31 CancelSelf Type = 32 ChangeState Type = 33 + NoOp Type = 34 ) var Map = map[string]Type{ @@ -76,6 +77,7 @@ var Map = map[string]Type{ ReadSelf.String(): ReadSelf, CancelSelf.String(): CancelSelf, ChangeState.String(): ChangeState, + NoOp.String(): NoOp, } func (a Type) String() string { @@ -114,6 +116,7 @@ func (a Type) String() string { "read:self", "cancel:self", "change-state", + "no-op", }[a] } diff --git a/internal/types/action/action_test.go b/internal/types/action/action_test.go index 52620acd83..ebd5c6303f 100644 --- a/internal/types/action/action_test.go +++ b/internal/types/action/action_test.go @@ -87,6 +87,10 @@ func TestAction(t *testing.T) { action: ChangeState, want: "change-state", }, + { + action: NoOp, + want: "no-op", + }, } for _, tt := range tests { t.Run(tt.want, func(t *testing.T) { diff --git a/website/content/docs/common-workflows/manage-roles.mdx b/website/content/docs/common-workflows/manage-roles.mdx index 4a0833031d..a9a75dbf7d 100644 --- a/website/content/docs/common-workflows/manage-roles.mdx +++ b/website/content/docs/common-workflows/manage-roles.mdx @@ -139,7 +139,7 @@ In this example we give a role read and list permissions to all resources. ```bash -boundary roles add-grants -id $role_id -grant 'id=*;type=*;actions=read,list' +boundary roles add-grants -id $role_id -grant 'id=*;type=*;actions=no-op,list' Role information: Created Time: Fri, 09 Oct 2020 14:45:47 PDT @@ -162,7 +162,7 @@ Role information: Scope ID: o_1234567890 Canonical Grants: - id=*;type=*;actions=list,read + id=*;type=*;actions=list,no-op ``` diff --git a/website/content/docs/concepts/security/permissions.mdx b/website/content/docs/concepts/security/permissions.mdx index 0760cb5576..6fab029d32 100644 --- a/website/content/docs/concepts/security/permissions.mdx +++ b/website/content/docs/concepts/security/permissions.mdx @@ -36,6 +36,21 @@ level action infers being granted all subactions. Thus, if a grant conveys grant conveys `read:self`, it will match the API action `read:self` but will not match `read`. +## The `no-op` Action + +Starting in Boundary 0.2.1 there is an action that can be granted called +`no-op`. As might be apparent, `no-op` is not used for any real action in +Boundary; the purpose of this action is for listing visibility. Boundary only +shows resources in the output of a `list` action for which a user has at least +one granted action. Thus, without `no-op`, in order for a resource to be visible +in a list, a different action such as `read` would have to be granted to a user. +This could result in exposing more information than desired, especially in the +case of listing scopes and authentication methods so that users can perform +initial authentication to Boundary (that is, granting access to `u_anon`). + +By granting the `no-op` action to users, they can see the resources in the +output of a list command without needing other capability grants as well. + ## Applicable Resource Types Boundary's [domain model](/docs/concepts/domain-model) is based on resource