1 package integration_test
2
3 import (
4 "errors"
5 "fmt"
6 "strings"
7 "time"
8
9 "edge-infra.dev/test/framework/integration"
10
11 "edge-infra.dev/pkg/edge/api/graph/model"
12 "edge-infra.dev/pkg/edge/api/services/clustersecrets"
13 )
14
15 var (
16 secretTypes = []string{"breakglass", "grub"}
17 ErrLeaseAlreadyInUse = errors.New("lease is already owned by another user")
18 ErrUserDoesNotOwnLease = errors.New("user does not own the lease")
19 ErrBannerOptedOutOfCompliance = errors.New("cluster secret lease feature has been turned off as the banner has opted out of edge security compliance")
20 ErrBannerOptedIntoCompliance = errors.New("updating cluster secrets has been turned off as the banner has opted in to edge security compliance")
21 ErrCannotRevokeUser = errors.New("cannot revoke user from lease as they do not own it")
22 leaseExpirationTime = time.Now().Local().Add(time.Hour * 48).Format(time.RFC3339)
23 secretExpirationTime = time.Now().Local().Add(time.Hour * 24 * 60).Format(time.RFC3339)
24 releaseClusterSecretLeaseMutation = "mutation{releaseClusterSecretLease(clusterEdgeId:\"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass)}"
25 revokeClusterSecretLeaseMutation = fmt.Sprintf("mutation{revokeClusterSecretLease(clusterEdgeId:\"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass, username:\"%s\")}", testUser)
26 testSecurityClusterEdgeID = "92283f29-b1aa-4f8d-8773-dcde1fb58c98"
27 testSecurityBannerID = "4cb5d0e5-42cd-4483-8dca-547507d2adb0"
28 )
29
30 func (s *Suite) TestGetSecret() {
31 integration.SkipIf(s.Framework)
32 s.obtainClusterSecretLease(testUser)
33 var response struct {
34 ClusterSecret string
35 }
36 query := "query{clusterSecret(clusterEdgeID: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass)}"
37 err = ResolverClient.Post(query, &response)
38 s.NoError(err)
39 }
40
41 func (s *Suite) TestGetSecretFailsLeaseAlreadyInUse() {
42 integration.SkipIf(s.Framework)
43 s.obtainClusterSecretLease("testUser")
44 var response struct {
45 ClusterSecretVersions []*model.ClusterSecretVersionInfo
46 }
47 query := "query{clusterSecret(clusterEdgeID: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass)}"
48 err = ResolverClient.Post(query, &response)
49 s.Error(err)
50 s.True(strings.Contains(err.Error(), ErrLeaseAlreadyInUse.Error()))
51 }
52
53 func (s *Suite) TestGetClusterSecretLease() {
54 integration.SkipIf(s.Framework)
55 s.obtainClusterSecretLease(testUser)
56 var response struct{ ClusterSecretLease *model.ClusterSecretLease }
57 query := "query{clusterSecretLease(clusterEdgeID:\"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass) {expiresAt, owner, secretTypes}}"
58 err = ResolverClient.Post(query, &response)
59 s.NoError(err)
60 s.Equal(testUser, response.ClusterSecretLease.Owner)
61 s.Equal(secretTypes, response.ClusterSecretLease.SecretTypes)
62 }
63
64 func (s *Suite) TestGetClusterSecretVersions() {
65 integration.SkipIf(s.Framework)
66 var response struct {
67 ClusterSecretVersions []*model.ClusterSecretVersionInfo
68 }
69 query := "query{clusterSecretVersions(clusterEdgeID: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass) {expiresAt, version}}"
70 err = ResolverClient.Post(query, &response)
71 s.NoError(err)
72 s.Equal(response.ClusterSecretVersions[0].ExpiresAt, secretExpirationTime)
73 s.Equal(response.ClusterSecretVersions[0].Version, "1")
74 }
75
76 func (s *Suite) TestReleaseClusterSecretLease() {
77 integration.SkipIf(s.Framework)
78 s.obtainClusterSecretLease(testUser)
79 var response struct{ ReleaseClusterSecretLease *bool }
80 err = ResolverClient.Post(releaseClusterSecretLeaseMutation, &response)
81 s.NoError(err)
82 s.True(*response.ReleaseClusterSecretLease)
83 }
84
85 func (s *Suite) TestReleaseClusterSecretLeaseFailsOnWrongUser() {
86 integration.SkipIf(s.Framework)
87 expirationTime := time.Now().UTC().Add(time.Hour * 48).Format(time.RFC3339)
88 _, err := s.DB.Exec(clustersecrets.ObtainLeaseQuery, expirationTime, "mockUser", time.Now().UTC().Format(time.RFC3339), testSecurityClusterEdgeID)
89 s.NoError(err)
90 var response struct{ ReleaseClusterSecretLease *bool }
91 err = ResolverClient.Post(releaseClusterSecretLeaseMutation, &response)
92 s.Error(err)
93 s.True(strings.Contains(err.Error(), ErrUserDoesNotOwnLease.Error()))
94 }
95
96 func (s *Suite) TestReleaseClusterSecretLeaseOptedOut() {
97 integration.SkipIf(s.Framework)
98 var response struct{ ReleaseClusterSecretLease *bool }
99 releaseClusterSecretLeaseMutation = "mutation{releaseClusterSecretLease(clusterEdgeId:\"3396a52c-6a22-4049-9593-5a63b596a200\", secretType:breakglass)}"
100 err = ResolverClient.Post(releaseClusterSecretLeaseMutation, &response)
101 s.Error(err)
102 s.True(strings.Contains(err.Error(), ErrBannerOptedOutOfCompliance.Error()))
103 }
104
105 func (s *Suite) TestRevokeClusterSecretLease() {
106 integration.SkipIf(s.Framework)
107 s.updateBannerSecurityCompliance(testSecurityBannerID, true)
108 s.obtainClusterSecretLease(testUser)
109 var response struct{ RevokeClusterSecretLease *bool }
110 err = ResolverClient.Post(revokeClusterSecretLeaseMutation, &response)
111 s.NoError(err)
112 s.True(*response.RevokeClusterSecretLease)
113 }
114
115 func (s *Suite) TestRevokeClusterSecretLeaseFailsOnWrongUser() {
116 integration.SkipIf(s.Framework)
117 s.obtainClusterSecretLease("mockUser")
118 s.NoError(err)
119 var response struct{ RevokeClusterSecretLease *bool }
120 err = ResolverClient.Post(revokeClusterSecretLeaseMutation, &response)
121 s.Error(err)
122 s.True(strings.Contains(err.Error(), ErrCannotRevokeUser.Error()))
123 }
124
125 func (s *Suite) TestRevokeClusterSecretOptedOut() {
126 integration.SkipIf(s.Framework)
127 var response struct{ RevokeClusterSecretLease *bool }
128 mutation := "mutation{revokeClusterSecretLease(clusterEdgeId:\"3396a52c-6a22-4049-9593-5a63b596a101\", secretType: breakglass, username:\"mockUser\")}"
129 err = ResolverClient.Post(mutation, &response)
130 s.Error(err)
131 s.True(strings.Contains(err.Error(), ErrBannerOptedOutOfCompliance.Error()))
132 }
133
134 func (s *Suite) TestUpdateClusterSecretOptedIn() {
135 integration.SkipIf(s.Framework)
136 s.updateBannerSecurityCompliance(testSecurityBannerID, true)
137 var response struct{ UpdateClusterSecret *bool }
138 mutation := "mutation{updateClusterSecret(clusterEdgeId: \"92283f29-b1aa-4f8d-8773-dcde1fb58c98\", secretType: breakglass, secretValue: \"Pa55word\")}"
139 err = ResolverClient.Post(mutation, &response)
140 s.Error(err)
141 s.True(strings.Contains(err.Error(), ErrBannerOptedIntoCompliance.Error()))
142 }
143
144 func (s *Suite) TestUpdateClusterSecretOptedOut() {
145 integration.SkipIf(s.Framework)
146 s.updateBannerSecurityCompliance(testSecurityBannerID, false)
147 var response struct{ UpdateClusterSecret *bool }
148 mutation := "mutation{updateClusterSecret(clusterEdgeId: \"3396a52c-6a22-4049-9593-5a63b596a200\", secretType: breakglass, secretValue: \"Pa55word\")}"
149 err = ResolverClient.Post(mutation, &response)
150 s.NoError(err)
151 s.True(*response.UpdateClusterSecret)
152 s.updateBannerSecurityCompliance(testSecurityBannerID, true)
153 }
154
155 func (s *Suite) obtainClusterSecretLease(user string) {
156 _, err := s.DB.Exec(clustersecrets.ObtainLeaseQuery, leaseExpirationTime, user, time.Now().UTC().Format(time.RFC3339), testSecurityClusterEdgeID)
157 s.NoError(err)
158 }
159
160 func (s *Suite) updateBannerSecurityCompliance(bannerEdgeID string, optIn bool) {
161 var response struct{ UpdateBanner *model.EdgeResponsePayload }
162 var mutation string
163 if optIn {
164 mutation = fmt.Sprintf("mutation{updateBanner(bannerEdgeId: \"%s\", edgeSecurityCompliance: optIn){message, statusCode}}", bannerEdgeID)
165 } else {
166 mutation = fmt.Sprintf("mutation{updateBanner(bannerEdgeId: \"%s\", edgeSecurityCompliance: optOut){message, statusCode}}", bannerEdgeID)
167 }
168 err = ResolverClient.Post(mutation, &response)
169 s.NoError(err)
170 s.NotNil(response.UpdateBanner)
171 }
172
View as plain text