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