github.com/hashicorp/nomad/api@v0.0.0-20240306165712-3193ac204f65/acl_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package api
     5  
     6  import (
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/hashicorp/nomad/api/internal/testutil"
    11  	"github.com/shoenig/test/must"
    12  )
    13  
    14  func TestACLPolicies_ListUpsert(t *testing.T) {
    15  	testutil.Parallel(t)
    16  
    17  	c, s, _ := makeACLClient(t, nil, nil)
    18  	defer s.Stop()
    19  	ap := c.ACLPolicies()
    20  
    21  	// Listing when nothing exists returns empty
    22  	result, qm, err := ap.List(nil)
    23  	must.NoError(t, err)
    24  	must.One(t, qm.LastIndex)
    25  	must.Len(t, 0, result)
    26  
    27  	// Register a policy
    28  	policy := &ACLPolicy{
    29  		Name:        "test",
    30  		Description: "test",
    31  		Rules: `namespace "default" {
    32  			policy = "read"
    33  		}
    34  		`,
    35  	}
    36  	wm, err := ap.Upsert(policy, nil)
    37  	must.NoError(t, err)
    38  	assertWriteMeta(t, wm)
    39  
    40  	// Check the list again
    41  	result, qm, err = ap.List(nil)
    42  	must.NoError(t, err)
    43  
    44  	assertQueryMeta(t, qm)
    45  	must.Len(t, 1, result)
    46  }
    47  
    48  func TestACLPolicies_Delete(t *testing.T) {
    49  	testutil.Parallel(t)
    50  
    51  	c, s, _ := makeACLClient(t, nil, nil)
    52  	defer s.Stop()
    53  	ap := c.ACLPolicies()
    54  
    55  	// Register a policy
    56  	policy := &ACLPolicy{
    57  		Name:        "test",
    58  		Description: "test",
    59  		Rules: `namespace "default" {
    60  			policy = "read"
    61  		}
    62  		`,
    63  	}
    64  	wm, err := ap.Upsert(policy, nil)
    65  	must.NoError(t, err)
    66  	assertWriteMeta(t, wm)
    67  
    68  	// Delete the policy
    69  	wm, err = ap.Delete(policy.Name, nil)
    70  	must.NoError(t, err)
    71  	assertWriteMeta(t, wm)
    72  
    73  	// Check the list again
    74  	result, qm, err := ap.List(nil)
    75  	must.NoError(t, err)
    76  
    77  	assertQueryMeta(t, qm)
    78  	must.Len(t, 0, result)
    79  }
    80  
    81  func TestACLPolicies_Info(t *testing.T) {
    82  	testutil.Parallel(t)
    83  
    84  	c, s, _ := makeACLClient(t, nil, nil)
    85  	defer s.Stop()
    86  	ap := c.ACLPolicies()
    87  
    88  	// Register a policy
    89  	policy := &ACLPolicy{
    90  		Name:        "test",
    91  		Description: "test",
    92  		Rules: `namespace "default" {
    93  			policy = "read"
    94  		}
    95  		`,
    96  	}
    97  	wm, err := ap.Upsert(policy, nil)
    98  	must.NoError(t, err)
    99  	assertWriteMeta(t, wm)
   100  
   101  	// Query the policy
   102  	out, qm, err := ap.Info(policy.Name, nil)
   103  	must.NoError(t, err)
   104  	assertQueryMeta(t, qm)
   105  	must.Eq(t, policy.Name, out.Name)
   106  }
   107  
   108  func TestACLTokens_List(t *testing.T) {
   109  	testutil.Parallel(t)
   110  
   111  	c, s, _ := makeACLClient(t, nil, nil)
   112  	defer s.Stop()
   113  	at := c.ACLTokens()
   114  
   115  	// Expect the bootstrap token.
   116  	result, qm, err := at.List(nil)
   117  	must.NoError(t, err)
   118  	must.NonZero(t, qm.LastIndex)
   119  	must.Len(t, 1, result)
   120  	must.Nil(t, result[0].ExpirationTime)
   121  
   122  	// Create a token with an expiry.
   123  	token := &ACLToken{
   124  		Name:          "token-with-expiry",
   125  		Type:          "client",
   126  		Policies:      []string{"foo1"},
   127  		ExpirationTTL: 1 * time.Hour,
   128  	}
   129  	createExpirationResp, _, err := at.Create(token, nil)
   130  	must.NoError(t, err)
   131  
   132  	// Perform the listing again and ensure we have two entries along with the
   133  	// expiration correctly set and available.
   134  	listResp, qm, err := at.List(nil)
   135  	must.Nil(t, err)
   136  	assertQueryMeta(t, qm)
   137  	must.Len(t, 2, listResp)
   138  
   139  	for _, tokenStub := range listResp {
   140  		if tokenStub.AccessorID == createExpirationResp.AccessorID {
   141  			must.NotNil(t, tokenStub.ExpirationTime)
   142  		}
   143  	}
   144  }
   145  
   146  func TestACLTokens_CreateUpdate(t *testing.T) {
   147  	testutil.Parallel(t)
   148  
   149  	c, s, _ := makeACLClient(t, nil, nil)
   150  	defer s.Stop()
   151  	at := c.ACLTokens()
   152  
   153  	token := &ACLToken{
   154  		Name:     "foo",
   155  		Type:     "client",
   156  		Policies: []string{"foo1"},
   157  	}
   158  
   159  	// Create the token
   160  	out, wm, err := at.Create(token, nil)
   161  	must.NoError(t, err)
   162  	assertWriteMeta(t, wm)
   163  	must.NotNil(t, out)
   164  
   165  	// Update the token
   166  	out.Name = "other"
   167  	out2, wm, err := at.Update(out, nil)
   168  	must.NoError(t, err)
   169  	assertWriteMeta(t, wm)
   170  	must.NotNil(t, out2)
   171  
   172  	// Verify the change took hold
   173  	must.Eq(t, out.Name, out2.Name)
   174  
   175  	// Try updating the token to include a TTL which is not allowed.
   176  	out2.ExpirationTTL = 10 * time.Minute
   177  	out3, _, err := at.Update(out2, nil)
   178  	must.Error(t, err)
   179  	must.Nil(t, out3)
   180  
   181  	// Try adding a role link to our token, which should be possible. For this
   182  	// we need to create a policy and link to this from a role.
   183  	aclPolicy := ACLPolicy{
   184  		Name:  "acl-role-api-test",
   185  		Rules: `namespace "default" { policy = "read" }`,
   186  	}
   187  	writeMeta, err := c.ACLPolicies().Upsert(&aclPolicy, nil)
   188  	must.NoError(t, err)
   189  	assertWriteMeta(t, writeMeta)
   190  
   191  	// Create an ACL role referencing the previously created
   192  	// policy.
   193  	role := ACLRole{
   194  		Name:     "acl-role-api-test",
   195  		Policies: []*ACLRolePolicyLink{{Name: aclPolicy.Name}},
   196  	}
   197  	aclRoleCreateResp, writeMeta, err := c.ACLRoles().Create(&role, nil)
   198  	must.NoError(t, err)
   199  	assertWriteMeta(t, writeMeta)
   200  	must.UUIDv4(t, aclRoleCreateResp.ID)
   201  	must.Eq(t, role.Name, aclRoleCreateResp.Name)
   202  
   203  	out2.Roles = []*ACLTokenRoleLink{{Name: aclRoleCreateResp.Name}}
   204  	out2.ExpirationTTL = 0
   205  
   206  	out3, _, err = at.Update(out2, nil)
   207  	must.NoError(t, err)
   208  	must.NotNil(t, out3)
   209  	must.Len(t, 1, out3.Policies)
   210  	must.Eq(t, "foo1", out3.Policies[0])
   211  	must.Len(t, 1, out3.Roles)
   212  	must.Eq(t, role.Name, out3.Roles[0].Name)
   213  }
   214  
   215  func TestACLTokens_Info(t *testing.T) {
   216  	testutil.Parallel(t)
   217  
   218  	testClient, testServer, _ := makeACLClient(t, nil, nil)
   219  	defer testServer.Stop()
   220  
   221  	testCases := []struct {
   222  		name   string
   223  		testFn func(client *Client)
   224  	}{
   225  		{
   226  			name: "token without expiry",
   227  			testFn: func(client *Client) {
   228  
   229  				token := &ACLToken{
   230  					Name:     "foo",
   231  					Type:     "client",
   232  					Policies: []string{"foo1"},
   233  				}
   234  
   235  				// Create the token
   236  				out, wm, err := client.ACLTokens().Create(token, nil)
   237  				must.NoError(t, err)
   238  				assertWriteMeta(t, wm)
   239  				must.NotNil(t, out)
   240  
   241  				// Query the token
   242  				out2, qm, err := client.ACLTokens().Info(out.AccessorID, nil)
   243  				must.NoError(t, err)
   244  				assertQueryMeta(t, qm)
   245  				must.Eq(t, out, out2)
   246  			},
   247  		},
   248  		{
   249  			name: "token with expiry",
   250  			testFn: func(client *Client) {
   251  
   252  				token := &ACLToken{
   253  					Name:          "token-with-expiry",
   254  					Type:          "client",
   255  					Policies:      []string{"foo1"},
   256  					ExpirationTTL: 10 * time.Minute,
   257  				}
   258  
   259  				// Create the token
   260  				out, wm, err := client.ACLTokens().Create(token, nil)
   261  				must.NoError(t, err)
   262  				assertWriteMeta(t, wm)
   263  				must.NotNil(t, out)
   264  
   265  				// Query the token and ensure it matches what was returned
   266  				// during the creation as well as ensuring the expiration time
   267  				// is set.
   268  				out2, qm, err := client.ACLTokens().Info(out.AccessorID, nil)
   269  				must.NoError(t, err)
   270  				assertQueryMeta(t, qm)
   271  				must.Eq(t, out, out2)
   272  				must.NotNil(t, out2.ExpirationTime)
   273  			},
   274  		},
   275  		{
   276  			name: "token with role link",
   277  			testFn: func(client *Client) {
   278  
   279  				// Create an ACL policy that can be referenced within the ACL
   280  				// role.
   281  				aclPolicy := ACLPolicy{
   282  					Name:  "acl-role-api-test",
   283  					Rules: `namespace "default" { policy = "read" }`,
   284  				}
   285  				writeMeta, err := testClient.ACLPolicies().Upsert(&aclPolicy, nil)
   286  				must.NoError(t, err)
   287  				assertWriteMeta(t, writeMeta)
   288  
   289  				// Create an ACL role referencing the previously created
   290  				// policy.
   291  				role := ACLRole{
   292  					Name:     "acl-role-api-test",
   293  					Policies: []*ACLRolePolicyLink{{Name: aclPolicy.Name}},
   294  				}
   295  				aclRoleCreateResp, writeMeta, err := testClient.ACLRoles().Create(&role, nil)
   296  				must.NoError(t, err)
   297  				assertWriteMeta(t, writeMeta)
   298  				must.UUIDv4(t, aclRoleCreateResp.ID)
   299  				must.Eq(t, role.Name, aclRoleCreateResp.Name)
   300  
   301  				// Create a token with a role linking.
   302  				token := &ACLToken{
   303  					Name:  "token-with-role-link",
   304  					Type:  "client",
   305  					Roles: []*ACLTokenRoleLink{{Name: role.Name}},
   306  				}
   307  
   308  				out, wm, err := client.ACLTokens().Create(token, nil)
   309  				must.NoError(t, err)
   310  				assertWriteMeta(t, wm)
   311  				must.NotNil(t, out)
   312  
   313  				// Query the token and ensure it matches what was returned
   314  				// during the creation.
   315  				out2, qm, err := client.ACLTokens().Info(out.AccessorID, nil)
   316  				must.NoError(t, err)
   317  				assertQueryMeta(t, qm)
   318  				must.Eq(t, out, out2)
   319  				must.Len(t, 1, out.Roles)
   320  				must.Eq(t, out.Roles[0].Name, aclPolicy.Name)
   321  			},
   322  		},
   323  
   324  		{
   325  			name: "token with role and policy link",
   326  			testFn: func(client *Client) {
   327  
   328  				// Create an ACL policy that can be referenced within the ACL
   329  				// role.
   330  				aclPolicy1 := ACLPolicy{
   331  					Name:  "acl-role-api-test-1",
   332  					Rules: `namespace "default" { policy = "read" }`,
   333  				}
   334  				writeMeta, err := testClient.ACLPolicies().Upsert(&aclPolicy1, nil)
   335  				must.NoError(t, err)
   336  				assertWriteMeta(t, writeMeta)
   337  
   338  				// Create another that can be referenced within the ACL token
   339  				// directly.
   340  				aclPolicy2 := ACLPolicy{
   341  					Name:  "acl-role-api-test-2",
   342  					Rules: `namespace "fawlty" { policy = "read" }`,
   343  				}
   344  				writeMeta, err = testClient.ACLPolicies().Upsert(&aclPolicy2, nil)
   345  				must.NoError(t, err)
   346  				assertWriteMeta(t, writeMeta)
   347  
   348  				// Create an ACL role referencing the previously created
   349  				// policy.
   350  				role := ACLRole{
   351  					Name:     "acl-role-api-test-role-and-policy",
   352  					Policies: []*ACLRolePolicyLink{{Name: aclPolicy1.Name}},
   353  				}
   354  				aclRoleCreateResp, writeMeta, err := testClient.ACLRoles().Create(&role, nil)
   355  				must.NoError(t, err)
   356  				assertWriteMeta(t, writeMeta)
   357  				must.NotEq(t, "", aclRoleCreateResp.ID)
   358  				must.Eq(t, role.Name, aclRoleCreateResp.Name)
   359  
   360  				// Create a token with a role linking.
   361  				token := &ACLToken{
   362  					Name:     "token-with-role-and-policy-link",
   363  					Type:     "client",
   364  					Policies: []string{aclPolicy2.Name},
   365  					Roles:    []*ACLTokenRoleLink{{Name: role.Name}},
   366  				}
   367  
   368  				out, wm, err := client.ACLTokens().Create(token, nil)
   369  				must.NoError(t, err)
   370  				assertWriteMeta(t, wm)
   371  				must.NotNil(t, out)
   372  				must.Len(t, 1, out.Policies)
   373  				must.Eq(t, out.Policies[0], aclPolicy2.Name)
   374  				must.Len(t, 1, out.Roles)
   375  				must.Eq(t, out.Roles[0].Name, role.Name)
   376  
   377  				// Query the token and ensure it matches what was returned
   378  				// during the creation.
   379  				out2, qm, err := client.ACLTokens().Info(out.AccessorID, nil)
   380  				must.NoError(t, err)
   381  				assertQueryMeta(t, qm)
   382  				must.Eq(t, out, out2)
   383  			},
   384  		},
   385  	}
   386  
   387  	for _, tc := range testCases {
   388  		t.Run(tc.name, func(t *testing.T) {
   389  			tc.testFn(testClient)
   390  		})
   391  	}
   392  }
   393  
   394  func TestACLTokens_Self(t *testing.T) {
   395  	testutil.Parallel(t)
   396  
   397  	c, s, _ := makeACLClient(t, nil, nil)
   398  	defer s.Stop()
   399  	at := c.ACLTokens()
   400  
   401  	token := &ACLToken{
   402  		Name:     "foo",
   403  		Type:     "client",
   404  		Policies: []string{"foo1"},
   405  	}
   406  
   407  	// Create the token
   408  	out, wm, err := at.Create(token, nil)
   409  	must.NoError(t, err)
   410  	assertWriteMeta(t, wm)
   411  	must.NotNil(t, out)
   412  
   413  	// Set the clients token to the new token
   414  	c.SetSecretID(out.SecretID)
   415  	at = c.ACLTokens()
   416  
   417  	// Query the token
   418  	out2, qm, err := at.Self(nil)
   419  	must.NoError(t, err)
   420  	assertQueryMeta(t, qm)
   421  	must.Eq(t, out, out2)
   422  }
   423  
   424  func TestACLTokens_Delete(t *testing.T) {
   425  	testutil.Parallel(t)
   426  
   427  	c, s, _ := makeACLClient(t, nil, nil)
   428  	defer s.Stop()
   429  	at := c.ACLTokens()
   430  
   431  	token := &ACLToken{
   432  		Name:     "foo",
   433  		Type:     "client",
   434  		Policies: []string{"foo1"},
   435  	}
   436  
   437  	// Create the token
   438  	out, wm, err := at.Create(token, nil)
   439  	must.NoError(t, err)
   440  	assertWriteMeta(t, wm)
   441  	must.NotNil(t, out)
   442  
   443  	// Delete the token
   444  	wm, err = at.Delete(out.AccessorID, nil)
   445  	must.NoError(t, err)
   446  	assertWriteMeta(t, wm)
   447  }
   448  
   449  func TestACL_OneTimeToken(t *testing.T) {
   450  	testutil.Parallel(t)
   451  
   452  	c, s, _ := makeACLClient(t, nil, nil)
   453  	defer s.Stop()
   454  	at := c.ACLTokens()
   455  
   456  	token := &ACLToken{
   457  		Name:     "foo",
   458  		Type:     "client",
   459  		Policies: []string{"foo1"},
   460  	}
   461  
   462  	// Create the ACL token
   463  	out, wm, err := at.Create(token, nil)
   464  	must.NoError(t, err)
   465  	assertWriteMeta(t, wm)
   466  	must.NotNil(t, out)
   467  
   468  	// Get a one-time token
   469  	c.SetSecretID(out.SecretID)
   470  	out2, wm, err := at.UpsertOneTimeToken(nil)
   471  	must.NoError(t, err)
   472  	assertWriteMeta(t, wm)
   473  	must.NotNil(t, out2)
   474  
   475  	// Exchange the one-time token
   476  	out3, wm, err := at.ExchangeOneTimeToken(out2.OneTimeSecretID, nil)
   477  	must.NoError(t, err)
   478  	assertWriteMeta(t, wm)
   479  	must.NotNil(t, out3)
   480  	must.Eq(t, out.AccessorID, out3.AccessorID)
   481  }
   482  
   483  func TestACLTokens_BootstrapInvalidToken(t *testing.T) {
   484  	testutil.Parallel(t)
   485  
   486  	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
   487  		c.ACL.Enabled = true
   488  	})
   489  	defer s.Stop()
   490  	at := c.ACLTokens()
   491  
   492  	bootkn := "badtoken"
   493  	// Bootstrap with invalid token
   494  	_, _, err := at.BootstrapOpts(bootkn, nil)
   495  	must.EqError(t, err, "Unexpected response code: 400 (invalid acl token)")
   496  }
   497  
   498  func TestACLTokens_BootstrapValidToken(t *testing.T) {
   499  	testutil.Parallel(t)
   500  	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
   501  		c.ACL.Enabled = true
   502  	})
   503  	defer s.Stop()
   504  	at := c.ACLTokens()
   505  
   506  	bootkn := "2b778dd9-f5f1-6f29-b4b4-9a5fa948757a"
   507  	// Bootstrap with Valid token
   508  	out, wm, err := at.BootstrapOpts(bootkn, nil)
   509  	must.NoError(t, err)
   510  	assertWriteMeta(t, wm)
   511  	must.Eq(t, bootkn, out.SecretID)
   512  }
   513  
   514  func TestACLRoles(t *testing.T) {
   515  	testutil.Parallel(t)
   516  
   517  	testClient, testServer, _ := makeACLClient(t, nil, nil)
   518  	defer testServer.Stop()
   519  
   520  	// An initial listing shouldn't return any results.
   521  	aclRoleListResp, queryMeta, err := testClient.ACLRoles().List(nil)
   522  	must.NoError(t, err)
   523  	must.SliceEmpty(t, aclRoleListResp)
   524  	assertQueryMeta(t, queryMeta)
   525  
   526  	// Create an ACL policy that can be referenced within the ACL role.
   527  	aclPolicy := ACLPolicy{
   528  		Name: "acl-role-api-test",
   529  		Rules: `namespace "default" {
   530  			policy = "read"
   531  		}
   532  		`,
   533  	}
   534  	writeMeta, err := testClient.ACLPolicies().Upsert(&aclPolicy, nil)
   535  	must.NoError(t, err)
   536  	assertWriteMeta(t, writeMeta)
   537  
   538  	// Create an ACL role referencing the previously created policy.
   539  	role := ACLRole{
   540  		Name:     "acl-role-api-test",
   541  		Policies: []*ACLRolePolicyLink{{Name: aclPolicy.Name}},
   542  	}
   543  	aclRoleCreateResp, writeMeta, err := testClient.ACLRoles().Create(&role, nil)
   544  	must.NoError(t, err)
   545  	assertWriteMeta(t, writeMeta)
   546  	must.UUIDv4(t, aclRoleCreateResp.ID)
   547  	must.Eq(t, role.Name, aclRoleCreateResp.Name)
   548  
   549  	// Another listing should return one result.
   550  	aclRoleListResp, queryMeta, err = testClient.ACLRoles().List(nil)
   551  	must.NoError(t, err)
   552  	must.Len(t, 1, aclRoleListResp)
   553  	assertQueryMeta(t, queryMeta)
   554  
   555  	// Read the role using its ID.
   556  	aclRoleReadResp, queryMeta, err := testClient.ACLRoles().Get(aclRoleCreateResp.ID, nil)
   557  	must.NoError(t, err)
   558  	assertQueryMeta(t, queryMeta)
   559  	must.Eq(t, aclRoleCreateResp, aclRoleReadResp)
   560  
   561  	// Read the role using its name.
   562  	aclRoleReadResp, queryMeta, err = testClient.ACLRoles().GetByName(aclRoleCreateResp.Name, nil)
   563  	must.NoError(t, err)
   564  	assertQueryMeta(t, queryMeta)
   565  	must.Eq(t, aclRoleCreateResp, aclRoleReadResp)
   566  
   567  	// Update the role name.
   568  	role.Name = "acl-role-api-test-badger-badger-badger"
   569  	role.ID = aclRoleCreateResp.ID
   570  	aclRoleUpdateResp, writeMeta, err := testClient.ACLRoles().Update(&role, nil)
   571  	must.NoError(t, err)
   572  	assertWriteMeta(t, writeMeta)
   573  	must.Eq(t, role.Name, aclRoleUpdateResp.Name)
   574  	must.Eq(t, role.ID, aclRoleUpdateResp.ID)
   575  
   576  	// Delete the role.
   577  	writeMeta, err = testClient.ACLRoles().Delete(aclRoleCreateResp.ID, nil)
   578  	must.NoError(t, err)
   579  	assertWriteMeta(t, writeMeta)
   580  
   581  	// Make sure there are no ACL roles now present.
   582  	aclRoleListResp, queryMeta, err = testClient.ACLRoles().List(nil)
   583  	must.NoError(t, err)
   584  	must.SliceEmpty(t, aclRoleListResp)
   585  	assertQueryMeta(t, queryMeta)
   586  }
   587  
   588  func TestACLAuthMethods(t *testing.T) {
   589  	testutil.Parallel(t)
   590  
   591  	testClient, testServer, _ := makeACLClient(t, nil, nil)
   592  	defer testServer.Stop()
   593  
   594  	// An initial listing shouldn't return any results.
   595  	aclAuthMethodsListResp, queryMeta, err := testClient.ACLAuthMethods().List(nil)
   596  	must.NoError(t, err)
   597  	must.Len(t, 0, aclAuthMethodsListResp)
   598  	assertQueryMeta(t, queryMeta)
   599  
   600  	// Create an ACL auth-method.
   601  	authMethod := ACLAuthMethod{
   602  		Name:          "acl-auth-method-api-test",
   603  		Type:          ACLAuthMethodTypeOIDC,
   604  		TokenLocality: ACLAuthMethodTokenLocalityLocal,
   605  		MaxTokenTTL:   15 * time.Minute,
   606  		Default:       true,
   607  	}
   608  	_, writeMeta, err := testClient.ACLAuthMethods().Create(&authMethod, nil)
   609  	must.NoError(t, err)
   610  	assertWriteMeta(t, writeMeta)
   611  
   612  	// Another listing should return one result.
   613  	aclAuthMethodsListResp, queryMeta, err = testClient.ACLAuthMethods().List(nil)
   614  	must.NoError(t, err)
   615  	must.Len(t, 1, aclAuthMethodsListResp)
   616  	must.Eq(t, authMethod.Name, aclAuthMethodsListResp[0].Name)
   617  	must.True(t, aclAuthMethodsListResp[0].Default)
   618  	assertQueryMeta(t, queryMeta)
   619  
   620  	// Read the auth-method.
   621  	aclAuthMethodReadResp, queryMeta, err := testClient.ACLAuthMethods().Get(authMethod.Name, nil)
   622  	must.NoError(t, err)
   623  	assertQueryMeta(t, queryMeta)
   624  	must.NotNil(t, aclAuthMethodReadResp)
   625  	must.Eq(t, authMethod.Name, aclAuthMethodReadResp.Name)
   626  	must.Eq(t, authMethod.TokenLocality, aclAuthMethodReadResp.TokenLocality)
   627  	must.Eq(t, authMethod.Type, aclAuthMethodReadResp.Type)
   628  
   629  	// Update the auth-method token locality.
   630  	authMethod.TokenLocality = ACLAuthMethodTokenLocalityGlobal
   631  	_, writeMeta, err = testClient.ACLAuthMethods().Update(&authMethod, nil)
   632  	must.NoError(t, err)
   633  	assertWriteMeta(t, writeMeta)
   634  
   635  	// Re-read the auth-method and check the locality.
   636  	aclAuthMethodReadResp, queryMeta, err = testClient.ACLAuthMethods().Get(authMethod.Name, nil)
   637  	must.NoError(t, err)
   638  	assertQueryMeta(t, queryMeta)
   639  	must.NotNil(t, aclAuthMethodReadResp)
   640  	must.Eq(t, authMethod.Name, aclAuthMethodReadResp.Name)
   641  	must.Eq(t, authMethod.TokenLocality, aclAuthMethodReadResp.TokenLocality)
   642  
   643  	// Delete the role.
   644  	writeMeta, err = testClient.ACLAuthMethods().Delete(authMethod.Name, nil)
   645  	must.NoError(t, err)
   646  	assertWriteMeta(t, writeMeta)
   647  
   648  	// Make sure there are no ACL auth-methods now present.
   649  	aclAuthMethodsListResp, queryMeta, err = testClient.ACLAuthMethods().List(nil)
   650  	must.NoError(t, err)
   651  	must.Len(t, 0, aclAuthMethodsListResp)
   652  	assertQueryMeta(t, queryMeta)
   653  }
   654  
   655  func TestACLBindingRules(t *testing.T) {
   656  	testutil.Parallel(t)
   657  
   658  	testClient, testServer, _ := makeACLClient(t, nil, nil)
   659  	defer testServer.Stop()
   660  
   661  	aclAuthMethod := ACLAuthMethod{
   662  		Name:          "auth0",
   663  		Type:          ACLAuthMethodTypeOIDC,
   664  		TokenLocality: ACLAuthMethodTokenLocalityGlobal,
   665  		MaxTokenTTL:   10 * time.Hour,
   666  		Default:       true,
   667  	}
   668  	_, _, err := testClient.ACLAuthMethods().Create(&aclAuthMethod, nil)
   669  	must.NoError(t, err)
   670  
   671  	// An initial listing shouldn't return any results.
   672  	aclBindingRulesListResp, queryMeta, err := testClient.ACLBindingRules().List(nil)
   673  	must.NoError(t, err)
   674  	must.Len(t, 0, aclBindingRulesListResp)
   675  	assertQueryMeta(t, queryMeta)
   676  
   677  	// Create an ACL auth-method.
   678  	bindingRule := ACLBindingRule{
   679  		Description: "my-binding-rule",
   680  		AuthMethod:  "auth0",
   681  		Selector:    "nomad_engineering_team in list.groups",
   682  		BindType:    "role",
   683  		BindName:    "cluster-admin",
   684  	}
   685  	_, writeMeta, err := testClient.ACLBindingRules().Create(&bindingRule, nil)
   686  	must.NoError(t, err)
   687  	assertWriteMeta(t, writeMeta)
   688  
   689  	// Another listing should return one result.
   690  	aclBindingRulesListResp, queryMeta, err = testClient.ACLBindingRules().List(nil)
   691  	must.NoError(t, err)
   692  	must.Len(t, 1, aclBindingRulesListResp)
   693  	must.NotEq(t, "", aclBindingRulesListResp[0].ID)
   694  	must.Eq(t, "auth0", aclBindingRulesListResp[0].AuthMethod)
   695  	assertQueryMeta(t, queryMeta)
   696  
   697  	bindingRuleID := aclBindingRulesListResp[0].ID
   698  
   699  	// Read the binding rule.
   700  	aclBindingRuleReadResp, queryMeta, err := testClient.ACLBindingRules().Get(bindingRuleID, nil)
   701  	must.NoError(t, err)
   702  	assertQueryMeta(t, queryMeta)
   703  	must.NotNil(t, aclBindingRuleReadResp)
   704  	must.Eq(t, bindingRuleID, aclBindingRuleReadResp.ID)
   705  	must.Eq(t, bindingRule.Description, aclBindingRuleReadResp.Description)
   706  	must.Eq(t, bindingRule.AuthMethod, aclBindingRuleReadResp.AuthMethod)
   707  	must.Eq(t, bindingRule.Selector, aclBindingRuleReadResp.Selector)
   708  	must.Eq(t, bindingRule.BindType, aclBindingRuleReadResp.BindType)
   709  	must.Eq(t, bindingRule.BindName, aclBindingRuleReadResp.BindName)
   710  
   711  	// Update the binding rule description.
   712  	bindingRule.ID = bindingRuleID
   713  	bindingRule.Description = "my-binding-rule-updated"
   714  	aclBindingRuleUpdateResp, writeMeta, err := testClient.ACLBindingRules().Update(&bindingRule, nil)
   715  	must.NoError(t, err)
   716  	assertWriteMeta(t, writeMeta)
   717  	must.Eq(t, bindingRuleID, aclBindingRuleUpdateResp.ID)
   718  	must.Eq(t, bindingRule.Description, aclBindingRuleUpdateResp.Description)
   719  	must.Eq(t, bindingRule.AuthMethod, aclBindingRuleUpdateResp.AuthMethod)
   720  	must.Eq(t, bindingRule.Selector, aclBindingRuleUpdateResp.Selector)
   721  	must.Eq(t, bindingRule.BindType, aclBindingRuleUpdateResp.BindType)
   722  	must.Eq(t, bindingRule.BindName, aclBindingRuleUpdateResp.BindName)
   723  
   724  	// Delete the role.
   725  	writeMeta, err = testClient.ACLBindingRules().Delete(bindingRuleID, nil)
   726  	must.NoError(t, err)
   727  	assertWriteMeta(t, writeMeta)
   728  
   729  	// Make sure there are no ACL auth-methods now present.
   730  	aclBindingRulesListResp, queryMeta, err = testClient.ACLBindingRules().List(nil)
   731  	must.NoError(t, err)
   732  	must.Len(t, 0, aclBindingRulesListResp)
   733  	assertQueryMeta(t, queryMeta)
   734  }