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(grants): GrantsForUsers tests for Group resource #5443

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

Conversation

dkanney
Copy link
Collaborator

@dkanney dkanney commented Jan 21, 2025

Goal: Write direct & indirect tests for the GrantsForUser function against the Group resource

  • Direct: Directly associating a user to a role
  • Indirect: Associating a user to a role via one of the following:
    1. Group
    2. Managed Group (e.g. OIDC, LDAP)

I created one test for each case: one direct test, one group test, and one managed group test (performed via OIDC). All tests contain grants against the Group resource (and its associated actions)

@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch 3 times, most recently from 6bdc21d to 34114df Compare January 22, 2025 21:52
@dkanney dkanney marked this pull request as ready for review January 22, 2025 21:54
@dkanney dkanney requested a review from a team as a code owner January 22, 2025 21:54
@dkanney dkanney requested review from tmessi, elimt and bosorawis January 22, 2025 22:56
repo := iam.TestRepo(t, conn, wrap)
kmsCache := kms.TestKms(t, conn, wrap)

grant := "ids=*;type=*;actions=*"
Copy link
Member

Choose a reason for hiding this comment

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

For the grant, if we're testing against the groups resource, we should set set the grant to look like ids=*;type=group;actions=*.

Copy link
Member

Choose a reason for hiding this comment

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

I also think we should have multiple grants and multiple roles so we can have multiple grantTuples and assert it's what we expect

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated these tests to only test against the Groups resource

res: perms.Resource{
ScopeId: directGrantProj1a.PublicId,
Id: "cs_abcd1234",
Type: resource.Credential,
Copy link
Member

Choose a reason for hiding this comment

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

Do we hae dedicated tests for Groups resource

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We do now 👍

Copy link
Collaborator Author

@dkanney dkanney Jan 29, 2025

Choose a reason for hiding this comment

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

We also have tests against the Groups resource here: Test_MarshalingAndCloning

@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch from 34114df to 79b9462 Compare January 24, 2025 18:48
@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch 3 times, most recently from e7cb846 to 0b6ee1a Compare January 28, 2025 20:22
@dkanney dkanney changed the title test(grants): tests for group associations test(grants): GrantsForUsers tests for Group resource Jan 29, 2025
@dkanney dkanney requested a review from mgaffney January 29, 2025 17:55
directGrantOrg1, directGrantProj1a, directGrantProj1b := iam.SetupDirectGrantScopes(t, conn, repo)
directGrantOrg1Role := iam.TestRole(t, conn, directGrantOrg1.PublicId)
iam.TestUserRole(t, conn, directGrantOrg1Role.PublicId, user.PublicId)
directGrantOrg1RoleGrant1 := "ids=*;type=group;actions=*"
Copy link
Member

Choose a reason for hiding this comment

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

does this direct association only test group resource? The title of the test just says TestGrantsForUser_DirectAssociation and the grantString is has type set to "ids=*;type=group;actions=*". When we want to test other resource, are you going to use the same test which builds a grantString for each resource or will they be separated?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes - only the group resource for now. This function should probably be renamed to something Group-specific if we don't plan on adding subtests for the other differently scoped resources (e.g. Auth Methods, Targets).

I figured we could create a separate function for each differently scoped resource since the scope combinations and actions will be different. For instance - Auth Methods apply to global and org scopes only, so we don't need to setup any project scopes like we do here.

RoleScopeId: directGrantOrg1.PublicId,
RoleParentScopeId: scope.Global.String(),
GrantScopeIds: globals.GrantScopeThis,
Grants: strings.Join([]string{directGrantOrg1RoleGrant1, directGrantOrg1RoleGrant2}, "^"),
Copy link
Member

Choose a reason for hiding this comment

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

what does ^ do or signify?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It looks like ^ is used as a delimiter to split grant strings/grant scope ids.

The grantsForUser query pulls in multiple grant strings/grant scope ids, aggregating them into a single string using ^ as a delimiter. In the code, we use strings.Split(..., "^") to split grant strings/grant scope ids into atomic pieces.

iam.WithGrantScopeIds([]string{
globals.GrantScopeChildren,
}))
iam.TestUserRole(t, conn, childGrantGlobalRole.PublicId, globals.AnyAuthenticatedUserId)
Copy link
Member

Choose a reason for hiding this comment

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

Why not set the userId here instead of assigning the role to u_auth?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oof, I didn't notice I was assigning u_auth to the role here instead of the test user I created.

Pushed a change to use user.PublicId instead of u_auth

Grants: childGrantGlobalRoleGrant,
},
}
for i, tuple := range expMultiGrantTuples {
Copy link
Member

Choose a reason for hiding this comment

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

Do we assign any roles to a different user to user it does not get returned?

Copy link
Member

Choose a reason for hiding this comment

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

I realized that did not make sense. I mean do we assign roles to a different user to ensure the only the grants for that 1 particular user gets returned?

In other words, how do we ensure do we have other non-applicable grants that are created but should not be returned because they are not applicable to the user

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a good test case - I'll add another user with different grants to each test

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK -- I added a second user/group/managed group to each test. I assign them some grants & check that their grants are separate from the grants assigned to the original user/group/managed group

@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch 2 times, most recently from b70e1b4 to 621ecda Compare February 7, 2025 17:56
@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch from 621ecda to 17ad5c3 Compare February 7, 2025 19:32
Ensure that non-applicable grants should not be returned because they are not applicable to the user
@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch from 17ad5c3 to e8bc074 Compare February 7, 2025 19:52
@@ -389,3 +394,2026 @@ func TestGrantsForUserRandomized(t *testing.T) {
", roles from ldap managed groups", rolesFromLdapManagedGroups)
}
}

func TestGrantsForUser_DirectAssociation(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.

The general feedback I have on the tests is the setup for the test. It looks like we setup everything in the beginning and then invoke tests below for assertions. I think because we're setting up everything before hand, we have to create a lot of roles and grants.

What do you think about grouping this some more? Maybe have a table test with a setup function like we have here. In the setup, we can create roles relevant for that function and name the test as well so it's easier for anyone looking at it to follow and understand the test coverage we have. Maybe there might be another way of grouping this better.

I also see some overlap here with @bosorawis PR where Bo has created some helper functions for creating roles and assigning grants to it. For example this for Direct Association, this for Group Association and this for Managed Groups. Bo's PR is still under review and subject to change but I think we could share and use some of those helper functions here to reduce the code we have here and may decide to set things up slightly differently if necessary.

Copy link
Collaborator Author

@dkanney dkanney Feb 13, 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 grouping this some more? Maybe have a table test with a setup function like we have here. In the setup, we can create roles relevant for that function and name the test as well so it's easier for anyone looking at it to follow and understand the test coverage we have.

Pushed what I have so far -- 2882623

Grouped the role granting logic & role-user association call together into a helper function:

func grantRoleAndAssociate(t *testing.T, conn *db.DB, roleId string, roleAssociationFunc func(), grants ...string) {
	t.Helper()
	for _, grant := range grants {
		iam.TestRoleGrant(t, conn, roleId, grant)
	}
	roleAssociationFunc()
}

The general feedback I have on the tests is the setup for the test. It looks like we setup everything in the beginning and then invoke tests below for assertions. I think because we're setting up everything before hand, we have to create a lot of roles and grants.
...
Maybe there might be another way of grouping this better.

I don't think I can group things together much more with the current test structure. Current top-level test setup:

  • Create a few scopes
  • Create a couple roles at each scope
  • Grant each role
  • Associate a user to each role
  • Create test cases. For each test case:
    • Do a single, big diff/comparison

If I refactor to look more like the other tests, they might look like this:

  • Create a few scopes
  • Create test cases. For each test case:
    • Create a role at a scope
    • Grant the role
    • Associate a user to the role
    • Do a single, small diff/comparison

This might be easier to follow since we'd be able to name each test case after the relationship (e.g. t.Run("direct grant org 1 role 1", ...) , t.Run("direct grant project 1a role 1", ...), etc.). However, I think we'd lose the ability to assign different roles to multiple users in a test case (mentioned in an earlier comment). There might be a way around this with maps, albeit with added complexity

Copy link
Member

Choose a reason for hiding this comment

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

I see what you mean with the way the tests are setup. I think this already looks better. Grouping it might be complicated after looking at the tests some more

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, after looking at this more I realized my tests assert on the created role's PublicId (via GrantTuple.RoleId) whereas TestUserDirectGrantsFunc() doesn't return the id(s) its created role(s)

@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch 2 times, most recently from 4c919f4 to 2882623 Compare February 13, 2025 22:48
@dkanney dkanney force-pushed the dkanney-test-grants-for-user-group-associations branch from 2882623 to debac4a Compare February 18, 2025 21:10
@dkanney dkanney self-assigned this Feb 26, 2025
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.

2 participants