github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/state/acl_test.go (about) 1 package state 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/hashicorp/consul/acl" 8 "github.com/hashicorp/consul/agent/structs" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func setupGlobalManagement(t *testing.T, s *Store) { 13 policy := structs.ACLPolicy{ 14 ID: structs.ACLPolicyGlobalManagementID, 15 Name: "global-management", 16 Description: "Builtin Policy that grants unlimited access", 17 Rules: structs.ACLPolicyGlobalManagement, 18 Syntax: acl.SyntaxCurrent, 19 } 20 policy.SetHash(true) 21 require.NoError(t, s.ACLPolicySet(1, &policy)) 22 } 23 24 func setupAnonymous(t *testing.T, s *Store) { 25 token := structs.ACLToken{ 26 AccessorID: structs.ACLTokenAnonymousID, 27 SecretID: "anonymous", 28 Description: "Anonymous Token", 29 } 30 token.SetHash(true) 31 require.NoError(t, s.ACLTokenSet(1, &token, false)) 32 } 33 34 func testACLStateStore(t *testing.T) *Store { 35 s := testStateStore(t) 36 setupGlobalManagement(t, s) 37 setupAnonymous(t, s) 38 return s 39 } 40 41 func setupExtraPolicies(t *testing.T, s *Store) { 42 policies := structs.ACLPolicies{ 43 &structs.ACLPolicy{ 44 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 45 Name: "node-read", 46 Description: "Allows reading all node information", 47 Rules: `node_prefix "" { policy = "read" }`, 48 Syntax: acl.SyntaxCurrent, 49 }, 50 } 51 52 for _, policy := range policies { 53 policy.SetHash(true) 54 } 55 56 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 57 } 58 59 func testACLTokensStateStore(t *testing.T) *Store { 60 s := testACLStateStore(t) 61 setupExtraPolicies(t, s) 62 return s 63 } 64 65 func TestStateStore_ACLBootstrap(t *testing.T) { 66 t.Parallel() 67 token1 := &structs.ACLToken{ 68 AccessorID: "30fca056-9fbb-4455-b94a-bf0e2bc575d6", 69 SecretID: "cbe1c6fd-d865-4034-9d6d-64fef7fb46a9", 70 Description: "Bootstrap Token (Global Management)", 71 Policies: []structs.ACLTokenPolicyLink{ 72 { 73 ID: structs.ACLPolicyGlobalManagementID, 74 }, 75 }, 76 CreateTime: time.Now(), 77 Local: false, 78 // DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs 79 Type: structs.ACLTokenTypeManagement, 80 } 81 82 token2 := &structs.ACLToken{ 83 AccessorID: "fd5c17fa-1503-4422-a424-dd44cdf35919", 84 SecretID: "7fd776b1-ded1-4d15-931b-db4770fc2317", 85 Description: "Bootstrap Token (Global Management)", 86 Policies: []structs.ACLTokenPolicyLink{ 87 { 88 ID: structs.ACLPolicyGlobalManagementID, 89 }, 90 }, 91 CreateTime: time.Now(), 92 Local: false, 93 // DEPRECATED (ACL-Legacy-Compat) - This is used so that the bootstrap token is still visible via the v1 acl APIs 94 Type: structs.ACLTokenTypeManagement, 95 } 96 97 stripIrrelevantFields := func(token *structs.ACLToken) *structs.ACLToken { 98 tokenCopy := token.Clone() 99 // When comparing the tokens disregard the policy link names. This 100 // data is not cleanly updated in a variety of scenarios and should not 101 // be relied upon. 102 for i, _ := range tokenCopy.Policies { 103 tokenCopy.Policies[i].Name = "" 104 } 105 // The raft indexes won't match either because the requester will not 106 // have access to that. 107 tokenCopy.RaftIndex = structs.RaftIndex{} 108 return tokenCopy 109 } 110 compareTokens := func(expected, actual *structs.ACLToken) { 111 require.Equal(t, stripIrrelevantFields(expected), stripIrrelevantFields(actual)) 112 } 113 114 s := testStateStore(t) 115 setupGlobalManagement(t, s) 116 117 canBootstrap, index, err := s.CanBootstrapACLToken() 118 require.NoError(t, err) 119 require.True(t, canBootstrap) 120 require.Equal(t, uint64(0), index) 121 122 // Perform a regular bootstrap. 123 require.NoError(t, s.ACLBootstrap(3, 0, token1.Clone(), false)) 124 125 // Make sure we can't bootstrap again 126 canBootstrap, index, err = s.CanBootstrapACLToken() 127 require.NoError(t, err) 128 require.False(t, canBootstrap) 129 require.Equal(t, uint64(3), index) 130 131 // Make sure another attempt fails. 132 err = s.ACLBootstrap(4, 0, token2.Clone(), false) 133 require.Error(t, err) 134 require.Equal(t, structs.ACLBootstrapNotAllowedErr, err) 135 136 // Check that the bootstrap state remains the same. 137 canBootstrap, index, err = s.CanBootstrapACLToken() 138 require.NoError(t, err) 139 require.False(t, canBootstrap) 140 require.Equal(t, uint64(3), index) 141 142 // Make sure the ACLs are in an expected state. 143 _, tokens, err := s.ACLTokenList(nil, true, true, "") 144 require.NoError(t, err) 145 require.Len(t, tokens, 1) 146 compareTokens(token1, tokens[0]) 147 148 // bootstrap reset 149 err = s.ACLBootstrap(32, index-1, token2.Clone(), false) 150 require.Error(t, err) 151 require.Equal(t, structs.ACLBootstrapInvalidResetIndexErr, err) 152 153 // bootstrap reset 154 err = s.ACLBootstrap(32, index, token2.Clone(), false) 155 require.NoError(t, err) 156 157 _, tokens, err = s.ACLTokenList(nil, true, true, "") 158 require.NoError(t, err) 159 require.Len(t, tokens, 2) 160 } 161 162 func TestStateStore_ACLToken_SetGet_Legacy(t *testing.T) { 163 t.Parallel() 164 t.Run("Legacy - Existing With Policies", func(t *testing.T) { 165 t.Parallel() 166 s := testACLTokensStateStore(t) 167 168 token := &structs.ACLToken{ 169 AccessorID: "c8d0378c-566a-4535-8fc9-c883a8cc9849", 170 SecretID: "6d48ce91-2558-4098-bdab-8737e4e57d5f", 171 Policies: []structs.ACLTokenPolicyLink{ 172 structs.ACLTokenPolicyLink{ 173 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 174 }, 175 }, 176 } 177 178 require.NoError(t, s.ACLTokenSet(2, token, false)) 179 180 // legacy flag is set so it should disallow setting this token 181 err := s.ACLTokenSet(3, token, true) 182 require.Error(t, err) 183 }) 184 185 t.Run("Legacy - Empty Type", func(t *testing.T) { 186 t.Parallel() 187 s := testACLTokensStateStore(t) 188 token := &structs.ACLToken{ 189 AccessorID: "271cd056-0038-4fd3-90e5-f97f50fb3ac8", 190 SecretID: "c0056225-5785-43b3-9b77-3954f06d6aee", 191 } 192 193 require.NoError(t, s.ACLTokenSet(2, token, false)) 194 195 // legacy flag is set so it should disallow setting this token 196 err := s.ACLTokenSet(3, token, true) 197 require.Error(t, err) 198 }) 199 200 t.Run("Legacy - New", func(t *testing.T) { 201 t.Parallel() 202 s := testACLTokensStateStore(t) 203 token := &structs.ACLToken{ 204 SecretID: "2989e271-6169-4f34-8fec-4618d70008fb", 205 Type: structs.ACLTokenTypeClient, 206 Rules: `service "" { policy = "read" }`, 207 } 208 209 require.NoError(t, s.ACLTokenSet(2, token, true)) 210 211 idx, rtoken, err := s.ACLTokenGetBySecret(nil, token.SecretID) 212 require.NoError(t, err) 213 require.Equal(t, uint64(2), idx) 214 require.NotNil(t, rtoken) 215 require.Equal(t, "", rtoken.AccessorID) 216 require.Equal(t, "2989e271-6169-4f34-8fec-4618d70008fb", rtoken.SecretID) 217 require.Equal(t, "", rtoken.Description) 218 require.Len(t, rtoken.Policies, 0) 219 require.Equal(t, structs.ACLTokenTypeClient, rtoken.Type) 220 require.Equal(t, uint64(2), rtoken.CreateIndex) 221 require.Equal(t, uint64(2), rtoken.ModifyIndex) 222 }) 223 224 t.Run("Legacy - Update", func(t *testing.T) { 225 t.Parallel() 226 s := testACLTokensStateStore(t) 227 original := &structs.ACLToken{ 228 SecretID: "2989e271-6169-4f34-8fec-4618d70008fb", 229 Type: structs.ACLTokenTypeClient, 230 Rules: `service "" { policy = "read" }`, 231 } 232 233 require.NoError(t, s.ACLTokenSet(2, original, true)) 234 235 updatedRules := `service "" { policy = "read" } service "foo" { policy = "deny"}` 236 update := &structs.ACLToken{ 237 SecretID: "2989e271-6169-4f34-8fec-4618d70008fb", 238 Type: structs.ACLTokenTypeClient, 239 Rules: updatedRules, 240 } 241 242 require.NoError(t, s.ACLTokenSet(3, update, true)) 243 244 idx, rtoken, err := s.ACLTokenGetBySecret(nil, original.SecretID) 245 require.NoError(t, err) 246 require.Equal(t, uint64(3), idx) 247 require.NotNil(t, rtoken) 248 require.Equal(t, "", rtoken.AccessorID) 249 require.Equal(t, "2989e271-6169-4f34-8fec-4618d70008fb", rtoken.SecretID) 250 require.Equal(t, "", rtoken.Description) 251 require.Len(t, rtoken.Policies, 0) 252 require.Equal(t, structs.ACLTokenTypeClient, rtoken.Type) 253 require.Equal(t, updatedRules, rtoken.Rules) 254 require.Equal(t, uint64(2), rtoken.CreateIndex) 255 require.Equal(t, uint64(3), rtoken.ModifyIndex) 256 }) 257 } 258 259 func TestStateStore_ACLToken_SetGet(t *testing.T) { 260 t.Parallel() 261 t.Run("Missing Secret", func(t *testing.T) { 262 t.Parallel() 263 s := testACLTokensStateStore(t) 264 token := &structs.ACLToken{ 265 AccessorID: "39171632-6f34-4411-827f-9416403687f4", 266 } 267 268 err := s.ACLTokenSet(2, token, false) 269 require.Error(t, err) 270 require.Equal(t, ErrMissingACLTokenSecret, err) 271 }) 272 273 t.Run("Missing Accessor", func(t *testing.T) { 274 t.Parallel() 275 s := testACLTokensStateStore(t) 276 token := &structs.ACLToken{ 277 SecretID: "39171632-6f34-4411-827f-9416403687f4", 278 } 279 280 err := s.ACLTokenSet(2, token, false) 281 require.Error(t, err) 282 require.Equal(t, ErrMissingACLTokenAccessor, err) 283 }) 284 285 t.Run("Missing Policy ID", func(t *testing.T) { 286 t.Parallel() 287 s := testACLTokensStateStore(t) 288 token := &structs.ACLToken{ 289 AccessorID: "daf37c07-d04d-4fd5-9678-a8206a57d61a", 290 SecretID: "39171632-6f34-4411-827f-9416403687f4", 291 Policies: []structs.ACLTokenPolicyLink{ 292 structs.ACLTokenPolicyLink{ 293 Name: "no-id", 294 }, 295 }, 296 } 297 298 err := s.ACLTokenSet(2, token, false) 299 require.Error(t, err) 300 }) 301 302 t.Run("Unresolvable Policy ID", func(t *testing.T) { 303 t.Parallel() 304 s := testACLTokensStateStore(t) 305 token := &structs.ACLToken{ 306 AccessorID: "daf37c07-d04d-4fd5-9678-a8206a57d61a", 307 SecretID: "39171632-6f34-4411-827f-9416403687f4", 308 Policies: []structs.ACLTokenPolicyLink{ 309 structs.ACLTokenPolicyLink{ 310 ID: "4f20e379-b496-4b99-9599-19a197126490", 311 }, 312 }, 313 } 314 315 err := s.ACLTokenSet(2, token, false) 316 require.Error(t, err) 317 }) 318 319 t.Run("New", func(t *testing.T) { 320 t.Parallel() 321 s := testACLTokensStateStore(t) 322 token := &structs.ACLToken{ 323 AccessorID: "daf37c07-d04d-4fd5-9678-a8206a57d61a", 324 SecretID: "39171632-6f34-4411-827f-9416403687f4", 325 Policies: []structs.ACLTokenPolicyLink{ 326 structs.ACLTokenPolicyLink{ 327 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 328 }, 329 }, 330 } 331 332 require.NoError(t, s.ACLTokenSet(2, token, false)) 333 334 idx, rtoken, err := s.ACLTokenGetByAccessor(nil, "daf37c07-d04d-4fd5-9678-a8206a57d61a") 335 require.NoError(t, err) 336 require.Equal(t, uint64(2), idx) 337 // pointer equality 338 require.True(t, rtoken == token) 339 require.Equal(t, uint64(2), rtoken.CreateIndex) 340 require.Equal(t, uint64(2), rtoken.ModifyIndex) 341 require.Len(t, rtoken.Policies, 1) 342 require.Equal(t, "node-read", rtoken.Policies[0].Name) 343 }) 344 345 t.Run("Update", func(t *testing.T) { 346 t.Parallel() 347 s := testACLTokensStateStore(t) 348 token := &structs.ACLToken{ 349 AccessorID: "daf37c07-d04d-4fd5-9678-a8206a57d61a", 350 SecretID: "39171632-6f34-4411-827f-9416403687f4", 351 Policies: []structs.ACLTokenPolicyLink{ 352 structs.ACLTokenPolicyLink{ 353 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 354 }, 355 }, 356 } 357 358 require.NoError(t, s.ACLTokenSet(2, token, false)) 359 360 updated := &structs.ACLToken{ 361 AccessorID: "daf37c07-d04d-4fd5-9678-a8206a57d61a", 362 SecretID: "39171632-6f34-4411-827f-9416403687f4", 363 Policies: []structs.ACLTokenPolicyLink{ 364 structs.ACLTokenPolicyLink{ 365 ID: structs.ACLPolicyGlobalManagementID, 366 }, 367 }, 368 } 369 370 require.NoError(t, s.ACLTokenSet(3, updated, false)) 371 372 idx, rtoken, err := s.ACLTokenGetByAccessor(nil, "daf37c07-d04d-4fd5-9678-a8206a57d61a") 373 require.NoError(t, err) 374 require.Equal(t, uint64(3), idx) 375 // pointer equality 376 require.True(t, rtoken == updated) 377 require.Equal(t, uint64(2), rtoken.CreateIndex) 378 require.Equal(t, uint64(3), rtoken.ModifyIndex) 379 require.Len(t, rtoken.Policies, 1) 380 require.Equal(t, structs.ACLPolicyGlobalManagementID, rtoken.Policies[0].ID) 381 require.Equal(t, "global-management", rtoken.Policies[0].Name) 382 }) 383 } 384 385 func TestStateStore_ACLTokens_UpsertBatchRead(t *testing.T) { 386 t.Parallel() 387 388 t.Run("CAS - Deleted", func(t *testing.T) { 389 t.Parallel() 390 s := testACLTokensStateStore(t) 391 392 // CAS op + nonexistent token should not work. This prevents modifying 393 // deleted tokens 394 395 tokens := structs.ACLTokens{ 396 &structs.ACLToken{ 397 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 398 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 399 RaftIndex: structs.RaftIndex{CreateIndex: 2, ModifyIndex: 3}, 400 }, 401 } 402 403 require.NoError(t, s.ACLTokenBatchSet(2, tokens, true)) 404 405 _, token, err := s.ACLTokenGetByAccessor(nil, tokens[0].AccessorID) 406 require.NoError(t, err) 407 require.Nil(t, token) 408 }) 409 410 t.Run("CAS - Updated", func(t *testing.T) { 411 t.Parallel() 412 s := testACLTokensStateStore(t) 413 414 // CAS op + nonexistent token should not work. This prevents modifying 415 // deleted tokens 416 417 tokens := structs.ACLTokens{ 418 &structs.ACLToken{ 419 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 420 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 421 }, 422 } 423 424 require.NoError(t, s.ACLTokenBatchSet(5, tokens, true)) 425 426 updated := structs.ACLTokens{ 427 &structs.ACLToken{ 428 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 429 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 430 Description: "wont update", 431 RaftIndex: structs.RaftIndex{CreateIndex: 1, ModifyIndex: 4}, 432 }, 433 } 434 435 require.NoError(t, s.ACLTokenBatchSet(6, updated, true)) 436 437 _, token, err := s.ACLTokenGetByAccessor(nil, tokens[0].AccessorID) 438 require.NoError(t, err) 439 require.NotNil(t, token) 440 require.Equal(t, "", token.Description) 441 }) 442 443 t.Run("CAS - Already Exists", func(t *testing.T) { 444 t.Parallel() 445 s := testACLTokensStateStore(t) 446 447 tokens := structs.ACLTokens{ 448 &structs.ACLToken{ 449 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 450 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 451 }, 452 } 453 454 require.NoError(t, s.ACLTokenBatchSet(5, tokens, true)) 455 456 updated := structs.ACLTokens{ 457 &structs.ACLToken{ 458 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 459 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 460 Description: "wont update", 461 }, 462 } 463 464 require.NoError(t, s.ACLTokenBatchSet(6, updated, true)) 465 466 _, token, err := s.ACLTokenGetByAccessor(nil, tokens[0].AccessorID) 467 require.NoError(t, err) 468 require.NotNil(t, token) 469 require.Equal(t, "", token.Description) 470 }) 471 472 t.Run("Normal", func(t *testing.T) { 473 t.Parallel() 474 s := testACLTokensStateStore(t) 475 476 tokens := structs.ACLTokens{ 477 &structs.ACLToken{ 478 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 479 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 480 }, 481 &structs.ACLToken{ 482 AccessorID: "a2719052-40b3-4a4b-baeb-f3df1831a217", 483 SecretID: "ff826eaf-4b88-4881-aaef-52b1089e5d5d", 484 }, 485 } 486 487 require.NoError(t, s.ACLTokenBatchSet(2, tokens, false)) 488 489 idx, rtokens, err := s.ACLTokenBatchGet(nil, []string{ 490 "a4f68bd6-3af5-4f56-b764-3c6f20247879", 491 "a2719052-40b3-4a4b-baeb-f3df1831a217"}) 492 493 require.NoError(t, err) 494 require.Equal(t, uint64(2), idx) 495 require.Len(t, rtokens, 2) 496 require.ElementsMatch(t, tokens, rtokens) 497 require.Equal(t, uint64(2), rtokens[0].CreateIndex) 498 require.Equal(t, uint64(2), rtokens[0].ModifyIndex) 499 require.Equal(t, uint64(2), rtokens[1].CreateIndex) 500 require.Equal(t, uint64(2), rtokens[1].ModifyIndex) 501 }) 502 503 t.Run("Update", func(t *testing.T) { 504 t.Parallel() 505 s := testACLTokensStateStore(t) 506 507 tokens := structs.ACLTokens{ 508 &structs.ACLToken{ 509 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 510 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 511 }, 512 &structs.ACLToken{ 513 AccessorID: "a2719052-40b3-4a4b-baeb-f3df1831a217", 514 SecretID: "ff826eaf-4b88-4881-aaef-52b1089e5d5d", 515 }, 516 } 517 518 require.NoError(t, s.ACLTokenBatchSet(2, tokens, false)) 519 520 updates := structs.ACLTokens{ 521 &structs.ACLToken{ 522 AccessorID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 523 SecretID: "00ff4564-dd96-4d1b-8ad6-578a08279f79", 524 Description: "first token", 525 Policies: []structs.ACLTokenPolicyLink{ 526 structs.ACLTokenPolicyLink{ 527 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 528 }, 529 }, 530 }, 531 &structs.ACLToken{ 532 AccessorID: "a2719052-40b3-4a4b-baeb-f3df1831a217", 533 SecretID: "ff826eaf-4b88-4881-aaef-52b1089e5d5d", 534 Description: "second token", 535 Policies: []structs.ACLTokenPolicyLink{ 536 structs.ACLTokenPolicyLink{ 537 ID: structs.ACLPolicyGlobalManagementID, 538 }, 539 }, 540 }, 541 } 542 543 require.NoError(t, s.ACLTokenBatchSet(3, updates, false)) 544 545 idx, rtokens, err := s.ACLTokenBatchGet(nil, []string{ 546 "a4f68bd6-3af5-4f56-b764-3c6f20247879", 547 "a2719052-40b3-4a4b-baeb-f3df1831a217"}) 548 549 require.NoError(t, err) 550 require.Equal(t, uint64(3), idx) 551 require.Len(t, rtokens, 2) 552 rtokens.Sort() 553 require.Equal(t, "a2719052-40b3-4a4b-baeb-f3df1831a217", rtokens[0].AccessorID) 554 require.Equal(t, "ff826eaf-4b88-4881-aaef-52b1089e5d5d", rtokens[0].SecretID) 555 require.Equal(t, "second token", rtokens[0].Description) 556 require.Len(t, rtokens[0].Policies, 1) 557 require.Equal(t, structs.ACLPolicyGlobalManagementID, rtokens[0].Policies[0].ID) 558 require.Equal(t, "global-management", rtokens[0].Policies[0].Name) 559 require.Equal(t, uint64(2), rtokens[0].CreateIndex) 560 require.Equal(t, uint64(3), rtokens[0].ModifyIndex) 561 562 require.Equal(t, "a4f68bd6-3af5-4f56-b764-3c6f20247879", rtokens[1].AccessorID) 563 require.Equal(t, "00ff4564-dd96-4d1b-8ad6-578a08279f79", rtokens[1].SecretID) 564 require.Equal(t, "first token", rtokens[1].Description) 565 require.Len(t, rtokens[1].Policies, 1) 566 require.Equal(t, "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", rtokens[1].Policies[0].ID) 567 require.Equal(t, "node-read", rtokens[1].Policies[0].Name) 568 require.Equal(t, uint64(2), rtokens[1].CreateIndex) 569 require.Equal(t, uint64(3), rtokens[1].ModifyIndex) 570 }) 571 } 572 573 func TestStateStore_ACLTokens_ListUpgradeable(t *testing.T) { 574 t.Parallel() 575 s := testACLTokensStateStore(t) 576 577 require.NoError(t, s.ACLTokenSet(2, &structs.ACLToken{ 578 SecretID: "34ec8eb3-095d-417a-a937-b439af7a8e8b", 579 Type: structs.ACLTokenTypeManagement, 580 }, true)) 581 582 require.NoError(t, s.ACLTokenSet(3, &structs.ACLToken{ 583 SecretID: "8de2dd39-134d-4cb1-950b-b7ab96ea20ba", 584 Type: structs.ACLTokenTypeManagement, 585 }, true)) 586 587 require.NoError(t, s.ACLTokenSet(4, &structs.ACLToken{ 588 SecretID: "548bdb8e-c0d6-477b-bcc4-67fb836e9e61", 589 Type: structs.ACLTokenTypeManagement, 590 }, true)) 591 592 require.NoError(t, s.ACLTokenSet(5, &structs.ACLToken{ 593 SecretID: "3ee33676-d9b8-4144-bf0b-92618cff438b", 594 Type: structs.ACLTokenTypeManagement, 595 }, true)) 596 597 require.NoError(t, s.ACLTokenSet(6, &structs.ACLToken{ 598 SecretID: "fa9d658a-6e26-42ab-a5f0-1ea05c893dee", 599 Type: structs.ACLTokenTypeManagement, 600 }, true)) 601 602 tokens, _, err := s.ACLTokenListUpgradeable(3) 603 require.NoError(t, err) 604 require.Len(t, tokens, 3) 605 606 tokens, _, err = s.ACLTokenListUpgradeable(10) 607 require.NoError(t, err) 608 require.Len(t, tokens, 5) 609 610 updates := structs.ACLTokens{ 611 &structs.ACLToken{ 612 AccessorID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 613 SecretID: "34ec8eb3-095d-417a-a937-b439af7a8e8b", 614 Policies: []structs.ACLTokenPolicyLink{ 615 structs.ACLTokenPolicyLink{ 616 ID: structs.ACLPolicyGlobalManagementID, 617 }, 618 }, 619 }, 620 &structs.ACLToken{ 621 AccessorID: "54866514-3cf2-4fec-8a8a-710583831834", 622 SecretID: "8de2dd39-134d-4cb1-950b-b7ab96ea20ba", 623 Policies: []structs.ACLTokenPolicyLink{ 624 structs.ACLTokenPolicyLink{ 625 ID: structs.ACLPolicyGlobalManagementID, 626 }, 627 }, 628 }, 629 &structs.ACLToken{ 630 AccessorID: "47eea4da-bda1-48a6-901c-3e36d2d9262f", 631 SecretID: "548bdb8e-c0d6-477b-bcc4-67fb836e9e61", 632 Policies: []structs.ACLTokenPolicyLink{ 633 structs.ACLTokenPolicyLink{ 634 ID: structs.ACLPolicyGlobalManagementID, 635 }, 636 }, 637 }, 638 &structs.ACLToken{ 639 AccessorID: "af1dffe5-8ac2-4282-9336-aeed9f7d951a", 640 SecretID: "3ee33676-d9b8-4144-bf0b-92618cff438b", 641 Policies: []structs.ACLTokenPolicyLink{ 642 structs.ACLTokenPolicyLink{ 643 ID: structs.ACLPolicyGlobalManagementID, 644 }, 645 }, 646 }, 647 &structs.ACLToken{ 648 AccessorID: "511df589-3316-4784-b503-6e25ead4d4e1", 649 SecretID: "fa9d658a-6e26-42ab-a5f0-1ea05c893dee", 650 Policies: []structs.ACLTokenPolicyLink{ 651 structs.ACLTokenPolicyLink{ 652 ID: structs.ACLPolicyGlobalManagementID, 653 }, 654 }, 655 }, 656 } 657 658 require.NoError(t, s.ACLTokenBatchSet(7, updates, false)) 659 660 tokens, _, err = s.ACLTokenListUpgradeable(10) 661 require.NoError(t, err) 662 require.Len(t, tokens, 0) 663 } 664 665 func TestStateStore_ACLToken_List(t *testing.T) { 666 t.Parallel() 667 s := testACLTokensStateStore(t) 668 669 tokens := structs.ACLTokens{ 670 // the local token 671 &structs.ACLToken{ 672 AccessorID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 673 SecretID: "34ec8eb3-095d-417a-a937-b439af7a8e8b", 674 Policies: []structs.ACLTokenPolicyLink{ 675 structs.ACLTokenPolicyLink{ 676 ID: structs.ACLPolicyGlobalManagementID, 677 }, 678 }, 679 Local: true, 680 }, 681 // the global token 682 &structs.ACLToken{ 683 AccessorID: "54866514-3cf2-4fec-8a8a-710583831834", 684 SecretID: "8de2dd39-134d-4cb1-950b-b7ab96ea20ba", 685 Policies: []structs.ACLTokenPolicyLink{ 686 structs.ACLTokenPolicyLink{ 687 ID: structs.ACLPolicyGlobalManagementID, 688 }, 689 }, 690 }, 691 // the policy specific token 692 &structs.ACLToken{ 693 AccessorID: "47eea4da-bda1-48a6-901c-3e36d2d9262f", 694 SecretID: "548bdb8e-c0d6-477b-bcc4-67fb836e9e61", 695 Policies: []structs.ACLTokenPolicyLink{ 696 structs.ACLTokenPolicyLink{ 697 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 698 }, 699 }, 700 }, 701 // the policy specific token and local 702 &structs.ACLToken{ 703 AccessorID: "4915fc9d-3726-4171-b588-6c271f45eecd", 704 SecretID: "f6998577-fd9b-4e6c-b202-cc3820513d32", 705 Policies: []structs.ACLTokenPolicyLink{ 706 structs.ACLTokenPolicyLink{ 707 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 708 }, 709 }, 710 Local: true, 711 }, 712 } 713 714 require.NoError(t, s.ACLTokenBatchSet(2, tokens, false)) 715 716 type testCase struct { 717 name string 718 local bool 719 global bool 720 policy string 721 accessors []string 722 } 723 724 cases := []testCase{ 725 { 726 name: "Global", 727 local: false, 728 global: true, 729 policy: "", 730 accessors: []string{ 731 structs.ACLTokenAnonymousID, 732 "47eea4da-bda1-48a6-901c-3e36d2d9262f", 733 "54866514-3cf2-4fec-8a8a-710583831834", 734 }, 735 }, 736 { 737 name: "Local", 738 local: true, 739 global: false, 740 policy: "", 741 accessors: []string{ 742 "4915fc9d-3726-4171-b588-6c271f45eecd", 743 "f1093997-b6c7-496d-bfb8-6b1b1895641b", 744 }, 745 }, 746 { 747 name: "Policy", 748 local: true, 749 global: true, 750 policy: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 751 accessors: []string{ 752 "47eea4da-bda1-48a6-901c-3e36d2d9262f", 753 "4915fc9d-3726-4171-b588-6c271f45eecd", 754 }, 755 }, 756 { 757 name: "Policy - Local", 758 local: true, 759 global: false, 760 policy: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 761 accessors: []string{ 762 "4915fc9d-3726-4171-b588-6c271f45eecd", 763 }, 764 }, 765 { 766 name: "Policy - Global", 767 local: false, 768 global: true, 769 policy: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 770 accessors: []string{ 771 "47eea4da-bda1-48a6-901c-3e36d2d9262f", 772 "4915fc9d-3726-4171-b588-6c271f45eecd", 773 }, 774 }, 775 { 776 name: "All", 777 local: true, 778 global: true, 779 policy: "", 780 accessors: []string{ 781 structs.ACLTokenAnonymousID, 782 "47eea4da-bda1-48a6-901c-3e36d2d9262f", 783 "4915fc9d-3726-4171-b588-6c271f45eecd", 784 "54866514-3cf2-4fec-8a8a-710583831834", 785 "f1093997-b6c7-496d-bfb8-6b1b1895641b", 786 }, 787 }, 788 } 789 790 for _, tc := range cases { 791 t.Run(tc.name, func(t *testing.T) { 792 t.Parallel() 793 _, tokens, err := s.ACLTokenList(nil, tc.local, tc.global, tc.policy) 794 require.NoError(t, err) 795 require.Len(t, tokens, len(tc.accessors)) 796 tokens.Sort() 797 for i, token := range tokens { 798 require.Equal(t, tc.accessors[i], token.AccessorID) 799 } 800 }) 801 } 802 } 803 804 func TestStateStore_ACLToken_FixupPolicyLinks(t *testing.T) { 805 // This test wants to ensure a couple of things. 806 // 807 // 1. Doing a token list/get should never modify the data 808 // tracked by memdb 809 // 2. Token list/get operations should return an accurate set 810 // of policy links 811 t.Parallel() 812 s := testACLTokensStateStore(t) 813 814 // the policy specific token 815 token := &structs.ACLToken{ 816 AccessorID: "47eea4da-bda1-48a6-901c-3e36d2d9262f", 817 SecretID: "548bdb8e-c0d6-477b-bcc4-67fb836e9e61", 818 Policies: []structs.ACLTokenPolicyLink{ 819 structs.ACLTokenPolicyLink{ 820 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 821 }, 822 }, 823 } 824 825 require.NoError(t, s.ACLTokenSet(2, token, false)) 826 827 _, retrieved, err := s.ACLTokenGetByAccessor(nil, token.AccessorID) 828 require.NoError(t, err) 829 // pointer equality check these should be identical 830 require.True(t, token == retrieved) 831 require.Len(t, retrieved.Policies, 1) 832 require.Equal(t, "node-read", retrieved.Policies[0].Name) 833 834 // rename the policy 835 renamed := &structs.ACLPolicy{ 836 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 837 Name: "node-read-renamed", 838 Description: "Allows reading all node information", 839 Rules: `node_prefix "" { policy = "read" }`, 840 Syntax: acl.SyntaxCurrent, 841 } 842 renamed.SetHash(true) 843 require.NoError(t, s.ACLPolicySet(3, renamed)) 844 845 // retrieve the token again 846 _, retrieved, err = s.ACLTokenGetByAccessor(nil, token.AccessorID) 847 require.NoError(t, err) 848 // pointer equality check these should be different if we cloned things appropriately 849 require.True(t, token != retrieved) 850 require.Len(t, retrieved.Policies, 1) 851 require.Equal(t, "node-read-renamed", retrieved.Policies[0].Name) 852 853 // list tokens without stale links 854 _, tokens, err := s.ACLTokenList(nil, true, true, "") 855 require.NoError(t, err) 856 857 found := false 858 for _, tok := range tokens { 859 if tok.AccessorID == token.AccessorID { 860 // these pointers shouldn't be equal because the link should have been fixed 861 require.True(t, tok != token) 862 require.Len(t, tok.Policies, 1) 863 require.Equal(t, "node-read-renamed", tok.Policies[0].Name) 864 found = true 865 break 866 } 867 } 868 require.True(t, found) 869 870 // batch get without stale links 871 _, tokens, err = s.ACLTokenBatchGet(nil, []string{token.AccessorID}) 872 require.NoError(t, err) 873 874 found = false 875 for _, tok := range tokens { 876 if tok.AccessorID == token.AccessorID { 877 // these pointers shouldn't be equal because the link should have been fixed 878 require.True(t, tok != token) 879 require.Len(t, tok.Policies, 1) 880 require.Equal(t, "node-read-renamed", tok.Policies[0].Name) 881 found = true 882 break 883 } 884 } 885 require.True(t, found) 886 887 // delete the policy 888 require.NoError(t, s.ACLPolicyDeleteByID(4, "a0625e95-9b3e-42de-a8d6-ceef5b6f3286")) 889 890 // retrieve the token again 891 _, retrieved, err = s.ACLTokenGetByAccessor(nil, token.AccessorID) 892 require.NoError(t, err) 893 // pointer equality check these should be different if we cloned things appropriately 894 require.True(t, token != retrieved) 895 require.Len(t, retrieved.Policies, 0) 896 897 // list tokens without stale links 898 _, tokens, err = s.ACLTokenList(nil, true, true, "") 899 require.NoError(t, err) 900 901 found = false 902 for _, tok := range tokens { 903 if tok.AccessorID == token.AccessorID { 904 // these pointers shouldn't be equal because the link should have been fixed 905 require.True(t, tok != token) 906 require.Len(t, tok.Policies, 0) 907 found = true 908 break 909 } 910 } 911 require.True(t, found) 912 913 // batch get without stale links 914 _, tokens, err = s.ACLTokenBatchGet(nil, []string{token.AccessorID}) 915 require.NoError(t, err) 916 917 found = false 918 for _, tok := range tokens { 919 if tok.AccessorID == token.AccessorID { 920 // these pointers shouldn't be equal because the link should have been fixed 921 require.True(t, tok != token) 922 require.Len(t, tok.Policies, 0) 923 found = true 924 break 925 } 926 } 927 require.True(t, found) 928 } 929 930 func TestStateStore_ACLToken_Delete(t *testing.T) { 931 t.Parallel() 932 933 t.Run("Accessor", func(t *testing.T) { 934 t.Parallel() 935 s := testACLTokensStateStore(t) 936 937 token := &structs.ACLToken{ 938 AccessorID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 939 SecretID: "34ec8eb3-095d-417a-a937-b439af7a8e8b", 940 Policies: []structs.ACLTokenPolicyLink{ 941 structs.ACLTokenPolicyLink{ 942 ID: structs.ACLPolicyGlobalManagementID, 943 }, 944 }, 945 Local: true, 946 } 947 948 require.NoError(t, s.ACLTokenSet(2, token, false)) 949 950 _, rtoken, err := s.ACLTokenGetByAccessor(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 951 require.NoError(t, err) 952 require.NotNil(t, rtoken) 953 954 require.NoError(t, s.ACLTokenDeleteByAccessor(3, "f1093997-b6c7-496d-bfb8-6b1b1895641b")) 955 956 _, rtoken, err = s.ACLTokenGetByAccessor(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 957 require.NoError(t, err) 958 require.Nil(t, rtoken) 959 }) 960 961 t.Run("Secret", func(t *testing.T) { 962 t.Parallel() 963 s := testACLTokensStateStore(t) 964 965 token := &structs.ACLToken{ 966 AccessorID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 967 SecretID: "34ec8eb3-095d-417a-a937-b439af7a8e8b", 968 Policies: []structs.ACLTokenPolicyLink{ 969 structs.ACLTokenPolicyLink{ 970 ID: structs.ACLPolicyGlobalManagementID, 971 }, 972 }, 973 Local: true, 974 } 975 976 require.NoError(t, s.ACLTokenSet(2, token, false)) 977 978 _, rtoken, err := s.ACLTokenGetByAccessor(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 979 require.NoError(t, err) 980 require.NotNil(t, rtoken) 981 982 require.NoError(t, s.ACLTokenDeleteBySecret(3, "34ec8eb3-095d-417a-a937-b439af7a8e8b")) 983 984 _, rtoken, err = s.ACLTokenGetByAccessor(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 985 require.NoError(t, err) 986 require.Nil(t, rtoken) 987 }) 988 989 t.Run("Multiple", func(t *testing.T) { 990 t.Parallel() 991 s := testACLTokensStateStore(t) 992 993 tokens := structs.ACLTokens{ 994 &structs.ACLToken{ 995 AccessorID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 996 SecretID: "34ec8eb3-095d-417a-a937-b439af7a8e8b", 997 Policies: []structs.ACLTokenPolicyLink{ 998 structs.ACLTokenPolicyLink{ 999 ID: structs.ACLPolicyGlobalManagementID, 1000 }, 1001 }, 1002 Local: true, 1003 }, 1004 &structs.ACLToken{ 1005 AccessorID: "a0bfe8d4-b2f3-4b48-b387-f28afb820eab", 1006 SecretID: "be444e46-fb95-4ccc-80d5-c873f34e6fa6", 1007 Policies: []structs.ACLTokenPolicyLink{ 1008 structs.ACLTokenPolicyLink{ 1009 ID: structs.ACLPolicyGlobalManagementID, 1010 }, 1011 }, 1012 Local: true, 1013 }, 1014 } 1015 1016 require.NoError(t, s.ACLTokenBatchSet(2, tokens, false)) 1017 1018 _, rtoken, err := s.ACLTokenGetByAccessor(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 1019 require.NoError(t, err) 1020 require.NotNil(t, rtoken) 1021 _, rtoken, err = s.ACLTokenGetByAccessor(nil, "a0bfe8d4-b2f3-4b48-b387-f28afb820eab") 1022 require.NoError(t, err) 1023 require.NotNil(t, rtoken) 1024 1025 require.NoError(t, s.ACLTokenBatchDelete(2, []string{ 1026 "f1093997-b6c7-496d-bfb8-6b1b1895641b", 1027 "a0bfe8d4-b2f3-4b48-b387-f28afb820eab"})) 1028 1029 _, rtoken, err = s.ACLTokenGetByAccessor(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 1030 require.NoError(t, err) 1031 require.Nil(t, rtoken) 1032 _, rtoken, err = s.ACLTokenGetByAccessor(nil, "a0bfe8d4-b2f3-4b48-b387-f28afb820eab") 1033 require.NoError(t, err) 1034 require.Nil(t, rtoken) 1035 }) 1036 1037 t.Run("Anonymous", func(t *testing.T) { 1038 t.Parallel() 1039 s := testACLTokensStateStore(t) 1040 1041 require.Error(t, s.ACLTokenDeleteByAccessor(3, structs.ACLTokenAnonymousID)) 1042 require.Error(t, s.ACLTokenDeleteBySecret(3, "anonymous")) 1043 }) 1044 1045 t.Run("Not Found", func(t *testing.T) { 1046 t.Parallel() 1047 s := testACLStateStore(t) 1048 1049 // deletion of non-existent policies is not an error 1050 require.NoError(t, s.ACLTokenDeleteByAccessor(3, "ea58a09c-2100-4aef-816b-8ee0ade77dcd")) 1051 require.NoError(t, s.ACLTokenDeleteBySecret(3, "376d0cae-dd50-4213-9668-2c7797a7fb2d")) 1052 }) 1053 } 1054 1055 func TestStateStore_ACLPolicy_SetGet(t *testing.T) { 1056 t.Parallel() 1057 1058 t.Run("Missing ID", func(t *testing.T) { 1059 t.Parallel() 1060 s := testACLStateStore(t) 1061 1062 policy := structs.ACLPolicy{ 1063 Name: "test-policy", 1064 Description: "test", 1065 Rules: `keyring = "write"`, 1066 } 1067 1068 require.Error(t, s.ACLPolicySet(3, &policy)) 1069 }) 1070 1071 t.Run("Missing Name", func(t *testing.T) { 1072 t.Parallel() 1073 s := testACLStateStore(t) 1074 1075 policy := structs.ACLPolicy{ 1076 ID: "2c74a9b8-271c-4a21-b727-200db397c01c", 1077 Description: "test", 1078 Rules: `keyring = "write"`, 1079 } 1080 1081 require.Error(t, s.ACLPolicySet(3, &policy)) 1082 }) 1083 1084 t.Run("Global Management", func(t *testing.T) { 1085 t.Parallel() 1086 s := testACLStateStore(t) 1087 1088 t.Run("Rules", func(t *testing.T) { 1089 t.Parallel() 1090 1091 policy := structs.ACLPolicy{ 1092 ID: structs.ACLPolicyGlobalManagementID, 1093 Name: "global-management", 1094 Description: "Global Management", 1095 Rules: `acl = "write"`, 1096 } 1097 1098 require.Error(t, s.ACLPolicySet(3, &policy)) 1099 }) 1100 1101 t.Run("Datacenters", func(t *testing.T) { 1102 t.Parallel() 1103 1104 policy := structs.ACLPolicy{ 1105 ID: structs.ACLPolicyGlobalManagementID, 1106 Name: "global-management", 1107 Description: "Global Management", 1108 Rules: structs.ACLPolicyGlobalManagement, 1109 Datacenters: []string{"dc1"}, 1110 } 1111 1112 require.Error(t, s.ACLPolicySet(3, &policy)) 1113 }) 1114 1115 t.Run("Change", func(t *testing.T) { 1116 t.Parallel() 1117 1118 policy := structs.ACLPolicy{ 1119 ID: structs.ACLPolicyGlobalManagementID, 1120 Name: "management", 1121 Description: "Modified", 1122 Rules: structs.ACLPolicyGlobalManagement, 1123 } 1124 1125 require.NoError(t, s.ACLPolicySet(3, &policy)) 1126 1127 _, rpolicy, err := s.ACLPolicyGetByName(nil, "management") 1128 require.NoError(t, err) 1129 require.NotNil(t, rpolicy) 1130 require.Equal(t, structs.ACLPolicyGlobalManagementID, rpolicy.ID) 1131 require.Equal(t, "management", rpolicy.Name) 1132 require.Equal(t, "Modified", rpolicy.Description) 1133 require.Equal(t, uint64(1), rpolicy.CreateIndex) 1134 require.Equal(t, uint64(3), rpolicy.ModifyIndex) 1135 }) 1136 }) 1137 1138 t.Run("New", func(t *testing.T) { 1139 t.Parallel() 1140 // this actually creates a new policy - we just need to verify it. 1141 s := testACLStateStore(t) 1142 1143 policy := structs.ACLPolicy{ 1144 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 1145 Name: "node-read", 1146 Description: "Allows reading all node information", 1147 Rules: `node_prefix "" { policy = "read" }`, 1148 Syntax: acl.SyntaxCurrent, 1149 Datacenters: []string{"dc1"}, 1150 } 1151 1152 require.NoError(t, s.ACLPolicySet(3, &policy)) 1153 1154 idx, rpolicy, err := s.ACLPolicyGetByID(nil, "a0625e95-9b3e-42de-a8d6-ceef5b6f3286") 1155 require.Equal(t, uint64(3), idx) 1156 require.NoError(t, err) 1157 require.NotNil(t, rpolicy) 1158 require.Equal(t, "node-read", rpolicy.Name) 1159 require.Equal(t, "Allows reading all node information", rpolicy.Description) 1160 require.Equal(t, `node_prefix "" { policy = "read" }`, rpolicy.Rules) 1161 require.Equal(t, acl.SyntaxCurrent, rpolicy.Syntax) 1162 require.Len(t, rpolicy.Datacenters, 1) 1163 require.Equal(t, "dc1", rpolicy.Datacenters[0]) 1164 require.Equal(t, uint64(3), rpolicy.CreateIndex) 1165 require.Equal(t, uint64(3), rpolicy.ModifyIndex) 1166 1167 // also verify the global management policy that testACLStateStore Set while we are at it. 1168 idx, rpolicy, err = s.ACLPolicyGetByID(nil, structs.ACLPolicyGlobalManagementID) 1169 require.Equal(t, uint64(3), idx) 1170 require.NoError(t, err) 1171 require.NotNil(t, rpolicy) 1172 require.Equal(t, "global-management", rpolicy.Name) 1173 require.Equal(t, "Builtin Policy that grants unlimited access", rpolicy.Description) 1174 require.Equal(t, structs.ACLPolicyGlobalManagement, rpolicy.Rules) 1175 require.Equal(t, acl.SyntaxCurrent, rpolicy.Syntax) 1176 require.Len(t, rpolicy.Datacenters, 0) 1177 require.Equal(t, uint64(1), rpolicy.CreateIndex) 1178 require.Equal(t, uint64(1), rpolicy.ModifyIndex) 1179 }) 1180 1181 t.Run("Update", func(t *testing.T) { 1182 t.Parallel() 1183 // this creates the node read policy which we can update 1184 s := testACLTokensStateStore(t) 1185 1186 update := structs.ACLPolicy{ 1187 ID: "a0625e95-9b3e-42de-a8d6-ceef5b6f3286", 1188 Name: "node-read-modified", 1189 Description: "Modified", 1190 Rules: `node_prefix "" { policy = "read" } node "secret" { policy = "deny" }`, 1191 Syntax: acl.SyntaxCurrent, 1192 Datacenters: []string{"dc1", "dc2"}, 1193 } 1194 1195 require.NoError(t, s.ACLPolicySet(3, &update)) 1196 1197 idx, rpolicy, err := s.ACLPolicyGetByID(nil, "a0625e95-9b3e-42de-a8d6-ceef5b6f3286") 1198 require.Equal(t, uint64(3), idx) 1199 require.NoError(t, err) 1200 require.NotNil(t, rpolicy) 1201 require.Equal(t, "node-read-modified", rpolicy.Name) 1202 require.Equal(t, "Modified", rpolicy.Description) 1203 require.Equal(t, `node_prefix "" { policy = "read" } node "secret" { policy = "deny" }`, rpolicy.Rules) 1204 require.Equal(t, acl.SyntaxCurrent, rpolicy.Syntax) 1205 require.ElementsMatch(t, []string{"dc1", "dc2"}, rpolicy.Datacenters) 1206 require.Equal(t, uint64(2), rpolicy.CreateIndex) 1207 require.Equal(t, uint64(3), rpolicy.ModifyIndex) 1208 }) 1209 } 1210 1211 func TestStateStore_ACLPolicy_UpsertBatchRead(t *testing.T) { 1212 t.Parallel() 1213 1214 t.Run("Normal", func(t *testing.T) { 1215 t.Parallel() 1216 s := testACLStateStore(t) 1217 1218 policies := structs.ACLPolicies{ 1219 &structs.ACLPolicy{ 1220 ID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 1221 Name: "service-read", 1222 Rules: `service_prefix "" { policy = "read" }`, 1223 }, 1224 &structs.ACLPolicy{ 1225 ID: "a2719052-40b3-4a4b-baeb-f3df1831a217", 1226 Name: "acl-write-dc3", 1227 Description: "Can manage ACLs in dc3", 1228 Datacenters: []string{"dc3"}, 1229 Rules: `acl = "write"`, 1230 }, 1231 } 1232 1233 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 1234 1235 idx, rpolicies, err := s.ACLPolicyBatchGet(nil, []string{ 1236 "a4f68bd6-3af5-4f56-b764-3c6f20247879", 1237 "a2719052-40b3-4a4b-baeb-f3df1831a217"}) 1238 1239 require.NoError(t, err) 1240 require.Equal(t, uint64(2), idx) 1241 require.Len(t, rpolicies, 2) 1242 require.ElementsMatch(t, policies, rpolicies) 1243 require.Equal(t, uint64(2), rpolicies[0].CreateIndex) 1244 require.Equal(t, uint64(2), rpolicies[0].ModifyIndex) 1245 require.Equal(t, uint64(2), rpolicies[1].CreateIndex) 1246 require.Equal(t, uint64(2), rpolicies[1].ModifyIndex) 1247 }) 1248 1249 t.Run("Update", func(t *testing.T) { 1250 t.Parallel() 1251 s := testACLStateStore(t) 1252 1253 policies := structs.ACLPolicies{ 1254 &structs.ACLPolicy{ 1255 ID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 1256 Name: "service-read", 1257 Rules: `service_prefix "" { policy = "read" }`, 1258 }, 1259 &structs.ACLPolicy{ 1260 ID: "a2719052-40b3-4a4b-baeb-f3df1831a217", 1261 Name: "acl-write-dc3", 1262 Description: "Can manage ACLs in dc3", 1263 Datacenters: []string{"dc3"}, 1264 Rules: `acl = "write"`, 1265 }, 1266 } 1267 1268 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 1269 1270 updates := structs.ACLPolicies{ 1271 &structs.ACLPolicy{ 1272 ID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 1273 Name: "service-write", 1274 Rules: `service_prefix "" { policy = "write" }`, 1275 Datacenters: []string{"dc1"}, 1276 }, 1277 &structs.ACLPolicy{ 1278 ID: "a2719052-40b3-4a4b-baeb-f3df1831a217", 1279 Name: "acl-write", 1280 Description: "Modified", 1281 Rules: `acl = "write"`, 1282 }, 1283 } 1284 1285 require.NoError(t, s.ACLPolicyBatchSet(3, updates)) 1286 1287 idx, rpolicies, err := s.ACLPolicyBatchGet(nil, []string{ 1288 "a4f68bd6-3af5-4f56-b764-3c6f20247879", 1289 "a2719052-40b3-4a4b-baeb-f3df1831a217"}) 1290 1291 require.NoError(t, err) 1292 require.Equal(t, uint64(3), idx) 1293 require.Len(t, rpolicies, 2) 1294 rpolicies.Sort() 1295 require.Equal(t, "a2719052-40b3-4a4b-baeb-f3df1831a217", rpolicies[0].ID) 1296 require.Equal(t, "acl-write", rpolicies[0].Name) 1297 require.Equal(t, "Modified", rpolicies[0].Description) 1298 require.Equal(t, `acl = "write"`, rpolicies[0].Rules) 1299 require.Empty(t, rpolicies[0].Datacenters) 1300 require.Equal(t, uint64(2), rpolicies[0].CreateIndex) 1301 require.Equal(t, uint64(3), rpolicies[0].ModifyIndex) 1302 1303 require.Equal(t, "a4f68bd6-3af5-4f56-b764-3c6f20247879", rpolicies[1].ID) 1304 require.Equal(t, "service-write", rpolicies[1].Name) 1305 require.Equal(t, "", rpolicies[1].Description) 1306 require.Equal(t, `service_prefix "" { policy = "write" }`, rpolicies[1].Rules) 1307 require.ElementsMatch(t, []string{"dc1"}, rpolicies[1].Datacenters) 1308 require.Equal(t, uint64(2), rpolicies[1].CreateIndex) 1309 require.Equal(t, uint64(3), rpolicies[1].ModifyIndex) 1310 }) 1311 } 1312 1313 func TestStateStore_ACLPolicy_List(t *testing.T) { 1314 t.Parallel() 1315 s := testACLStateStore(t) 1316 1317 policies := structs.ACLPolicies{ 1318 &structs.ACLPolicy{ 1319 ID: "a4f68bd6-3af5-4f56-b764-3c6f20247879", 1320 Name: "service-read", 1321 Rules: `service_prefix "" { policy = "read" }`, 1322 }, 1323 &structs.ACLPolicy{ 1324 ID: "a2719052-40b3-4a4b-baeb-f3df1831a217", 1325 Name: "acl-write-dc3", 1326 Description: "Can manage ACLs in dc3", 1327 Datacenters: []string{"dc3"}, 1328 Rules: `acl = "write"`, 1329 }, 1330 } 1331 1332 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 1333 1334 _, policies, err := s.ACLPolicyList(nil) 1335 require.NoError(t, err) 1336 require.Len(t, policies, 3) 1337 policies.Sort() 1338 require.Equal(t, structs.ACLPolicyGlobalManagementID, policies[0].ID) 1339 require.Equal(t, "global-management", policies[0].Name) 1340 require.Equal(t, "Builtin Policy that grants unlimited access", policies[0].Description) 1341 require.Empty(t, policies[0].Datacenters) 1342 require.NotEqual(t, []byte{}, policies[0].Hash) 1343 require.Equal(t, uint64(1), policies[0].CreateIndex) 1344 require.Equal(t, uint64(1), policies[0].ModifyIndex) 1345 1346 require.Equal(t, "a2719052-40b3-4a4b-baeb-f3df1831a217", policies[1].ID) 1347 require.Equal(t, "acl-write-dc3", policies[1].Name) 1348 require.Equal(t, "Can manage ACLs in dc3", policies[1].Description) 1349 require.ElementsMatch(t, []string{"dc3"}, policies[1].Datacenters) 1350 require.Nil(t, policies[1].Hash) 1351 require.Equal(t, uint64(2), policies[1].CreateIndex) 1352 require.Equal(t, uint64(2), policies[1].ModifyIndex) 1353 1354 require.Equal(t, "a4f68bd6-3af5-4f56-b764-3c6f20247879", policies[2].ID) 1355 require.Equal(t, "service-read", policies[2].Name) 1356 require.Equal(t, "", policies[2].Description) 1357 require.Empty(t, policies[2].Datacenters) 1358 require.Nil(t, policies[2].Hash) 1359 require.Equal(t, uint64(2), policies[2].CreateIndex) 1360 require.Equal(t, uint64(2), policies[2].ModifyIndex) 1361 } 1362 1363 func TestStateStore_ACLPolicy_Delete(t *testing.T) { 1364 t.Parallel() 1365 1366 t.Run("ID", func(t *testing.T) { 1367 t.Parallel() 1368 s := testACLStateStore(t) 1369 1370 policy := &structs.ACLPolicy{ 1371 ID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 1372 Name: "test-policy", 1373 Rules: `acl = "read"`, 1374 } 1375 1376 require.NoError(t, s.ACLPolicySet(2, policy)) 1377 1378 _, rpolicy, err := s.ACLPolicyGetByID(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 1379 require.NoError(t, err) 1380 require.NotNil(t, rpolicy) 1381 1382 require.NoError(t, s.ACLPolicyDeleteByID(3, "f1093997-b6c7-496d-bfb8-6b1b1895641b")) 1383 require.NoError(t, err) 1384 1385 _, rpolicy, err = s.ACLPolicyGetByID(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 1386 require.NoError(t, err) 1387 require.Nil(t, rpolicy) 1388 }) 1389 1390 t.Run("Name", func(t *testing.T) { 1391 t.Parallel() 1392 s := testACLStateStore(t) 1393 1394 policy := &structs.ACLPolicy{ 1395 ID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 1396 Name: "test-policy", 1397 Rules: `acl = "read"`, 1398 } 1399 1400 require.NoError(t, s.ACLPolicySet(2, policy)) 1401 1402 _, rpolicy, err := s.ACLPolicyGetByName(nil, "test-policy") 1403 require.NoError(t, err) 1404 require.NotNil(t, rpolicy) 1405 1406 require.NoError(t, s.ACLPolicyDeleteByName(3, "test-policy")) 1407 require.NoError(t, err) 1408 1409 _, rpolicy, err = s.ACLPolicyGetByName(nil, "test-policy") 1410 require.NoError(t, err) 1411 require.Nil(t, rpolicy) 1412 }) 1413 1414 t.Run("Multiple", func(t *testing.T) { 1415 t.Parallel() 1416 s := testACLStateStore(t) 1417 1418 policies := structs.ACLPolicies{ 1419 &structs.ACLPolicy{ 1420 ID: "f1093997-b6c7-496d-bfb8-6b1b1895641b", 1421 Name: "34ec8eb3-095d-417a-a937-b439af7a8e8b", 1422 Rules: `acl = "read"`, 1423 }, 1424 &structs.ACLPolicy{ 1425 ID: "a0bfe8d4-b2f3-4b48-b387-f28afb820eab", 1426 Name: "be444e46-fb95-4ccc-80d5-c873f34e6fa6", 1427 Rules: `acl = "write"`, 1428 }, 1429 } 1430 1431 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 1432 1433 _, rpolicy, err := s.ACLPolicyGetByID(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 1434 require.NoError(t, err) 1435 require.NotNil(t, rpolicy) 1436 _, rpolicy, err = s.ACLPolicyGetByID(nil, "a0bfe8d4-b2f3-4b48-b387-f28afb820eab") 1437 require.NoError(t, err) 1438 require.NotNil(t, rpolicy) 1439 1440 require.NoError(t, s.ACLPolicyBatchDelete(3, []string{ 1441 "f1093997-b6c7-496d-bfb8-6b1b1895641b", 1442 "a0bfe8d4-b2f3-4b48-b387-f28afb820eab"})) 1443 1444 _, rpolicy, err = s.ACLPolicyGetByID(nil, "f1093997-b6c7-496d-bfb8-6b1b1895641b") 1445 require.NoError(t, err) 1446 require.Nil(t, rpolicy) 1447 _, rpolicy, err = s.ACLPolicyGetByID(nil, "a0bfe8d4-b2f3-4b48-b387-f28afb820eab") 1448 require.NoError(t, err) 1449 require.Nil(t, rpolicy) 1450 }) 1451 1452 t.Run("Global-Management", func(t *testing.T) { 1453 t.Parallel() 1454 s := testACLStateStore(t) 1455 1456 require.Error(t, s.ACLPolicyDeleteByID(5, structs.ACLPolicyGlobalManagementID)) 1457 require.Error(t, s.ACLPolicyDeleteByName(5, "global-management")) 1458 }) 1459 1460 t.Run("Not Found", func(t *testing.T) { 1461 t.Parallel() 1462 s := testACLStateStore(t) 1463 1464 // deletion of non-existent policies is not an error 1465 require.NoError(t, s.ACLPolicyDeleteByName(3, "not-found")) 1466 require.NoError(t, s.ACLPolicyDeleteByID(3, "376d0cae-dd50-4213-9668-2c7797a7fb2d")) 1467 }) 1468 } 1469 1470 func TestStateStore_ACLTokens_Snapshot_Restore(t *testing.T) { 1471 s := testStateStore(t) 1472 1473 policies := structs.ACLPolicies{ 1474 &structs.ACLPolicy{ 1475 ID: "ca1fc52c-3676-4050-82ed-ca223e38b2c9", 1476 Name: "policy1", 1477 Description: "policy1", 1478 Rules: `node_prefix "" { policy = "read" }`, 1479 Syntax: acl.SyntaxCurrent, 1480 }, 1481 &structs.ACLPolicy{ 1482 ID: "7b70fa0f-58cd-412d-93c3-a0f17bb19a3e", 1483 Name: "policy2", 1484 Description: "policy2", 1485 Rules: `acl = "read"`, 1486 Syntax: acl.SyntaxCurrent, 1487 }, 1488 } 1489 1490 for _, policy := range policies { 1491 policy.SetHash(true) 1492 } 1493 1494 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 1495 1496 tokens := structs.ACLTokens{ 1497 &structs.ACLToken{ 1498 AccessorID: "68016c3d-835b-450c-a6f9-75db9ba740be", 1499 SecretID: "838f72b5-5c15-4a9e-aa6d-31734c3a0286", 1500 Description: "token1", 1501 Policies: []structs.ACLTokenPolicyLink{ 1502 structs.ACLTokenPolicyLink{ 1503 ID: "ca1fc52c-3676-4050-82ed-ca223e38b2c9", 1504 Name: "policy1", 1505 }, 1506 structs.ACLTokenPolicyLink{ 1507 ID: "7b70fa0f-58cd-412d-93c3-a0f17bb19a3e", 1508 Name: "policy2", 1509 }, 1510 }, 1511 Hash: []byte{1, 2, 3, 4}, 1512 RaftIndex: structs.RaftIndex{CreateIndex: 1, ModifyIndex: 2}, 1513 }, 1514 &structs.ACLToken{ 1515 AccessorID: "b2125a1b-2a52-41d4-88f3-c58761998a46", 1516 SecretID: "ba5d9239-a4ab-49b9-ae09-1f19eed92204", 1517 Description: "token2", 1518 Policies: []structs.ACLTokenPolicyLink{ 1519 structs.ACLTokenPolicyLink{ 1520 ID: "ca1fc52c-3676-4050-82ed-ca223e38b2c9", 1521 Name: "policy1", 1522 }, 1523 structs.ACLTokenPolicyLink{ 1524 ID: "7b70fa0f-58cd-412d-93c3-a0f17bb19a3e", 1525 Name: "policy2", 1526 }, 1527 }, 1528 Hash: []byte{1, 2, 3, 4}, 1529 RaftIndex: structs.RaftIndex{CreateIndex: 1, ModifyIndex: 2}, 1530 }, 1531 } 1532 1533 require.NoError(t, s.ACLTokenBatchSet(2, tokens, false)) 1534 1535 // Snapshot the ACLs. 1536 snap := s.Snapshot() 1537 defer snap.Close() 1538 1539 // Alter the real state store. 1540 require.NoError(t, s.ACLTokenDeleteByAccessor(3, tokens[0].AccessorID)) 1541 1542 // Verify the snapshot. 1543 require.Equal(t, uint64(2), snap.LastIndex()) 1544 1545 iter, err := snap.ACLTokens() 1546 require.NoError(t, err) 1547 1548 var dump structs.ACLTokens 1549 for token := iter.Next(); token != nil; token = iter.Next() { 1550 dump = append(dump, token.(*structs.ACLToken)) 1551 } 1552 require.ElementsMatch(t, dump, tokens) 1553 1554 // Restore the values into a new state store. 1555 func() { 1556 s := testStateStore(t) 1557 restore := s.Restore() 1558 for _, token := range dump { 1559 require.NoError(t, restore.ACLToken(token)) 1560 } 1561 restore.Commit() 1562 1563 // need to ensure we have the policies or else the links will be removed 1564 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 1565 1566 // Read the restored ACLs back out and verify that they match. 1567 idx, res, err := s.ACLTokenList(nil, true, true, "") 1568 require.NoError(t, err) 1569 require.Equal(t, uint64(2), idx) 1570 require.ElementsMatch(t, tokens, res) 1571 require.Equal(t, uint64(2), s.maxIndex("acl-tokens")) 1572 }() 1573 } 1574 1575 func TestStateStore_ACLPolicies_Snapshot_Restore(t *testing.T) { 1576 s := testStateStore(t) 1577 1578 policies := structs.ACLPolicies{ 1579 &structs.ACLPolicy{ 1580 ID: "68016c3d-835b-450c-a6f9-75db9ba740be", 1581 Name: "838f72b5-5c15-4a9e-aa6d-31734c3a0286", 1582 Description: "policy1", 1583 Rules: `acl = "read"`, 1584 Hash: []byte{1, 2, 3, 4}, 1585 RaftIndex: structs.RaftIndex{CreateIndex: 1, ModifyIndex: 2}, 1586 }, 1587 &structs.ACLPolicy{ 1588 ID: "b2125a1b-2a52-41d4-88f3-c58761998a46", 1589 Name: "ba5d9239-a4ab-49b9-ae09-1f19eed92204", 1590 Description: "policy2", 1591 Rules: `operator = "read"`, 1592 Hash: []byte{1, 2, 3, 4}, 1593 RaftIndex: structs.RaftIndex{CreateIndex: 1, ModifyIndex: 2}, 1594 }, 1595 } 1596 1597 require.NoError(t, s.ACLPolicyBatchSet(2, policies)) 1598 1599 // Snapshot the ACLs. 1600 snap := s.Snapshot() 1601 defer snap.Close() 1602 1603 // Alter the real state store. 1604 require.NoError(t, s.ACLPolicyDeleteByID(3, policies[0].ID)) 1605 1606 // Verify the snapshot. 1607 require.Equal(t, uint64(2), snap.LastIndex()) 1608 1609 iter, err := snap.ACLPolicies() 1610 require.NoError(t, err) 1611 1612 var dump structs.ACLPolicies 1613 for policy := iter.Next(); policy != nil; policy = iter.Next() { 1614 dump = append(dump, policy.(*structs.ACLPolicy)) 1615 } 1616 require.ElementsMatch(t, dump, policies) 1617 1618 // Restore the values into a new state store. 1619 func() { 1620 s := testStateStore(t) 1621 restore := s.Restore() 1622 for _, policy := range dump { 1623 require.NoError(t, restore.ACLPolicy(policy)) 1624 } 1625 restore.Commit() 1626 1627 // Read the restored ACLs back out and verify that they match. 1628 idx, res, err := s.ACLPolicyList(nil) 1629 require.NoError(t, err) 1630 require.Equal(t, uint64(2), idx) 1631 require.ElementsMatch(t, policies, res) 1632 require.Equal(t, uint64(2), s.maxIndex("acl-policies")) 1633 }() 1634 }