github.com/adityamillind98/nomad@v0.11.8/command/agent/consul/acl_testing.go (about) 1 package consul 2 3 import ( 4 "errors" 5 "sync" 6 "time" 7 8 "github.com/hashicorp/consul/api" 9 "github.com/hashicorp/go-hclog" 10 "github.com/hashicorp/nomad/helper/uuid" 11 ) 12 13 var _ ACLsAPI = (*MockACLsAPI)(nil) 14 15 // MockACLsAPI is a mock of consul.ACLsAPI 16 type MockACLsAPI struct { 17 logger hclog.Logger 18 19 lock sync.Mutex 20 state struct { 21 index uint64 22 error error 23 tokens map[string]*api.ACLToken 24 } 25 } 26 27 func NewMockACLsAPI(l hclog.Logger) *MockACLsAPI { 28 return &MockACLsAPI{ 29 logger: l.Named("mock_consul"), 30 state: struct { 31 index uint64 32 error error 33 tokens map[string]*api.ACLToken 34 }{tokens: make(map[string]*api.ACLToken)}, 35 } 36 } 37 38 // Example Consul policies for use in tests. 39 const ( 40 ExamplePolicyID1 = "a7c86856-0af5-4ab5-8834-03f4517e5564" 41 ExamplePolicyID2 = "ffa1b66c-967d-4468-8775-c687b5cfc16e" 42 ExamplePolicyID3 = "f68f0c36-51f8-4343-97dd-f0d4816c915f" 43 ) 44 45 func (m *MockACLsAPI) PolicyRead(policyID string, _ *api.QueryOptions) (*api.ACLPolicy, *api.QueryMeta, error) { 46 switch policyID { 47 48 case ExamplePolicyID1: 49 return &api.ACLPolicy{ 50 ID: ExamplePolicyID1, 51 Name: "example-policy-1", 52 Rules: `service "service1" { policy = "write" }`, 53 }, nil, nil 54 55 case ExamplePolicyID2: 56 return &api.ACLPolicy{ 57 ID: ExamplePolicyID2, 58 Rules: `service_prefix "foo-" { policy = "write" }`, 59 }, nil, nil 60 61 case ExamplePolicyID3: 62 return &api.ACLPolicy{ 63 ID: ExamplePolicyID3, 64 Rules: ` 65 service "service1" { policy = "read" } 66 service "service2" { policy = "write" }`, 67 }, nil, nil 68 69 default: 70 return nil, nil, errors.New("no such policy") 71 } 72 } 73 74 // Example Consul roles for use in tests. 75 const ( 76 ExampleRoleID1 = "e569a3a8-7dfb-b024-e492-e790fe3c4183" 77 ExampleRoleID2 = "88c825f4-d0da-1c2b-0c1c-cc9fe84c4468" 78 ExampleRoleID3 = "b19b2058-6205-6dff-d2b0-470f29b8e627" 79 ) 80 81 func (m *MockACLsAPI) RoleRead(roleID string, _ *api.QueryOptions) (*api.ACLRole, *api.QueryMeta, error) { 82 switch roleID { 83 case ExampleRoleID1: 84 return &api.ACLRole{ 85 ID: ExampleRoleID1, 86 Name: "example-role-1", 87 Policies: []*api.ACLRolePolicyLink{{ 88 ID: ExamplePolicyID1, 89 Name: "example-policy-1", 90 }}, 91 ServiceIdentities: nil, 92 }, nil, nil 93 case ExampleRoleID2: 94 return &api.ACLRole{ 95 ID: ExampleRoleID2, 96 Name: "example-role-2", 97 Policies: []*api.ACLRolePolicyLink{{ 98 ID: ExamplePolicyID2, 99 Name: "example-policy-2", 100 }}, 101 ServiceIdentities: nil, 102 }, nil, nil 103 case ExampleRoleID3: 104 return &api.ACLRole{ 105 ID: ExampleRoleID3, 106 Name: "example-role-3", 107 Policies: nil, // todo add more if needed 108 ServiceIdentities: nil, // todo add more if needed 109 }, nil, nil 110 default: 111 return nil, nil, nil 112 } 113 } 114 115 // Example Consul "operator" tokens for use in tests. 116 117 const ( 118 ExampleOperatorTokenID0 = "de591604-86eb-1e6f-8b44-d4db752921ae" 119 ExampleOperatorTokenID1 = "59c219c2-47e4-43f3-bb45-258fd13f59d5" 120 ExampleOperatorTokenID2 = "868cc216-e123-4c2b-b362-f4d4c087de8e" 121 ExampleOperatorTokenID3 = "6177d1b9-c0f6-4118-b891-d818a3cb80b1" 122 ExampleOperatorTokenID4 = "754ae26c-f3cc-e088-d486-9c0d20f5eaea" 123 ) 124 125 var ( 126 ExampleOperatorToken0 = &api.ACLToken{ 127 SecretID: ExampleOperatorTokenID0, 128 AccessorID: "228865c6-3bf6-6683-df03-06dea2779088 ", 129 Description: "Operator Token 0", 130 } 131 132 ExampleOperatorToken1 = &api.ACLToken{ 133 SecretID: ExampleOperatorTokenID1, 134 AccessorID: "e341bacd-535e-417c-8f45-f88d7faffcaf", 135 Description: "Operator Token 1", 136 Policies: []*api.ACLTokenPolicyLink{{ 137 ID: ExamplePolicyID1, 138 }}, 139 } 140 141 ExampleOperatorToken2 = &api.ACLToken{ 142 SecretID: ExampleOperatorTokenID2, 143 AccessorID: "615b4d77-5164-4ec6-b616-24c0b24ac9cb", 144 Description: "Operator Token 2", 145 Policies: []*api.ACLTokenPolicyLink{{ 146 ID: ExamplePolicyID2, 147 }}, 148 } 149 150 ExampleOperatorToken3 = &api.ACLToken{ 151 SecretID: ExampleOperatorTokenID3, 152 AccessorID: "6b7de0d7-15f7-45b4-95eb-fb775bfe3fdc", 153 Description: "Operator Token 3", 154 Policies: []*api.ACLTokenPolicyLink{{ 155 ID: ExamplePolicyID3, 156 }}, 157 } 158 159 ExampleOperatorToken4 = &api.ACLToken{ 160 SecretID: ExampleOperatorTokenID4, 161 AccessorID: "7b5fdb1a-71e5-f3d8-2cfe-448d973f327d", 162 Description: "Operator Token 4", 163 Policies: nil, // no direct policy, only roles 164 Roles: []*api.ACLTokenRoleLink{{ 165 ID: ExampleRoleID1, 166 Name: "example-role-1", 167 }}, 168 } 169 ) 170 171 func (m *MockACLsAPI) TokenReadSelf(q *api.QueryOptions) (*api.ACLToken, *api.QueryMeta, error) { 172 switch q.Token { 173 174 case ExampleOperatorTokenID1: 175 return ExampleOperatorToken1, nil, nil 176 177 case ExampleOperatorTokenID2: 178 return ExampleOperatorToken2, nil, nil 179 180 case ExampleOperatorTokenID3: 181 return ExampleOperatorToken3, nil, nil 182 183 case ExampleOperatorTokenID4: 184 return ExampleOperatorToken4, nil, nil 185 186 default: 187 return nil, nil, errors.New("no such token") 188 } 189 } 190 191 // SetError is a helper method for configuring an error that will be returned 192 // on future calls to mocked methods. 193 func (m *MockACLsAPI) SetError(err error) { 194 m.lock.Lock() 195 defer m.lock.Unlock() 196 m.state.error = err 197 } 198 199 // TokenCreate is a mock of ACLsAPI.TokenCreate 200 func (m *MockACLsAPI) TokenCreate(token *api.ACLToken, opts *api.WriteOptions) (*api.ACLToken, *api.WriteMeta, error) { 201 index, created, meta, err := m.tokenCreate(token, opts) 202 203 services := func(token *api.ACLToken) []string { 204 if token == nil { 205 return nil 206 } 207 var names []string 208 for _, id := range token.ServiceIdentities { 209 names = append(names, id.ServiceName) 210 } 211 return names 212 }(created) 213 214 description := func(token *api.ACLToken) string { 215 if token == nil { 216 return "<nil>" 217 } 218 return token.Description 219 }(created) 220 221 accessor := func(token *api.ACLToken) string { 222 if token == nil { 223 return "<nil>" 224 } 225 return token.AccessorID 226 }(created) 227 228 secret := func(token *api.ACLToken) string { 229 if token == nil { 230 return "<nil>" 231 } 232 return token.SecretID 233 }(created) 234 235 m.logger.Trace("TokenCreate()", "description", description, "service_identities", services, "accessor", accessor, "secret", secret, "index", index, "error", err) 236 return created, meta, err 237 } 238 239 func (m *MockACLsAPI) tokenCreate(token *api.ACLToken, _ *api.WriteOptions) (uint64, *api.ACLToken, *api.WriteMeta, error) { 240 m.lock.Lock() 241 defer m.lock.Unlock() 242 243 m.state.index++ 244 245 if m.state.error != nil { 246 return m.state.index, nil, nil, m.state.error 247 } 248 249 secret := &api.ACLToken{ 250 CreateIndex: m.state.index, 251 ModifyIndex: m.state.index, 252 AccessorID: uuid.Generate(), 253 SecretID: uuid.Generate(), 254 Description: token.Description, 255 ServiceIdentities: token.ServiceIdentities, 256 CreateTime: time.Now(), 257 } 258 259 m.state.tokens[secret.AccessorID] = secret 260 261 w := &api.WriteMeta{ 262 RequestTime: 1 * time.Millisecond, 263 } 264 265 return m.state.index, secret, w, nil 266 } 267 268 // TokenDelete is a mock of ACLsAPI.TokenDelete 269 func (m *MockACLsAPI) TokenDelete(accessorID string, opts *api.WriteOptions) (*api.WriteMeta, error) { 270 meta, err := m.tokenDelete(accessorID, opts) 271 m.logger.Trace("TokenDelete()", "accessor", accessorID, "error", err) 272 return meta, err 273 } 274 275 func (m *MockACLsAPI) tokenDelete(tokenID string, _ *api.WriteOptions) (*api.WriteMeta, error) { 276 m.lock.Lock() 277 defer m.lock.Unlock() 278 279 m.state.index++ 280 281 if m.state.error != nil { 282 return nil, m.state.error 283 } 284 285 if _, exists := m.state.tokens[tokenID]; !exists { 286 return nil, nil // consul no-ops delete of non-existent token 287 } 288 289 delete(m.state.tokens, tokenID) 290 291 m.logger.Trace("TokenDelete()") 292 293 return nil, nil 294 } 295 296 // TokenList is a mock of ACLsAPI.TokenList 297 func (m *MockACLsAPI) TokenList(_ *api.QueryOptions) ([]*api.ACLTokenListEntry, *api.QueryMeta, error) { 298 m.lock.Lock() 299 defer m.lock.Unlock() 300 301 //todo(shoenig): will need this for background token reconciliation 302 // coming in another issue 303 304 return nil, nil, nil 305 }