github.phpd.cn/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  }