github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/state/state_store_acl_test.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/hashicorp/go-memdb" 9 "github.com/hashicorp/nomad/ci" 10 "github.com/hashicorp/nomad/helper/pointer" 11 "github.com/hashicorp/nomad/helper/uuid" 12 "github.com/hashicorp/nomad/nomad/mock" 13 "github.com/hashicorp/nomad/nomad/structs" 14 "github.com/shoenig/test/must" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestStateStore_ACLTokensByExpired(t *testing.T) { 19 ci.Parallel(t) 20 testState := testStateStore(t) 21 22 // This function provides an easy way to get all tokens out of the 23 // iterator. 24 fromIteratorFunc := func(iter memdb.ResultIterator) []*structs.ACLToken { 25 var tokens []*structs.ACLToken 26 for raw := iter.Next(); raw != nil; raw = iter.Next() { 27 tokens = append(tokens, raw.(*structs.ACLToken)) 28 } 29 return tokens 30 } 31 32 // This time is the threshold for all expiry calls to be based on. All 33 // tokens with expiry can use this as their base and use Add(). 34 expiryTimeThreshold := time.Date(2022, time.April, 27, 14, 50, 0, 0, time.UTC) 35 36 // Generate two tokens without an expiry time. These tokens should never 37 // show up in calls to ACLTokensByExpired. 38 neverExpireLocalToken := mock.ACLToken() 39 neverExpireGlobalToken := mock.ACLToken() 40 neverExpireLocalToken.Global = true 41 42 // Upsert the tokens into state and perform a global and local read of 43 // the state. 44 err := testState.UpsertACLTokens(structs.MsgTypeTestSetup, 10, []*structs.ACLToken{ 45 neverExpireLocalToken, neverExpireGlobalToken}) 46 require.NoError(t, err) 47 48 iter, err := testState.ACLTokensByExpired(true) 49 require.NoError(t, err) 50 tokens := fromIteratorFunc(iter) 51 require.Len(t, tokens, 0) 52 53 iter, err = testState.ACLTokensByExpired(false) 54 require.NoError(t, err) 55 tokens = fromIteratorFunc(iter) 56 require.Len(t, tokens, 0) 57 58 // Generate, upsert, and test an expired local token. This token expired 59 // long ago and therefore before all others coming in the tests. It should 60 // therefore always be the first out. 61 expiredLocalToken := mock.ACLToken() 62 expiredLocalToken.ExpirationTime = pointer.Of(expiryTimeThreshold.Add(-48 * time.Hour)) 63 64 err = testState.UpsertACLTokens(structs.MsgTypeTestSetup, 20, []*structs.ACLToken{expiredLocalToken}) 65 require.NoError(t, err) 66 67 iter, err = testState.ACLTokensByExpired(false) 68 require.NoError(t, err) 69 tokens = fromIteratorFunc(iter) 70 require.Len(t, tokens, 1) 71 require.Equal(t, expiredLocalToken.AccessorID, tokens[0].AccessorID) 72 73 // Generate, upsert, and test an expired global token. This token expired 74 // long ago and therefore before all others coming in the tests. It should 75 // therefore always be the first out. 76 expiredGlobalToken := mock.ACLToken() 77 expiredGlobalToken.Global = true 78 expiredGlobalToken.ExpirationTime = pointer.Of(expiryTimeThreshold.Add(-48 * time.Hour)) 79 80 err = testState.UpsertACLTokens(structs.MsgTypeTestSetup, 30, []*structs.ACLToken{expiredGlobalToken}) 81 require.NoError(t, err) 82 83 iter, err = testState.ACLTokensByExpired(true) 84 require.NoError(t, err) 85 tokens = fromIteratorFunc(iter) 86 require.Len(t, tokens, 1) 87 require.Equal(t, expiredGlobalToken.AccessorID, tokens[0].AccessorID) 88 89 // This test function allows us to run the same test for local and global 90 // tokens. 91 testFn := func(oldToken *structs.ACLToken, global bool) { 92 93 // Track all the expected expired ACL tokens, including the long 94 // expired token. 95 var expiredTokens []*structs.ACLToken 96 expiredTokens = append(expiredTokens, oldToken) 97 98 // Generate and upsert a number of mixed expired, non-expired tokens. 99 mixedTokens := make([]*structs.ACLToken, 20) 100 for i := 0; i < 20; i++ { 101 mockedToken := mock.ACLToken() 102 mockedToken.Global = global 103 if i%2 == 0 { 104 expiredTokens = append(expiredTokens, mockedToken) 105 mockedToken.ExpirationTime = pointer.Of(expiryTimeThreshold.Add(-24 * time.Hour)) 106 } else { 107 mockedToken.ExpirationTime = pointer.Of(expiryTimeThreshold.Add(24 * time.Hour)) 108 } 109 mixedTokens[i] = mockedToken 110 } 111 112 err = testState.UpsertACLTokens(structs.MsgTypeTestSetup, 40, mixedTokens) 113 require.NoError(t, err) 114 115 // Check the full listing works as expected as the first 11 elements 116 // should all be our expired tokens. Ensure our oldest expired token is 117 // first in the list. 118 iter, err = testState.ACLTokensByExpired(global) 119 require.NoError(t, err) 120 tokens = fromIteratorFunc(iter) 121 require.ElementsMatch(t, expiredTokens, tokens[:11]) 122 require.Equal(t, tokens[0], oldToken) 123 } 124 125 testFn(expiredLocalToken, false) 126 testFn(expiredGlobalToken, true) 127 } 128 129 func Test_expiresIndexName(t *testing.T) { 130 testCases := []struct { 131 globalInput bool 132 expectedOutput string 133 name string 134 }{ 135 { 136 globalInput: false, 137 expectedOutput: indexExpiresLocal, 138 name: "local", 139 }, 140 { 141 globalInput: true, 142 expectedOutput: indexExpiresGlobal, 143 name: "global", 144 }, 145 } 146 147 for _, tc := range testCases { 148 t.Run(tc.name, func(t *testing.T) { 149 actualOutput := expiresIndexName(tc.globalInput) 150 require.Equal(t, tc.expectedOutput, actualOutput) 151 }) 152 } 153 } 154 155 func TestStateStore_UpsertACLRoles(t *testing.T) { 156 ci.Parallel(t) 157 testState := testStateStore(t) 158 159 // Generate a mocked ACL role for testing and attempt to upsert this 160 // straight into state. It should fail because the ACL policies do not 161 // exist. 162 mockedACLRoles := []*structs.ACLRole{mock.ACLRole()} 163 err := testState.UpsertACLRoles(structs.MsgTypeTestSetup, 10, mockedACLRoles, false) 164 require.ErrorContains(t, err, "policy not found") 165 166 // Create the policies our ACL roles wants to link to and then try the 167 // upsert again. 168 policy1 := mock.ACLPolicy() 169 policy1.Name = "mocked-test-policy-1" 170 policy2 := mock.ACLPolicy() 171 policy2.Name = "mocked-test-policy-2" 172 173 require.NoError(t, testState.UpsertACLPolicies( 174 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 175 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 20, mockedACLRoles, false)) 176 177 // Check that the index for the table was modified as expected. 178 initialIndex, err := testState.Index(TableACLRoles) 179 require.NoError(t, err) 180 must.Eq(t, 20, initialIndex) 181 182 // List all the ACL roles in the table, so we can perform a number of tests 183 // on the return array. 184 ws := memdb.NewWatchSet() 185 iter, err := testState.GetACLRoles(ws) 186 require.NoError(t, err) 187 188 // Count how many table entries we have, to ensure it is the expected 189 // number. 190 var count int 191 192 for raw := iter.Next(); raw != nil; raw = iter.Next() { 193 count++ 194 195 // Ensure the create and modify indexes are populated correctly. 196 aclRole := raw.(*structs.ACLRole) 197 must.Eq(t, 20, aclRole.CreateIndex) 198 must.Eq(t, 20, aclRole.ModifyIndex) 199 } 200 require.Equal(t, 1, count, "incorrect number of ACL roles found") 201 202 // Try writing the same ACL roles to state which should not result in an 203 // update to the table index. 204 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 30, mockedACLRoles, false)) 205 reInsertActualIndex, err := testState.Index(TableACLRoles) 206 require.NoError(t, err) 207 must.Eq(t, 20, reInsertActualIndex) 208 209 // Make a change to one of the ACL roles and ensure this update is accepted 210 // and the table index is updated. 211 updatedMockedACLRole := mockedACLRoles[0].Copy() 212 updatedMockedACLRole.Policies = []*structs.ACLRolePolicyLink{{Name: "mocked-test-policy-1"}} 213 updatedMockedACLRole.SetHash() 214 require.NoError(t, testState.UpsertACLRoles( 215 structs.MsgTypeTestSetup, 30, []*structs.ACLRole{updatedMockedACLRole}, false)) 216 217 // Check that the index for the table was modified as expected. 218 updatedIndex, err := testState.Index(TableACLRoles) 219 require.NoError(t, err) 220 must.Eq(t, 30, updatedIndex) 221 222 // List the ACL roles in state. 223 iter, err = testState.GetACLRoles(ws) 224 require.NoError(t, err) 225 226 // Count how many table entries we have, to ensure it is the expected 227 // number. 228 count = 0 229 230 for raw := iter.Next(); raw != nil; raw = iter.Next() { 231 count++ 232 233 // Ensure the create and modify indexes are populated correctly. 234 aclRole := raw.(*structs.ACLRole) 235 must.Eq(t, 20, aclRole.CreateIndex) 236 must.Eq(t, 30, aclRole.ModifyIndex) 237 } 238 require.Equal(t, 1, count, "incorrect number of ACL roles found") 239 240 // Now try inserting an ACL role using the missing policies' argument to 241 // simulate replication. 242 replicatedACLRole := mock.ACLRole() 243 replicatedACLRole.Policies = []*structs.ACLRolePolicyLink{{Name: "nope"}} 244 require.NoError(t, testState.UpsertACLRoles( 245 structs.MsgTypeTestSetup, 40, []*structs.ACLRole{replicatedACLRole}, true)) 246 247 replicatedACLRoleResp, err := testState.GetACLRoleByName(ws, replicatedACLRole.Name) 248 require.NoError(t, err) 249 must.Eq(t, replicatedACLRole.Hash, replicatedACLRoleResp.Hash) 250 251 // Try adding a new ACL role, which has a name clash with an existing 252 // entry. 253 dupRoleName := mock.ACLRole() 254 dupRoleName.Name = mockedACLRoles[0].Name 255 256 err = testState.UpsertACLRoles(structs.MsgTypeTestSetup, 50, 257 []*structs.ACLRole{dupRoleName}, false) 258 require.ErrorContains(t, err, fmt.Sprintf("ACL role with name %s already exists", dupRoleName.Name)) 259 } 260 261 func TestStateStore_ValidateACLRolePolicyLinks(t *testing.T) { 262 ci.Parallel(t) 263 testState := testStateStore(t) 264 265 // Create our mocked role which includes two ACL policy links. 266 mockedACLRoles := []*structs.ACLRole{mock.ACLRole()} 267 268 // This should error as no policies exist within state. 269 err := testState.UpsertACLRoles(structs.MsgTypeTestSetup, 10, mockedACLRoles, false) 270 require.ErrorContains(t, err, "ACL policy not found") 271 272 // Upsert one ACL policy and retry the role which should still fail. 273 policy1 := mock.ACLPolicy() 274 policy1.Name = "mocked-test-policy-1" 275 276 require.NoError(t, testState.UpsertACLPolicies(structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1})) 277 err = testState.UpsertACLRoles(structs.MsgTypeTestSetup, 20, mockedACLRoles, false) 278 require.ErrorContains(t, err, "ACL policy not found") 279 280 // Upsert the second ACL policy. The ACL role should now upsert into state 281 // without error. 282 policy2 := mock.ACLPolicy() 283 policy2.Name = "mocked-test-policy-2" 284 285 require.NoError(t, testState.UpsertACLPolicies(structs.MsgTypeTestSetup, 20, []*structs.ACLPolicy{policy2})) 286 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 30, mockedACLRoles, false)) 287 } 288 289 func TestStateStore_DeleteACLRolesByID(t *testing.T) { 290 ci.Parallel(t) 291 testState := testStateStore(t) 292 293 // Create the policies our ACL roles wants to link to. 294 policy1 := mock.ACLPolicy() 295 policy1.Name = "mocked-test-policy-1" 296 policy2 := mock.ACLPolicy() 297 policy2.Name = "mocked-test-policy-2" 298 299 require.NoError(t, testState.UpsertACLPolicies( 300 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 301 302 // Generate a some mocked ACL roles for testing and upsert these straight 303 // into state. 304 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 305 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 10, mockedACLRoles, false)) 306 307 // Try and delete a role using a name that doesn't exist. This should 308 // return an error and not change the index for the table. 309 err := testState.DeleteACLRolesByID(structs.MsgTypeTestSetup, 20, []string{"not-a-role"}) 310 require.ErrorContains(t, err, "ACL role not found") 311 312 tableIndex, err := testState.Index(TableACLRoles) 313 require.NoError(t, err) 314 must.Eq(t, 10, tableIndex) 315 316 // Delete one of the previously upserted ACL roles. This should succeed 317 // and modify the table index. 318 err = testState.DeleteACLRolesByID(structs.MsgTypeTestSetup, 20, []string{mockedACLRoles[0].ID}) 319 require.NoError(t, err) 320 321 tableIndex, err = testState.Index(TableACLRoles) 322 require.NoError(t, err) 323 must.Eq(t, 20, tableIndex) 324 325 // List the ACL roles and ensure we now only have one present and that it 326 // is the one we expect. 327 ws := memdb.NewWatchSet() 328 iter, err := testState.GetACLRoles(ws) 329 require.NoError(t, err) 330 331 var aclRoles []*structs.ACLRole 332 333 for raw := iter.Next(); raw != nil; raw = iter.Next() { 334 aclRoles = append(aclRoles, raw.(*structs.ACLRole)) 335 } 336 337 require.Len(t, aclRoles, 1, "incorrect number of ACL roles found") 338 require.True(t, aclRoles[0].Equal(mockedACLRoles[1])) 339 340 // Delete the final remaining ACL role. This should succeed and modify the 341 // table index. 342 err = testState.DeleteACLRolesByID(structs.MsgTypeTestSetup, 30, []string{mockedACLRoles[1].ID}) 343 require.NoError(t, err) 344 345 tableIndex, err = testState.Index(TableACLRoles) 346 require.NoError(t, err) 347 must.Eq(t, 30, tableIndex) 348 349 // List the ACL roles and ensure we have zero entries. 350 iter, err = testState.GetACLRoles(ws) 351 require.NoError(t, err) 352 353 aclRoles = []*structs.ACLRole{} 354 355 for raw := iter.Next(); raw != nil; raw = iter.Next() { 356 aclRoles = append(aclRoles, raw.(*structs.ACLRole)) 357 } 358 require.Len(t, aclRoles, 0, "incorrect number of ACL roles found") 359 } 360 361 func TestStateStore_GetACLRoles(t *testing.T) { 362 ci.Parallel(t) 363 testState := testStateStore(t) 364 365 // Create the policies our ACL roles wants to link to. 366 policy1 := mock.ACLPolicy() 367 policy1.Name = "mocked-test-policy-1" 368 policy2 := mock.ACLPolicy() 369 policy2.Name = "mocked-test-policy-2" 370 371 require.NoError(t, testState.UpsertACLPolicies( 372 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 373 374 // Generate a some mocked ACL roles for testing and upsert these straight 375 // into state. 376 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 377 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 10, mockedACLRoles, false)) 378 379 // List the ACL roles and ensure they are exactly as we expect. 380 ws := memdb.NewWatchSet() 381 iter, err := testState.GetACLRoles(ws) 382 require.NoError(t, err) 383 384 var aclRoles []*structs.ACLRole 385 386 for raw := iter.Next(); raw != nil; raw = iter.Next() { 387 aclRoles = append(aclRoles, raw.(*structs.ACLRole)) 388 } 389 390 expected := mockedACLRoles 391 for i := range expected { 392 expected[i].CreateIndex = 10 393 expected[i].ModifyIndex = 10 394 } 395 396 require.ElementsMatch(t, aclRoles, expected) 397 } 398 399 func TestStateStore_GetACLRoleByID(t *testing.T) { 400 ci.Parallel(t) 401 testState := testStateStore(t) 402 403 // Create the policies our ACL roles wants to link to. 404 policy1 := mock.ACLPolicy() 405 policy1.Name = "mocked-test-policy-1" 406 policy2 := mock.ACLPolicy() 407 policy2.Name = "mocked-test-policy-2" 408 409 require.NoError(t, testState.UpsertACLPolicies( 410 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 411 412 // Generate a some mocked ACL roles for testing and upsert these straight 413 // into state. 414 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 415 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 10, mockedACLRoles, false)) 416 417 ws := memdb.NewWatchSet() 418 419 // Try reading an ACL role that does not exist. 420 aclRole, err := testState.GetACLRoleByID(ws, "not-a-role") 421 require.NoError(t, err) 422 require.Nil(t, aclRole) 423 424 // Read the two ACL roles that we should find. 425 aclRole, err = testState.GetACLRoleByID(ws, mockedACLRoles[0].ID) 426 require.NoError(t, err) 427 require.Equal(t, mockedACLRoles[0], aclRole) 428 429 aclRole, err = testState.GetACLRoleByID(ws, mockedACLRoles[1].ID) 430 require.NoError(t, err) 431 require.Equal(t, mockedACLRoles[1], aclRole) 432 } 433 434 func TestStateStore_GetACLRoleByName(t *testing.T) { 435 ci.Parallel(t) 436 testState := testStateStore(t) 437 438 // Create the policies our ACL roles wants to link to. 439 policy1 := mock.ACLPolicy() 440 policy1.Name = "mocked-test-policy-1" 441 policy2 := mock.ACLPolicy() 442 policy2.Name = "mocked-test-policy-2" 443 444 require.NoError(t, testState.UpsertACLPolicies( 445 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 446 447 // Generate a some mocked ACL roles for testing and upsert these straight 448 // into state. 449 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 450 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 10, mockedACLRoles, false)) 451 452 ws := memdb.NewWatchSet() 453 454 // Try reading an ACL role that does not exist. 455 aclRole, err := testState.GetACLRoleByName(ws, "not-a-role") 456 require.NoError(t, err) 457 require.Nil(t, aclRole) 458 459 // Read the two ACL roles that we should find. 460 aclRole, err = testState.GetACLRoleByName(ws, mockedACLRoles[0].Name) 461 require.NoError(t, err) 462 require.Equal(t, mockedACLRoles[0], aclRole) 463 464 aclRole, err = testState.GetACLRoleByName(ws, mockedACLRoles[1].Name) 465 require.NoError(t, err) 466 require.Equal(t, mockedACLRoles[1], aclRole) 467 } 468 469 func TestStateStore_GetACLRoleByIDPrefix(t *testing.T) { 470 ci.Parallel(t) 471 testState := testStateStore(t) 472 473 // Create the policies our ACL roles wants to link to. 474 policy1 := mock.ACLPolicy() 475 policy1.Name = "mocked-test-policy-1" 476 policy2 := mock.ACLPolicy() 477 policy2.Name = "mocked-test-policy-2" 478 479 require.NoError(t, testState.UpsertACLPolicies( 480 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 481 482 // Generate a some mocked ACL roles for testing and upsert these straight 483 // into state. Set the ID to something with a prefix we know so it is easy 484 // to test. 485 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 486 mockedACLRoles[0].ID = "test-prefix-" + uuid.Generate() 487 mockedACLRoles[1].ID = "test-prefix-" + uuid.Generate() 488 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 10, mockedACLRoles, false)) 489 490 ws := memdb.NewWatchSet() 491 492 // Try using a prefix that doesn't match any entries. 493 iter, err := testState.GetACLRoleByIDPrefix(ws, "nope") 494 require.NoError(t, err) 495 496 var aclRoles []*structs.ACLRole 497 for raw := iter.Next(); raw != nil; raw = iter.Next() { 498 aclRoles = append(aclRoles, raw.(*structs.ACLRole)) 499 } 500 require.Len(t, aclRoles, 0) 501 502 // Use a prefix which should match two entries in state. 503 iter, err = testState.GetACLRoleByIDPrefix(ws, "test-prefix-") 504 require.NoError(t, err) 505 506 aclRoles = []*structs.ACLRole{} 507 for raw := iter.Next(); raw != nil; raw = iter.Next() { 508 aclRoles = append(aclRoles, raw.(*structs.ACLRole)) 509 } 510 require.Len(t, aclRoles, 2) 511 } 512 513 func TestStateStore_fixTokenRoleLinks(t *testing.T) { 514 ci.Parallel(t) 515 516 testCases := []struct { 517 name string 518 testFn func() 519 }{ 520 { 521 name: "no fix needed", 522 testFn: func() { 523 testState := testStateStore(t) 524 525 // Create the policies our ACL roles wants to link to. 526 policy1 := mock.ACLPolicy() 527 policy1.Name = "mocked-test-policy-1" 528 policy2 := mock.ACLPolicy() 529 policy2.Name = "mocked-test-policy-2" 530 531 require.NoError(t, testState.UpsertACLPolicies( 532 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 533 534 // Generate a some mocked ACL roles for testing and upsert these straight 535 // into state. 536 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 537 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 20, mockedACLRoles, false)) 538 539 // Create an ACL token linking to the ACL role. 540 token1 := mock.ACLToken() 541 token1.Roles = []*structs.ACLTokenRoleLink{{ID: mockedACLRoles[0].ID}} 542 require.NoError(t, testState.UpsertACLTokens( 543 structs.MsgTypeTestSetup, 20, []*structs.ACLToken{token1})) 544 545 // Perform the fix and check the returned token contains the 546 // correct roles. 547 readTxn := testState.db.ReadTxn() 548 outputToken, err := testState.fixTokenRoleLinks(readTxn, token1) 549 require.NoError(t, err) 550 require.Equal(t, outputToken.Roles, []*structs.ACLTokenRoleLink{{ 551 Name: mockedACLRoles[0].Name, ID: mockedACLRoles[0].ID, 552 }}) 553 }, 554 }, 555 { 556 name: "acl role from link deleted", 557 testFn: func() { 558 testState := testStateStore(t) 559 560 // Create the policies our ACL roles wants to link to. 561 policy1 := mock.ACLPolicy() 562 policy1.Name = "mocked-test-policy-1" 563 policy2 := mock.ACLPolicy() 564 policy2.Name = "mocked-test-policy-2" 565 566 require.NoError(t, testState.UpsertACLPolicies( 567 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 568 569 // Generate a some mocked ACL roles for testing and upsert these straight 570 // into state. 571 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 572 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 20, mockedACLRoles, false)) 573 574 // Create an ACL token linking to the ACL roles. 575 token1 := mock.ACLToken() 576 token1.Roles = []*structs.ACLTokenRoleLink{{ID: mockedACLRoles[0].ID}, {ID: mockedACLRoles[1].ID}} 577 require.NoError(t, testState.UpsertACLTokens( 578 structs.MsgTypeTestSetup, 30, []*structs.ACLToken{token1})) 579 580 // Now delete one of the ACL roles from state. 581 require.NoError(t, testState.DeleteACLRolesByID( 582 structs.MsgTypeTestSetup, 40, []string{mockedACLRoles[0].ID})) 583 584 // Perform the fix and check the returned token contains the 585 // correct roles. 586 readTxn := testState.db.ReadTxn() 587 outputToken, err := testState.fixTokenRoleLinks(readTxn, token1) 588 require.NoError(t, err) 589 require.Len(t, outputToken.Roles, 1) 590 require.Equal(t, outputToken.Roles, []*structs.ACLTokenRoleLink{{ 591 Name: mockedACLRoles[1].Name, ID: mockedACLRoles[1].ID, 592 }}) 593 }, 594 }, 595 { 596 name: "acl role from link name changed", 597 testFn: func() { 598 testState := testStateStore(t) 599 600 // Create the policies our ACL roles wants to link to. 601 policy1 := mock.ACLPolicy() 602 policy1.Name = "mocked-test-policy-1" 603 policy2 := mock.ACLPolicy() 604 policy2.Name = "mocked-test-policy-2" 605 606 require.NoError(t, testState.UpsertACLPolicies( 607 structs.MsgTypeTestSetup, 10, []*structs.ACLPolicy{policy1, policy2})) 608 609 // Generate a some mocked ACL roles for testing and upsert these straight 610 // into state. 611 mockedACLRoles := []*structs.ACLRole{mock.ACLRole(), mock.ACLRole()} 612 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 20, mockedACLRoles, false)) 613 614 // Create an ACL token linking to the ACL roles. 615 token1 := mock.ACLToken() 616 token1.Roles = []*structs.ACLTokenRoleLink{{ID: mockedACLRoles[0].ID}, {ID: mockedACLRoles[1].ID}} 617 require.NoError(t, testState.UpsertACLTokens( 618 structs.MsgTypeTestSetup, 30, []*structs.ACLToken{token1})) 619 620 // Now change the name of one of the ACL roles. 621 mockedACLRoles[0].Name = "badger-badger-badger" 622 require.NoError(t, testState.UpsertACLRoles(structs.MsgTypeTestSetup, 40, mockedACLRoles, false)) 623 624 // Perform the fix and check the returned token contains the 625 // correct roles. 626 readTxn := testState.db.ReadTxn() 627 outputToken, err := testState.fixTokenRoleLinks(readTxn, token1) 628 require.NoError(t, err) 629 require.Len(t, outputToken.Roles, 2) 630 require.ElementsMatch(t, outputToken.Roles, []*structs.ACLTokenRoleLink{ 631 {Name: mockedACLRoles[0].Name, ID: mockedACLRoles[0].ID}, 632 {Name: mockedACLRoles[1].Name, ID: mockedACLRoles[1].ID}, 633 }) 634 }, 635 }, 636 } 637 638 for _, tc := range testCases { 639 t.Run(tc.name, func(t *testing.T) { 640 tc.testFn() 641 }) 642 } 643 }