// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package managed_groups_test import ( "context" "fmt" "testing" "github.com/hashicorp/boundary/globals" a "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/auth/ldap" "github.com/hashicorp/boundary/internal/auth/oidc" "github.com/hashicorp/boundary/internal/auth/password" "github.com/hashicorp/boundary/internal/authtoken" "github.com/hashicorp/boundary/internal/daemon/controller/auth" "github.com/hashicorp/boundary/internal/daemon/controller/handlers" "github.com/hashicorp/boundary/internal/daemon/controller/handlers/managed_groups" "github.com/hashicorp/boundary/internal/db" pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/managedgroups" "github.com/hashicorp/go-uuid" "github.com/stretchr/testify/require" "google.golang.org/genproto/protobuf/field_mask" "google.golang.org/protobuf/types/known/wrapperspb" ) // TestGrants_ReadActions tests read actions to assert that grants are being applied properly // // Role - which scope the role is created in // - global level // - org level // - proj level // Grant - what IAM grant scope is set for the permission // - global: descendant // - org: children // - project: this // Scopes [resource]: // - global // - org1 // - proj1 func TestGrants_ReadActions(t *testing.T) { ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") wrap := db.TestWrapper(t) rw := db.New(conn) iamRepo := iam.TestRepo(t, conn, wrap) kmsCache := kms.TestKms(t, conn, wrap) oidcRepoFn := func() (*oidc.Repository, error) { // Use a small limit to test that membership lookup is explicitly unlimited return oidc.NewRepository(ctx, rw, rw, kmsCache, oidc.WithLimit(1)) } ldapRepoFn := func() (*ldap.Repository, error) { // Use a small limit to test that membership lookup is explicitly unlimited return ldap.NewRepository(ctx, rw, rw, kmsCache, ldap.WithLimit(ctx, 1)) } atRepo, err := authtoken.NewRepository(ctx, rw, rw, kmsCache) require.NoError(t, err) s, err := managed_groups.NewService(ctx, oidcRepoFn, ldapRepoFn, 1000) require.NoError(t, err) org, _ := iam.TestScopes(t, iamRepo) globalDBWrapper, err := kmsCache.GetWrapper(ctx, globals.GlobalPrefix, kms.KeyPurposeDatabase) require.NoError(t, err) orgDBWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) globalOidcAm := oidc.TestAuthMethod( t, conn, globalDBWrapper, globals.GlobalPrefix, oidc.ActivePrivateState, "alice-rp", "fido", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://www.alice.com")[0]), oidc.WithSigningAlgs(oidc.RS256), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://www.alice.com/callback")[0]), ) globalOidcAm2 := oidc.TestAuthMethod( t, conn, globalDBWrapper, globals.GlobalPrefix, oidc.ActivePrivateState, "alice-rp-global2", "fido", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://www.alice.com")[0]), oidc.WithSigningAlgs(oidc.RS256), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://www.alice.com/callback")[0]), ) orgOidcAm := oidc.TestAuthMethod( t, conn, orgDBWrapper, org.PublicId, oidc.ActivePrivateState, "alice_rp_2", "alices-dogs-name", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://alice-org.com")[0]), oidc.WithSigningAlgs(oidc.RS256), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://api.com")[0]), ) _ = oidc.TestAccount(t, conn, globalOidcAm, "test-subject-1", oidc.WithName("global-1"), oidc.WithDescription("global-1")) _ = oidc.TestAccount(t, conn, globalOidcAm, "test-subject-2", oidc.WithName("global-2"), oidc.WithDescription("global-2")) _ = oidc.TestAccount(t, conn, globalOidcAm2, "test-subject-3", oidc.WithName("global-3"), oidc.WithDescription("global-3")) _ = oidc.TestAccount(t, conn, orgOidcAm, "org-subject-1", oidc.WithName("org-1"), oidc.WithDescription("org-1")) globalMg1 := oidc.TestManagedGroup(t, conn, globalOidcAm, oidc.TestFakeManagedGroupFilter, oidc.WithName("global-1"), oidc.WithDescription("global-1")) globalMg2 := oidc.TestManagedGroup(t, conn, globalOidcAm, oidc.TestFakeManagedGroupFilter, oidc.WithName("global-2"), oidc.WithDescription("global-2")) globalMg3 := oidc.TestManagedGroup(t, conn, globalOidcAm2, oidc.TestFakeManagedGroupFilter, oidc.WithName("global-3"), oidc.WithDescription("global-3")) orgOidcMg := oidc.TestManagedGroup(t, conn, orgOidcAm, oidc.TestFakeManagedGroupFilter, oidc.WithName("org-1"), oidc.WithDescription("org-1")) globalLdapAm := ldap.TestAuthMethod(t, conn, globalDBWrapper, globals.GlobalPrefix, []string{"ldaps://ldap1"}, ldap.WithName(ctx, "global"), ldap.WithDescription(ctx, "global")) orgLdapAm := ldap.TestAuthMethod(t, conn, orgDBWrapper, org.PublicId, []string{"ldaps://ldap2"}, ldap.WithName(ctx, "org"), ldap.WithDescription(ctx, "org")) orgLdapAm2 := ldap.TestAuthMethod(t, conn, orgDBWrapper, org.PublicId, []string{"ldaps://ldap3"}, ldap.WithName(ctx, "org2"), ldap.WithDescription(ctx, "org2")) _ = ldap.TestAccount(t, conn, orgLdapAm, "test-login-name-1", ldap.WithMemberOfGroups(ctx, "admin"), ldap.WithName(ctx, "org-1"), ldap.WithDescription(ctx, "org-1")) _ = ldap.TestAccount(t, conn, orgLdapAm2, "test-login-name-2", ldap.WithMemberOfGroups(ctx, "admin"), ldap.WithName(ctx, "org-2"), ldap.WithDescription(ctx, "org-2")) _ = ldap.TestManagedGroup(t, conn, orgLdapAm2, []string{"admin", "users"}) orgLdapMg := ldap.TestManagedGroup(t, conn, orgLdapAm, []string{"admin", "users"}, ldap.WithName(ctx, "ldap-name"), ldap.WithDescription(ctx, "ldap-desc")) globalLdapMg := ldap.TestManagedGroup(t, conn, globalLdapAm, []string{"admin", "users"}, ldap.WithName(ctx, "globaldap-name"), ldap.WithDescription(ctx, "globaldap-desc")) t.Run("List", func(t *testing.T) { testcases := []struct { name string input *pbs.ListManagedGroupsRequest userFunc func() (*iam.User, a.Account) wantErr error wantIDs []string expectOutfields []string }{ // oidc { name: "global role grant this returns all global oidc managed groups", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read;output_fields=id,name,description"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantIDs: []string{globalMg1.PublicId, globalMg2.PublicId}, expectOutfields: []string{globals.IdField, globals.NameField, globals.DescriptionField}, }, { name: "global role grant this and children only returns global oidc managed groups", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read;output_fields=id,scope,created_time,updated_time"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, wantIDs: []string{globalMg1.PublicId, globalMg2.PublicId}, expectOutfields: []string{globals.IdField, globals.ScopeField, globals.CreatedTimeField, globals.UpdatedTimeField}, }, { name: "global role grant this and descendents only returns global oidc managed groups", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read;output_fields=id,version,type,auth_method_id"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, wantIDs: []string{globalMg1.PublicId, globalMg2.PublicId}, expectOutfields: []string{globals.IdField, globals.VersionField, globals.TypeField, globals.AuthMethodIdField}, }, { name: "global role grant this everything only returns global oidc managed groups", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*;output_fields=id,attrs,authorized_actions"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantIDs: []string{globalMg1.PublicId, globalMg2.PublicId}, expectOutfields: []string{globals.IdField, "attrs", globals.AuthorizedActionsField}, }, { name: "global role grant this pinned id returns specific global oidc managed group", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalOidcAm2.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=*", globalOidcAm2.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantIDs: []string{globalMg3.PublicId}, expectOutfields: []string{ globals.IdField, globals.ScopeField, globals.NameField, globals.DescriptionField, globals.VersionField, globals.TypeField, globals.AuthMethodIdField, globals.CreatedTimeField, globals.UpdatedTimeField, "attrs", globals.AuthorizedActionsField, "oidc_managed_group_attributes", }, }, { name: "org role grant this only returns org oidc managed groups", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: orgOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: org.PublicId, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantIDs: []string{orgOidcMg.PublicId}, expectOutfields: []string{ globals.IdField, globals.ScopeField, globals.NameField, globals.DescriptionField, globals.VersionField, globals.TypeField, globals.AuthMethodIdField, globals.CreatedTimeField, globals.UpdatedTimeField, "attrs", globals.AuthorizedActionsField, "oidc_managed_group_attributes", }, }, { name: "no list permission returns error", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: orgOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: org.PublicId, Grants: []string{"ids=*;type=managed-group;actions=read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: handlers.ForbiddenError(), wantIDs: nil, expectOutfields: nil, }, { name: "global role not granted group resources returns error", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: orgOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: org.PublicId, Grants: []string{"ids=*;type=target;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: handlers.ForbiddenError(), wantIDs: nil, expectOutfields: nil, }, // ldap { name: "global role grant this returns global created ldap managed group", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalLdapAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read;output_fields=id,name,description"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantIDs: []string{ globalLdapMg.PublicId, }, expectOutfields: []string{globals.IdField, globals.NameField, globals.DescriptionField}, }, { name: "global role grant this pinned id returns global created ldap managed group", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalLdapAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=list,read;output_fields=id,scope,created_time,updated_time", globalLdapAm.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantIDs: []string{ globalLdapMg.PublicId, }, expectOutfields: []string{globals.IdField, globals.ScopeField, globals.CreatedTimeField, globals.UpdatedTimeField}, }, { name: "global role grant this and children returns global created ldap managed group", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalLdapAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read;output_fields=id,version,type,auth_method_id"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, wantIDs: []string{ globalLdapMg.PublicId, }, expectOutfields: []string{globals.IdField, globals.VersionField, globals.TypeField, globals.AuthMethodIdField}, }, { name: "global role grant this and descendants returns global created ldap managed group", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: globalLdapAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read;output_fields=id,attrs,authorized_actions"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, wantIDs: []string{ globalLdapMg.PublicId, }, expectOutfields: []string{globals.IdField, "attrs", globals.AuthorizedActionsField}, }, { name: "org role grant this returns all org ldap managed groups", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: orgLdapAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: org.PublicId, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, wantIDs: []string{ orgLdapMg.PublicId, }, expectOutfields: []string{ globals.IdField, globals.ScopeField, globals.NameField, globals.DescriptionField, globals.VersionField, globals.TypeField, globals.AuthMethodIdField, globals.CreatedTimeField, globals.UpdatedTimeField, "attrs", globals.AuthorizedActionsField, "ldap_managed_group_attributes", }, }, { name: "no list permission returns error", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: orgOidcAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: org.PublicId, Grants: []string{"ids=*;type=managed-group;actions=read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: handlers.ForbiddenError(), wantIDs: nil, expectOutfields: nil, }, { name: "global role not granted group resources returns error", input: &pbs.ListManagedGroupsRequest{ AuthMethodId: orgLdapAm.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: org.PublicId, Grants: []string{"ids=*;type=target;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: handlers.ForbiddenError(), wantIDs: nil, expectOutfields: nil, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { user, acct := tc.userFunc() tok, err := atRepo.CreateAuthToken(ctx, user, acct.GetPublicId()) require.NoError(t, err) fullGrantAuthCtx := auth.TestAuthContextFromToken(t, conn, wrap, tok, iamRepo) got, finalErr := s.ListManagedGroups(fullGrantAuthCtx, tc.input) if tc.wantErr != nil { require.ErrorIs(t, finalErr, tc.wantErr) return } require.NoError(t, finalErr) var gotIDs []string for _, g := range got.Items { gotIDs = append(gotIDs, g.GetId()) } require.ElementsMatch(t, tc.wantIDs, gotIDs) for _, item := range got.Items { handlers.TestAssertOutputFields(t, item, tc.expectOutfields) } }) } }) t.Run("Get", func(t *testing.T) { testcases := []struct { name string input *pbs.GetManagedGroupRequest userFunc func() (*iam.User, a.Account) wantErr error wantID string }{ // oidc { name: "global role grant this returns specific global oidc managed group", input: &pbs.GetManagedGroupRequest{ Id: globalMg1.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantID: globalMg1.PublicId, }, { name: "global role grant pinned id returns specific global oidc managed group", input: &pbs.GetManagedGroupRequest{ Id: globalMg2.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=read", globalOidcAm.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantID: globalMg2.PublicId, }, { name: "global role grant wrong pinned id returns error", input: &pbs.GetManagedGroupRequest{ Id: globalMg2.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=list,read", globalOidcAm2.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: handlers.ForbiddenError(), wantID: "", }, { name: "org role grant this only returns error", input: &pbs.GetManagedGroupRequest{ Id: orgOidcMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: handlers.ForbiddenError(), wantID: "", }, { name: "org role grant this and children returns org", input: &pbs.GetManagedGroupRequest{ Id: orgOidcMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, wantID: orgOidcMg.PublicId, }, { name: "org role grant this and descendants returns org", input: &pbs.GetManagedGroupRequest{ Id: orgOidcMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, wantID: orgOidcMg.PublicId, }, // ldap { name: "global role grant this returns specific global ldap managed group", input: &pbs.GetManagedGroupRequest{ Id: globalLdapMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantID: globalLdapMg.PublicId, }, { name: "global role grant pinned id returns specific global ldap managed group", input: &pbs.GetManagedGroupRequest{ Id: globalLdapMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=read", globalLdapAm.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, wantID: globalLdapMg.PublicId, }, { name: "global role grant wrong pinned id returns error", input: &pbs.GetManagedGroupRequest{ Id: globalLdapMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=list,read", globalOidcAm2.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: handlers.ForbiddenError(), wantID: "", }, { name: "org role grant this only returns error", input: &pbs.GetManagedGroupRequest{ Id: orgLdapMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: handlers.ForbiddenError(), wantID: "", }, { name: "org role grant this and children returns org", input: &pbs.GetManagedGroupRequest{ Id: orgLdapMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, wantID: orgLdapMg.PublicId, }, { name: "org role grant this and descendants returns org", input: &pbs.GetManagedGroupRequest{ Id: orgLdapMg.PublicId, }, userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=list,read"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, wantID: orgLdapMg.PublicId, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { user, acct := tc.userFunc() tok, err := atRepo.CreateAuthToken(ctx, user, acct.GetPublicId()) require.NoError(t, err) fullGrantAuthCtx := auth.TestAuthContextFromToken(t, conn, wrap, tok, iamRepo) got, finalErr := s.GetManagedGroup(fullGrantAuthCtx, tc.input) if tc.wantErr != nil { require.ErrorIs(t, finalErr, tc.wantErr) return } require.NoError(t, finalErr) require.Equal(t, tc.wantID, got.Item.Id) }) } }) } func TestGrants_WriteActions(t *testing.T) { ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") wrap := db.TestWrapper(t) rw := db.New(conn) iamRepo := iam.TestRepo(t, conn, wrap) kmsCache := kms.TestKms(t, conn, wrap) oidcRepoFn := func() (*oidc.Repository, error) { // Use a small limit to test that membership lookup is explicitly unlimited return oidc.NewRepository(ctx, rw, rw, kmsCache, oidc.WithLimit(1)) } ldapRepoFn := func() (*ldap.Repository, error) { // Use a small limit to test that membership lookup is explicitly unlimited return ldap.NewRepository(ctx, rw, rw, kmsCache, ldap.WithLimit(ctx, 1)) } atRepo, err := authtoken.NewRepository(ctx, rw, rw, kmsCache) require.NoError(t, err) s, err := managed_groups.NewService(ctx, oidcRepoFn, ldapRepoFn, 1000) require.NoError(t, err) org, _ := iam.TestScopes(t, iamRepo) globalDBWrapper, err := kmsCache.GetWrapper(ctx, globals.GlobalPrefix, kms.KeyPurposeDatabase) require.NoError(t, err) orgDBWrapper, err := kmsCache.GetWrapper(ctx, org.PublicId, kms.KeyPurposeDatabase) require.NoError(t, err) globalOidcAm := oidc.TestAuthMethod( t, conn, globalDBWrapper, globals.GlobalPrefix, oidc.ActivePrivateState, "alice-rp", "fido", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://www.alice.com")[0]), oidc.WithSigningAlgs(oidc.RS256), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://www.alice.com/callback")[0]), ) orgOidcAm1 := oidc.TestAuthMethod( t, conn, orgDBWrapper, org.PublicId, oidc.ActivePrivateState, "alice_rp_2", "alices-dogs-name", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://alice-org.com")[0]), oidc.WithSigningAlgs(oidc.RS256), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://api.com")[0]), ) orgOidcAm2 := oidc.TestAuthMethod( t, conn, orgDBWrapper, org.PublicId, oidc.ActivePrivateState, "alice_rp_3", "alices-dogs-name", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://alice-oraoeug.com")[0]), oidc.WithSigningAlgs(oidc.RS256), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://apiaoeu.com")[0]), ) globalLdapAm := ldap.TestAuthMethod(t, conn, globalDBWrapper, globals.GlobalPrefix, []string{"ldaps://ldap1"}, ldap.WithName(ctx, "global"), ldap.WithDescription(ctx, "global")) orgLdapAm1 := ldap.TestAuthMethod(t, conn, orgDBWrapper, org.PublicId, []string{"ldaps://ldap2"}, ldap.WithName(ctx, "org"), ldap.WithDescription(ctx, "org")) orgLdapAm2 := ldap.TestAuthMethod(t, conn, orgDBWrapper, org.PublicId, []string{"ldaps://ldap3"}, ldap.WithName(ctx, "org2"), ldap.WithDescription(ctx, "org2")) t.Run("create oidc", func(t *testing.T) { testcases := []struct { name string userFunc func() (*iam.User, a.Account) authmethodIdExpectErrMap map[string]error }{ // oidc { name: "oidc global role grant this and children can create managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), authmethodIdExpectErrMap: map[string]error{ globalOidcAm.PublicId: nil, orgOidcAm1.PublicId: nil, orgOidcAm2.PublicId: nil, }, }, { name: "oidc global role grant this and descendants can create managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalOidcAm.PublicId: nil, orgOidcAm1.PublicId: nil, orgOidcAm2.PublicId: nil, }, }, { name: "oidc global role grant this only global can create managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), authmethodIdExpectErrMap: map[string]error{ globalOidcAm.PublicId: nil, orgOidcAm1.PublicId: handlers.ForbiddenError(), orgOidcAm2.PublicId: handlers.ForbiddenError(), }, }, { name: "oidc children at global can create accounts in org", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeChildren}, }, }), authmethodIdExpectErrMap: map[string]error{ globalOidcAm.PublicId: handlers.ForbiddenError(), orgOidcAm1.PublicId: nil, orgOidcAm2.PublicId: nil, }, }, { name: "oidc descendant at global can create accounts in org", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalOidcAm.PublicId: handlers.ForbiddenError(), orgOidcAm1.PublicId: nil, orgOidcAm2.PublicId: nil, }, }, { name: "oidc pinned org1 grant can only create accounts in org1", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=create", orgOidcAm1.PublicId)}, GrantScopes: []string{globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalOidcAm.PublicId: handlers.ForbiddenError(), orgOidcAm1.PublicId: nil, orgOidcAm2.PublicId: handlers.ForbiddenError(), }, }, { name: "oidc target type does not allow create managed group", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=target;actions=*"}, GrantScopes: []string{globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalOidcAm.PublicId: handlers.ForbiddenError(), orgOidcAm1.PublicId: handlers.ForbiddenError(), orgOidcAm2.PublicId: handlers.ForbiddenError(), }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { user, acct := tc.userFunc() tok, err := atRepo.CreateAuthToken(ctx, user, acct.GetPublicId()) require.NoError(t, err) fullGrantAuthCtx := auth.TestAuthContextFromToken(t, conn, wrap, tok, iamRepo) for am, wantErr := range tc.authmethodIdExpectErrMap { name, err := uuid.GenerateUUID() require.NoError(t, err) item := &pbs.CreateManagedGroupRequest{ Item: &pb.ManagedGroup{ AuthMethodId: am, Name: &wrapperspb.StringValue{Value: name}, Description: &wrapperspb.StringValue{Value: "desc"}, Type: oidc.Subtype.String(), Attrs: &pb.ManagedGroup_OidcManagedGroupAttributes{ OidcManagedGroupAttributes: &pb.OidcManagedGroupAttributes{ Filter: oidc.TestFakeManagedGroupFilter, }, }, }, } got, err := s.CreateManagedGroup(fullGrantAuthCtx, item) if wantErr != nil { require.ErrorIs(t, err, wantErr) return } require.NoError(t, err) require.NotNil(t, got) } }) } }) t.Run("create ldap", func(t *testing.T) { testcases := []struct { name string userFunc func() (*iam.User, a.Account) authmethodIdExpectErrMap map[string]error }{ { name: "ldap global role grant this and children can create managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), authmethodIdExpectErrMap: map[string]error{ globalLdapAm.PublicId: nil, orgLdapAm1.PublicId: nil, orgLdapAm2.PublicId: nil, }, }, { name: "ldap global role grant this and descendants can create managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalLdapAm.PublicId: nil, orgLdapAm1.PublicId: nil, orgLdapAm2.PublicId: nil, }, }, { name: "ldap global role grant this only global can create managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), authmethodIdExpectErrMap: map[string]error{ globalLdapAm.PublicId: nil, orgLdapAm1.PublicId: handlers.ForbiddenError(), orgLdapAm2.PublicId: handlers.ForbiddenError(), }, }, { name: "ldap children at global can create accounts in org", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeChildren}, }, }), authmethodIdExpectErrMap: map[string]error{ globalLdapAm.PublicId: handlers.ForbiddenError(), orgLdapAm1.PublicId: nil, orgLdapAm2.PublicId: nil, }, }, { name: "ldap descendant at global can create accounts in org", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalLdapAm.PublicId: handlers.ForbiddenError(), orgLdapAm1.PublicId: nil, orgLdapAm2.PublicId: nil, }, }, { name: "ldap pinned org1 grant can only create accounts in org1", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=create", orgLdapAm1.PublicId)}, GrantScopes: []string{globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalLdapAm.PublicId: handlers.ForbiddenError(), orgLdapAm1.PublicId: nil, orgLdapAm2.PublicId: handlers.ForbiddenError(), }, }, { name: "ldap target type does not allow create managed group", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=target;actions=*"}, GrantScopes: []string{globals.GrantScopeDescendants}, }, }), authmethodIdExpectErrMap: map[string]error{ globalLdapAm.PublicId: handlers.ForbiddenError(), orgLdapAm1.PublicId: handlers.ForbiddenError(), orgLdapAm2.PublicId: handlers.ForbiddenError(), }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { user, acct := tc.userFunc() tok, err := atRepo.CreateAuthToken(ctx, user, acct.GetPublicId()) require.NoError(t, err) fullGrantAuthCtx := auth.TestAuthContextFromToken(t, conn, wrap, tok, iamRepo) for am, wantErr := range tc.authmethodIdExpectErrMap { name, err := uuid.GenerateUUID() require.NoError(t, err) item := &pbs.CreateManagedGroupRequest{ Item: &pb.ManagedGroup{ AuthMethodId: am, Name: &wrapperspb.StringValue{Value: name}, Description: &wrapperspb.StringValue{Value: "desc"}, Type: ldap.Subtype.String(), Attrs: &pb.ManagedGroup_LdapManagedGroupAttributes{ LdapManagedGroupAttributes: &pb.LdapManagedGroupAttributes{ GroupNames: []string{"admin", "users"}, }, }, }, } got, err := s.CreateManagedGroup(fullGrantAuthCtx, item) if wantErr != nil { require.ErrorIs(t, err, wantErr) return } require.NoError(t, err) require.NotNil(t, got) } }) } }) t.Run("update oidc", func(t *testing.T) { testcases := []struct { name string userFunc func() (*iam.User, a.Account) wantErr error }{ { name: "oidc global role grant this can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, }, { name: "oidc global role grant this and children can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, }, { name: "oidc global role grant this and descendants can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=update"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, }, { name: "oidc global role pinned id grant this can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=*", globalOidcAm.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, }, { name: "oidc global role grant this cannot update managed groups in org scope", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{org.PublicId}, }, }), wantErr: handlers.ForbiddenError(), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { mg := oidc.TestManagedGroup(t, conn, globalOidcAm, oidc.TestFakeManagedGroupFilter, oidc.WithName("default"), oidc.WithDescription("default")) user, acct := tc.userFunc() tok, err := atRepo.CreateAuthToken(ctx, user, acct.GetPublicId()) require.NoError(t, err) fullGrantAuthCtx := auth.TestAuthContextFromToken(t, conn, wrap, tok, iamRepo) name, err := uuid.GenerateUUID() require.NoError(t, err) item := &pbs.UpdateManagedGroupRequest{ UpdateMask: &field_mask.FieldMask{ Paths: []string{globals.NameField, globals.DescriptionField}, }, Id: mg.GetPublicId(), Item: &pb.ManagedGroup{ Version: 1, Name: &wrapperspb.StringValue{Value: name}, Description: &wrapperspb.StringValue{Value: "desc"}, Type: oidc.Subtype.String(), }, } got, err := s.UpdateManagedGroup(fullGrantAuthCtx, item) if tc.wantErr != nil { require.ErrorIs(t, err, tc.wantErr) return } require.NoError(t, err) require.NotNil(t, got) }) } }) t.Run("update ldap", func(t *testing.T) { testcases := []struct { name string userFunc func() (*iam.User, a.Account) wantErr error }{ { name: "ldap global role grant this can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, }, { name: "ldap global role grant this and chlidren can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, }, { name: "ldap global role grant this and descendants can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, }, { name: "ldap global role pinned id grant this specific can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{fmt.Sprintf("ids=%s;type=managed-group;actions=*", globalLdapAm.PublicId)}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, }, { name: "ldap global role grant this specific can update managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=update"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, }, { name: "ldap global role grant this cannot update managed groups in org scope", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{org.PublicId}, }, }), wantErr: handlers.ForbiddenError(), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { mg := ldap.TestManagedGroup(t, conn, globalLdapAm, []string{"admin", "users"}, ldap.WithName(ctx, "default"), ldap.WithDescription(ctx, "default")) user, acct := tc.userFunc() tok, err := atRepo.CreateAuthToken(ctx, user, acct.GetPublicId()) require.NoError(t, err) fullGrantAuthCtx := auth.TestAuthContextFromToken(t, conn, wrap, tok, iamRepo) name, err := uuid.GenerateUUID() require.NoError(t, err) item := &pbs.UpdateManagedGroupRequest{ UpdateMask: &field_mask.FieldMask{ Paths: []string{globals.NameField, globals.DescriptionField}, }, Id: mg.GetPublicId(), Item: &pb.ManagedGroup{ Version: 1, Name: &wrapperspb.StringValue{Value: name}, Description: &wrapperspb.StringValue{Value: "desc"}, Type: ldap.Subtype.String(), }, } got, err := s.UpdateManagedGroup(fullGrantAuthCtx, item) if tc.wantErr != nil { require.ErrorIs(t, err, tc.wantErr) return } require.NoError(t, err) require.NotNil(t, got) }) } }) t.Run("delete", func(t *testing.T) { testcases := []struct { name string userFunc func() (*iam.User, a.Account) wantErr error mg a.ManagedGroup }{ { name: "oidc global role grant this can delete managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=delete"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, mg: oidc.TestManagedGroup(t, conn, globalOidcAm, oidc.TestFakeManagedGroupFilter), }, { name: "oidc global role grant this and children can delete managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=delete"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, mg: oidc.TestManagedGroup(t, conn, globalOidcAm, oidc.TestFakeManagedGroupFilter), }, { name: "oidc global role grant this and descendants can delete managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=delete"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, mg: oidc.TestManagedGroup(t, conn, globalOidcAm, oidc.TestFakeManagedGroupFilter), }, { name: "oidc org role grant this can delete managed groups in org scope", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: org.PublicId, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{org.PublicId}, }, }), wantErr: nil, mg: oidc.TestManagedGroup(t, conn, orgOidcAm1, oidc.TestFakeManagedGroupFilter), }, { name: "oidc global role grant this cannot delete managed groups in org scope", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{org.PublicId}, }, }), wantErr: handlers.ForbiddenError(), mg: oidc.TestManagedGroup(t, conn, globalOidcAm, oidc.TestFakeManagedGroupFilter), }, { name: "ldap global role grant this can delete managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=delete"}, GrantScopes: []string{globals.GrantScopeThis}, }, }), wantErr: nil, mg: ldap.TestManagedGroup(t, conn, globalLdapAm, []string{"admin", "users"}), }, { name: "ldap global role grant this and children can delete managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=*"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeChildren}, }, }), wantErr: nil, mg: ldap.TestManagedGroup(t, conn, globalLdapAm, []string{"admin", "users"}), }, { name: "ldap global role grant this and descendants can delete managed groups everywhere", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=managed-group;actions=delete"}, GrantScopes: []string{globals.GrantScopeThis, globals.GrantScopeDescendants}, }, }), wantErr: nil, mg: ldap.TestManagedGroup(t, conn, globalLdapAm, []string{"admin", "users"}), }, { name: "ldap global role grant this cannot delete wrong type", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=target;actions=delete"}, GrantScopes: []string{org.PublicId}, }, }), wantErr: handlers.ForbiddenError(), mg: ldap.TestManagedGroup(t, conn, globalLdapAm, []string{"admin", "users"}), }, { name: "ldap global role grant this cannot delete managed groups in org scope", userFunc: iam.TestUserGroupGrantsFunc(t, conn, kmsCache, globals.GlobalPrefix, password.TestAuthMethodWithAccount, []iam.TestRoleGrantsRequest{ { RoleScopeId: globals.GlobalPrefix, Grants: []string{"ids=*;type=*;actions=*"}, GrantScopes: []string{org.PublicId}, }, }), wantErr: handlers.ForbiddenError(), mg: ldap.TestManagedGroup(t, conn, globalLdapAm, []string{"admin", "users"}), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { user, acct := tc.userFunc() tok, err := atRepo.CreateAuthToken(ctx, user, acct.GetPublicId()) require.NoError(t, err) fullGrantAuthCtx := auth.TestAuthContextFromToken(t, conn, wrap, tok, iamRepo) req := &pbs.DeleteManagedGroupRequest{ Id: tc.mg.GetPublicId(), } _, err = s.DeleteManagedGroup(fullGrantAuthCtx, req) if tc.wantErr != nil { require.ErrorIs(t, err, tc.wantErr) return } require.NoError(t, err) }) } }) }