package integration_test import ( "errors" "fmt" "strings" "time" "edge-infra.dev/test/framework/integration" "edge-infra.dev/pkg/edge/api/graph/model" "edge-infra.dev/pkg/edge/api/services/clustersecrets" ) var ( secretTypes = []string{"breakglass", "grub"} ErrLeaseAlreadyInUse = errors.New("lease is already owned by another user") ErrUserDoesNotOwnLease = errors.New("user does not own the lease") ErrBannerOptedOutOfCompliance = errors.New("cluster secret lease feature has been turned off as the banner has opted out of edge security compliance") ErrBannerOptedIntoCompliance = errors.New("updating cluster secrets has been turned off as the banner has opted in to edge security compliance") ErrCannotRevokeUser = errors.New("cannot revoke user from lease as they do not own it") leaseExpirationTime = time.Now().Local().Add(time.Hour * 48).Format(time.RFC3339) secretExpirationTime = time.Now().Local().Add(time.Hour * 24 * 60).Format(time.RFC3339) releaseClusterSecretLeaseMutation = "mutation{releaseClusterSecretLease(clusterEdgeId:\"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass)}" revokeClusterSecretLeaseMutation = fmt.Sprintf("mutation{revokeClusterSecretLease(clusterEdgeId:\"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass, username:\"%s\")}", testUser) testSecurityClusterEdgeID = "92283f29-b1aa-4f8d-8773-dcde1fb58c98" testSecurityBannerID = "4cb5d0e5-42cd-4483-8dca-547507d2adb0" ) func (s *Suite) TestGetSecret() { integration.SkipIf(s.Framework) s.obtainClusterSecretLease(testUser) var response struct { ClusterSecret string } query := "query{clusterSecret(clusterEdgeID: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass)}" err = ResolverClient.Post(query, &response) s.NoError(err) } func (s *Suite) TestGetSecretFailsLeaseAlreadyInUse() { integration.SkipIf(s.Framework) s.obtainClusterSecretLease("testUser") var response struct { ClusterSecretVersions []*model.ClusterSecretVersionInfo } query := "query{clusterSecret(clusterEdgeID: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass)}" err = ResolverClient.Post(query, &response) s.Error(err) s.True(strings.Contains(err.Error(), ErrLeaseAlreadyInUse.Error())) } func (s *Suite) TestGetClusterSecretLease() { integration.SkipIf(s.Framework) s.obtainClusterSecretLease(testUser) var response struct{ ClusterSecretLease *model.ClusterSecretLease } query := "query{clusterSecretLease(clusterEdgeID:\"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass) {expiresAt, owner, secretTypes}}" err = ResolverClient.Post(query, &response) s.NoError(err) s.Equal(testUser, response.ClusterSecretLease.Owner) s.Equal(secretTypes, response.ClusterSecretLease.SecretTypes) } func (s *Suite) TestGetClusterSecretVersions() { integration.SkipIf(s.Framework) var response struct { ClusterSecretVersions []*model.ClusterSecretVersionInfo } query := "query{clusterSecretVersions(clusterEdgeID: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass) {expiresAt, version}}" err = ResolverClient.Post(query, &response) s.NoError(err) s.Equal(response.ClusterSecretVersions[0].ExpiresAt, secretExpirationTime) s.Equal(response.ClusterSecretVersions[0].Version, "1") } func (s *Suite) TestReleaseClusterSecretLease() { integration.SkipIf(s.Framework) s.obtainClusterSecretLease(testUser) var response struct{ ReleaseClusterSecretLease *bool } err = ResolverClient.Post(releaseClusterSecretLeaseMutation, &response) s.NoError(err) s.True(*response.ReleaseClusterSecretLease) } func (s *Suite) TestReleaseClusterSecretLeaseFailsOnWrongUser() { integration.SkipIf(s.Framework) expirationTime := time.Now().UTC().Add(time.Hour * 48).Format(time.RFC3339) _, err := s.DB.Exec(clustersecrets.ObtainLeaseQuery, expirationTime, "mockUser", time.Now().UTC().Format(time.RFC3339), testSecurityClusterEdgeID) s.NoError(err) var response struct{ ReleaseClusterSecretLease *bool } err = ResolverClient.Post(releaseClusterSecretLeaseMutation, &response) s.Error(err) s.True(strings.Contains(err.Error(), ErrUserDoesNotOwnLease.Error())) } func (s *Suite) TestReleaseClusterSecretLeaseOptedOut() { integration.SkipIf(s.Framework) var response struct{ ReleaseClusterSecretLease *bool } releaseClusterSecretLeaseMutation = "mutation{releaseClusterSecretLease(clusterEdgeId:\"3396a52c-6a22-4049-9593-5a63b596a200\", secretType:breakglass)}" err = ResolverClient.Post(releaseClusterSecretLeaseMutation, &response) s.Error(err) s.True(strings.Contains(err.Error(), ErrBannerOptedOutOfCompliance.Error())) } func (s *Suite) TestRevokeClusterSecretLease() { integration.SkipIf(s.Framework) s.updateBannerSecurityCompliance(testSecurityBannerID, true) s.obtainClusterSecretLease(testUser) var response struct{ RevokeClusterSecretLease *bool } err = ResolverClient.Post(revokeClusterSecretLeaseMutation, &response) s.NoError(err) s.True(*response.RevokeClusterSecretLease) } func (s *Suite) TestRevokeClusterSecretLeaseFailsOnWrongUser() { integration.SkipIf(s.Framework) s.obtainClusterSecretLease("mockUser") s.NoError(err) var response struct{ RevokeClusterSecretLease *bool } err = ResolverClient.Post(revokeClusterSecretLeaseMutation, &response) s.Error(err) s.True(strings.Contains(err.Error(), ErrCannotRevokeUser.Error())) } func (s *Suite) TestRevokeClusterSecretOptedOut() { integration.SkipIf(s.Framework) var response struct{ RevokeClusterSecretLease *bool } mutation := "mutation{revokeClusterSecretLease(clusterEdgeId:\"3396a52c-6a22-4049-9593-5a63b596a101\", secretType: breakglass, username:\"mockUser\")}" err = ResolverClient.Post(mutation, &response) s.Error(err) s.True(strings.Contains(err.Error(), ErrBannerOptedOutOfCompliance.Error())) } func (s *Suite) TestUpdateClusterSecretOptedIn() { integration.SkipIf(s.Framework) s.updateBannerSecurityCompliance(testSecurityBannerID, true) var response struct{ UpdateClusterSecret *bool } mutation := "mutation{updateClusterSecret(clusterEdgeId: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass, secretValue: \"Pa55word\")}" err = ResolverClient.Post(mutation, &response) s.Error(err) s.True(strings.Contains(err.Error(), ErrBannerOptedIntoCompliance.Error())) } func (s *Suite) TestUpdateClusterSecretOptedOut() { integration.SkipIf(s.Framework) s.updateBannerSecurityCompliance(testSecurityBannerID, false) var response struct{ UpdateClusterSecret *bool } mutation := "mutation{updateClusterSecret(clusterEdgeId: \"3396a52c-6a22-4049-9593-5a63b596a200\", secretType: breakglass, secretValue: \"Pa55word\")}" err = ResolverClient.Post(mutation, &response) s.NoError(err) s.True(*response.UpdateClusterSecret) s.updateBannerSecurityCompliance(testSecurityBannerID, true) } func (s *Suite) obtainClusterSecretLease(user string) { _, err := s.DB.Exec(clustersecrets.ObtainLeaseQuery, leaseExpirationTime, user, time.Now().UTC().Format(time.RFC3339), testSecurityClusterEdgeID) s.NoError(err) } func (s *Suite) updateBannerSecurityCompliance(bannerEdgeID string, optIn bool) { var response struct{ UpdateBanner *model.EdgeResponsePayload } var mutation string if optIn { mutation = fmt.Sprintf("mutation{updateBanner(bannerEdgeId: \"%s\", edgeSecurityCompliance: optIn){message, statusCode}}", bannerEdgeID) } else { mutation = fmt.Sprintf("mutation{updateBanner(bannerEdgeId: \"%s\", edgeSecurityCompliance: optOut){message, statusCode}}", bannerEdgeID) } err = ResolverClient.Post(mutation, &response) s.NoError(err) s.NotNil(response.UpdateBanner) }