github.com/aminovpavel/nomad@v0.11.8/nomad/acl_endpoint_test.go (about)

     1  package nomad
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc"
    13  	"github.com/hashicorp/nomad/helper/uuid"
    14  	"github.com/hashicorp/nomad/nomad/mock"
    15  	"github.com/hashicorp/nomad/nomad/structs"
    16  	"github.com/hashicorp/nomad/testutil"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func TestACLEndpoint_GetPolicy(t *testing.T) {
    22  	t.Parallel()
    23  
    24  	s1, root, cleanupS1 := TestACLServer(t, nil)
    25  	defer cleanupS1()
    26  	codec := rpcClient(t, s1)
    27  	testutil.WaitForLeader(t, s1.RPC)
    28  
    29  	// Create the register request
    30  	policy := mock.ACLPolicy()
    31  	s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{policy})
    32  
    33  	anonymousPolicy := mock.ACLPolicy()
    34  	anonymousPolicy.Name = "anonymous"
    35  	s1.fsm.State().UpsertACLPolicies(1001, []*structs.ACLPolicy{anonymousPolicy})
    36  
    37  	// Create a token with one the policy
    38  	token := mock.ACLToken()
    39  	token.Policies = []string{policy.Name}
    40  	s1.fsm.State().UpsertACLTokens(1002, []*structs.ACLToken{token})
    41  
    42  	// Lookup the policy
    43  	get := &structs.ACLPolicySpecificRequest{
    44  		Name: policy.Name,
    45  		QueryOptions: structs.QueryOptions{
    46  			Region:    "global",
    47  			AuthToken: root.SecretID,
    48  		},
    49  	}
    50  	var resp structs.SingleACLPolicyResponse
    51  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp); err != nil {
    52  		t.Fatalf("err: %v", err)
    53  	}
    54  	assert.Equal(t, uint64(1000), resp.Index)
    55  	assert.Equal(t, policy, resp.Policy)
    56  
    57  	// Lookup non-existing policy
    58  	get.Name = uuid.Generate()
    59  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp); err != nil {
    60  		t.Fatalf("err: %v", err)
    61  	}
    62  	assert.Equal(t, uint64(1001), resp.Index)
    63  	assert.Nil(t, resp.Policy)
    64  
    65  	// Lookup the policy with the token
    66  	get = &structs.ACLPolicySpecificRequest{
    67  		Name: policy.Name,
    68  		QueryOptions: structs.QueryOptions{
    69  			Region:    "global",
    70  			AuthToken: token.SecretID,
    71  		},
    72  	}
    73  	var resp2 structs.SingleACLPolicyResponse
    74  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp2); err != nil {
    75  		t.Fatalf("err: %v", err)
    76  	}
    77  	assert.EqualValues(t, 1000, resp2.Index)
    78  	assert.Equal(t, policy, resp2.Policy)
    79  
    80  	// Lookup the anonymous policy with no token
    81  	get = &structs.ACLPolicySpecificRequest{
    82  		Name: anonymousPolicy.Name,
    83  		QueryOptions: structs.QueryOptions{
    84  			Region: "global",
    85  		},
    86  	}
    87  	var resp3 structs.SingleACLPolicyResponse
    88  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp3); err != nil {
    89  		require.NoError(t, err)
    90  	}
    91  	assert.EqualValues(t, 1001, resp3.Index)
    92  	assert.Equal(t, anonymousPolicy, resp3.Policy)
    93  
    94  	// Lookup non-anonoymous policy with no token
    95  	get = &structs.ACLPolicySpecificRequest{
    96  		Name: policy.Name,
    97  		QueryOptions: structs.QueryOptions{
    98  			Region: "global",
    99  		},
   100  	}
   101  	var resp4 structs.SingleACLPolicyResponse
   102  	err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", get, &resp4)
   103  	require.Error(t, err)
   104  	require.Contains(t, err.Error(), structs.ErrPermissionDenied.Error())
   105  }
   106  
   107  func TestACLEndpoint_GetPolicy_Blocking(t *testing.T) {
   108  	t.Parallel()
   109  
   110  	s1, root, cleanupS1 := TestACLServer(t, nil)
   111  	defer cleanupS1()
   112  	state := s1.fsm.State()
   113  	codec := rpcClient(t, s1)
   114  	testutil.WaitForLeader(t, s1.RPC)
   115  
   116  	// Create the policies
   117  	p1 := mock.ACLPolicy()
   118  	p2 := mock.ACLPolicy()
   119  
   120  	// First create an unrelated policy
   121  	time.AfterFunc(100*time.Millisecond, func() {
   122  		err := state.UpsertACLPolicies(100, []*structs.ACLPolicy{p1})
   123  		if err != nil {
   124  			t.Fatalf("err: %v", err)
   125  		}
   126  	})
   127  
   128  	// Upsert the policy we are watching later
   129  	time.AfterFunc(200*time.Millisecond, func() {
   130  		err := state.UpsertACLPolicies(200, []*structs.ACLPolicy{p2})
   131  		if err != nil {
   132  			t.Fatalf("err: %v", err)
   133  		}
   134  	})
   135  
   136  	// Lookup the policy
   137  	req := &structs.ACLPolicySpecificRequest{
   138  		Name: p2.Name,
   139  		QueryOptions: structs.QueryOptions{
   140  			Region:        "global",
   141  			MinQueryIndex: 150,
   142  			AuthToken:     root.SecretID,
   143  		},
   144  	}
   145  	var resp structs.SingleACLPolicyResponse
   146  	start := time.Now()
   147  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", req, &resp); err != nil {
   148  		t.Fatalf("err: %v", err)
   149  	}
   150  
   151  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
   152  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   153  	}
   154  	if resp.Index != 200 {
   155  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   156  	}
   157  	if resp.Policy == nil || resp.Policy.Name != p2.Name {
   158  		t.Fatalf("bad: %#v", resp.Policy)
   159  	}
   160  
   161  	// Eval delete triggers watches
   162  	time.AfterFunc(100*time.Millisecond, func() {
   163  		err := state.DeleteACLPolicies(300, []string{p2.Name})
   164  		if err != nil {
   165  			t.Fatalf("err: %v", err)
   166  		}
   167  	})
   168  
   169  	req.QueryOptions.MinQueryIndex = 250
   170  	var resp2 structs.SingleACLPolicyResponse
   171  	start = time.Now()
   172  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", req, &resp2); err != nil {
   173  		t.Fatalf("err: %v", err)
   174  	}
   175  
   176  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   177  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   178  	}
   179  	if resp2.Index != 300 {
   180  		t.Fatalf("Bad index: %d %d", resp2.Index, 300)
   181  	}
   182  	if resp2.Policy != nil {
   183  		t.Fatalf("bad: %#v", resp2.Policy)
   184  	}
   185  }
   186  
   187  func TestACLEndpoint_GetPolicies(t *testing.T) {
   188  	t.Parallel()
   189  
   190  	s1, root, cleanupS1 := TestACLServer(t, nil)
   191  	defer cleanupS1()
   192  	codec := rpcClient(t, s1)
   193  	testutil.WaitForLeader(t, s1.RPC)
   194  
   195  	// Create the register request
   196  	policy := mock.ACLPolicy()
   197  	policy2 := mock.ACLPolicy()
   198  	s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{policy, policy2})
   199  
   200  	// Lookup the policy
   201  	get := &structs.ACLPolicySetRequest{
   202  		Names: []string{policy.Name, policy2.Name},
   203  		QueryOptions: structs.QueryOptions{
   204  			Region:    "global",
   205  			AuthToken: root.SecretID,
   206  		},
   207  	}
   208  	var resp structs.ACLPolicySetResponse
   209  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err != nil {
   210  		t.Fatalf("err: %v", err)
   211  	}
   212  	assert.Equal(t, uint64(1000), resp.Index)
   213  	assert.Equal(t, 2, len(resp.Policies))
   214  	assert.Equal(t, policy, resp.Policies[policy.Name])
   215  	assert.Equal(t, policy2, resp.Policies[policy2.Name])
   216  
   217  	// Lookup non-existing policy
   218  	get.Names = []string{uuid.Generate()}
   219  	resp = structs.ACLPolicySetResponse{}
   220  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err != nil {
   221  		t.Fatalf("err: %v", err)
   222  	}
   223  	assert.Equal(t, uint64(1000), resp.Index)
   224  	assert.Equal(t, 0, len(resp.Policies))
   225  }
   226  
   227  func TestACLEndpoint_GetPolicies_TokenSubset(t *testing.T) {
   228  	t.Parallel()
   229  
   230  	s1, _, cleanupS1 := TestACLServer(t, nil)
   231  	defer cleanupS1()
   232  	codec := rpcClient(t, s1)
   233  	testutil.WaitForLeader(t, s1.RPC)
   234  
   235  	// Create the register request
   236  	policy := mock.ACLPolicy()
   237  	policy2 := mock.ACLPolicy()
   238  	s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{policy, policy2})
   239  
   240  	token := mock.ACLToken()
   241  	token.Policies = []string{policy.Name}
   242  	s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token})
   243  
   244  	// Lookup the policy which is a subset of our tokens
   245  	get := &structs.ACLPolicySetRequest{
   246  		Names: []string{policy.Name},
   247  		QueryOptions: structs.QueryOptions{
   248  			Region:    "global",
   249  			AuthToken: token.SecretID,
   250  		},
   251  	}
   252  	var resp structs.ACLPolicySetResponse
   253  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err != nil {
   254  		t.Fatalf("err: %v", err)
   255  	}
   256  	assert.Equal(t, uint64(1000), resp.Index)
   257  	assert.Equal(t, 1, len(resp.Policies))
   258  	assert.Equal(t, policy, resp.Policies[policy.Name])
   259  
   260  	// Lookup non-associated policy
   261  	get.Names = []string{policy2.Name}
   262  	resp = structs.ACLPolicySetResponse{}
   263  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", get, &resp); err == nil {
   264  		t.Fatalf("expected error")
   265  	}
   266  }
   267  
   268  func TestACLEndpoint_GetPolicies_Blocking(t *testing.T) {
   269  	t.Parallel()
   270  
   271  	s1, root, cleanupS1 := TestACLServer(t, nil)
   272  	defer cleanupS1()
   273  	state := s1.fsm.State()
   274  	codec := rpcClient(t, s1)
   275  	testutil.WaitForLeader(t, s1.RPC)
   276  
   277  	// Create the policies
   278  	p1 := mock.ACLPolicy()
   279  	p2 := mock.ACLPolicy()
   280  
   281  	// First create an unrelated policy
   282  	time.AfterFunc(100*time.Millisecond, func() {
   283  		err := state.UpsertACLPolicies(100, []*structs.ACLPolicy{p1})
   284  		if err != nil {
   285  			t.Fatalf("err: %v", err)
   286  		}
   287  	})
   288  
   289  	// Upsert the policy we are watching later
   290  	time.AfterFunc(200*time.Millisecond, func() {
   291  		err := state.UpsertACLPolicies(200, []*structs.ACLPolicy{p2})
   292  		if err != nil {
   293  			t.Fatalf("err: %v", err)
   294  		}
   295  	})
   296  
   297  	// Lookup the policy
   298  	req := &structs.ACLPolicySetRequest{
   299  		Names: []string{p2.Name},
   300  		QueryOptions: structs.QueryOptions{
   301  			Region:        "global",
   302  			MinQueryIndex: 150,
   303  			AuthToken:     root.SecretID,
   304  		},
   305  	}
   306  	var resp structs.ACLPolicySetResponse
   307  	start := time.Now()
   308  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", req, &resp); err != nil {
   309  		t.Fatalf("err: %v", err)
   310  	}
   311  
   312  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
   313  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   314  	}
   315  	if resp.Index != 200 {
   316  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   317  	}
   318  	if len(resp.Policies) == 0 || resp.Policies[p2.Name] == nil {
   319  		t.Fatalf("bad: %#v", resp.Policies)
   320  	}
   321  
   322  	// Eval delete triggers watches
   323  	time.AfterFunc(100*time.Millisecond, func() {
   324  		err := state.DeleteACLPolicies(300, []string{p2.Name})
   325  		if err != nil {
   326  			t.Fatalf("err: %v", err)
   327  		}
   328  	})
   329  
   330  	req.QueryOptions.MinQueryIndex = 250
   331  	var resp2 structs.ACLPolicySetResponse
   332  	start = time.Now()
   333  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicies", req, &resp2); err != nil {
   334  		t.Fatalf("err: %v", err)
   335  	}
   336  
   337  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   338  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   339  	}
   340  	if resp2.Index != 300 {
   341  		t.Fatalf("Bad index: %d %d", resp2.Index, 300)
   342  	}
   343  	if len(resp2.Policies) != 0 {
   344  		t.Fatalf("bad: %#v", resp2.Policies)
   345  	}
   346  }
   347  
   348  func TestACLEndpoint_ListPolicies(t *testing.T) {
   349  	assert := assert.New(t)
   350  	t.Parallel()
   351  
   352  	s1, root, cleanupS1 := TestACLServer(t, nil)
   353  	defer cleanupS1()
   354  	codec := rpcClient(t, s1)
   355  	testutil.WaitForLeader(t, s1.RPC)
   356  
   357  	// Create the register request
   358  	p1 := mock.ACLPolicy()
   359  	p2 := mock.ACLPolicy()
   360  
   361  	p1.Name = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9"
   362  	p2.Name = "aaaabbbb-3350-4b4b-d185-0e1992ed43e9"
   363  	s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{p1, p2})
   364  
   365  	// Create a token with one of those policies
   366  	token := mock.ACLToken()
   367  	token.Policies = []string{p1.Name}
   368  	s1.fsm.State().UpsertACLTokens(1001, []*structs.ACLToken{token})
   369  
   370  	// Lookup the policies
   371  	get := &structs.ACLPolicyListRequest{
   372  		QueryOptions: structs.QueryOptions{
   373  			Region:    "global",
   374  			AuthToken: root.SecretID,
   375  		},
   376  	}
   377  	var resp structs.ACLPolicyListResponse
   378  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp); err != nil {
   379  		t.Fatalf("err: %v", err)
   380  	}
   381  	assert.EqualValues(1000, resp.Index)
   382  	assert.Len(resp.Policies, 2)
   383  
   384  	// Lookup the policies by prefix
   385  	get = &structs.ACLPolicyListRequest{
   386  		QueryOptions: structs.QueryOptions{
   387  			Region:    "global",
   388  			Prefix:    "aaaabb",
   389  			AuthToken: root.SecretID,
   390  		},
   391  	}
   392  	var resp2 structs.ACLPolicyListResponse
   393  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp2); err != nil {
   394  		t.Fatalf("err: %v", err)
   395  	}
   396  	assert.EqualValues(1000, resp2.Index)
   397  	assert.Len(resp2.Policies, 1)
   398  
   399  	// List policies using the created token
   400  	get = &structs.ACLPolicyListRequest{
   401  		QueryOptions: structs.QueryOptions{
   402  			Region:    "global",
   403  			AuthToken: token.SecretID,
   404  		},
   405  	}
   406  	var resp3 structs.ACLPolicyListResponse
   407  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp3); err != nil {
   408  		t.Fatalf("err: %v", err)
   409  	}
   410  	assert.EqualValues(1000, resp3.Index)
   411  	if assert.Len(resp3.Policies, 1) {
   412  		assert.Equal(resp3.Policies[0].Name, p1.Name)
   413  	}
   414  }
   415  
   416  // TestACLEndpoint_ListPolicies_Unauthenticated asserts that
   417  // unauthenticated ListPolicies returns anonymous policy if one
   418  // exists, otherwise, empty
   419  func TestACLEndpoint_ListPolicies_Unauthenticated(t *testing.T) {
   420  	t.Parallel()
   421  
   422  	s1, _, cleanupS1 := TestACLServer(t, nil)
   423  	defer cleanupS1()
   424  	codec := rpcClient(t, s1)
   425  	testutil.WaitForLeader(t, s1.RPC)
   426  
   427  	listPolicies := func() (*structs.ACLPolicyListResponse, error) {
   428  		// Lookup the policies
   429  		get := &structs.ACLPolicyListRequest{
   430  			QueryOptions: structs.QueryOptions{
   431  				Region: "global",
   432  			},
   433  		}
   434  
   435  		var resp structs.ACLPolicyListResponse
   436  		err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", get, &resp)
   437  		if err != nil {
   438  			return nil, err
   439  		}
   440  		return &resp, nil
   441  	}
   442  
   443  	p1 := mock.ACLPolicy()
   444  	p1.Name = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9"
   445  	s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{p1})
   446  
   447  	t.Run("no anonymous policy", func(t *testing.T) {
   448  		resp, err := listPolicies()
   449  		require.NoError(t, err)
   450  		require.Empty(t, resp.Policies)
   451  		require.Equal(t, uint64(1000), resp.Index)
   452  	})
   453  
   454  	// now try with anonymous policy
   455  	p2 := mock.ACLPolicy()
   456  	p2.Name = "anonymous"
   457  	s1.fsm.State().UpsertACLPolicies(1001, []*structs.ACLPolicy{p2})
   458  
   459  	t.Run("with anonymous policy", func(t *testing.T) {
   460  		resp, err := listPolicies()
   461  		require.NoError(t, err)
   462  		require.Len(t, resp.Policies, 1)
   463  		require.Equal(t, "anonymous", resp.Policies[0].Name)
   464  		require.Equal(t, uint64(1001), resp.Index)
   465  	})
   466  }
   467  
   468  func TestACLEndpoint_ListPolicies_Blocking(t *testing.T) {
   469  	t.Parallel()
   470  
   471  	s1, root, cleanupS1 := TestACLServer(t, nil)
   472  	defer cleanupS1()
   473  	state := s1.fsm.State()
   474  	codec := rpcClient(t, s1)
   475  	testutil.WaitForLeader(t, s1.RPC)
   476  
   477  	// Create the policy
   478  	policy := mock.ACLPolicy()
   479  
   480  	// Upsert eval triggers watches
   481  	time.AfterFunc(100*time.Millisecond, func() {
   482  		if err := state.UpsertACLPolicies(2, []*structs.ACLPolicy{policy}); err != nil {
   483  			t.Fatalf("err: %v", err)
   484  		}
   485  	})
   486  
   487  	req := &structs.ACLPolicyListRequest{
   488  		QueryOptions: structs.QueryOptions{
   489  			Region:        "global",
   490  			MinQueryIndex: 1,
   491  			AuthToken:     root.SecretID,
   492  		},
   493  	}
   494  	start := time.Now()
   495  	var resp structs.ACLPolicyListResponse
   496  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", req, &resp); err != nil {
   497  		t.Fatalf("err: %v", err)
   498  	}
   499  
   500  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   501  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   502  	}
   503  	assert.Equal(t, uint64(2), resp.Index)
   504  	if len(resp.Policies) != 1 || resp.Policies[0].Name != policy.Name {
   505  		t.Fatalf("bad: %#v", resp.Policies)
   506  	}
   507  
   508  	// Eval deletion triggers watches
   509  	time.AfterFunc(100*time.Millisecond, func() {
   510  		if err := state.DeleteACLPolicies(3, []string{policy.Name}); err != nil {
   511  			t.Fatalf("err: %v", err)
   512  		}
   513  	})
   514  
   515  	req.MinQueryIndex = 2
   516  	start = time.Now()
   517  	var resp2 structs.ACLPolicyListResponse
   518  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListPolicies", req, &resp2); err != nil {
   519  		t.Fatalf("err: %v", err)
   520  	}
   521  
   522  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   523  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   524  	}
   525  	assert.Equal(t, uint64(3), resp2.Index)
   526  	assert.Equal(t, 0, len(resp2.Policies))
   527  }
   528  
   529  func TestACLEndpoint_DeletePolicies(t *testing.T) {
   530  	t.Parallel()
   531  
   532  	s1, root, cleanupS1 := TestACLServer(t, nil)
   533  	defer cleanupS1()
   534  	codec := rpcClient(t, s1)
   535  	testutil.WaitForLeader(t, s1.RPC)
   536  
   537  	// Create the register request
   538  	p1 := mock.ACLPolicy()
   539  	s1.fsm.State().UpsertACLPolicies(1000, []*structs.ACLPolicy{p1})
   540  
   541  	// Lookup the policies
   542  	req := &structs.ACLPolicyDeleteRequest{
   543  		Names: []string{p1.Name},
   544  		WriteRequest: structs.WriteRequest{
   545  			Region:    "global",
   546  			AuthToken: root.SecretID,
   547  		},
   548  	}
   549  	var resp structs.GenericResponse
   550  	if err := msgpackrpc.CallWithCodec(codec, "ACL.DeletePolicies", req, &resp); err != nil {
   551  		t.Fatalf("err: %v", err)
   552  	}
   553  	assert.NotEqual(t, uint64(0), resp.Index)
   554  }
   555  
   556  func TestACLEndpoint_UpsertPolicies(t *testing.T) {
   557  	t.Parallel()
   558  
   559  	s1, root, cleanupS1 := TestACLServer(t, nil)
   560  	defer cleanupS1()
   561  	codec := rpcClient(t, s1)
   562  	testutil.WaitForLeader(t, s1.RPC)
   563  
   564  	// Create the register request
   565  	p1 := mock.ACLPolicy()
   566  
   567  	// Lookup the policies
   568  	req := &structs.ACLPolicyUpsertRequest{
   569  		Policies: []*structs.ACLPolicy{p1},
   570  		WriteRequest: structs.WriteRequest{
   571  			Region:    "global",
   572  			AuthToken: root.SecretID,
   573  		},
   574  	}
   575  	var resp structs.GenericResponse
   576  	if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertPolicies", req, &resp); err != nil {
   577  		t.Fatalf("err: %v", err)
   578  	}
   579  	assert.NotEqual(t, uint64(0), resp.Index)
   580  
   581  	// Check we created the policy
   582  	out, err := s1.fsm.State().ACLPolicyByName(nil, p1.Name)
   583  	assert.Nil(t, err)
   584  	assert.NotNil(t, out)
   585  }
   586  
   587  func TestACLEndpoint_UpsertPolicies_Invalid(t *testing.T) {
   588  	t.Parallel()
   589  
   590  	s1, root, cleanupS1 := TestACLServer(t, nil)
   591  	defer cleanupS1()
   592  	codec := rpcClient(t, s1)
   593  	testutil.WaitForLeader(t, s1.RPC)
   594  
   595  	// Create the register request
   596  	p1 := mock.ACLPolicy()
   597  	p1.Rules = "blah blah invalid"
   598  
   599  	// Lookup the policies
   600  	req := &structs.ACLPolicyUpsertRequest{
   601  		Policies: []*structs.ACLPolicy{p1},
   602  		WriteRequest: structs.WriteRequest{
   603  			Region:    "global",
   604  			AuthToken: root.SecretID,
   605  		},
   606  	}
   607  	var resp structs.GenericResponse
   608  	err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertPolicies", req, &resp)
   609  	assert.NotNil(t, err)
   610  	if !strings.Contains(err.Error(), "failed to parse") {
   611  		t.Fatalf("bad: %s", err)
   612  	}
   613  }
   614  
   615  func TestACLEndpoint_GetToken(t *testing.T) {
   616  	t.Parallel()
   617  
   618  	s1, root, cleanupS1 := TestACLServer(t, nil)
   619  	defer cleanupS1()
   620  	codec := rpcClient(t, s1)
   621  	testutil.WaitForLeader(t, s1.RPC)
   622  
   623  	// Create the register request
   624  	token := mock.ACLToken()
   625  	s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token})
   626  
   627  	// Lookup the token
   628  	get := &structs.ACLTokenSpecificRequest{
   629  		AccessorID: token.AccessorID,
   630  		QueryOptions: structs.QueryOptions{
   631  			Region:    "global",
   632  			AuthToken: root.SecretID,
   633  		},
   634  	}
   635  	var resp structs.SingleACLTokenResponse
   636  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", get, &resp); err != nil {
   637  		t.Fatalf("err: %v", err)
   638  	}
   639  	assert.Equal(t, uint64(1000), resp.Index)
   640  	assert.Equal(t, token, resp.Token)
   641  
   642  	// Lookup non-existing token
   643  	get.AccessorID = uuid.Generate()
   644  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", get, &resp); err != nil {
   645  		t.Fatalf("err: %v", err)
   646  	}
   647  	assert.Equal(t, uint64(1000), resp.Index)
   648  	assert.Nil(t, resp.Token)
   649  
   650  	// Lookup the token by accessor id using the tokens secret ID
   651  	get.AccessorID = token.AccessorID
   652  	get.AuthToken = token.SecretID
   653  	var resp2 structs.SingleACLTokenResponse
   654  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", get, &resp2); err != nil {
   655  		t.Fatalf("err: %v", err)
   656  	}
   657  	assert.Equal(t, uint64(1000), resp2.Index)
   658  	assert.Equal(t, token, resp2.Token)
   659  }
   660  
   661  func TestACLEndpoint_GetToken_Blocking(t *testing.T) {
   662  	t.Parallel()
   663  
   664  	s1, root, cleanupS1 := TestACLServer(t, nil)
   665  	defer cleanupS1()
   666  	state := s1.fsm.State()
   667  	codec := rpcClient(t, s1)
   668  	testutil.WaitForLeader(t, s1.RPC)
   669  
   670  	// Create the tokens
   671  	p1 := mock.ACLToken()
   672  	p2 := mock.ACLToken()
   673  
   674  	// First create an unrelated token
   675  	time.AfterFunc(100*time.Millisecond, func() {
   676  		err := state.UpsertACLTokens(100, []*structs.ACLToken{p1})
   677  		if err != nil {
   678  			t.Fatalf("err: %v", err)
   679  		}
   680  	})
   681  
   682  	// Upsert the token we are watching later
   683  	time.AfterFunc(200*time.Millisecond, func() {
   684  		err := state.UpsertACLTokens(200, []*structs.ACLToken{p2})
   685  		if err != nil {
   686  			t.Fatalf("err: %v", err)
   687  		}
   688  	})
   689  
   690  	// Lookup the token
   691  	req := &structs.ACLTokenSpecificRequest{
   692  		AccessorID: p2.AccessorID,
   693  		QueryOptions: structs.QueryOptions{
   694  			Region:        "global",
   695  			MinQueryIndex: 150,
   696  			AuthToken:     root.SecretID,
   697  		},
   698  	}
   699  	var resp structs.SingleACLTokenResponse
   700  	start := time.Now()
   701  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", req, &resp); err != nil {
   702  		t.Fatalf("err: %v", err)
   703  	}
   704  
   705  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
   706  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   707  	}
   708  	if resp.Index != 200 {
   709  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   710  	}
   711  	if resp.Token == nil || resp.Token.AccessorID != p2.AccessorID {
   712  		t.Fatalf("bad: %#v", resp.Token)
   713  	}
   714  
   715  	// Eval delete triggers watches
   716  	time.AfterFunc(100*time.Millisecond, func() {
   717  		err := state.DeleteACLTokens(300, []string{p2.AccessorID})
   718  		if err != nil {
   719  			t.Fatalf("err: %v", err)
   720  		}
   721  	})
   722  
   723  	req.QueryOptions.MinQueryIndex = 250
   724  	var resp2 structs.SingleACLTokenResponse
   725  	start = time.Now()
   726  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetToken", req, &resp2); err != nil {
   727  		t.Fatalf("err: %v", err)
   728  	}
   729  
   730  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   731  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   732  	}
   733  	if resp2.Index != 300 {
   734  		t.Fatalf("Bad index: %d %d", resp2.Index, 300)
   735  	}
   736  	if resp2.Token != nil {
   737  		t.Fatalf("bad: %#v", resp2.Token)
   738  	}
   739  }
   740  
   741  func TestACLEndpoint_GetTokens(t *testing.T) {
   742  	t.Parallel()
   743  
   744  	s1, root, cleanupS1 := TestACLServer(t, nil)
   745  	defer cleanupS1()
   746  	codec := rpcClient(t, s1)
   747  	testutil.WaitForLeader(t, s1.RPC)
   748  
   749  	// Create the register request
   750  	token := mock.ACLToken()
   751  	token2 := mock.ACLToken()
   752  	s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token, token2})
   753  
   754  	// Lookup the token
   755  	get := &structs.ACLTokenSetRequest{
   756  		AccessorIDS: []string{token.AccessorID, token2.AccessorID},
   757  		QueryOptions: structs.QueryOptions{
   758  			Region:    "global",
   759  			AuthToken: root.SecretID,
   760  		},
   761  	}
   762  	var resp structs.ACLTokenSetResponse
   763  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", get, &resp); err != nil {
   764  		t.Fatalf("err: %v", err)
   765  	}
   766  	assert.Equal(t, uint64(1000), resp.Index)
   767  	assert.Equal(t, 2, len(resp.Tokens))
   768  	assert.Equal(t, token, resp.Tokens[token.AccessorID])
   769  
   770  	// Lookup non-existing token
   771  	get.AccessorIDS = []string{uuid.Generate()}
   772  	resp = structs.ACLTokenSetResponse{}
   773  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", get, &resp); err != nil {
   774  		t.Fatalf("err: %v", err)
   775  	}
   776  	assert.Equal(t, uint64(1000), resp.Index)
   777  	assert.Equal(t, 0, len(resp.Tokens))
   778  }
   779  
   780  func TestACLEndpoint_GetTokens_Blocking(t *testing.T) {
   781  	t.Parallel()
   782  
   783  	s1, root, cleanupS1 := TestACLServer(t, nil)
   784  	defer cleanupS1()
   785  	state := s1.fsm.State()
   786  	codec := rpcClient(t, s1)
   787  	testutil.WaitForLeader(t, s1.RPC)
   788  
   789  	// Create the tokens
   790  	p1 := mock.ACLToken()
   791  	p2 := mock.ACLToken()
   792  
   793  	// First create an unrelated token
   794  	time.AfterFunc(100*time.Millisecond, func() {
   795  		err := state.UpsertACLTokens(100, []*structs.ACLToken{p1})
   796  		if err != nil {
   797  			t.Fatalf("err: %v", err)
   798  		}
   799  	})
   800  
   801  	// Upsert the token we are watching later
   802  	time.AfterFunc(200*time.Millisecond, func() {
   803  		err := state.UpsertACLTokens(200, []*structs.ACLToken{p2})
   804  		if err != nil {
   805  			t.Fatalf("err: %v", err)
   806  		}
   807  	})
   808  
   809  	// Lookup the token
   810  	req := &structs.ACLTokenSetRequest{
   811  		AccessorIDS: []string{p2.AccessorID},
   812  		QueryOptions: structs.QueryOptions{
   813  			Region:        "global",
   814  			MinQueryIndex: 150,
   815  			AuthToken:     root.SecretID,
   816  		},
   817  	}
   818  	var resp structs.ACLTokenSetResponse
   819  	start := time.Now()
   820  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", req, &resp); err != nil {
   821  		t.Fatalf("err: %v", err)
   822  	}
   823  
   824  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
   825  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   826  	}
   827  	if resp.Index != 200 {
   828  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   829  	}
   830  	if len(resp.Tokens) == 0 || resp.Tokens[p2.AccessorID] == nil {
   831  		t.Fatalf("bad: %#v", resp.Tokens)
   832  	}
   833  
   834  	// Eval delete triggers watches
   835  	time.AfterFunc(100*time.Millisecond, func() {
   836  		err := state.DeleteACLTokens(300, []string{p2.AccessorID})
   837  		if err != nil {
   838  			t.Fatalf("err: %v", err)
   839  		}
   840  	})
   841  
   842  	req.QueryOptions.MinQueryIndex = 250
   843  	var resp2 structs.ACLTokenSetResponse
   844  	start = time.Now()
   845  	if err := msgpackrpc.CallWithCodec(codec, "ACL.GetTokens", req, &resp2); err != nil {
   846  		t.Fatalf("err: %v", err)
   847  	}
   848  
   849  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   850  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   851  	}
   852  	if resp2.Index != 300 {
   853  		t.Fatalf("Bad index: %d %d", resp2.Index, 300)
   854  	}
   855  	if len(resp2.Tokens) != 0 {
   856  		t.Fatalf("bad: %#v", resp2.Tokens)
   857  	}
   858  }
   859  
   860  func TestACLEndpoint_ListTokens(t *testing.T) {
   861  	t.Parallel()
   862  
   863  	s1, root, cleanupS1 := TestACLServer(t, nil)
   864  	defer cleanupS1()
   865  	codec := rpcClient(t, s1)
   866  	testutil.WaitForLeader(t, s1.RPC)
   867  
   868  	// Create the register request
   869  	p1 := mock.ACLToken()
   870  	p2 := mock.ACLToken()
   871  	p2.Global = true
   872  
   873  	p1.AccessorID = "aaaaaaaa-3350-4b4b-d185-0e1992ed43e9"
   874  	p2.AccessorID = "aaaabbbb-3350-4b4b-d185-0e1992ed43e9"
   875  	s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{p1, p2})
   876  
   877  	// Lookup the tokens
   878  	get := &structs.ACLTokenListRequest{
   879  		QueryOptions: structs.QueryOptions{
   880  			Region:    "global",
   881  			AuthToken: root.SecretID,
   882  		},
   883  	}
   884  	var resp structs.ACLTokenListResponse
   885  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", get, &resp); err != nil {
   886  		t.Fatalf("err: %v", err)
   887  	}
   888  	assert.Equal(t, uint64(1000), resp.Index)
   889  	assert.Equal(t, 3, len(resp.Tokens))
   890  
   891  	// Lookup the tokens by prefix
   892  	get = &structs.ACLTokenListRequest{
   893  		QueryOptions: structs.QueryOptions{
   894  			Region:    "global",
   895  			Prefix:    "aaaabb",
   896  			AuthToken: root.SecretID,
   897  		},
   898  	}
   899  	var resp2 structs.ACLTokenListResponse
   900  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", get, &resp2); err != nil {
   901  		t.Fatalf("err: %v", err)
   902  	}
   903  	assert.Equal(t, uint64(1000), resp2.Index)
   904  	assert.Equal(t, 1, len(resp2.Tokens))
   905  
   906  	// Lookup the global tokens
   907  	get = &structs.ACLTokenListRequest{
   908  		GlobalOnly: true,
   909  		QueryOptions: structs.QueryOptions{
   910  			Region:    "global",
   911  			AuthToken: root.SecretID,
   912  		},
   913  	}
   914  	var resp3 structs.ACLTokenListResponse
   915  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", get, &resp3); err != nil {
   916  		t.Fatalf("err: %v", err)
   917  	}
   918  	assert.Equal(t, uint64(1000), resp3.Index)
   919  	assert.Equal(t, 2, len(resp3.Tokens))
   920  }
   921  
   922  func TestACLEndpoint_ListTokens_Blocking(t *testing.T) {
   923  	t.Parallel()
   924  
   925  	s1, root, cleanupS1 := TestACLServer(t, nil)
   926  	defer cleanupS1()
   927  	state := s1.fsm.State()
   928  	codec := rpcClient(t, s1)
   929  	testutil.WaitForLeader(t, s1.RPC)
   930  
   931  	// Create the token
   932  	token := mock.ACLToken()
   933  
   934  	// Upsert eval triggers watches
   935  	time.AfterFunc(100*time.Millisecond, func() {
   936  		if err := state.UpsertACLTokens(3, []*structs.ACLToken{token}); err != nil {
   937  			t.Fatalf("err: %v", err)
   938  		}
   939  	})
   940  
   941  	req := &structs.ACLTokenListRequest{
   942  		QueryOptions: structs.QueryOptions{
   943  			Region:        "global",
   944  			MinQueryIndex: 2,
   945  			AuthToken:     root.SecretID,
   946  		},
   947  	}
   948  	start := time.Now()
   949  	var resp structs.ACLTokenListResponse
   950  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", req, &resp); err != nil {
   951  		t.Fatalf("err: %v", err)
   952  	}
   953  
   954  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   955  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   956  	}
   957  	assert.Equal(t, uint64(3), resp.Index)
   958  	if len(resp.Tokens) != 2 {
   959  		t.Fatalf("bad: %#v", resp.Tokens)
   960  	}
   961  
   962  	// Eval deletion triggers watches
   963  	time.AfterFunc(100*time.Millisecond, func() {
   964  		if err := state.DeleteACLTokens(4, []string{token.AccessorID}); err != nil {
   965  			t.Fatalf("err: %v", err)
   966  		}
   967  	})
   968  
   969  	req.MinQueryIndex = 3
   970  	start = time.Now()
   971  	var resp2 structs.ACLTokenListResponse
   972  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ListTokens", req, &resp2); err != nil {
   973  		t.Fatalf("err: %v", err)
   974  	}
   975  
   976  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   977  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   978  	}
   979  	assert.Equal(t, uint64(4), resp2.Index)
   980  	assert.Equal(t, 1, len(resp2.Tokens))
   981  }
   982  
   983  func TestACLEndpoint_DeleteTokens(t *testing.T) {
   984  	t.Parallel()
   985  
   986  	s1, root, cleanupS1 := TestACLServer(t, nil)
   987  	defer cleanupS1()
   988  	codec := rpcClient(t, s1)
   989  	testutil.WaitForLeader(t, s1.RPC)
   990  
   991  	// Create the register request
   992  	p1 := mock.ACLToken()
   993  	s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{p1})
   994  
   995  	// Lookup the tokens
   996  	req := &structs.ACLTokenDeleteRequest{
   997  		AccessorIDs: []string{p1.AccessorID},
   998  		WriteRequest: structs.WriteRequest{
   999  			Region:    "global",
  1000  			AuthToken: root.SecretID,
  1001  		},
  1002  	}
  1003  	var resp structs.GenericResponse
  1004  	if err := msgpackrpc.CallWithCodec(codec, "ACL.DeleteTokens", req, &resp); err != nil {
  1005  		t.Fatalf("err: %v", err)
  1006  	}
  1007  	assert.NotEqual(t, uint64(0), resp.Index)
  1008  }
  1009  
  1010  func TestACLEndpoint_DeleteTokens_WithNonexistentToken(t *testing.T) {
  1011  	t.Parallel()
  1012  	assert := assert.New(t)
  1013  
  1014  	s1, root, cleanupS1 := TestACLServer(t, nil)
  1015  	defer cleanupS1()
  1016  	codec := rpcClient(t, s1)
  1017  	testutil.WaitForLeader(t, s1.RPC)
  1018  
  1019  	nonexistentToken := mock.ACLToken()
  1020  
  1021  	// Lookup the policies
  1022  	req := &structs.ACLTokenDeleteRequest{
  1023  		AccessorIDs: []string{nonexistentToken.AccessorID},
  1024  		WriteRequest: structs.WriteRequest{
  1025  			Region:    "global",
  1026  			AuthToken: root.SecretID,
  1027  		},
  1028  	}
  1029  	var resp structs.GenericResponse
  1030  	err := msgpackrpc.CallWithCodec(codec, "ACL.DeleteTokens", req, &resp)
  1031  
  1032  	assert.NotNil(err)
  1033  	expectedError := fmt.Sprintf("Cannot delete nonexistent tokens: %s", nonexistentToken.AccessorID)
  1034  	assert.Contains(err.Error(), expectedError)
  1035  }
  1036  
  1037  func TestACLEndpoint_Bootstrap(t *testing.T) {
  1038  	t.Parallel()
  1039  	s1, cleanupS1 := TestServer(t, func(c *Config) {
  1040  		c.ACLEnabled = true
  1041  	})
  1042  	defer cleanupS1()
  1043  	codec := rpcClient(t, s1)
  1044  	testutil.WaitForLeader(t, s1.RPC)
  1045  
  1046  	// Lookup the tokens
  1047  	req := &structs.ACLTokenBootstrapRequest{
  1048  		WriteRequest: structs.WriteRequest{Region: "global"},
  1049  	}
  1050  	var resp structs.ACLTokenUpsertResponse
  1051  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err != nil {
  1052  		t.Fatalf("err: %v", err)
  1053  	}
  1054  	assert.NotEqual(t, uint64(0), resp.Index)
  1055  	assert.NotNil(t, resp.Tokens[0])
  1056  
  1057  	// Get the token out from the response
  1058  	created := resp.Tokens[0]
  1059  	assert.NotEqual(t, "", created.AccessorID)
  1060  	assert.NotEqual(t, "", created.SecretID)
  1061  	assert.NotEqual(t, time.Time{}, created.CreateTime)
  1062  	assert.Equal(t, structs.ACLManagementToken, created.Type)
  1063  	assert.Equal(t, "Bootstrap Token", created.Name)
  1064  	assert.Equal(t, true, created.Global)
  1065  
  1066  	// Check we created the token
  1067  	out, err := s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID)
  1068  	assert.Nil(t, err)
  1069  	assert.Equal(t, created, out)
  1070  }
  1071  
  1072  func TestACLEndpoint_Bootstrap_Reset(t *testing.T) {
  1073  	t.Parallel()
  1074  	dir := tmpDir(t)
  1075  	defer os.RemoveAll(dir)
  1076  	s1, cleanupS1 := TestServer(t, func(c *Config) {
  1077  		c.ACLEnabled = true
  1078  		c.DataDir = dir
  1079  		c.DevMode = false
  1080  	})
  1081  	defer cleanupS1()
  1082  	codec := rpcClient(t, s1)
  1083  	testutil.WaitForLeader(t, s1.RPC)
  1084  
  1085  	// Lookup the tokens
  1086  	req := &structs.ACLTokenBootstrapRequest{
  1087  		WriteRequest: structs.WriteRequest{Region: "global"},
  1088  	}
  1089  	var resp structs.ACLTokenUpsertResponse
  1090  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err != nil {
  1091  		t.Fatalf("err: %v", err)
  1092  	}
  1093  	assert.NotEqual(t, uint64(0), resp.Index)
  1094  	assert.NotNil(t, resp.Tokens[0])
  1095  	resetIdx := resp.Tokens[0].CreateIndex
  1096  
  1097  	// Try again, should fail
  1098  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err == nil {
  1099  		t.Fatalf("expected err")
  1100  	}
  1101  
  1102  	// Create the reset file
  1103  	output := []byte(fmt.Sprintf("%d", resetIdx))
  1104  	path := filepath.Join(dir, aclBootstrapReset)
  1105  	assert.Nil(t, ioutil.WriteFile(path, output, 0755))
  1106  
  1107  	// Try again, should work with reset
  1108  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err != nil {
  1109  		t.Fatalf("err: %v", err)
  1110  	}
  1111  	assert.NotEqual(t, uint64(0), resp.Index)
  1112  	assert.NotNil(t, resp.Tokens[0])
  1113  
  1114  	// Get the token out from the response
  1115  	created := resp.Tokens[0]
  1116  	assert.NotEqual(t, "", created.AccessorID)
  1117  	assert.NotEqual(t, "", created.SecretID)
  1118  	assert.NotEqual(t, time.Time{}, created.CreateTime)
  1119  	assert.Equal(t, structs.ACLManagementToken, created.Type)
  1120  	assert.Equal(t, "Bootstrap Token", created.Name)
  1121  	assert.Equal(t, true, created.Global)
  1122  
  1123  	// Check we created the token
  1124  	out, err := s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID)
  1125  	assert.Nil(t, err)
  1126  	assert.Equal(t, created, out)
  1127  
  1128  	// Try again, should fail
  1129  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", req, &resp); err == nil {
  1130  		t.Fatalf("expected err")
  1131  	}
  1132  }
  1133  
  1134  func TestACLEndpoint_UpsertTokens(t *testing.T) {
  1135  	t.Parallel()
  1136  
  1137  	s1, root, cleanupS1 := TestACLServer(t, nil)
  1138  	defer cleanupS1()
  1139  	codec := rpcClient(t, s1)
  1140  	testutil.WaitForLeader(t, s1.RPC)
  1141  
  1142  	// Create the register request
  1143  	p1 := mock.ACLToken()
  1144  	p1.AccessorID = "" // Blank to create
  1145  
  1146  	// Lookup the tokens
  1147  	req := &structs.ACLTokenUpsertRequest{
  1148  		Tokens: []*structs.ACLToken{p1},
  1149  		WriteRequest: structs.WriteRequest{
  1150  			Region:    "global",
  1151  			AuthToken: root.SecretID,
  1152  		},
  1153  	}
  1154  	var resp structs.ACLTokenUpsertResponse
  1155  	if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp); err != nil {
  1156  		t.Fatalf("err: %v", err)
  1157  	}
  1158  	assert.NotEqual(t, uint64(0), resp.Index)
  1159  
  1160  	// Get the token out from the response
  1161  	created := resp.Tokens[0]
  1162  	assert.NotEqual(t, "", created.AccessorID)
  1163  	assert.NotEqual(t, "", created.SecretID)
  1164  	assert.NotEqual(t, time.Time{}, created.CreateTime)
  1165  	assert.Equal(t, p1.Type, created.Type)
  1166  	assert.Equal(t, p1.Policies, created.Policies)
  1167  	assert.Equal(t, p1.Name, created.Name)
  1168  
  1169  	// Check we created the token
  1170  	out, err := s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID)
  1171  	assert.Nil(t, err)
  1172  	assert.Equal(t, created, out)
  1173  
  1174  	// Update the token type
  1175  	req.Tokens[0] = created
  1176  	created.Type = "management"
  1177  	created.Policies = nil
  1178  
  1179  	// Upsert again
  1180  	if err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp); err != nil {
  1181  		t.Fatalf("err: %v", err)
  1182  	}
  1183  	assert.NotEqual(t, uint64(0), resp.Index)
  1184  
  1185  	// Check we modified the token
  1186  	out, err = s1.fsm.State().ACLTokenByAccessorID(nil, created.AccessorID)
  1187  	assert.Nil(t, err)
  1188  	assert.Equal(t, created, out)
  1189  }
  1190  
  1191  func TestACLEndpoint_UpsertTokens_Invalid(t *testing.T) {
  1192  	t.Parallel()
  1193  
  1194  	s1, root, cleanupS1 := TestACLServer(t, nil)
  1195  	defer cleanupS1()
  1196  	codec := rpcClient(t, s1)
  1197  	testutil.WaitForLeader(t, s1.RPC)
  1198  
  1199  	// Create the register request
  1200  	p1 := mock.ACLToken()
  1201  	p1.Type = "blah blah"
  1202  
  1203  	// Lookup the tokens
  1204  	req := &structs.ACLTokenUpsertRequest{
  1205  		Tokens: []*structs.ACLToken{p1},
  1206  		WriteRequest: structs.WriteRequest{
  1207  			Region:    "global",
  1208  			AuthToken: root.SecretID,
  1209  		},
  1210  	}
  1211  	var resp structs.GenericResponse
  1212  	err := msgpackrpc.CallWithCodec(codec, "ACL.UpsertTokens", req, &resp)
  1213  	assert.NotNil(t, err)
  1214  	if !strings.Contains(err.Error(), "client or management") {
  1215  		t.Fatalf("bad: %s", err)
  1216  	}
  1217  }
  1218  
  1219  func TestACLEndpoint_ResolveToken(t *testing.T) {
  1220  	t.Parallel()
  1221  	s1, _, cleanupS1 := TestACLServer(t, nil)
  1222  	defer cleanupS1()
  1223  	codec := rpcClient(t, s1)
  1224  	testutil.WaitForLeader(t, s1.RPC)
  1225  
  1226  	// Create the register request
  1227  	token := mock.ACLToken()
  1228  	s1.fsm.State().UpsertACLTokens(1000, []*structs.ACLToken{token})
  1229  
  1230  	// Lookup the token
  1231  	get := &structs.ResolveACLTokenRequest{
  1232  		SecretID:     token.SecretID,
  1233  		QueryOptions: structs.QueryOptions{Region: "global"},
  1234  	}
  1235  	var resp structs.ResolveACLTokenResponse
  1236  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ResolveToken", get, &resp); err != nil {
  1237  		t.Fatalf("err: %v", err)
  1238  	}
  1239  	assert.Equal(t, uint64(1000), resp.Index)
  1240  	assert.Equal(t, token, resp.Token)
  1241  
  1242  	// Lookup non-existing token
  1243  	get.SecretID = uuid.Generate()
  1244  	if err := msgpackrpc.CallWithCodec(codec, "ACL.ResolveToken", get, &resp); err != nil {
  1245  		t.Fatalf("err: %v", err)
  1246  	}
  1247  	assert.Equal(t, uint64(1000), resp.Index)
  1248  	assert.Nil(t, resp.Token)
  1249  }