Skip to content

Add options to create default and admin roles #5843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 55 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
a49545c
Create function to define valid set of scopes for each resource (#5558)
dkanney Feb 27, 2025
1b852a2
test(grants): GrantsForUsers tests for Group resource (#5443)
dkanney Mar 4, 2025
6d887d6
feat: Define new grants tables (#5486)
elimt Mar 10, 2025
fbfe878
add name scope id unique constraints to all iam_role tables (#5623)
bosorawis Mar 24, 2025
50d31f6
Bosorawis domain iam role subtypes (#5626)
bosorawis Apr 14, 2025
96d827a
bosorawis sql split global grants scope table (#5638)
bosorawis Apr 21, 2025
414f9b6
bosorawis domain iam implement getRoleScopeType (#5629)
bosorawis Apr 24, 2025
0d51e52
domain: iam: upgrade repository code to use new tables (#5643)
bosorawis Apr 30, 2025
492c921
Domain: iam: Repository: update list-grant-scope and test setup to us…
bosorawis Apr 30, 2025
7c7e7da
feat: grantsForUser for Global Resources (#5612)
elimt May 12, 2025
6b871e1
Bosorawis domain iam implement role grant scopes all (#5701)
bosorawis May 16, 2025
9f1cff9
feat: add grant_this_role_scope column to iam_role_project (#5738)
bosorawis May 16, 2025
6fba764
feat: grantsForUser for Org resources (#5663)
dkanney May 16, 2025
6fb4160
feat: grantsForUser for Project resources (#5669)
dkanney May 19, 2025
7f42173
Change reqScope parameter type from `Scope` to `string` (#5748)
dkanney May 20, 2025
fae8d57
Test: GrantsForUser for Accounts for various user to role relationshi…
dkanney May 21, 2025
acacf5e
feat: grantsForUser for recursive Global or Org resources (#5747)
dkanney May 23, 2025
2d130cd
feat: grantsForUser for recursive Project resources (#5783)
dkanney May 29, 2025
8b1f041
feat: migration hook grants refactor (#5733)
bosorawis Jun 5, 2025
03a12f9
feat: grantsForUser for Global/Org/Project resources (#5807)
dkanney Jun 5, 2025
5153c10
feat: grants: add resource type parameters to GrantsForUser (#5750)
bosorawis Jun 11, 2025
e5aee5e
Support previous grants use-cases (#5823)
bosorawis Jun 11, 2025
416f310
Migrate roles and grants to new table structure (#5814)
mikemountain Jun 12, 2025
ff51747
Refactor GrantsForUser subqueries to use aggregate functions (#5822)
dkanney Jun 13, 2025
3b62148
fix broken test (#5842)
mikemountain Jun 13, 2025
8377ea4
update tests to not check a table that will be dropped in the migrati…
mikemountain Jun 16, 2025
3d43e2d
Fix global scope's parent scope id (#5844)
dkanney Jun 16, 2025
5225fd4
Clean up migrated tables (#5837)
mikemountain Jun 16, 2025
8d53955
fix broken sql from removing iam role grant scope (#5860)
bosorawis Jun 17, 2025
3b4af12
test(groups): add grants tests for groups API (#5403)
bosorawis Mar 26, 2025
f3e5bd4
feat: add grants tests for billing resource (#5559)
elimt Mar 27, 2025
99726d8
Add grants tests for accounts (#5566)
bosorawis Mar 27, 2025
3460aa6
test(credentials): Add grants tests (#5608)
dkanney Mar 28, 2025
0694656
feat: add grants tests for alias (#5550)
elimt Mar 31, 2025
9ac1319
test: add grants tests for host_catalogs (#5573)
elimt Apr 2, 2025
eb9934c
Add grants tests for authmethods (#5569)
dkanney Apr 3, 2025
d3bfcdd
test(hostsets): add grants tests (#5591)
dkanney Apr 3, 2025
3ca059b
test: credentials store grants (#5592)
bosorawis Apr 15, 2025
33e3cb4
test: add grants tests for managed groups resource (#5642)
mikemountain Apr 17, 2025
931c47c
test: add grants tests for auth tokens resource (#5644)
mikemountain Apr 23, 2025
bff7160
add authorized actions tests for resources with sub-resources (#5835)
bosorawis Jun 11, 2025
44d05af
bosorawis remove TestRoleGrantsForToken (#5840)
bosorawis Jun 17, 2025
505ef19
Remove old test Role creation code
dkanney Jun 17, 2025
f81adcb
update go mod
mikemountain Jun 18, 2025
6f93d74
run make gen and move new migrations to new folder (#5862)
mikemountain Jun 18, 2025
f7a0da2
test: add grants tests for session resource (#5855)
bosorawis Jun 18, 2025
c11a42a
API: add CreateDefaultRole and CreateAdminRole options
mikemountain Jun 6, 2025
ffb3699
Add CreateDefaultRole and CreateAdminRole options
mikemountain Jun 13, 2025
ed76b5f
repo: add CreateDefaultRole and CreateAdminRole options
mikemountain Jun 13, 2025
b37aff6
rerun make gen
bosorawis Jun 18, 2025
d98a06e
domain layer additions
mikemountain Jun 19, 2025
a440966
update domain layer
mikemountain Jun 19, 2025
507b48c
update tests
mikemountain Jun 19, 2025
6ba2bc7
address pr comments
mikemountain Jun 19, 2025
a54db19
address pr comments
mikemountain Jun 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ protobuild:
@protoc-go-inject-tag -input=./internal/oplog/oplog_test/oplog_test.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/group_member.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_global_individual_org_grant_scope.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_global_individual_project_grant_scope.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_org_individual_grant_scope.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_global.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_org.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_project.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/principal_role.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_grant.pb.go
@protoc-go-inject-tag -input=./internal/iam/store/role_grant_scope.pb.go
Expand Down
24 changes: 24 additions & 0 deletions api/scopes/option.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions globals/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
GrantScopeThis = "this"
GrantScopeChildren = "children"
GrantScopeDescendants = "descendants"
GrantScopeIndividual = "individual"

// CorrelationIdKey defines the http header and grpc metadata key used for specifying a
// correlation id. When getting the correlationId (from the http header or grpc metadata)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ require (
github.com/kelseyhightower/envconfig v1.4.0
github.com/kr/pretty v0.3.1
github.com/kr/text v0.2.0
github.com/lib/pq v1.10.9
github.com/mattn/go-colorable v0.1.14
github.com/miekg/dns v1.1.66
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a
Expand Down Expand Up @@ -172,7 +173,6 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
Expand Down
12 changes: 12 additions & 0 deletions internal/api/genapi/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,18 @@ var inputStructs = []*structInfo{
FieldType: "bool",
Query: true,
},
{
Name: "CreateAdminRole",
ProtoName: "create_admin_role",
FieldType: "bool",
Query: true,
},
{
Name: "CreateDefaultRole",
ProtoName: "create_default_role",
FieldType: "bool",
Query: true,
},
},
versionEnabled: true,
createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType},
Expand Down
118 changes: 113 additions & 5 deletions internal/auth/additional_verification_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestFetchActionSetForId(t *testing.T) {
func TestFetchActionSetForId_orgRole(t *testing.T) {
tc := controller.NewTestController(t, nil)
defer tc.Shutdown()

Expand Down Expand Up @@ -73,7 +73,116 @@ func TestFetchActionSetForId(t *testing.T) {
iam.TestUserRole(t, conn, orgRole.PublicId, token.UserId)
iam.TestRoleGrant(t, conn, orgRole.PublicId, "ids=ttcp_foo;actions=read,update")
iam.TestRoleGrant(t, conn, orgRole.PublicId, "ids=ttcp_bar;actions=read,update,delete,authorize-session")
iam.TestRoleGrant(t, conn, orgRole.PublicId, "ids=*;type=role;actions=add-grants,remove-grants")
iam.TestRoleGrant(t, conn, orgRole.PublicId, "ids=*;type=policy;actions=add-grants,remove-grants")

cases := []struct {
name string
id string
avail action.ActionSet
allowed action.ActionSet
typeOverride resource.Type
}{
{
name: "base",
},
{
name: "no match",
id: "zip",
avail: action.NewActionSet(action.Read, action.Update),
},
{
name: "disjoint match",
id: "ttcp_bar",
avail: action.NewActionSet(action.Delete, action.AddGrants, action.Read, action.RemoveHostSets),
allowed: action.NewActionSet(action.Delete, action.Read),
},
{
name: "different type",
id: "anything",
typeOverride: resource.Scope,
},
{
name: "type match",
id: "anything",
typeOverride: resource.Policy,
avail: action.NewActionSet(action.Read, action.AddGrants),
allowed: action.NewActionSet(action.AddGrants),
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
req := require.New(t)
ctx := auth.NewVerifierContext(
context.Background(),
iamRepoFn,
authTokenRepoFn,
serversRepoFn,
tc.Kms(),
&authpb.RequestInfo{
PublicId: token.Id,
EncryptedToken: strings.Split(token.Token, "_")[2],
TokenFormat: uint32(auth.AuthTokenTypeBearer),
})
typ := resource.Role
if tt.typeOverride != resource.Unknown {
typ = tt.typeOverride
}
res := auth.Verify(ctx, typ, []auth.Option{
auth.WithId("ttcp_foo"),
auth.WithAction(action.Read),
auth.WithScopeId(org.PublicId),
}...)
req.NoError(res.Error)
assert.Equal(t, tt.allowed, res.FetchActionSetForId(ctx, tt.id, tt.avail))
})
}
}

func TestFetchActionSetForId_projRole(t *testing.T) {
tc := controller.NewTestController(t, nil)
defer tc.Shutdown()

conn := tc.DbConn()
client := tc.Client()
token := tc.Token()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId), iam.WithSkipAdminRoleCreation(true), iam.WithSkipDefaultRoleCreation(true))

iamRepoFn := func() (*iam.Repository, error) {
return tc.IamRepo(), nil
}
serversRepoFn := func() (*server.Repository, error) {
return tc.ServersRepo(), nil
}
authTokenRepoFn := func() (*authtoken.Repository, error) {
return tc.AuthTokenRepo(), nil
}

// Delete the global default role so it doesn't interfere with the
// permissions we're testing here
rolesClient := roles.NewClient(tc.Client())
rolesResp, err := rolesClient.List(tc.Context(), scope.Global.String())
require.NoError(t, err)
require.NotNil(t, rolesResp)
assert.Len(t, rolesResp.GetItems(), 3)
var adminRoleId string
for _, item := range rolesResp.GetItems() {
if strings.Contains(item.Name, "Authenticated User") ||
strings.Contains(item.Name, "Login") {
_, err := rolesClient.Delete(tc.Context(), item.Id)
require.NoError(t, err)
} else {
adminRoleId = item.Id
}
}
_, err = rolesClient.Delete(tc.Context(), adminRoleId)
require.NoError(t, err)

projRole := iam.TestRole(t, conn, proj.GetPublicId())
iam.TestUserRole(t, conn, projRole.PublicId, token.UserId)
iam.TestRoleGrant(t, conn, projRole.PublicId, "ids=ttcp_foo;actions=read,update")
iam.TestRoleGrant(t, conn, projRole.PublicId, "ids=ttcp_bar;actions=read,update,delete,authorize-session")
iam.TestRoleGrant(t, conn, projRole.PublicId, "ids=*;type=role;actions=add-grants,remove-grants")

cases := []struct {
name string
Expand Down Expand Up @@ -127,11 +236,10 @@ func TestFetchActionSetForId(t *testing.T) {
if tt.typeOverride != resource.Unknown {
typ = tt.typeOverride
}
res := auth.Verify(ctx, []auth.Option{
res := auth.Verify(ctx, typ, []auth.Option{
auth.WithId("ttcp_foo"),
auth.WithAction(action.Read),
auth.WithScopeId(org.PublicId),
auth.WithType(typ),
auth.WithScopeId(proj.PublicId),
}...)
req.NoError(res.Error)
assert.Equal(t, tt.allowed, res.FetchActionSetForId(ctx, tt.id, tt.avail))
Expand Down
2 changes: 1 addition & 1 deletion internal/auth/db_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package auth
package auth_test

import (
"context"
Expand Down
8 changes: 5 additions & 3 deletions internal/auth/ldap/managed_group_role_grants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -73,7 +74,8 @@ func TestLdapManagedGroupRoleGrants(t *testing.T) {

// okay, let's try the CTE and make sure the user has the grants given via
// the ldap managed group
tuples, err := iamRepo.GrantsForUser(testCtx, testUser.PublicId)
// resource type does not matter here since testGrants has type=*
tuples, err := iamRepo.GrantsForUser(testCtx, testUser.PublicId, []resource.Type{resource.Scope}, testScopeId)
require.NoError(t, err)
// De-dupe role IDs
roleIds := make(map[string]bool, len(tuples))
Expand All @@ -86,7 +88,7 @@ func TestLdapManagedGroupRoleGrants(t *testing.T) {

// make sure a user without the appropriate managed group doesn't have grants
testUserWithoutManagedGroupRole := iam.TestUser(t, iamRepo, testScopeId)
tuples, err = iamRepo.GrantsForUser(testCtx, testUserWithoutManagedGroupRole.PublicId)
tuples, err = iamRepo.GrantsForUser(testCtx, testUserWithoutManagedGroupRole.PublicId, []resource.Type{resource.Scope}, testScopeId)
require.NoError(t, err)
assert.Equal(t, 0, len(tuples))

Expand All @@ -111,7 +113,7 @@ func TestLdapManagedGroupRoleGrants(t *testing.T) {
_ = iam.TestRoleGrant(t, testConn, testRole2.GetPublicId(), testGrant)
iam.TestManagedGroupRole(t, testConn, testRole2.GetPublicId(), testOidcManagedGrp.GetPublicId())

tuples, err = iamRepo.GrantsForUser(testCtx, testUser.GetPublicId())
tuples, err = iamRepo.GrantsForUser(testCtx, testUser.GetPublicId(), []resource.Type{resource.SessionRecording}, testScopeId)
require.NoError(t, err)
assert.Equal(t, 2, len(tuples))
t.Log("tuples:", tuples)
Expand Down
19 changes: 19 additions & 0 deletions internal/auth/ldap/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@ import (
"crypto/x509/pkix"
"encoding/json"
"encoding/pem"
"fmt"
"math/big"
"net"
"net/url"
"sort"
"testing"
"time"

"github.com/hashicorp/boundary/internal/auth"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/kms"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
"github.com/hashicorp/go-secure-stdlib/parseutil"
"github.com/hashicorp/go-uuid"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -176,6 +180,21 @@ func TestAccount(t testing.TB, conn *db.DB, am *AuthMethod, loginName string, op
return a
}

// TestAuthMethodWithAccountInManagedGroup creates an authMethod, and an account within that authmethod, an
// LDAP managed group, and add the newly created account as a member of the LDAP managed group.
func TestAuthMethodWithAccountInManagedGroup(t *testing.T, conn *db.DB, kmsCache *kms.Kms, scopeId string) (auth.AuthMethod, auth.Account, auth.ManagedGroup) {
t.Helper()
uuid, err := uuid.GenerateUUID()
require.NoError(t, err)
ctx := context.Background()
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), scopeId, kms.KeyPurposeDatabase)
require.NoError(t, err)
am := TestAuthMethod(t, conn, databaseWrapper, scopeId, []string{fmt.Sprintf("ldap://%s", uuid)})
managedGroup := TestManagedGroup(t, conn, am, []string{uuid})
acct := TestAccount(t, conn, am, "testacct", WithMemberOfGroups(ctx, uuid))
return am, acct, managedGroup
}

// TestManagedGroup creates a test ldap managed group.
func TestManagedGroup(t testing.TB, conn *db.DB, am *AuthMethod, grpNames []string, opt ...Option) *ManagedGroup {
t.Helper()
Expand Down
25 changes: 23 additions & 2 deletions internal/auth/oidc/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"testing"
"time"

"github.com/hashicorp/boundary/internal/auth"
"github.com/hashicorp/boundary/internal/auth/oidc/request"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/db"
Expand All @@ -32,6 +33,7 @@ import (
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/cap/oidc"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
"github.com/hashicorp/go-uuid"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
)
Expand Down Expand Up @@ -192,6 +194,25 @@ func TestAccount(t testing.TB, conn *db.DB, am *AuthMethod, subject string, opt
return a
}

// TestAuthMethodWithAccountInManagedGroup creates an authMethod, and an account within that authmethod, an
// OIDC managed group, and add the newly created account as a member of the OIDC managed group.
func TestAuthMethodWithAccountInManagedGroup(t *testing.T, conn *db.DB, kmsCache *kms.Kms, scopeId string) (auth.AuthMethod, auth.Account, auth.ManagedGroup) {
t.Helper()
uuid, err := uuid.GenerateUUID()
require.NoError(t, err)
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), scopeId, kms.KeyPurposeDatabase)
require.NoError(t, err)
testAuthMethod := TestAuthMethod(t, conn, databaseWrapper, scopeId, ActivePublicState,
"alice-rp", "fido",
WithIssuer(TestConvertToUrls(t, fmt.Sprintf("https://%s.com", uuid))[0]),
WithSigningAlgs(Alg(oidc.RS256)),
WithApiUrl(TestConvertToUrls(t, fmt.Sprintf("https://%s.com/callback", uuid))[0]))
account := TestAccount(t, conn, testAuthMethod, "testacct")
managedGroup := TestManagedGroup(t, conn, testAuthMethod, `"/token/sub" matches ".*"`)
TestManagedGroupMember(t, conn, managedGroup.PublicId, account.PublicId)
return testAuthMethod, account, managedGroup
}

// TestManagedGroup creates a test oidc managed group.
func TestManagedGroup(t testing.TB, conn *db.DB, am *AuthMethod, filter string, opt ...Option) *ManagedGroup {
t.Helper()
Expand All @@ -211,13 +232,13 @@ func TestManagedGroup(t testing.TB, conn *db.DB, am *AuthMethod, filter string,
}

// TestManagedGroupMember adds given account IDs to a managed group
func TestManagedGroupMember(t testing.TB, conn *db.DB, managedGroupId, memberId string, opt ...Option) *ManagedGroupMemberAccount {
func TestManagedGroupMember(t testing.TB, conn *db.DB, managedGroupId, accountId string, opt ...Option) *ManagedGroupMemberAccount {
t.Helper()
require := require.New(t)
rw := db.New(conn)
ctx := context.Background()

mg, err := NewManagedGroupMemberAccount(ctx, managedGroupId, memberId, opt...)
mg, err := NewManagedGroupMemberAccount(ctx, managedGroupId, accountId, opt...)
require.NoError(err)

require.NoError(rw.Create(ctx, mg))
Expand Down
Loading
Loading