Skip to content
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

test(groups): add grants tests for groups API #5403

Open
wants to merge 35 commits into
base: llb-normalized-grants
Choose a base branch
from

Conversation

bosorawis
Copy link
Collaborator

Add tests that validate covering grants in preparation for grants system rework

@bosorawis bosorawis requested a review from a team as a code owner January 3, 2025 17:47
@bosorawis bosorawis force-pushed the bosorawis-prototype-grant-test branch from ffbb1c6 to e18100e Compare January 3, 2025 17:48
@bosorawis bosorawis marked this pull request as draft January 3, 2025 17:49
Copy link
Collaborator

@johanbrandhorst johanbrandhorst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool, thanks for this!

internal/daemon/controller/handlers/groups/grants_test.go Outdated Show resolved Hide resolved
@bosorawis bosorawis changed the base branch from main to llb-normalized-grants January 3, 2025 19:19
@bosorawis bosorawis force-pushed the bosorawis-prototype-grant-test branch from fa1bac8 to 8a31f36 Compare January 3, 2025 19:19
@johanbrandhorst
Copy link
Collaborator

Looks like you need a "go mod tidy"

// genAuthTokenCtx creates an auth.VerifierContext which contains a valid auth token
// for a user which is associated with roles in the roles parameter
// this function creates an authMethod, account, user at global scope
func genAuthTokenCtx(t *testing.T,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a prefix of Test to the function since it's only used for testing. So nobody accidentally calls it. I think we have a pattern of this in Boundary

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the function takes *testing.T as its first parameter so I don't think this can be accidentally called outside of test but I'll add test... prefix to its name 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also note that this function is defined in an _test.go file, which means it does not get compiled into the final binary. As such it can only be called via the tests. The pattern of using a Test prefix is usually for things defined in testing.go.

wantIDs: []string{globalGroup.PublicId, org1Group.PublicId, org2Group.PublicId, proj1Group.PublicId, proj2Group.PublicId, proj3Group.PublicId},
},
{
name: "org role grant children IDs only org children",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So descendants will also include items in the current scope which is org2Group. I expected only proj2Group and proj3Group to be returned just like GetGroup works with descendants

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, this is a bad test name. The role is in global with descendant access - calling list at org2 will return org2, proj2, proj3. AFAIK, there's no way to make a list exclude the "listing scope". You always get all the groups in ScopeId of the list call.

proj2Group := iam.TestGroup(t, conn, proj2.GetPublicId(), iam.WithDescription("proj2"), iam.WithName("proj2"))
proj3Group := iam.TestGroup(t, conn, proj3.GetPublicId(), iam.WithDescription("proj3"), iam.WithName("proj3"))

t.Run("List", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add test coverage for:

  • List with grant string with specific scope id
  • Test permission error with type that is not a group

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added tests to cover both cases

},
},
{
name: "global_role_grant_all_specific_permissions",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test and the previous are the same or? Unless I am missing the difference

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another test I forgot to rename 🤦

},
},
{
name: "global_role_grant_all_specific_permissions",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test name here is also the same as the last 2 tests. Not distinct enough

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch! my bad, will push a fix soon

t.Run("update", func(t *testing.T) {
testcases := []struct {
name string
setupScopesResourcesRoles func(t *testing.T, conn *db.DB, iamRepo *iam.Repository) (*iam.Group, []roleRequest)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why we can't pass only roleRequest and allow the for loop to create a test group to follow the pattern of other tests? is it because we want to create groups in different scopes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because in some cases we need ID of the group for testing resource-specific grant string

@bosorawis bosorawis marked this pull request as ready for review January 6, 2025 23:34
@bosorawis bosorawis force-pushed the bosorawis-prototype-grant-test branch from e44604f to 8e8eceb Compare January 7, 2025 01:21
@bosorawis bosorawis changed the title add grants tests for groups API test(groups): add grants tests for groups API Jan 30, 2025
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the Get call to test the behaviour of output_fields? We could also create a separate test that does this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO output_fields should be tested across all CRUDL methods, not just the the read operations. I'm still working on adding a specific output_fields tests which encompasses all the method types.

testcases := []struct {
name string
userFunc func() *iam.User
canCreateInScopes []string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, why don't we follow what we do for Get between tests where we attempt an action and evaluate the result for each group. Makes it easier add to it and to follow

inputWantErrMap: map[*pbs.CreateGroupRequest]error{
					{Id: globalGroup.PublicId}: nil,
					{Id: org1Group.PublicId}:   nil,
					{Id: proj1Group.PublicId}:  nil,
					{Id: org2Group.PublicId}:   handlers.ForbiddenError(),
					{Id: proj2Group.PublicId}:  handlers.ForbiddenError(),
				}

Comment on lines 359 to 405
ctx := context.Background()
rw := db.New(conn)
repo, err := NewRepository(ctx, rw, rw, kmsCache)
require.NoError(t, err)
u, err := NewUser(ctx, scopeID)
require.NoError(t, err)
user, err := repo.CreateUser(ctx, u)
require.NoError(t, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part of it can be done with iam.TestUser

require.NoError(t, err)
user, err := repo.CreateUser(ctx, u)
require.NoError(t, err)
for _, trg := range testRoleGrants {
Copy link
Member

@elimt elimt Feb 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about splitting this up some more. Have functions that only creates the target resource(direct,group or managed_group) and another function that does the associating of the target resources to roles set in TestRoleGrantsRequest by type

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO that makes writing the test table more complicated since they cannot be normalized across all types of grants associations.

I wanted to incorporate all grants type to under one setup interface (func() *iam.User) so the table-driven tests can use the same table so tests don't need to be repeated. I'm happy to make them more distinct though but I'm afraid people might ended up ignoring the more complicated test setup (like LDAP/OIDC)

@bosorawis bosorawis force-pushed the bosorawis-prototype-grant-test branch from 44f89b4 to 4c13c6a Compare February 12, 2025 02:47
// TestRoleWithGrants creates a role suitable for testing along with grants
// Functional options for GrantScopes aren't used to express that
// this function does not provide any default grant scope unlike TestRole
func TestRoleWithGrants(t testing.TB, conn *db.DB, scopeId string, grantScopeIDs []string, grants []string) *Role {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will be moved to an unexported function if the setup pattern is accepted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants