Skip to content

Commit

Permalink
deflake TestListUnifiedResources_WithLogins
Browse files Browse the repository at this point in the history
This PR tries to fix the flakiness of the `TestListUnifiedResources_WithLogins` test. The primary issue identified was that the role was first created and then updated via a separate update call. Since the role, by default, grants wildcard access to all labels, the resources were being returned after the role was created but before the cache had synchronized with the updated role event.

As a result, the system failed to return the expected logins, except for the SSH logins, which were created during the initial role creation event.

Close #45086

Signed-off-by: Tiago Silva <[email protected]>
  • Loading branch information
tigrato authored and github-actions committed Dec 2, 2024
1 parent 05a9fd4 commit cd788d0
Showing 1 changed file with 28 additions and 20 deletions.
48 changes: 28 additions & 20 deletions lib/auth/auth_with_roles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,7 @@ func TestGenerateUserCertsWithMFAVerification(t *testing.T) {
})
}
}

func TestGenerateUserCertsWithRoleRequest(t *testing.T) {
ctx := context.Background()
srv := newTestTLSServer(t)
Expand Down Expand Up @@ -5077,6 +5078,19 @@ func TestListUnifiedResources_WithLogins(t *testing.T) {
return srv.Auth().UnifiedResourceCache.IsInitialized()
}, 5*time.Second, 200*time.Millisecond, "unified resource watcher never initialized")

// create user and client
logins := []string{"llama", "fish"}
user, _, err := CreateUserAndRole(srv.Auth(), "user", nil /*mutated with role mutator*/, nil,
WithRoleMutator(
func(role types.Role) {
role.SetLogins(types.Allow, logins)
role.SetWindowsLogins(types.Allow, logins)
role.SetWindowsDesktopLabels(types.Allow, types.Labels{types.Wildcard: []string{types.Wildcard}})
role.SetAWSRoleARNs(types.Allow, logins)
}),
)
require.NoError(t, err)

for i := 0; i < 5; i++ {
name := uuid.New().String()
node, err := types.NewServerWithLabels(
Expand Down Expand Up @@ -5134,32 +5148,18 @@ func TestListUnifiedResources_WithLogins(t *testing.T) {
require.NoError(t, err)
}

// create user and client
logins := []string{"llama", "fish"}
user, role, err := CreateUserAndRole(srv.Auth(), "user", logins, nil)
require.NoError(t, err)
role.SetWindowsDesktopLabels(types.Allow, types.Labels{types.Wildcard: []string{types.Wildcard}})
role.SetWindowsLogins(types.Allow, logins)
role.SetAppLabels(types.Allow, types.Labels{types.Wildcard: []string{types.Wildcard}})
role.SetAWSRoleARNs(types.Allow, logins)
_, err = srv.Auth().UpdateRole(ctx, role)
require.NoError(t, err)

clt, err := srv.NewClient(TestUser(user.GetName()))
require.NoError(t, err)

var results []*proto.PaginatedResource
resultsC := make(chan []*proto.PaginatedResource, 1)

// Immediately listing resources can be problematic, given that not all were
// necessarily replicated in the unified resources cache. To cover this
// scenario, perform multiple attempts (if necessary) to read the complete
// list of resources.
require.EventuallyWithT(t, func(t *assert.CollectT) {
// Reset the resources list to avoid having items from previous
// iterations.
results = nil

var start string
var results []*proto.PaginatedResource
for {
resp, err := clt.ListUnifiedResources(ctx, &proto.ListUnifiedResourcesRequest{
Limit: 5,
Expand All @@ -5180,13 +5180,21 @@ func TestListUnifiedResources_WithLogins(t *testing.T) {

// Note: this number should be updated in case we add more resources to
// the setup loop.
assert.Len(t, results, 20)
}, 10*time.Second, 100*time.Millisecond, "unable to list all resources, expected 20 but got %d", len(results))
if !assert.Len(t, results, 20) {
return
}
resultsC <- results
}, 10*time.Second, 100*time.Millisecond, "unable to list all resources")

results := <-resultsC
// Check that only server, desktop, and app server resources contain the expected logins
for _, resource := range results {
expectPrincipals := func(resource *proto.PaginatedResource) bool {
isAWSConsoleApp := resource.GetAppServer() != nil && resource.GetAppServer().GetApp().IsAWSConsole()
if resource.GetNode() != nil || resource.GetWindowsDesktop() != nil || isAWSConsoleApp {
return resource.GetNode() != nil || resource.GetWindowsDesktop() != nil || isAWSConsoleApp
}

for _, resource := range results {
if expectPrincipals(resource) {
require.Empty(t, cmp.Diff(resource.Logins, logins, cmpopts.SortSlices(func(a, b string) bool {
return strings.Compare(a, b) < 0
})), "mismatch on expected logins list for resource %T", resource.Resource)
Expand Down

0 comments on commit cd788d0

Please sign in to comment.