1package consul
2
3import (
4	"fmt"
5	"io/ioutil"
6	"net/rpc"
7	"os"
8	"path/filepath"
9	"strings"
10	"testing"
11	"time"
12
13	uuid "github.com/hashicorp/go-uuid"
14	msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc"
15	"github.com/stretchr/testify/require"
16	"gopkg.in/square/go-jose.v2/jwt"
17
18	"github.com/hashicorp/consul/acl"
19	"github.com/hashicorp/consul/agent/consul/authmethod/kubeauth"
20	"github.com/hashicorp/consul/agent/consul/authmethod/testauth"
21	"github.com/hashicorp/consul/agent/structs"
22	"github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest"
23	"github.com/hashicorp/consul/sdk/freeport"
24	"github.com/hashicorp/consul/sdk/testutil"
25	"github.com/hashicorp/consul/sdk/testutil/retry"
26)
27
28func TestACLEndpoint_Bootstrap(t *testing.T) {
29	if testing.Short() {
30		t.Skip("too slow for testing.Short")
31	}
32
33	t.Parallel()
34	_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
35		c.Build = "0.8.0" // Too low for auto init of bootstrap.
36		c.ACLDatacenter = "dc1"
37		c.ACLsEnabled = true
38		// remove the default as we want to bootstrap
39		c.ACLMasterToken = ""
40	}, false)
41	waitForLeaderEstablishment(t, srv)
42
43	// Expect an error initially since ACL bootstrap is not initialized.
44	arg := structs.DCSpecificRequest{
45		Datacenter: "dc1",
46	}
47	var out structs.ACL
48	// We can only do some high
49	// level checks on the ACL since we don't have control over the UUID or
50	// Raft indexes at this level.
51	err := msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", &arg, &out)
52	require.NoError(t, err)
53	require.Len(t, out.ID, len("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"))
54	require.True(t, strings.HasPrefix(out.Name, "Bootstrap Token"))
55	require.Equal(t, structs.ACLTokenTypeManagement, out.Type)
56	require.NotEqual(t, uint64(0), out.CreateIndex)
57	require.NotEqual(t, uint64(0), out.ModifyIndex)
58
59	// Finally, make sure that another attempt is rejected.
60	err = msgpackrpc.CallWithCodec(codec, "ACL.Bootstrap", &arg, &out)
61	testutil.RequireErrorContains(t, err, structs.ACLBootstrapNotAllowedErr.Error())
62}
63
64func TestACLEndpoint_BootstrapTokens(t *testing.T) {
65	if testing.Short() {
66		t.Skip("too slow for testing.Short")
67	}
68
69	t.Parallel()
70	dir, srv, codec := testACLServerWithConfig(t, func(c *Config) {
71		// remove this as we are bootstrapping
72		c.ACLMasterToken = ""
73	}, false)
74	waitForLeaderEstablishment(t, srv)
75
76	// Expect an error initially since ACL bootstrap is not initialized.
77	arg := structs.DCSpecificRequest{
78		Datacenter: "dc1",
79	}
80	var out structs.ACLToken
81	// We can only do some high
82	// level checks on the ACL since we don't have control over the UUID or
83	// Raft indexes at this level.
84	require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.BootstrapTokens", &arg, &out))
85	require.Equal(t, 36, len(out.AccessorID))
86	require.True(t, strings.HasPrefix(out.Description, "Bootstrap Token"))
87	require.Equal(t, out.Type, structs.ACLTokenTypeManagement)
88	require.True(t, out.CreateIndex > 0)
89	require.Equal(t, out.CreateIndex, out.ModifyIndex)
90
91	// Finally, make sure that another attempt is rejected.
92	err := msgpackrpc.CallWithCodec(codec, "ACL.BootstrapTokens", &arg, &out)
93	require.Error(t, err)
94	require.True(t, strings.HasPrefix(err.Error(), structs.ACLBootstrapNotAllowedErr.Error()))
95
96	_, resetIdx, err := srv.fsm.State().CanBootstrapACLToken()
97	require.NoError(t, err)
98
99	resetPath := filepath.Join(dir, "acl-bootstrap-reset")
100	require.NoError(t, ioutil.WriteFile(resetPath, []byte(fmt.Sprintf("%d", resetIdx)), 0600))
101
102	oldID := out.AccessorID
103	// Finally, make sure that another attempt is rejected.
104	require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.BootstrapTokens", &arg, &out))
105	require.Equal(t, 36, len(out.AccessorID))
106	require.NotEqual(t, oldID, out.AccessorID)
107	require.True(t, strings.HasPrefix(out.Description, "Bootstrap Token"))
108	require.Equal(t, out.Type, structs.ACLTokenTypeManagement)
109	require.True(t, out.CreateIndex > 0)
110	require.Equal(t, out.CreateIndex, out.ModifyIndex)
111}
112
113func TestACLEndpoint_Apply(t *testing.T) {
114	if testing.Short() {
115		t.Skip("too slow for testing.Short")
116	}
117
118	t.Parallel()
119	_, srv, codec := testACLServerWithConfig(t, nil, false)
120	waitForLeaderEstablishment(t, srv)
121
122	arg := structs.ACLRequest{
123		Datacenter: "dc1",
124		Op:         structs.ACLSet,
125		ACL: structs.ACL{
126			Name: "User token",
127			Type: structs.ACLTokenTypeClient,
128		},
129		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
130	}
131	var out string
132	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
133	require.NoError(t, err)
134	id := out
135
136	// Verify
137	state := srv.fsm.State()
138	_, s, err := state.ACLTokenGetBySecret(nil, out, nil)
139	require.NoError(t, err)
140	require.NotNil(t, s)
141	require.Equal(t, out, s.SecretID)
142	require.Equal(t, "User token", s.Description)
143
144	// Do a delete
145	arg.Op = structs.ACLDelete
146	arg.ACL.ID = out
147	err = msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
148	require.NoError(t, err)
149
150	// Verify
151	_, s, err = state.ACLTokenGetBySecret(nil, id, nil)
152	require.NoError(t, err)
153	require.Nil(t, s)
154}
155
156func TestACLEndpoint_Update_PurgeCache(t *testing.T) {
157	if testing.Short() {
158		t.Skip("too slow for testing.Short")
159	}
160
161	t.Parallel()
162	_, srv, codec := testACLServerWithConfig(t, nil, false)
163	waitForLeaderEstablishment(t, srv)
164
165	arg := structs.ACLRequest{
166		Datacenter: "dc1",
167		Op:         structs.ACLSet,
168		ACL: structs.ACL{
169			Name:  "User token",
170			Type:  structs.ACLTokenTypeClient,
171			Rules: `key "" { policy = "read"}`,
172		},
173		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
174	}
175	var out string
176	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
177	require.NoError(t, err)
178	id := out
179
180	// Resolve
181	acl1, err := srv.ResolveToken(id)
182	require.NoError(t, err)
183	require.NotNil(t, acl1)
184	require.Equal(t, acl.Allow, acl1.KeyRead("foo", nil))
185
186	// Do an update
187	arg.ACL.ID = out
188	arg.ACL.Rules = `{"key": {"": {"policy": "deny"}}}`
189	err = msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
190	require.NoError(t, err)
191
192	// Resolve again
193	acl2, err := srv.ResolveToken(id)
194	require.NoError(t, err)
195	require.NotNil(t, acl2)
196	require.NotSame(t, acl2, acl1)
197	require.NotEqual(t, acl.Allow, acl2.KeyRead("foo", nil))
198
199	// Do a delete
200	arg.Op = structs.ACLDelete
201	arg.ACL.Rules = ""
202	err = msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
203	require.NoError(t, err)
204
205	// Resolve again
206	acl3, err := srv.ResolveToken(id)
207	require.True(t, acl.IsErrNotFound(err), "Error %v is not acl.ErrNotFound", err)
208	require.Nil(t, acl3)
209}
210
211func TestACLEndpoint_Apply_CustomID(t *testing.T) {
212	if testing.Short() {
213		t.Skip("too slow for testing.Short")
214	}
215
216	t.Parallel()
217	_, srv, codec := testACLServerWithConfig(t, nil, false)
218	waitForLeaderEstablishment(t, srv)
219
220	arg := structs.ACLRequest{
221		Datacenter: "dc1",
222		Op:         structs.ACLSet,
223		ACL: structs.ACL{
224			ID:   "foobarbaz", // Specify custom ID, does not exist
225			Name: "User token",
226			Type: structs.ACLTokenTypeClient,
227		},
228		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
229	}
230	var out string
231	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
232	require.NoError(t, err)
233	require.Equal(t, "foobarbaz", out)
234
235	// Verify
236	state := srv.fsm.State()
237	_, s, err := state.ACLTokenGetBySecret(nil, out, nil)
238	require.NoError(t, err)
239	require.NotNil(t, s)
240	require.Equal(t, out, s.SecretID)
241	require.Equal(t, "User token", s.Description)
242}
243
244func TestACLEndpoint_Apply_Denied(t *testing.T) {
245	if testing.Short() {
246		t.Skip("too slow for testing.Short")
247	}
248
249	t.Parallel()
250	_, srv, codec := testACLServerWithConfig(t, nil, false)
251	waitForLeaderEstablishment(t, srv)
252
253	arg := structs.ACLRequest{
254		Datacenter: "dc1",
255		Op:         structs.ACLSet,
256		ACL: structs.ACL{
257			Name: "User token",
258			Type: structs.ACLTokenTypeClient,
259		},
260	}
261	var out string
262	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
263	require.True(t, acl.IsErrPermissionDenied(err), "Err %v is not acl.PermissionDenied", err)
264}
265
266func TestACLEndpoint_Apply_DeleteAnon(t *testing.T) {
267	if testing.Short() {
268		t.Skip("too slow for testing.Short")
269	}
270
271	t.Parallel()
272	_, srv, codec := testACLServerWithConfig(t, nil, false)
273	waitForLeaderEstablishment(t, srv)
274
275	arg := structs.ACLRequest{
276		Datacenter: "dc1",
277		Op:         structs.ACLDelete,
278		ACL: structs.ACL{
279			ID:   anonymousToken,
280			Name: "User token",
281			Type: structs.ACLTokenTypeClient,
282		},
283		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
284	}
285	var out string
286	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
287	testutil.RequireErrorContains(t, err, "delete anonymous")
288}
289
290func TestACLEndpoint_Apply_RootChange(t *testing.T) {
291	if testing.Short() {
292		t.Skip("too slow for testing.Short")
293	}
294
295	t.Parallel()
296	_, srv, codec := testACLServerWithConfig(t, nil, false)
297	waitForLeaderEstablishment(t, srv)
298
299	arg := structs.ACLRequest{
300		Datacenter: "dc1",
301		Op:         structs.ACLSet,
302		ACL: structs.ACL{
303			ID:   "manage",
304			Name: "User token",
305			Type: structs.ACLTokenTypeClient,
306		},
307		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
308	}
309	var out string
310	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
311	testutil.RequireErrorContains(t, err, "root ACL")
312}
313
314func TestACLEndpoint_Get(t *testing.T) {
315	if testing.Short() {
316		t.Skip("too slow for testing.Short")
317	}
318
319	t.Parallel()
320	_, srv, codec := testACLServerWithConfig(t, nil, false)
321	waitForLeaderEstablishment(t, srv)
322
323	arg := structs.ACLRequest{
324		Datacenter: "dc1",
325		Op:         structs.ACLSet,
326		ACL: structs.ACL{
327			Name: "User token",
328			Type: structs.ACLTokenTypeClient,
329		},
330		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
331	}
332	var out string
333	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
334	require.NoError(t, err)
335
336	getR := structs.ACLSpecificRequest{
337		Datacenter: "dc1",
338		ACL:        out,
339	}
340	var acls structs.IndexedACLs
341	err = msgpackrpc.CallWithCodec(codec, "ACL.Get", &getR, &acls)
342	require.NoError(t, err)
343	require.NotEqual(t, uint64(0), acls.Index)
344	require.Len(t, acls.ACLs, 1)
345	require.Equal(t, out, acls.ACLs[0].ID)
346}
347
348func TestACLEndpoint_GetPolicy(t *testing.T) {
349	if testing.Short() {
350		t.Skip("too slow for testing.Short")
351	}
352
353	t.Parallel()
354	_, srv, codec := testACLServerWithConfig(t, nil, false)
355	waitForLeaderEstablishment(t, srv)
356
357	arg := structs.ACLRequest{
358		Datacenter: "dc1",
359		Op:         structs.ACLSet,
360		ACL: structs.ACL{
361			Name: "User token",
362			Type: structs.ACLTokenTypeClient,
363		},
364		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
365	}
366	var out string
367	err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
368	require.NoError(t, err)
369
370	getR := structs.ACLPolicyResolveLegacyRequest{
371		Datacenter: "dc1",
372		ACL:        out,
373	}
374
375	var acls structs.ACLPolicyResolveLegacyResponse
376	retry.Run(t, func(r *retry.R) {
377		err := msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", &getR, &acls)
378
379		require.NoError(r, err)
380		require.NotNil(t, acls.Policy)
381		require.Equal(t, 30*time.Second, acls.TTL)
382	})
383
384	// Do a conditional lookup with etag
385	getR.ETag = acls.ETag
386	var out2 structs.ACLPolicyResolveLegacyResponse
387	require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", &getR, &out2))
388
389	require.Nil(t, out2.Policy)
390	require.Equal(t, 30*time.Second, out2.TTL)
391}
392
393func TestACLEndpoint_GetPolicy_Management(t *testing.T) {
394	if testing.Short() {
395		t.Skip("too slow for testing.Short")
396	}
397
398	t.Parallel()
399	_, srv, codec := testACLServerWithConfig(t, nil, false)
400
401	// wait for leader election and leader establishment to finish.
402	// after this the global management policy, master token and
403	// anonymous token will have been injected into the state store
404	// and we will be ready to resolve the master token
405	waitForLeaderEstablishment(t, srv)
406
407	req := structs.ACLPolicyResolveLegacyRequest{
408		Datacenter: srv.config.Datacenter,
409		ACL:        TestDefaultMasterToken,
410	}
411
412	var resp structs.ACLPolicyResolveLegacyResponse
413	require.NoError(t, msgpackrpc.CallWithCodec(codec, "ACL.GetPolicy", &req, &resp))
414	require.Equal(t, "manage", resp.Parent)
415}
416
417func TestACLEndpoint_List(t *testing.T) {
418	if testing.Short() {
419		t.Skip("too slow for testing.Short")
420	}
421
422	t.Parallel()
423	_, srv, codec := testACLServerWithConfig(t, nil, false)
424	waitForLeaderEstablishment(t, srv)
425	var expectedIDs []string
426
427	for i := 0; i < 5; i++ {
428		arg := structs.ACLRequest{
429			Datacenter: "dc1",
430			Op:         structs.ACLSet,
431			ACL: structs.ACL{
432				Name: "User token",
433				Type: structs.ACLTokenTypeClient,
434			},
435			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
436		}
437		var out string
438		err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out)
439		require.NoError(t, err)
440		expectedIDs = append(expectedIDs, out)
441	}
442
443	getR := structs.DCSpecificRequest{
444		Datacenter:   "dc1",
445		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
446	}
447	var acls structs.IndexedACLs
448	err := msgpackrpc.CallWithCodec(codec, "ACL.List", &getR, &acls)
449	require.NoError(t, err)
450	require.NotEqual(t, uint64(0), acls.Index)
451
452	// 5  + master
453	require.Len(t, acls.ACLs, 6)
454	var actualIDs []string
455	for i := 0; i < len(acls.ACLs); i++ {
456		s := acls.ACLs[i]
457		if s.ID == anonymousToken || s.ID == TestDefaultMasterToken {
458			continue
459		}
460
461		require.Equal(t, "User token", s.Name)
462
463		actualIDs = append(actualIDs, s.ID)
464	}
465
466	require.ElementsMatch(t, expectedIDs, actualIDs)
467}
468
469func TestACLEndpoint_List_Denied(t *testing.T) {
470	if testing.Short() {
471		t.Skip("too slow for testing.Short")
472	}
473
474	t.Parallel()
475	_, srv, codec := testACLServerWithConfig(t, nil, false)
476	waitForLeaderEstablishment(t, srv)
477
478	getR := structs.DCSpecificRequest{
479		Datacenter: "dc1",
480	}
481	var acls structs.IndexedACLs
482	err := msgpackrpc.CallWithCodec(codec, "ACL.List", &getR, &acls)
483	require.True(t, acl.IsErrPermissionDenied(err), "Err %v is not an acl.ErrPermissionDenied", err)
484}
485
486func TestACLEndpoint_ReplicationStatus(t *testing.T) {
487	if testing.Short() {
488		t.Skip("too slow for testing.Short")
489	}
490
491	t.Parallel()
492	_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
493		c.ACLDatacenter = "dc2"
494		c.ACLTokenReplication = true
495		c.ACLReplicationRate = 100
496		c.ACLReplicationBurst = 100
497	}, true)
498	waitForLeaderEstablishment(t, srv)
499
500	getR := structs.DCSpecificRequest{
501		Datacenter: "dc1",
502	}
503
504	retry.Run(t, func(r *retry.R) {
505		var status structs.ACLReplicationStatus
506		err := msgpackrpc.CallWithCodec(codec, "ACL.ReplicationStatus", &getR, &status)
507		require.NoError(t, err)
508
509		require.True(r, status.Enabled)
510		require.True(r, status.Running)
511		require.Equal(r, "dc2", status.SourceDatacenter)
512	})
513}
514
515func TestACLEndpoint_TokenRead(t *testing.T) {
516	if testing.Short() {
517		t.Skip("too slow for testing.Short")
518	}
519
520	t.Parallel()
521	_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
522		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
523		c.ACLTokenMaxExpirationTTL = 5 * time.Second
524	}, false)
525
526	waitForLeaderEstablishment(t, srv)
527
528	acl := ACL{srv: srv}
529
530	t.Run("exists and matches what we created", func(t *testing.T) {
531		token, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil)
532		require.NoError(t, err)
533
534		req := structs.ACLTokenGetRequest{
535			Datacenter:   "dc1",
536			TokenID:      token.AccessorID,
537			TokenIDType:  structs.ACLTokenAccessor,
538			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
539		}
540
541		resp := structs.ACLTokenResponse{}
542
543		err = acl.TokenRead(&req, &resp)
544		require.NoError(t, err)
545
546		require.Equal(t, token, resp.Token)
547	})
548
549	t.Run("expired tokens are filtered", func(t *testing.T) {
550		// insert a token that will expire
551		token, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(t *structs.ACLToken) {
552			t.ExpirationTTL = 200 * time.Millisecond
553		})
554		require.NoError(t, err)
555
556		t.Run("readable until expiration", func(t *testing.T) {
557			req := structs.ACLTokenGetRequest{
558				Datacenter:   "dc1",
559				TokenID:      token.AccessorID,
560				TokenIDType:  structs.ACLTokenAccessor,
561				QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
562			}
563
564			resp := structs.ACLTokenResponse{}
565
566			require.NoError(t, acl.TokenRead(&req, &resp))
567			require.Equal(t, token, resp.Token)
568		})
569
570		t.Run("not returned when expired", func(t *testing.T) {
571			req := structs.ACLTokenGetRequest{
572				Datacenter:   "dc1",
573				TokenID:      token.AccessorID,
574				TokenIDType:  structs.ACLTokenAccessor,
575				QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
576			}
577
578			resp := structs.ACLTokenResponse{}
579
580			retry.Run(t, func(r *retry.R) {
581				require.NoError(r, acl.TokenRead(&req, &resp))
582				require.Nil(r, resp.Token)
583			})
584		})
585	})
586
587	t.Run("nil when token does not exist", func(t *testing.T) {
588		fakeID, err := uuid.GenerateUUID()
589		require.NoError(t, err)
590
591		req := structs.ACLTokenGetRequest{
592			Datacenter:   "dc1",
593			TokenID:      fakeID,
594			TokenIDType:  structs.ACLTokenAccessor,
595			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
596		}
597
598		resp := structs.ACLTokenResponse{}
599
600		err = acl.TokenRead(&req, &resp)
601		require.Nil(t, resp.Token)
602		require.NoError(t, err)
603	})
604
605	t.Run("validates ID format", func(t *testing.T) {
606		req := structs.ACLTokenGetRequest{
607			Datacenter:   "dc1",
608			TokenID:      "definitely-really-certainly-not-a-uuid",
609			TokenIDType:  structs.ACLTokenAccessor,
610			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
611		}
612
613		resp := structs.ACLTokenResponse{}
614
615		err := acl.TokenRead(&req, &resp)
616		require.Nil(t, resp.Token)
617		require.EqualError(t, err, "failed acl token lookup: index error: UUID must be 36 characters")
618	})
619}
620
621func TestACLEndpoint_TokenClone(t *testing.T) {
622	if testing.Short() {
623		t.Skip("too slow for testing.Short")
624	}
625
626	t.Parallel()
627
628	_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
629		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
630		c.ACLTokenMaxExpirationTTL = 5 * time.Second
631	}, false)
632	waitForLeaderEstablishment(t, srv)
633
634	p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
635	require.NoError(t, err)
636
637	r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
638	require.NoError(t, err)
639
640	t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(t *structs.ACLToken) {
641		t.Policies = []structs.ACLTokenPolicyLink{
642			{ID: p1.ID},
643		}
644		t.Roles = []structs.ACLTokenRoleLink{
645			{ID: r1.ID},
646		}
647		t.ServiceIdentities = []*structs.ACLServiceIdentity{
648			{ServiceName: "web"},
649		}
650		t.NodeIdentities = []*structs.ACLNodeIdentity{
651			{NodeName: "foo", Datacenter: "bar"},
652		}
653	})
654	require.NoError(t, err)
655
656	endpoint := ACL{srv: srv}
657
658	t.Run("normal", func(t *testing.T) {
659		req := structs.ACLTokenSetRequest{
660			Datacenter:   "dc1",
661			ACLToken:     structs.ACLToken{AccessorID: t1.AccessorID},
662			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
663		}
664
665		t2 := structs.ACLToken{}
666
667		err = endpoint.TokenClone(&req, &t2)
668		require.NoError(t, err)
669
670		require.Equal(t, t1.Description, t2.Description)
671		require.Equal(t, t1.Policies, t2.Policies)
672		require.Equal(t, t1.Roles, t2.Roles)
673		require.Equal(t, t1.ServiceIdentities, t2.ServiceIdentities)
674		require.Equal(t, t1.NodeIdentities, t2.NodeIdentities)
675		require.Equal(t, t1.Rules, t2.Rules)
676		require.Equal(t, t1.Local, t2.Local)
677		require.NotEqual(t, t1.AccessorID, t2.AccessorID)
678		require.NotEqual(t, t1.SecretID, t2.SecretID)
679	})
680
681	t.Run("can't clone expired token", func(t *testing.T) {
682		// insert a token that will expire
683		t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(t *structs.ACLToken) {
684			t.ExpirationTTL = 11 * time.Millisecond
685		})
686		require.NoError(t, err)
687
688		time.Sleep(30 * time.Millisecond)
689
690		req := structs.ACLTokenSetRequest{
691			Datacenter:   "dc1",
692			ACLToken:     structs.ACLToken{AccessorID: t1.AccessorID},
693			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
694		}
695
696		t2 := structs.ACLToken{}
697
698		err = endpoint.TokenClone(&req, &t2)
699		require.Error(t, err)
700		require.Equal(t, acl.ErrNotFound, err)
701	})
702}
703
704func TestACLEndpoint_TokenSet(t *testing.T) {
705	if testing.Short() {
706		t.Skip("too slow for testing.Short")
707	}
708
709	t.Parallel()
710
711	_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
712		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
713		c.ACLTokenMaxExpirationTTL = 5 * time.Second
714	}, false)
715	waitForLeaderEstablishment(t, srv)
716
717	acl := ACL{srv: srv}
718
719	var tokenID string
720
721	t.Run("Create it", func(t *testing.T) {
722		req := structs.ACLTokenSetRequest{
723			Datacenter: "dc1",
724			ACLToken: structs.ACLToken{
725				Description: "foobar",
726				Policies:    nil,
727				Local:       false,
728				NodeIdentities: []*structs.ACLNodeIdentity{
729					{
730						NodeName:   "foo",
731						Datacenter: "dc1",
732					},
733				},
734			},
735			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
736		}
737
738		resp := structs.ACLToken{}
739
740		err := acl.TokenSet(&req, &resp)
741		require.NoError(t, err)
742
743		// Get the token directly to validate that it exists
744		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
745		require.NoError(t, err)
746		token := tokenResp.Token
747
748		require.NotNil(t, token)
749		require.NotNil(t, token.AccessorID)
750		require.Equal(t, token.Description, "foobar")
751		require.Equal(t, token.AccessorID, resp.AccessorID)
752		require.Len(t, token.NodeIdentities, 1)
753		require.Equal(t, "foo", token.NodeIdentities[0].NodeName)
754		require.Equal(t, "dc1", token.NodeIdentities[0].Datacenter)
755
756		tokenID = token.AccessorID
757	})
758
759	t.Run("Update it", func(t *testing.T) {
760		req := structs.ACLTokenSetRequest{
761			Datacenter: "dc1",
762			ACLToken: structs.ACLToken{
763				Description: "new-description",
764				AccessorID:  tokenID,
765			},
766			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
767		}
768
769		resp := structs.ACLToken{}
770
771		err := acl.TokenSet(&req, &resp)
772		require.NoError(t, err)
773
774		// Get the token directly to validate that it exists
775		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
776		require.NoError(t, err)
777		token := tokenResp.Token
778
779		require.NotNil(t, token)
780		require.NotNil(t, token.AccessorID)
781		require.Equal(t, token.Description, "new-description")
782		require.Equal(t, token.AccessorID, resp.AccessorID)
783		require.Empty(t, token.NodeIdentities)
784	})
785
786	t.Run("Create it using Policies linked by id and name", func(t *testing.T) {
787		policy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
788		require.NoError(t, err)
789		policy2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
790		require.NoError(t, err)
791
792		req := structs.ACLTokenSetRequest{
793			Datacenter: "dc1",
794			ACLToken: structs.ACLToken{
795				Description: "foobar",
796				Policies: []structs.ACLTokenPolicyLink{
797					{
798						ID: policy1.ID,
799					},
800					{
801						Name: policy2.Name,
802					},
803				},
804				Local: false,
805			},
806			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
807		}
808
809		resp := structs.ACLToken{}
810
811		err = acl.TokenSet(&req, &resp)
812		require.NoError(t, err)
813
814		// Delete both policies to ensure that we skip resolving ID->Name
815		// in the returned data.
816		require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy1.ID))
817		require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy2.ID))
818
819		// Get the token directly to validate that it exists
820		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
821		require.NoError(t, err)
822		token := tokenResp.Token
823
824		require.NotNil(t, token)
825		require.NotNil(t, token.AccessorID)
826		require.Equal(t, token.Description, "foobar")
827		require.Equal(t, token.AccessorID, resp.AccessorID)
828
829		require.Len(t, token.Policies, 0)
830	})
831
832	t.Run("Create it using Roles linked by id and name", func(t *testing.T) {
833		role1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
834		require.NoError(t, err)
835		role2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
836		require.NoError(t, err)
837
838		req := structs.ACLTokenSetRequest{
839			Datacenter: "dc1",
840			ACLToken: structs.ACLToken{
841				Description: "foobar",
842				Roles: []structs.ACLTokenRoleLink{
843					{
844						ID: role1.ID,
845					},
846					{
847						Name: role2.Name,
848					},
849				},
850				Local: false,
851			},
852			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
853		}
854
855		resp := structs.ACLToken{}
856
857		err = acl.TokenSet(&req, &resp)
858		require.NoError(t, err)
859
860		// Delete both roles to ensure that we skip resolving ID->Name
861		// in the returned data.
862		require.NoError(t, deleteTestRole(codec, TestDefaultMasterToken, "dc1", role1.ID))
863		require.NoError(t, deleteTestRole(codec, TestDefaultMasterToken, "dc1", role2.ID))
864
865		// Get the token directly to validate that it exists
866		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
867		require.NoError(t, err)
868		token := tokenResp.Token
869
870		require.NotNil(t, token)
871		require.NotNil(t, token.AccessorID)
872		require.Equal(t, token.Description, "foobar")
873		require.Equal(t, token.AccessorID, resp.AccessorID)
874
875		require.Len(t, token.Roles, 0)
876	})
877
878	t.Run("Create it with AuthMethod set outside of login", func(t *testing.T) {
879		req := structs.ACLTokenSetRequest{
880			Datacenter: "dc1",
881			ACLToken: structs.ACLToken{
882				Description: "foobar",
883				AuthMethod:  "fakemethod",
884			},
885			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
886		}
887
888		resp := structs.ACLToken{}
889
890		err := acl.TokenSet(&req, &resp)
891		testutil.RequireErrorContains(t, err, "AuthMethod field is disallowed outside of Login")
892	})
893
894	t.Run("Update auth method linked token and try to change auth method", func(t *testing.T) {
895		acl := ACL{srv: srv}
896
897		testSessionID := testauth.StartSession()
898		defer testauth.ResetSession(testSessionID)
899		testauth.InstallSessionToken(testSessionID, "fake-token", "default", "demo", "abc123")
900
901		method1, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID)
902		require.NoError(t, err)
903
904		_, err = upsertTestBindingRule(codec, TestDefaultMasterToken, "dc1", method1.Name, "", structs.BindingRuleBindTypeService, "demo")
905		require.NoError(t, err)
906
907		// create a token in one method
908		methodToken := structs.ACLToken{}
909		require.NoError(t, acl.Login(&structs.ACLLoginRequest{
910			Auth: &structs.ACLLoginParams{
911				AuthMethod:  method1.Name,
912				BearerToken: "fake-token",
913			},
914			Datacenter: "dc1",
915		}, &methodToken))
916
917		method2, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "")
918		require.NoError(t, err)
919
920		// try to update the token and change the method
921		req := structs.ACLTokenSetRequest{
922			Datacenter: "dc1",
923			ACLToken: structs.ACLToken{
924				AccessorID:  methodToken.AccessorID,
925				SecretID:    methodToken.SecretID,
926				AuthMethod:  method2.Name,
927				Description: "updated token",
928				Local:       true,
929			},
930			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
931		}
932
933		resp := structs.ACLToken{}
934
935		err = acl.TokenSet(&req, &resp)
936		testutil.RequireErrorContains(t, err, "Cannot change AuthMethod")
937	})
938
939	t.Run("Update auth method linked token and let the SecretID and AuthMethod be defaulted", func(t *testing.T) {
940		acl := ACL{srv: srv}
941
942		testSessionID := testauth.StartSession()
943		defer testauth.ResetSession(testSessionID)
944		testauth.InstallSessionToken(testSessionID, "fake-token", "default", "demo", "abc123")
945
946		method, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID)
947		require.NoError(t, err)
948
949		_, err = upsertTestBindingRule(codec, TestDefaultMasterToken, "dc1", method.Name, "", structs.BindingRuleBindTypeService, "demo")
950		require.NoError(t, err)
951
952		methodToken := structs.ACLToken{}
953		require.NoError(t, acl.Login(&structs.ACLLoginRequest{
954			Auth: &structs.ACLLoginParams{
955				AuthMethod:  method.Name,
956				BearerToken: "fake-token",
957			},
958			Datacenter: "dc1",
959		}, &methodToken))
960
961		req := structs.ACLTokenSetRequest{
962			Datacenter: "dc1",
963			ACLToken: structs.ACLToken{
964				AccessorID: methodToken.AccessorID,
965				// SecretID:    methodToken.SecretID,
966				// AuthMethod:     method.Name,
967				Description: "updated token",
968				Local:       true,
969			},
970			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
971		}
972
973		resp := structs.ACLToken{}
974
975		require.NoError(t, acl.TokenSet(&req, &resp))
976
977		// Get the token directly to validate that it exists
978		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
979		require.NoError(t, err)
980		token := tokenResp.Token
981
982		require.NotNil(t, token)
983		require.Len(t, token.Roles, 0)
984		require.Equal(t, "updated token", token.Description)
985		require.True(t, token.Local)
986		require.Equal(t, methodToken.SecretID, token.SecretID)
987		require.Equal(t, methodToken.AuthMethod, token.AuthMethod)
988	})
989
990	t.Run("Create it with invalid service identity (empty)", func(t *testing.T) {
991		req := structs.ACLTokenSetRequest{
992			Datacenter: "dc1",
993			ACLToken: structs.ACLToken{
994				Description: "foobar",
995				Policies:    nil,
996				Local:       false,
997				ServiceIdentities: []*structs.ACLServiceIdentity{
998					{ServiceName: ""},
999				},
1000			},
1001			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1002		}
1003
1004		resp := structs.ACLToken{}
1005
1006		err := acl.TokenSet(&req, &resp)
1007		testutil.RequireErrorContains(t, err, "Service identity is missing the service name field")
1008	})
1009
1010	t.Run("Create it with invalid service identity (too large)", func(t *testing.T) {
1011		long := strings.Repeat("x", serviceIdentityNameMaxLength+1)
1012		req := structs.ACLTokenSetRequest{
1013			Datacenter: "dc1",
1014			ACLToken: structs.ACLToken{
1015				Description: "foobar",
1016				Policies:    nil,
1017				Local:       false,
1018				ServiceIdentities: []*structs.ACLServiceIdentity{
1019					{ServiceName: long},
1020				},
1021			},
1022			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1023		}
1024
1025		resp := structs.ACLToken{}
1026
1027		err := acl.TokenSet(&req, &resp)
1028		require.NotNil(t, err)
1029	})
1030
1031	for _, test := range []struct {
1032		name string
1033		ok   bool
1034	}{
1035		{"-abc", false},
1036		{"abc-", false},
1037		{"a-bc", true},
1038		{"_abc", false},
1039		{"abc_", false},
1040		{"a_bc", true},
1041		{":abc", false},
1042		{"abc:", false},
1043		{"a:bc", false},
1044		{"Abc", false},
1045		{"aBc", false},
1046		{"abC", false},
1047		{"0abc", true},
1048		{"abc0", true},
1049		{"a0bc", true},
1050	} {
1051		var testName string
1052		if test.ok {
1053			testName = "Create it with valid service identity (by regex): " + test.name
1054		} else {
1055			testName = "Create it with invalid service identity (by regex): " + test.name
1056		}
1057		t.Run(testName, func(t *testing.T) {
1058			req := structs.ACLTokenSetRequest{
1059				Datacenter: "dc1",
1060				ACLToken: structs.ACLToken{
1061					Description: "foobar",
1062					Policies:    nil,
1063					Local:       false,
1064					ServiceIdentities: []*structs.ACLServiceIdentity{
1065						{ServiceName: test.name},
1066					},
1067				},
1068				WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1069			}
1070
1071			resp := structs.ACLToken{}
1072
1073			err := acl.TokenSet(&req, &resp)
1074			if test.ok {
1075				require.NoError(t, err)
1076
1077				// Get the token directly to validate that it exists
1078				tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1079				require.NoError(t, err)
1080				token := tokenResp.Token
1081				require.NotNil(t, token)
1082				require.ElementsMatch(t, req.ACLToken.ServiceIdentities, token.ServiceIdentities)
1083			} else {
1084				require.NotNil(t, err)
1085			}
1086		})
1087	}
1088
1089	t.Run("Create it with two of the same service identities", func(t *testing.T) {
1090		req := structs.ACLTokenSetRequest{
1091			Datacenter: "dc1",
1092			ACLToken: structs.ACLToken{
1093				Description: "foobar",
1094				Policies:    nil,
1095				Local:       false,
1096				ServiceIdentities: []*structs.ACLServiceIdentity{
1097					{ServiceName: "example"},
1098					{ServiceName: "example"},
1099				},
1100			},
1101			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1102		}
1103
1104		resp := structs.ACLToken{}
1105
1106		err := acl.TokenSet(&req, &resp)
1107		require.NoError(t, err)
1108
1109		// Get the token directly to validate that it exists
1110		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1111		require.NoError(t, err)
1112		token := tokenResp.Token
1113		require.NotNil(t, token)
1114		require.Len(t, token.ServiceIdentities, 1)
1115	})
1116
1117	t.Run("Create it with two of the same service identities and different DCs", func(t *testing.T) {
1118		req := structs.ACLTokenSetRequest{
1119			Datacenter: "dc1",
1120			ACLToken: structs.ACLToken{
1121				Description: "foobar",
1122				Policies:    nil,
1123				Local:       false,
1124				ServiceIdentities: []*structs.ACLServiceIdentity{
1125					{
1126						ServiceName: "example",
1127						Datacenters: []string{"dc2", "dc3"},
1128					},
1129					{
1130						ServiceName: "example",
1131						Datacenters: []string{"dc1", "dc2"},
1132					},
1133				},
1134			},
1135			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1136		}
1137
1138		resp := structs.ACLToken{}
1139
1140		err := acl.TokenSet(&req, &resp)
1141		require.NoError(t, err)
1142
1143		// Get the token directly to validate that it exists
1144		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1145		require.NoError(t, err)
1146		token := tokenResp.Token
1147		require.NotNil(t, token)
1148		require.Len(t, token.ServiceIdentities, 1)
1149		svcid := token.ServiceIdentities[0]
1150		require.Equal(t, "example", svcid.ServiceName)
1151		require.ElementsMatch(t, []string{"dc1", "dc2", "dc3"}, svcid.Datacenters)
1152	})
1153
1154	t.Run("Create it with invalid service identity (datacenters set on local token)", func(t *testing.T) {
1155		req := structs.ACLTokenSetRequest{
1156			Datacenter: "dc1",
1157			ACLToken: structs.ACLToken{
1158				Description: "foobar",
1159				Policies:    nil,
1160				Local:       true,
1161				ServiceIdentities: []*structs.ACLServiceIdentity{
1162					{ServiceName: "foo", Datacenters: []string{"dc2"}},
1163				},
1164			},
1165			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1166		}
1167
1168		resp := structs.ACLToken{}
1169
1170		err := acl.TokenSet(&req, &resp)
1171		testutil.RequireErrorContains(t, err, "cannot specify a list of datacenters on a local token")
1172	})
1173
1174	for _, test := range []struct {
1175		name         string
1176		offset       time.Duration
1177		errString    string
1178		errStringTTL string
1179	}{
1180		{"before create time", -5 * time.Minute, "ExpirationTime cannot be before CreateTime", ""},
1181		{"too soon", 1 * time.Millisecond, "ExpirationTime cannot be less than", "ExpirationTime cannot be less than"},
1182		{"too distant", 25 * time.Hour, "ExpirationTime cannot be more than", "ExpirationTime cannot be more than"},
1183	} {
1184		t.Run("Create it with an expiration time that is "+test.name, func(t *testing.T) {
1185			req := structs.ACLTokenSetRequest{
1186				Datacenter: "dc1",
1187				ACLToken: structs.ACLToken{
1188					Description:    "foobar",
1189					Policies:       nil,
1190					Local:          false,
1191					ExpirationTime: timePointer(time.Now().Add(test.offset)),
1192				},
1193				WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1194			}
1195
1196			resp := structs.ACLToken{}
1197
1198			err := acl.TokenSet(&req, &resp)
1199			if test.errString != "" {
1200				testutil.RequireErrorContains(t, err, test.errString)
1201			} else {
1202				require.NotNil(t, err)
1203			}
1204		})
1205
1206		t.Run("Create it with an expiration TTL that is "+test.name, func(t *testing.T) {
1207			req := structs.ACLTokenSetRequest{
1208				Datacenter: "dc1",
1209				ACLToken: structs.ACLToken{
1210					Description:   "foobar",
1211					Policies:      nil,
1212					Local:         false,
1213					ExpirationTTL: test.offset,
1214				},
1215				WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1216			}
1217
1218			resp := structs.ACLToken{}
1219
1220			err := acl.TokenSet(&req, &resp)
1221			if test.errString != "" {
1222				testutil.RequireErrorContains(t, err, test.errStringTTL)
1223			} else {
1224				require.NotNil(t, err)
1225			}
1226		})
1227	}
1228
1229	t.Run("Create it with expiration time AND expiration TTL set (error)", func(t *testing.T) {
1230		req := structs.ACLTokenSetRequest{
1231			Datacenter: "dc1",
1232			ACLToken: structs.ACLToken{
1233				Description:    "foobar",
1234				Policies:       nil,
1235				Local:          false,
1236				ExpirationTime: timePointer(time.Now().Add(4 * time.Second)),
1237				ExpirationTTL:  4 * time.Second,
1238			},
1239			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1240		}
1241
1242		resp := structs.ACLToken{}
1243
1244		err := acl.TokenSet(&req, &resp)
1245		testutil.RequireErrorContains(t, err, "Expiration TTL and Expiration Time cannot both be set")
1246	})
1247
1248	t.Run("Create it with expiration time using TTLs", func(t *testing.T) {
1249		req := structs.ACLTokenSetRequest{
1250			Datacenter: "dc1",
1251			ACLToken: structs.ACLToken{
1252				Description:   "foobar",
1253				Policies:      nil,
1254				Local:         false,
1255				ExpirationTTL: 4 * time.Second,
1256			},
1257			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1258		}
1259
1260		resp := structs.ACLToken{}
1261
1262		err := acl.TokenSet(&req, &resp)
1263		require.NoError(t, err)
1264
1265		// Get the token directly to validate that it exists
1266		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1267		require.NoError(t, err)
1268		token := tokenResp.Token
1269
1270		expectExpTime := resp.CreateTime.Add(4 * time.Second)
1271
1272		require.NotNil(t, token)
1273		require.NotNil(t, token.AccessorID)
1274		require.Equal(t, token.Description, "foobar")
1275		require.Equal(t, token.AccessorID, resp.AccessorID)
1276		requireTimeEquals(t, &expectExpTime, resp.ExpirationTime)
1277
1278		tokenID = token.AccessorID
1279	})
1280
1281	var expTime time.Time
1282	t.Run("Create it with expiration time", func(t *testing.T) {
1283		expTime = time.Now().Add(4 * time.Second)
1284		req := structs.ACLTokenSetRequest{
1285			Datacenter: "dc1",
1286			ACLToken: structs.ACLToken{
1287				Description:    "foobar",
1288				Policies:       nil,
1289				Local:          false,
1290				ExpirationTime: &expTime,
1291			},
1292			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1293		}
1294
1295		resp := structs.ACLToken{}
1296
1297		err := acl.TokenSet(&req, &resp)
1298		require.NoError(t, err)
1299
1300		// Get the token directly to validate that it exists
1301		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1302		require.NoError(t, err)
1303		token := tokenResp.Token
1304
1305		require.NotNil(t, token)
1306		require.NotNil(t, token.AccessorID)
1307		require.Equal(t, token.Description, "foobar")
1308		require.Equal(t, token.AccessorID, resp.AccessorID)
1309		requireTimeEquals(t, &expTime, resp.ExpirationTime)
1310
1311		tokenID = token.AccessorID
1312	})
1313
1314	// do not insert another test at this point: these tests need to be serial
1315
1316	t.Run("Update expiration time is not allowed", func(t *testing.T) {
1317		req := structs.ACLTokenSetRequest{
1318			Datacenter: "dc1",
1319			ACLToken: structs.ACLToken{
1320				Description:    "new-description",
1321				AccessorID:     tokenID,
1322				ExpirationTime: timePointer(expTime.Add(-1 * time.Second)),
1323			},
1324			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1325		}
1326
1327		resp := structs.ACLToken{}
1328
1329		err := acl.TokenSet(&req, &resp)
1330		testutil.RequireErrorContains(t, err, "Cannot change expiration time")
1331	})
1332
1333	// do not insert another test at this point: these tests need to be serial
1334
1335	t.Run("Update anything except expiration time is ok - omit expiration time and let it default", func(t *testing.T) {
1336		req := structs.ACLTokenSetRequest{
1337			Datacenter: "dc1",
1338			ACLToken: structs.ACLToken{
1339				Description: "new-description-1",
1340				AccessorID:  tokenID,
1341			},
1342			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1343		}
1344
1345		resp := structs.ACLToken{}
1346
1347		err := acl.TokenSet(&req, &resp)
1348		require.NoError(t, err)
1349
1350		// Get the token directly to validate that it exists
1351		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1352		require.NoError(t, err)
1353		token := tokenResp.Token
1354
1355		require.NotNil(t, token)
1356		require.NotNil(t, token.AccessorID)
1357		require.Equal(t, token.Description, "new-description-1")
1358		require.Equal(t, token.AccessorID, resp.AccessorID)
1359		requireTimeEquals(t, &expTime, resp.ExpirationTime)
1360	})
1361
1362	t.Run("Update anything except expiration time is ok", func(t *testing.T) {
1363		req := structs.ACLTokenSetRequest{
1364			Datacenter: "dc1",
1365			ACLToken: structs.ACLToken{
1366				Description:    "new-description-2",
1367				AccessorID:     tokenID,
1368				ExpirationTime: &expTime,
1369			},
1370			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1371		}
1372
1373		resp := structs.ACLToken{}
1374
1375		err := acl.TokenSet(&req, &resp)
1376		require.NoError(t, err)
1377
1378		// Get the token directly to validate that it exists
1379		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1380		require.NoError(t, err)
1381		token := tokenResp.Token
1382
1383		require.NotNil(t, token)
1384		require.NotNil(t, token.AccessorID)
1385		require.Equal(t, token.Description, "new-description-2")
1386		require.Equal(t, token.AccessorID, resp.AccessorID)
1387		requireTimeEquals(t, &expTime, resp.ExpirationTime)
1388	})
1389
1390	t.Run("cannot update a token that is past its expiration time", func(t *testing.T) {
1391		// create a token that will expire
1392		expiringToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) {
1393			token.ExpirationTTL = 11 * time.Millisecond
1394		})
1395		require.NoError(t, err)
1396
1397		time.Sleep(20 * time.Millisecond) // now 'expiringToken' is expired
1398
1399		req := structs.ACLTokenSetRequest{
1400			Datacenter: "dc1",
1401			ACLToken: structs.ACLToken{
1402				Description:   "new-description",
1403				AccessorID:    expiringToken.AccessorID,
1404				ExpirationTTL: 4 * time.Second,
1405			},
1406			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1407		}
1408
1409		resp := structs.ACLToken{}
1410
1411		err = acl.TokenSet(&req, &resp)
1412		testutil.RequireErrorContains(t, err, "Cannot find token")
1413	})
1414
1415	t.Run("invalid node identity - no name", func(t *testing.T) {
1416		req := structs.ACLTokenSetRequest{
1417			Datacenter: "dc1",
1418			ACLToken: structs.ACLToken{
1419				NodeIdentities: []*structs.ACLNodeIdentity{
1420					{
1421						Datacenter: "dc1",
1422					},
1423				},
1424			},
1425			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1426		}
1427
1428		resp := structs.ACLToken{}
1429
1430		err := acl.TokenSet(&req, &resp)
1431		testutil.RequireErrorContains(t, err, "Node identity is missing the node name field on this token")
1432	})
1433
1434	t.Run("invalid node identity - invalid name", func(t *testing.T) {
1435		req := structs.ACLTokenSetRequest{
1436			Datacenter: "dc1",
1437			ACLToken: structs.ACLToken{
1438				NodeIdentities: []*structs.ACLNodeIdentity{
1439					{
1440						NodeName:   "foo.bar",
1441						Datacenter: "dc1",
1442					},
1443				},
1444			},
1445			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1446		}
1447
1448		resp := structs.ACLToken{}
1449
1450		err := acl.TokenSet(&req, &resp)
1451		testutil.RequireErrorContains(t, err, "Node identity has an invalid name.")
1452	})
1453	t.Run("invalid node identity - no datacenter", func(t *testing.T) {
1454		req := structs.ACLTokenSetRequest{
1455			Datacenter: "dc1",
1456			ACLToken: structs.ACLToken{
1457				NodeIdentities: []*structs.ACLNodeIdentity{
1458					{
1459						NodeName: "foo",
1460					},
1461				},
1462			},
1463			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1464		}
1465
1466		resp := structs.ACLToken{}
1467
1468		err := acl.TokenSet(&req, &resp)
1469		testutil.RequireErrorContains(t, err, "Node identity is missing the datacenter field on this token")
1470	})
1471}
1472
1473func TestACLEndpoint_TokenSet_CustomID(t *testing.T) {
1474	if testing.Short() {
1475		t.Skip("too slow for testing.Short")
1476	}
1477
1478	t.Parallel()
1479
1480	_, srv, codec := testACLServerWithConfig(t, nil, false)
1481	waitForLeaderEstablishment(t, srv)
1482
1483	acl := ACL{srv: srv}
1484
1485	// No Create Arg
1486	t.Run("no create arg", func(t *testing.T) {
1487		req := structs.ACLTokenSetRequest{
1488			Datacenter: "dc1",
1489			ACLToken: structs.ACLToken{
1490				AccessorID:  "5d62a983-bcab-4e0c-9bcd-5dabebe3e273",
1491				SecretID:    "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb",
1492				Description: "foobar",
1493				Policies:    nil,
1494				Local:       false,
1495			},
1496			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1497		}
1498
1499		resp := structs.ACLToken{}
1500
1501		err := acl.TokenSet(&req, &resp)
1502		require.Error(t, err)
1503	})
1504
1505	// Use the Create Arg
1506	t.Run("create arg", func(t *testing.T) {
1507		req := structs.ACLTokenSetRequest{
1508			Datacenter: "dc1",
1509			ACLToken: structs.ACLToken{
1510				AccessorID:  "5d62a983-bcab-4e0c-9bcd-5dabebe3e273",
1511				SecretID:    "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb",
1512				Description: "foobar",
1513				Policies:    nil,
1514				Local:       false,
1515			},
1516			Create:       true,
1517			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1518		}
1519
1520		resp := structs.ACLToken{}
1521
1522		err := acl.TokenSet(&req, &resp)
1523		require.NoError(t, err)
1524
1525		// Get the token directly to validate that it exists
1526		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", resp.AccessorID)
1527		require.NoError(t, err)
1528		token := tokenResp.Token
1529
1530		require.NotNil(t, token)
1531		require.Equal(t, req.ACLToken.AccessorID, token.AccessorID)
1532		require.Equal(t, req.ACLToken.SecretID, token.SecretID)
1533		require.Equal(t, token.Description, "foobar")
1534	})
1535
1536	// Reserved AccessorID
1537	t.Run("reserved AccessorID", func(t *testing.T) {
1538		req := structs.ACLTokenSetRequest{
1539			Datacenter: "dc1",
1540			ACLToken: structs.ACLToken{
1541				AccessorID:  "00000000-0000-0000-0000-000000000073",
1542				Description: "foobar",
1543				Policies:    nil,
1544				Local:       false,
1545			},
1546			Create:       true,
1547			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1548		}
1549
1550		resp := structs.ACLToken{}
1551
1552		err := acl.TokenSet(&req, &resp)
1553		require.Error(t, err)
1554	})
1555
1556	// Reserved SecretID
1557	t.Run("reserved SecretID", func(t *testing.T) {
1558		req := structs.ACLTokenSetRequest{
1559			Datacenter: "dc1",
1560			ACLToken: structs.ACLToken{
1561				SecretID:    "00000000-0000-0000-0000-000000000073",
1562				Description: "foobar",
1563				Policies:    nil,
1564				Local:       false,
1565			},
1566			Create:       true,
1567			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1568		}
1569
1570		resp := structs.ACLToken{}
1571
1572		err := acl.TokenSet(&req, &resp)
1573		require.Error(t, err)
1574	})
1575
1576	// Accessor is dup
1577	t.Run("accessor Dup", func(t *testing.T) {
1578		req := structs.ACLTokenSetRequest{
1579			Datacenter: "dc1",
1580			ACLToken: structs.ACLToken{
1581				AccessorID:  "5d62a983-bcab-4e0c-9bcd-5dabebe3e273",
1582				Description: "foobar",
1583				Policies:    nil,
1584				Local:       false,
1585			},
1586			Create:       true,
1587			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1588		}
1589
1590		resp := structs.ACLToken{}
1591
1592		err := acl.TokenSet(&req, &resp)
1593		require.Error(t, err)
1594	})
1595
1596	// Accessor is dup of secret
1597	t.Run("accessor dup of secret", func(t *testing.T) {
1598		req := structs.ACLTokenSetRequest{
1599			Datacenter: "dc1",
1600			ACLToken: structs.ACLToken{
1601				AccessorID:  "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb",
1602				Description: "foobar",
1603				Policies:    nil,
1604				Local:       false,
1605			},
1606			Create:       true,
1607			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1608		}
1609
1610		resp := structs.ACLToken{}
1611
1612		err := acl.TokenSet(&req, &resp)
1613		require.Error(t, err)
1614	})
1615
1616	// Secret is dup of Accessor
1617	t.Run("secret dup of accessor", func(t *testing.T) {
1618		req := structs.ACLTokenSetRequest{
1619			Datacenter: "dc1",
1620			ACLToken: structs.ACLToken{
1621				SecretID:    "5d62a983-bcab-4e0c-9bcd-5dabebe3e273",
1622				Description: "foobar",
1623				Policies:    nil,
1624				Local:       false,
1625			},
1626			Create:       true,
1627			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1628		}
1629
1630		resp := structs.ACLToken{}
1631
1632		err := acl.TokenSet(&req, &resp)
1633		require.Error(t, err)
1634	})
1635
1636	// Secret is dup
1637	t.Run("secret dup", func(t *testing.T) {
1638		req := structs.ACLTokenSetRequest{
1639			Datacenter: "dc1",
1640			ACLToken: structs.ACLToken{
1641				SecretID:    "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb",
1642				Description: "foobar",
1643				Policies:    nil,
1644				Local:       false,
1645			},
1646			Create:       true,
1647			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1648		}
1649
1650		resp := structs.ACLToken{}
1651
1652		err := acl.TokenSet(&req, &resp)
1653		require.Error(t, err)
1654	})
1655
1656	// Update Accessor attempt
1657	t.Run("update accessor", func(t *testing.T) {
1658		req := structs.ACLTokenSetRequest{
1659			Datacenter: "dc1",
1660			ACLToken: structs.ACLToken{
1661				AccessorID:  "75a0d6a9-6882-4f7a-a053-906db1d55a73",
1662				SecretID:    "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb",
1663				Description: "foobar",
1664				Policies:    nil,
1665				Local:       false,
1666			},
1667			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1668		}
1669
1670		resp := structs.ACLToken{}
1671
1672		err := acl.TokenSet(&req, &resp)
1673		require.Error(t, err)
1674	})
1675
1676	// Update Accessor attempt - with Create
1677	t.Run("update accessor create", func(t *testing.T) {
1678		req := structs.ACLTokenSetRequest{
1679			Datacenter: "dc1",
1680			ACLToken: structs.ACLToken{
1681				AccessorID:  "75a0d6a9-6882-4f7a-a053-906db1d55a73",
1682				SecretID:    "10a8ad77-2bdf-4939-a9d7-1b7de79d6beb",
1683				Description: "foobar",
1684				Policies:    nil,
1685				Local:       false,
1686			},
1687			Create:       true,
1688			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1689		}
1690
1691		resp := structs.ACLToken{}
1692
1693		err := acl.TokenSet(&req, &resp)
1694		require.Error(t, err)
1695	})
1696
1697	// Update Secret attempt
1698	t.Run("update secret", func(t *testing.T) {
1699		req := structs.ACLTokenSetRequest{
1700			Datacenter: "dc1",
1701			ACLToken: structs.ACLToken{
1702				AccessorID:  "5d62a983-bcab-4e0c-9bcd-5dabebe3e273",
1703				SecretID:    "f551f807-b3a7-4483-9ade-97230c974bf3",
1704				Description: "foobar",
1705				Policies:    nil,
1706				Local:       false,
1707			},
1708			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1709		}
1710
1711		resp := structs.ACLToken{}
1712
1713		err := acl.TokenSet(&req, &resp)
1714		require.Error(t, err)
1715	})
1716
1717	// Update Secret attempt - with Create
1718	t.Run("update secret create", func(t *testing.T) {
1719		req := structs.ACLTokenSetRequest{
1720			Datacenter: "dc1",
1721			ACLToken: structs.ACLToken{
1722				AccessorID:  "5d62a983-bcab-4e0c-9bcd-5dabebe3e273",
1723				SecretID:    "f551f807-b3a7-4483-9ade-97230c974bf3",
1724				Description: "foobar",
1725				Policies:    nil,
1726				Local:       false,
1727			},
1728			Create:       true,
1729			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1730		}
1731
1732		resp := structs.ACLToken{}
1733
1734		err := acl.TokenSet(&req, &resp)
1735		require.Error(t, err)
1736	})
1737}
1738
1739func TestACLEndpoint_TokenSet_anon(t *testing.T) {
1740	if testing.Short() {
1741		t.Skip("too slow for testing.Short")
1742	}
1743
1744	t.Parallel()
1745
1746	_, srv, codec := testACLServerWithConfig(t, nil, false)
1747	waitForLeaderEstablishment(t, srv)
1748
1749	policy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
1750	require.NoError(t, err)
1751
1752	acl := ACL{srv: srv}
1753
1754	// Assign the policies to a token
1755	tokenUpsertReq := structs.ACLTokenSetRequest{
1756		Datacenter: "dc1",
1757		ACLToken: structs.ACLToken{
1758			AccessorID: structs.ACLTokenAnonymousID,
1759			Policies: []structs.ACLTokenPolicyLink{
1760				{
1761					ID: policy.ID,
1762				},
1763			},
1764		},
1765		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1766	}
1767	token := structs.ACLToken{}
1768	err = acl.TokenSet(&tokenUpsertReq, &token)
1769	require.NoError(t, err)
1770	require.NotEmpty(t, token.SecretID)
1771
1772	tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", structs.ACLTokenAnonymousID)
1773	require.NoError(t, err)
1774	require.Equal(t, len(tokenResp.Token.Policies), 1)
1775	require.Equal(t, tokenResp.Token.Policies[0].ID, policy.ID)
1776
1777}
1778
1779func TestACLEndpoint_TokenDelete(t *testing.T) {
1780	if testing.Short() {
1781		t.Skip("too slow for testing.Short")
1782	}
1783
1784	t.Parallel()
1785
1786	_, s1, codec := testACLServerWithConfig(t, func(c *Config) {
1787		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
1788		c.ACLTokenMaxExpirationTTL = 5 * time.Second
1789	}, false)
1790
1791	_, s2, codec2 := testACLServerWithConfig(t, func(c *Config) {
1792		c.Datacenter = "dc2"
1793		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
1794		c.ACLTokenMaxExpirationTTL = 5 * time.Second
1795		// token replication is required to test deleting non-local tokens in secondary dc
1796		c.ACLTokenReplication = true
1797	}, true)
1798
1799	waitForLeaderEstablishment(t, s1)
1800	waitForLeaderEstablishment(t, s2)
1801
1802	// Try to join
1803	joinWAN(t, s2, s1)
1804
1805	waitForNewACLs(t, s1)
1806	waitForNewACLs(t, s2)
1807
1808	// Ensure s2 is authoritative.
1809	waitForNewACLReplication(t, s2, structs.ACLReplicateTokens, 1, 1, 0)
1810
1811	acl := ACL{srv: s1}
1812	acl2 := ACL{srv: s2}
1813
1814	existingToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil)
1815	require.NoError(t, err)
1816
1817	t.Run("deletes a token that has an expiration time in the future", func(t *testing.T) {
1818		// create a token that will expire
1819		testToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) {
1820			token.ExpirationTTL = 4 * time.Second
1821		})
1822		require.NoError(t, err)
1823
1824		// Make sure the token is listable
1825		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", testToken.AccessorID)
1826		require.NoError(t, err)
1827		require.NotNil(t, tokenResp.Token)
1828
1829		// Now try to delete it (this should work).
1830		req := structs.ACLTokenDeleteRequest{
1831			Datacenter:   "dc1",
1832			TokenID:      testToken.AccessorID,
1833			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1834		}
1835
1836		var resp string
1837
1838		err = acl.TokenDelete(&req, &resp)
1839		require.NoError(t, err)
1840
1841		// Make sure the token is gone
1842		tokenResp, err = retrieveTestToken(codec, TestDefaultMasterToken, "dc1", testToken.AccessorID)
1843		require.NoError(t, err)
1844		require.Nil(t, tokenResp.Token)
1845	})
1846
1847	t.Run("deletes a token that is past its expiration time", func(t *testing.T) {
1848		// create a token that will expire
1849		expiringToken, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) {
1850			token.ExpirationTTL = 11 * time.Millisecond
1851		})
1852		require.NoError(t, err)
1853
1854		time.Sleep(20 * time.Millisecond) // now 'expiringToken' is expired
1855
1856		// Make sure the token is not listable (filtered due to expiry)
1857		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", expiringToken.AccessorID)
1858		require.NoError(t, err)
1859		require.Nil(t, tokenResp.Token)
1860
1861		// Now try to delete it (this should work).
1862		req := structs.ACLTokenDeleteRequest{
1863			Datacenter:   "dc1",
1864			TokenID:      expiringToken.AccessorID,
1865			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1866		}
1867
1868		var resp string
1869
1870		err = acl.TokenDelete(&req, &resp)
1871		require.NoError(t, err)
1872
1873		// Make sure the token is still gone (this time it's actually gone)
1874		tokenResp, err = retrieveTestToken(codec, TestDefaultMasterToken, "dc1", expiringToken.AccessorID)
1875		require.NoError(t, err)
1876		require.Nil(t, tokenResp.Token)
1877	})
1878
1879	t.Run("deletes a token", func(t *testing.T) {
1880		req := structs.ACLTokenDeleteRequest{
1881			Datacenter:   "dc1",
1882			TokenID:      existingToken.AccessorID,
1883			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1884		}
1885
1886		var resp string
1887
1888		err = acl.TokenDelete(&req, &resp)
1889		require.NoError(t, err)
1890
1891		// Make sure the token is gone
1892		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", existingToken.AccessorID)
1893		require.Nil(t, tokenResp.Token)
1894		require.NoError(t, err)
1895	})
1896
1897	t.Run("can't delete itself", func(t *testing.T) {
1898		readReq := structs.ACLTokenGetRequest{
1899			Datacenter:   "dc1",
1900			TokenID:      TestDefaultMasterToken,
1901			TokenIDType:  structs.ACLTokenSecret,
1902			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
1903		}
1904
1905		var out structs.ACLTokenResponse
1906
1907		err := acl.TokenRead(&readReq, &out)
1908
1909		require.NoError(t, err)
1910
1911		req := structs.ACLTokenDeleteRequest{
1912			Datacenter:   "dc1",
1913			TokenID:      out.Token.AccessorID,
1914			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1915		}
1916
1917		var resp string
1918		err = acl.TokenDelete(&req, &resp)
1919		require.EqualError(t, err, "Deletion of the request's authorization token is not permitted")
1920	})
1921
1922	t.Run("errors when token doesn't exist", func(t *testing.T) {
1923		fakeID, err := uuid.GenerateUUID()
1924		require.NoError(t, err)
1925
1926		req := structs.ACLTokenDeleteRequest{
1927			Datacenter:   "dc1",
1928			TokenID:      fakeID,
1929			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1930		}
1931
1932		var resp string
1933
1934		err = acl.TokenDelete(&req, &resp)
1935		require.NoError(t, err)
1936
1937		// token should be nil
1938		tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", existingToken.AccessorID)
1939		require.Nil(t, tokenResp.Token)
1940		require.NoError(t, err)
1941	})
1942
1943	t.Run("don't segfault when attempting to delete non existent token in secondary dc", func(t *testing.T) {
1944		fakeID, err := uuid.GenerateUUID()
1945		require.NoError(t, err)
1946
1947		req := structs.ACLTokenDeleteRequest{
1948			Datacenter:   "dc2",
1949			TokenID:      fakeID,
1950			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1951		}
1952
1953		var resp string
1954
1955		err = acl2.TokenDelete(&req, &resp)
1956		require.NoError(t, err)
1957
1958		// token should be nil
1959		tokenResp, err := retrieveTestToken(codec2, TestDefaultMasterToken, "dc1", existingToken.AccessorID)
1960		require.Nil(t, tokenResp.Token)
1961		require.NoError(t, err)
1962	})
1963}
1964
1965func TestACLEndpoint_TokenDelete_anon(t *testing.T) {
1966	if testing.Short() {
1967		t.Skip("too slow for testing.Short")
1968	}
1969
1970	t.Parallel()
1971
1972	_, srv, codec := testACLServerWithConfig(t, nil, false)
1973	waitForLeaderEstablishment(t, srv)
1974
1975	acl := ACL{srv: srv}
1976
1977	req := structs.ACLTokenDeleteRequest{
1978		Datacenter:   "dc1",
1979		TokenID:      structs.ACLTokenAnonymousID,
1980		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
1981	}
1982
1983	var resp string
1984
1985	err := acl.TokenDelete(&req, &resp)
1986	require.EqualError(t, err, "Delete operation not permitted on the anonymous token")
1987
1988	// Make sure the token is still there
1989	tokenResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", structs.ACLTokenAnonymousID)
1990	require.NoError(t, err)
1991	require.NotNil(t, tokenResp.Token)
1992}
1993
1994func TestACLEndpoint_TokenList(t *testing.T) {
1995	if testing.Short() {
1996		t.Skip("too slow for testing.Short")
1997	}
1998
1999	t.Parallel()
2000
2001	_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
2002		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
2003		c.ACLTokenMaxExpirationTTL = 5 * time.Second
2004	}, false)
2005	waitForLeaderEstablishment(t, srv)
2006
2007	acl := ACL{srv: srv}
2008
2009	t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil)
2010	require.NoError(t, err)
2011
2012	t2, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil)
2013	require.NoError(t, err)
2014
2015	masterTokenAccessorID, err := retrieveTestTokenAccessorForSecret(codec, TestDefaultMasterToken, "dc1", TestDefaultMasterToken)
2016	require.NoError(t, err)
2017
2018	t.Run("normal", func(t *testing.T) {
2019		// this will still be racey even with inserting the token + ttl inside the test function
2020		// however previously inserting it outside of the subtest func resulted in this being
2021		// extra flakey due to there being more code that needed to run to setup the subtest
2022		// between when we inserted the token and when we performed the listing.
2023		t3, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) {
2024			token.ExpirationTTL = 50 * time.Millisecond
2025		})
2026		require.NoError(t, err)
2027
2028		req := structs.ACLTokenListRequest{
2029			Datacenter:   "dc1",
2030			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2031		}
2032
2033		resp := structs.ACLTokenListResponse{}
2034
2035		err = acl.TokenList(&req, &resp)
2036		require.NoError(t, err)
2037
2038		tokens := []string{
2039			masterTokenAccessorID,
2040			structs.ACLTokenAnonymousID,
2041			t1.AccessorID,
2042			t2.AccessorID,
2043			t3.AccessorID,
2044		}
2045		require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens)
2046	})
2047
2048	time.Sleep(50 * time.Millisecond) // now 't3' is expired
2049
2050	t.Run("filter expired", func(t *testing.T) {
2051		req := structs.ACLTokenListRequest{
2052			Datacenter:   "dc1",
2053			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2054		}
2055
2056		resp := structs.ACLTokenListResponse{}
2057
2058		err = acl.TokenList(&req, &resp)
2059		require.NoError(t, err)
2060
2061		tokens := []string{
2062			masterTokenAccessorID,
2063			structs.ACLTokenAnonymousID,
2064			t1.AccessorID,
2065			t2.AccessorID,
2066		}
2067		require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens)
2068	})
2069
2070	t.Run("filter SecretID for acl:read", func(t *testing.T) {
2071		rules := `
2072			acl = "read"
2073		`
2074		readOnlyToken, err := upsertTestTokenWithPolicyRules(codec, TestDefaultMasterToken, "dc1", rules)
2075		require.NoError(t, err)
2076
2077		req := structs.ACLTokenListRequest{
2078			Datacenter:   "dc1",
2079			QueryOptions: structs.QueryOptions{Token: readOnlyToken.SecretID},
2080		}
2081
2082		resp := structs.ACLTokenListResponse{}
2083
2084		err = acl.TokenList(&req, &resp)
2085		require.NoError(t, err)
2086
2087		tokens := []string{
2088			masterTokenAccessorID,
2089			structs.ACLTokenAnonymousID,
2090			readOnlyToken.AccessorID,
2091			t1.AccessorID,
2092			t2.AccessorID,
2093		}
2094		require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens)
2095		for _, token := range resp.Tokens {
2096			require.Equal(t, redactedToken, token.SecretID)
2097		}
2098	})
2099}
2100
2101func TestACLEndpoint_TokenBatchRead(t *testing.T) {
2102	if testing.Short() {
2103		t.Skip("too slow for testing.Short")
2104	}
2105
2106	t.Parallel()
2107
2108	_, srv, codec := testACLServerWithConfig(t, func(c *Config) {
2109		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
2110		c.ACLTokenMaxExpirationTTL = 5 * time.Second
2111	}, false)
2112	waitForLeaderEstablishment(t, srv)
2113
2114	acl := ACL{srv: srv}
2115
2116	t1, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil)
2117	require.NoError(t, err)
2118
2119	t2, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", nil)
2120	require.NoError(t, err)
2121
2122	t3, err := upsertTestToken(codec, TestDefaultMasterToken, "dc1", func(token *structs.ACLToken) {
2123		token.ExpirationTTL = 4 * time.Second
2124	})
2125	require.NoError(t, err)
2126
2127	t.Run("normal", func(t *testing.T) {
2128		tokens := []string{t1.AccessorID, t2.AccessorID, t3.AccessorID}
2129
2130		req := structs.ACLTokenBatchGetRequest{
2131			Datacenter:   "dc1",
2132			AccessorIDs:  tokens,
2133			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2134		}
2135
2136		resp := structs.ACLTokenBatchResponse{}
2137
2138		err = acl.TokenBatchRead(&req, &resp)
2139		require.NoError(t, err)
2140		require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens)
2141	})
2142
2143	time.Sleep(20 * time.Millisecond) // now 't3' is expired
2144
2145	t.Run("returns expired tokens", func(t *testing.T) {
2146		tokens := []string{t1.AccessorID, t2.AccessorID, t3.AccessorID}
2147
2148		req := structs.ACLTokenBatchGetRequest{
2149			Datacenter:   "dc1",
2150			AccessorIDs:  tokens,
2151			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2152		}
2153
2154		resp := structs.ACLTokenBatchResponse{}
2155
2156		err = acl.TokenBatchRead(&req, &resp)
2157		require.NoError(t, err)
2158		require.ElementsMatch(t, gatherIDs(t, resp.Tokens), tokens)
2159	})
2160}
2161
2162func TestACLEndpoint_PolicyRead(t *testing.T) {
2163	if testing.Short() {
2164		t.Skip("too slow for testing.Short")
2165	}
2166
2167	t.Parallel()
2168	_, srv, codec := testACLServerWithConfig(t, nil, false)
2169	waitForLeaderEstablishment(t, srv)
2170
2171	policy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2172	require.NoError(t, err)
2173
2174	acl := ACL{srv: srv}
2175
2176	req := structs.ACLPolicyGetRequest{
2177		Datacenter:   "dc1",
2178		PolicyID:     policy.ID,
2179		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2180	}
2181
2182	resp := structs.ACLPolicyResponse{}
2183
2184	err = acl.PolicyRead(&req, &resp)
2185	require.NoError(t, err)
2186	require.Equal(t, policy, resp.Policy)
2187}
2188
2189func TestACLEndpoint_PolicyReadByName(t *testing.T) {
2190	if testing.Short() {
2191		t.Skip("too slow for testing.Short")
2192	}
2193
2194	t.Parallel()
2195	_, srv, codec := testACLServerWithConfig(t, nil, false)
2196	waitForLeaderEstablishment(t, srv)
2197
2198	policy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2199	require.NoError(t, err)
2200
2201	acl := ACL{srv: srv}
2202
2203	req := structs.ACLPolicyGetRequest{
2204		Datacenter:   "dc1",
2205		PolicyName:   policy.Name,
2206		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2207	}
2208
2209	resp := structs.ACLPolicyResponse{}
2210
2211	err = acl.PolicyRead(&req, &resp)
2212	require.NoError(t, err)
2213	require.Equal(t, policy, resp.Policy)
2214}
2215
2216func TestACLEndpoint_PolicyBatchRead(t *testing.T) {
2217	if testing.Short() {
2218		t.Skip("too slow for testing.Short")
2219	}
2220
2221	t.Parallel()
2222
2223	_, srv, codec := testACLServerWithConfig(t, nil, false)
2224	waitForLeaderEstablishment(t, srv)
2225
2226	p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2227	require.NoError(t, err)
2228
2229	p2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2230	require.NoError(t, err)
2231
2232	acl := ACL{srv: srv}
2233	policies := []string{p1.ID, p2.ID}
2234
2235	req := structs.ACLPolicyBatchGetRequest{
2236		Datacenter:   "dc1",
2237		PolicyIDs:    policies,
2238		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2239	}
2240
2241	resp := structs.ACLPolicyBatchResponse{}
2242
2243	err = acl.PolicyBatchRead(&req, &resp)
2244	require.NoError(t, err)
2245	require.ElementsMatch(t, gatherIDs(t, resp.Policies), []string{p1.ID, p2.ID})
2246}
2247
2248func TestACLEndpoint_PolicySet(t *testing.T) {
2249	if testing.Short() {
2250		t.Skip("too slow for testing.Short")
2251	}
2252
2253	t.Parallel()
2254
2255	_, srv, codec := testACLServerWithConfig(t, nil, false)
2256	waitForLeaderEstablishment(t, srv)
2257	acl := ACL{srv: srv}
2258
2259	var policyID string
2260
2261	t.Run("Create it", func(t *testing.T) {
2262		req := structs.ACLPolicySetRequest{
2263			Datacenter: "dc1",
2264			Policy: structs.ACLPolicy{
2265				Description: "foobar",
2266				Name:        "baz",
2267				Rules:       "service \"\" { policy = \"read\" }",
2268			},
2269			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2270		}
2271		resp := structs.ACLPolicy{}
2272
2273		err := acl.PolicySet(&req, &resp)
2274		require.NoError(t, err)
2275		require.NotNil(t, resp.ID)
2276
2277		// Get the policy directly to validate that it exists
2278		policyResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", resp.ID)
2279		require.NoError(t, err)
2280		policy := policyResp.Policy
2281
2282		require.NotNil(t, policy.ID)
2283		require.Equal(t, policy.Description, "foobar")
2284		require.Equal(t, policy.Name, "baz")
2285		require.Equal(t, policy.Rules, "service \"\" { policy = \"read\" }")
2286
2287		policyID = policy.ID
2288	})
2289
2290	t.Run("Name Dup", func(t *testing.T) {
2291		req := structs.ACLPolicySetRequest{
2292			Datacenter: "dc1",
2293			Policy: structs.ACLPolicy{
2294				Description: "foobar",
2295				Name:        "baz",
2296				Rules:       "service \"\" { policy = \"read\" }",
2297			},
2298			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2299		}
2300		resp := structs.ACLPolicy{}
2301
2302		err := acl.PolicySet(&req, &resp)
2303		require.Error(t, err)
2304	})
2305
2306	t.Run("Update it", func(t *testing.T) {
2307		req := structs.ACLPolicySetRequest{
2308			Datacenter: "dc1",
2309			Policy: structs.ACLPolicy{
2310				ID:          policyID,
2311				Description: "bat",
2312				Name:        "bar",
2313				Rules:       "service \"\" { policy = \"write\" }",
2314			},
2315			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2316		}
2317		resp := structs.ACLPolicy{}
2318
2319		err := acl.PolicySet(&req, &resp)
2320		require.NoError(t, err)
2321		require.NotNil(t, resp.ID)
2322
2323		// Get the policy directly to validate that it exists
2324		policyResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", resp.ID)
2325		require.NoError(t, err)
2326		policy := policyResp.Policy
2327
2328		require.NotNil(t, policy.ID)
2329		require.Equal(t, policy.Description, "bat")
2330		require.Equal(t, policy.Name, "bar")
2331		require.Equal(t, policy.Rules, "service \"\" { policy = \"write\" }")
2332	})
2333}
2334
2335func TestACLEndpoint_PolicySet_CustomID(t *testing.T) {
2336	if testing.Short() {
2337		t.Skip("too slow for testing.Short")
2338	}
2339
2340	t.Parallel()
2341
2342	_, srv, _ := testACLServerWithConfig(t, nil, false)
2343	waitForLeaderEstablishment(t, srv)
2344
2345	acl := ACL{srv: srv}
2346
2347	// Attempt to create policy with ID
2348	req := structs.ACLPolicySetRequest{
2349		Datacenter: "dc1",
2350		Policy: structs.ACLPolicy{
2351			ID:          "7ee166a5-b4b7-453c-bdc0-bca8ce50823e",
2352			Description: "foobar",
2353			Name:        "baz",
2354			Rules:       "service \"\" { policy = \"read\" }",
2355		},
2356		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2357	}
2358	resp := structs.ACLPolicy{}
2359
2360	err := acl.PolicySet(&req, &resp)
2361	require.Error(t, err)
2362}
2363
2364func TestACLEndpoint_PolicySet_globalManagement(t *testing.T) {
2365	if testing.Short() {
2366		t.Skip("too slow for testing.Short")
2367	}
2368
2369	t.Parallel()
2370
2371	_, srv, codec := testACLServerWithConfig(t, nil, false)
2372	waitForLeaderEstablishment(t, srv)
2373
2374	acl := ACL{srv: srv}
2375
2376	// Can't change the rules
2377	{
2378		req := structs.ACLPolicySetRequest{
2379			Datacenter: "dc1",
2380			Policy: structs.ACLPolicy{
2381				ID:    structs.ACLPolicyGlobalManagementID,
2382				Name:  "foobar", // This is required to get past validation
2383				Rules: "service \"\" { policy = \"write\" }",
2384			},
2385			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2386		}
2387		resp := structs.ACLPolicy{}
2388
2389		err := acl.PolicySet(&req, &resp)
2390		require.EqualError(t, err, "Changing the Rules for the builtin global-management policy is not permitted")
2391	}
2392
2393	// Can rename it
2394	{
2395		req := structs.ACLPolicySetRequest{
2396			Datacenter: "dc1",
2397			Policy: structs.ACLPolicy{
2398				ID:    structs.ACLPolicyGlobalManagementID,
2399				Name:  "foobar",
2400				Rules: structs.ACLPolicyGlobalManagement,
2401			},
2402			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2403		}
2404		resp := structs.ACLPolicy{}
2405
2406		err := acl.PolicySet(&req, &resp)
2407		require.NoError(t, err)
2408
2409		// Get the policy again
2410		policyResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", structs.ACLPolicyGlobalManagementID)
2411		require.NoError(t, err)
2412		policy := policyResp.Policy
2413
2414		require.Equal(t, policy.ID, structs.ACLPolicyGlobalManagementID)
2415		require.Equal(t, policy.Name, "foobar")
2416
2417	}
2418}
2419
2420func TestACLEndpoint_PolicyDelete(t *testing.T) {
2421	if testing.Short() {
2422		t.Skip("too slow for testing.Short")
2423	}
2424
2425	t.Parallel()
2426
2427	_, srv, codec := testACLServerWithConfig(t, nil, false)
2428	waitForLeaderEstablishment(t, srv)
2429
2430	existingPolicy, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2431	require.NoError(t, err)
2432
2433	acl := ACL{srv: srv}
2434
2435	req := structs.ACLPolicyDeleteRequest{
2436		Datacenter:   "dc1",
2437		PolicyID:     existingPolicy.ID,
2438		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2439	}
2440
2441	var resp string
2442
2443	err = acl.PolicyDelete(&req, &resp)
2444	require.NoError(t, err)
2445
2446	// Make sure the policy is gone
2447	tokenResp, err := retrieveTestPolicy(codec, TestDefaultMasterToken, "dc1", existingPolicy.ID)
2448	require.NoError(t, err)
2449	require.Nil(t, tokenResp.Policy)
2450}
2451
2452func TestACLEndpoint_PolicyDelete_globalManagement(t *testing.T) {
2453	if testing.Short() {
2454		t.Skip("too slow for testing.Short")
2455	}
2456
2457	t.Parallel()
2458
2459	_, srv, _ := testACLServerWithConfig(t, nil, false)
2460	waitForLeaderEstablishment(t, srv)
2461	acl := ACL{srv: srv}
2462
2463	req := structs.ACLPolicyDeleteRequest{
2464		Datacenter:   "dc1",
2465		PolicyID:     structs.ACLPolicyGlobalManagementID,
2466		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2467	}
2468	var resp string
2469
2470	err := acl.PolicyDelete(&req, &resp)
2471
2472	require.EqualError(t, err, "Delete operation not permitted on the builtin global-management policy")
2473}
2474
2475func TestACLEndpoint_PolicyList(t *testing.T) {
2476	if testing.Short() {
2477		t.Skip("too slow for testing.Short")
2478	}
2479
2480	t.Parallel()
2481
2482	_, srv, codec := testACLServerWithConfig(t, nil, false)
2483	waitForLeaderEstablishment(t, srv)
2484
2485	p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2486	require.NoError(t, err)
2487
2488	p2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2489	require.NoError(t, err)
2490
2491	acl := ACL{srv: srv}
2492
2493	req := structs.ACLPolicyListRequest{
2494		Datacenter:   "dc1",
2495		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2496	}
2497
2498	resp := structs.ACLPolicyListResponse{}
2499
2500	err = acl.PolicyList(&req, &resp)
2501	require.NoError(t, err)
2502
2503	policies := []string{
2504		structs.ACLPolicyGlobalManagementID,
2505		p1.ID,
2506		p2.ID,
2507	}
2508	require.ElementsMatch(t, gatherIDs(t, resp.Policies), policies)
2509}
2510
2511func TestACLEndpoint_PolicyResolve(t *testing.T) {
2512	if testing.Short() {
2513		t.Skip("too slow for testing.Short")
2514	}
2515
2516	t.Parallel()
2517
2518	_, srv, codec := testACLServerWithConfig(t, nil, false)
2519	waitForLeaderEstablishment(t, srv)
2520
2521	p1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2522	require.NoError(t, err)
2523
2524	p2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2525	require.NoError(t, err)
2526
2527	acl := ACL{srv: srv}
2528
2529	policies := []string{p1.ID, p2.ID}
2530
2531	// Assign the policies to a token
2532	tokenUpsertReq := structs.ACLTokenSetRequest{
2533		Datacenter: "dc1",
2534		ACLToken: structs.ACLToken{
2535			Policies: []structs.ACLTokenPolicyLink{
2536				{
2537					ID: p1.ID,
2538				},
2539				{
2540					ID: p2.ID,
2541				},
2542			},
2543		},
2544		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2545	}
2546	token := structs.ACLToken{}
2547	err = acl.TokenSet(&tokenUpsertReq, &token)
2548	require.NoError(t, err)
2549	require.NotEmpty(t, token.SecretID)
2550
2551	resp := structs.ACLPolicyBatchResponse{}
2552	req := structs.ACLPolicyBatchGetRequest{
2553		Datacenter:   "dc1",
2554		PolicyIDs:    []string{p1.ID, p2.ID},
2555		QueryOptions: structs.QueryOptions{Token: token.SecretID},
2556	}
2557	err = acl.PolicyResolve(&req, &resp)
2558	require.NoError(t, err)
2559	require.ElementsMatch(t, gatherIDs(t, resp.Policies), policies)
2560}
2561
2562func TestACLEndpoint_RoleRead(t *testing.T) {
2563	if testing.Short() {
2564		t.Skip("too slow for testing.Short")
2565	}
2566
2567	t.Parallel()
2568	_, srv, codec := testACLServerWithConfig(t, nil, false)
2569	waitForLeaderEstablishment(t, srv)
2570
2571	role, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
2572	require.NoError(t, err)
2573
2574	acl := ACL{srv: srv}
2575
2576	req := structs.ACLRoleGetRequest{
2577		Datacenter:   "dc1",
2578		RoleID:       role.ID,
2579		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2580	}
2581
2582	resp := structs.ACLRoleResponse{}
2583
2584	err = acl.RoleRead(&req, &resp)
2585	require.NoError(t, err)
2586	require.Equal(t, role, resp.Role)
2587}
2588
2589func TestACLEndpoint_RoleBatchRead(t *testing.T) {
2590	if testing.Short() {
2591		t.Skip("too slow for testing.Short")
2592	}
2593
2594	t.Parallel()
2595
2596	_, srv, codec := testACLServerWithConfig(t, nil, false)
2597	waitForLeaderEstablishment(t, srv)
2598
2599	r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
2600	require.NoError(t, err)
2601
2602	r2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
2603	require.NoError(t, err)
2604
2605	acl := ACL{srv: srv}
2606	roles := []string{r1.ID, r2.ID}
2607
2608	req := structs.ACLRoleBatchGetRequest{
2609		Datacenter:   "dc1",
2610		RoleIDs:      roles,
2611		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
2612	}
2613
2614	resp := structs.ACLRoleBatchResponse{}
2615
2616	err = acl.RoleBatchRead(&req, &resp)
2617	require.NoError(t, err)
2618	require.ElementsMatch(t, gatherIDs(t, resp.Roles), roles)
2619}
2620
2621func TestACLEndpoint_RoleSet(t *testing.T) {
2622	if testing.Short() {
2623		t.Skip("too slow for testing.Short")
2624	}
2625
2626	t.Parallel()
2627
2628	_, srv, codec := testACLServerWithConfig(t, nil, false)
2629	waitForLeaderEstablishment(t, srv)
2630
2631	acl := ACL{srv: srv}
2632	var roleID string
2633
2634	testPolicy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2635	require.NoError(t, err)
2636	testPolicy2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2637	require.NoError(t, err)
2638
2639	t.Run("Create it", func(t *testing.T) {
2640		req := structs.ACLRoleSetRequest{
2641			Datacenter: "dc1",
2642			Role: structs.ACLRole{
2643				Description: "foobar",
2644				Name:        "baz",
2645				Policies: []structs.ACLRolePolicyLink{
2646					{
2647						ID: testPolicy1.ID,
2648					},
2649				},
2650				NodeIdentities: []*structs.ACLNodeIdentity{
2651					{
2652						NodeName:   "foo",
2653						Datacenter: "bar",
2654					},
2655				},
2656			},
2657			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2658		}
2659		resp := structs.ACLRole{}
2660
2661		err := acl.RoleSet(&req, &resp)
2662		require.NoError(t, err)
2663		require.NotNil(t, resp.ID)
2664
2665		// Get the role directly to validate that it exists
2666		roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID)
2667		require.NoError(t, err)
2668		role := roleResp.Role
2669
2670		require.NotNil(t, role.ID)
2671		require.Equal(t, role.Description, "foobar")
2672		require.Equal(t, role.Name, "baz")
2673		require.Len(t, role.Policies, 1)
2674		require.Equal(t, testPolicy1.ID, role.Policies[0].ID)
2675		require.Len(t, role.NodeIdentities, 1)
2676		require.Equal(t, "foo", role.NodeIdentities[0].NodeName)
2677		require.Equal(t, "bar", role.NodeIdentities[0].Datacenter)
2678
2679		roleID = role.ID
2680	})
2681
2682	t.Run("Update it", func(t *testing.T) {
2683		req := structs.ACLRoleSetRequest{
2684			Datacenter: "dc1",
2685			Role: structs.ACLRole{
2686				ID:          roleID,
2687				Description: "bat",
2688				Name:        "bar",
2689				Policies: []structs.ACLRolePolicyLink{
2690					{
2691						ID: testPolicy2.ID,
2692					},
2693				},
2694			},
2695			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2696		}
2697		resp := structs.ACLRole{}
2698
2699		err := acl.RoleSet(&req, &resp)
2700		require.NoError(t, err)
2701		require.NotNil(t, resp.ID)
2702
2703		// Get the role directly to validate that it exists
2704		roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID)
2705		require.NoError(t, err)
2706		role := roleResp.Role
2707
2708		require.NotNil(t, role.ID)
2709		require.Equal(t, role.Description, "bat")
2710		require.Equal(t, role.Name, "bar")
2711		require.Len(t, role.Policies, 1)
2712		require.Equal(t, testPolicy2.ID, role.Policies[0].ID)
2713		require.Empty(t, role.NodeIdentities)
2714	})
2715
2716	t.Run("Create it using Policies linked by id and name", func(t *testing.T) {
2717		policy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2718		require.NoError(t, err)
2719		policy2, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2720		require.NoError(t, err)
2721
2722		req := structs.ACLRoleSetRequest{
2723			Datacenter: "dc1",
2724			Role: structs.ACLRole{
2725				Description: "foobar",
2726				Name:        "baz",
2727				Policies: []structs.ACLRolePolicyLink{
2728					{
2729						ID: policy1.ID,
2730					},
2731					{
2732						Name: policy2.Name,
2733					},
2734				},
2735			},
2736			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2737		}
2738		resp := structs.ACLRole{}
2739
2740		err = acl.RoleSet(&req, &resp)
2741		require.NoError(t, err)
2742		require.NotNil(t, resp.ID)
2743
2744		// Delete both policies to ensure that we skip resolving ID->Name
2745		// in the returned data.
2746		require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy1.ID))
2747		require.NoError(t, deleteTestPolicy(codec, TestDefaultMasterToken, "dc1", policy2.ID))
2748
2749		// Get the role directly to validate that it exists
2750		roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID)
2751		require.NoError(t, err)
2752		role := roleResp.Role
2753
2754		require.NotNil(t, role.ID)
2755		require.Equal(t, role.Description, "foobar")
2756		require.Equal(t, role.Name, "baz")
2757
2758		require.Len(t, role.Policies, 0)
2759	})
2760
2761	roleNameGen := func(t *testing.T) string {
2762		t.Helper()
2763		name, err := uuid.GenerateUUID()
2764		require.NoError(t, err)
2765		return name
2766	}
2767
2768	t.Run("Create it with invalid service identity (empty)", func(t *testing.T) {
2769		req := structs.ACLRoleSetRequest{
2770			Datacenter: "dc1",
2771			Role: structs.ACLRole{
2772				Description: "foobar",
2773				Name:        roleNameGen(t),
2774				ServiceIdentities: []*structs.ACLServiceIdentity{
2775					{ServiceName: ""},
2776				},
2777			},
2778			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2779		}
2780		resp := structs.ACLRole{}
2781
2782		err := acl.RoleSet(&req, &resp)
2783		testutil.RequireErrorContains(t, err, "Service identity is missing the service name field")
2784	})
2785
2786	t.Run("Create it with invalid service identity (too large)", func(t *testing.T) {
2787		long := strings.Repeat("x", serviceIdentityNameMaxLength+1)
2788		req := structs.ACLRoleSetRequest{
2789			Datacenter: "dc1",
2790			Role: structs.ACLRole{
2791				Description: "foobar",
2792				Name:        roleNameGen(t),
2793				ServiceIdentities: []*structs.ACLServiceIdentity{
2794					{ServiceName: long},
2795				},
2796			},
2797			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2798		}
2799		resp := structs.ACLRole{}
2800
2801		err := acl.RoleSet(&req, &resp)
2802		require.NotNil(t, err)
2803	})
2804
2805	for _, test := range []struct {
2806		name string
2807		ok   bool
2808	}{
2809		{"-abc", false},
2810		{"abc-", false},
2811		{"a-bc", true},
2812		{"_abc", false},
2813		{"abc_", false},
2814		{"a_bc", true},
2815		{":abc", false},
2816		{"abc:", false},
2817		{"a:bc", false},
2818		{"Abc", false},
2819		{"aBc", false},
2820		{"abC", false},
2821		{"0abc", true},
2822		{"abc0", true},
2823		{"a0bc", true},
2824	} {
2825		var testName string
2826		if test.ok {
2827			testName = "Create it with valid service identity (by regex): " + test.name
2828		} else {
2829			testName = "Create it with invalid service identity (by regex): " + test.name
2830		}
2831		t.Run(testName, func(t *testing.T) {
2832			req := structs.ACLRoleSetRequest{
2833				Datacenter: "dc1",
2834				Role: structs.ACLRole{
2835					Description: "foobar",
2836					Name:        roleNameGen(t),
2837					ServiceIdentities: []*structs.ACLServiceIdentity{
2838						{ServiceName: test.name},
2839					},
2840				},
2841				WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2842			}
2843
2844			resp := structs.ACLRole{}
2845
2846			err := acl.RoleSet(&req, &resp)
2847			if test.ok {
2848				require.NoError(t, err)
2849
2850				// Get the token directly to validate that it exists
2851				roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID)
2852				require.NoError(t, err)
2853				role := roleResp.Role
2854				require.ElementsMatch(t, req.Role.ServiceIdentities, role.ServiceIdentities)
2855			} else {
2856				require.NotNil(t, err)
2857			}
2858		})
2859	}
2860
2861	t.Run("Create it with two of the same service identities", func(t *testing.T) {
2862		req := structs.ACLRoleSetRequest{
2863			Datacenter: "dc1",
2864			Role: structs.ACLRole{
2865				Description: "foobar",
2866				Name:        roleNameGen(t),
2867				ServiceIdentities: []*structs.ACLServiceIdentity{
2868					{ServiceName: "example"},
2869					{ServiceName: "example"},
2870				},
2871			},
2872			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2873		}
2874
2875		resp := structs.ACLRole{}
2876
2877		err := acl.RoleSet(&req, &resp)
2878		require.NoError(t, err)
2879
2880		// Get the role directly to validate that it exists
2881		roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID)
2882		require.NoError(t, err)
2883		role := roleResp.Role
2884		require.Len(t, role.ServiceIdentities, 1)
2885	})
2886
2887	t.Run("Create it with two of the same service identities and different DCs", func(t *testing.T) {
2888		req := structs.ACLRoleSetRequest{
2889			Datacenter: "dc1",
2890			Role: structs.ACLRole{
2891				Description: "foobar",
2892				Name:        roleNameGen(t),
2893				ServiceIdentities: []*structs.ACLServiceIdentity{
2894					{
2895						ServiceName: "example",
2896						Datacenters: []string{"dc2", "dc3"},
2897					},
2898					{
2899						ServiceName: "example",
2900						Datacenters: []string{"dc1", "dc2"},
2901					},
2902				},
2903			},
2904			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2905		}
2906
2907		resp := structs.ACLRole{}
2908
2909		err := acl.RoleSet(&req, &resp)
2910		require.NoError(t, err)
2911
2912		// Get the role directly to validate that it exists
2913		roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID)
2914		require.NoError(t, err)
2915		role := roleResp.Role
2916		require.Len(t, role.ServiceIdentities, 1)
2917		svcid := role.ServiceIdentities[0]
2918		require.Equal(t, "example", svcid.ServiceName)
2919		require.ElementsMatch(t, []string{"dc1", "dc2", "dc3"}, svcid.Datacenters)
2920	})
2921
2922	t.Run("invalid node identity - no name", func(t *testing.T) {
2923		req := structs.ACLRoleSetRequest{
2924			Datacenter: "dc1",
2925			Role: structs.ACLRole{
2926				Name: roleNameGen(t),
2927				NodeIdentities: []*structs.ACLNodeIdentity{
2928					{
2929						Datacenter: "dc1",
2930					},
2931				},
2932			},
2933			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2934		}
2935
2936		resp := structs.ACLRole{}
2937
2938		err := acl.RoleSet(&req, &resp)
2939		testutil.RequireErrorContains(t, err, "Node identity is missing the node name field on this role")
2940	})
2941
2942	t.Run("invalid node identity - invalid name", func(t *testing.T) {
2943		req := structs.ACLRoleSetRequest{
2944			Datacenter: "dc1",
2945			Role: structs.ACLRole{
2946				Name: roleNameGen(t),
2947				NodeIdentities: []*structs.ACLNodeIdentity{
2948					{
2949						NodeName:   "foo.bar",
2950						Datacenter: "dc1",
2951					},
2952				},
2953			},
2954			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2955		}
2956
2957		resp := structs.ACLRole{}
2958
2959		err := acl.RoleSet(&req, &resp)
2960		testutil.RequireErrorContains(t, err, "Node identity has an invalid name.")
2961	})
2962	t.Run("invalid node identity - no datacenter", func(t *testing.T) {
2963		req := structs.ACLRoleSetRequest{
2964			Datacenter: "dc1",
2965			Role: structs.ACLRole{
2966				Name: roleNameGen(t),
2967				NodeIdentities: []*structs.ACLNodeIdentity{
2968					{
2969						NodeName: "foo",
2970					},
2971				},
2972			},
2973			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
2974		}
2975
2976		resp := structs.ACLRole{}
2977
2978		err := acl.RoleSet(&req, &resp)
2979		testutil.RequireErrorContains(t, err, "Node identity is missing the datacenter field on this role")
2980	})
2981}
2982
2983func TestACLEndpoint_RoleSet_names(t *testing.T) {
2984	if testing.Short() {
2985		t.Skip("too slow for testing.Short")
2986	}
2987
2988	t.Parallel()
2989
2990	_, srv, codec := testACLServerWithConfig(t, nil, false)
2991	waitForLeaderEstablishment(t, srv)
2992
2993	acl := ACL{srv: srv}
2994	testPolicy1, err := upsertTestPolicy(codec, TestDefaultMasterToken, "dc1")
2995
2996	require.NoError(t, err)
2997
2998	for _, test := range []struct {
2999		name string
3000		ok   bool
3001	}{
3002		{"", false},
3003		{"-bad", true},
3004		{"bad-", true},
3005		{"bad?bad", false},
3006		{strings.Repeat("x", 257), false},
3007		{strings.Repeat("x", 256), true},
3008		{"-abc", true},
3009		{"abc-", true},
3010		{"a-bc", true},
3011		{"_abc", true},
3012		{"abc_", true},
3013		{"a_bc", true},
3014		{":abc", false},
3015		{"abc:", false},
3016		{"a:bc", false},
3017		{"Abc", true},
3018		{"aBc", true},
3019		{"abC", true},
3020		{"0abc", true},
3021		{"abc0", true},
3022		{"a0bc", true},
3023	} {
3024		var testName string
3025		if test.ok {
3026			testName = "create with valid name: " + test.name
3027		} else {
3028			testName = "create with invalid name: " + test.name
3029		}
3030
3031		t.Run(testName, func(t *testing.T) {
3032			// cleanup from a prior insertion that may have succeeded
3033			require.NoError(t, deleteTestRoleByName(codec, TestDefaultMasterToken, "dc1", test.name))
3034
3035			req := structs.ACLRoleSetRequest{
3036				Datacenter: "dc1",
3037				Role: structs.ACLRole{
3038					Name:        test.name,
3039					Description: "foobar",
3040					Policies: []structs.ACLRolePolicyLink{
3041						{
3042							ID: testPolicy1.ID,
3043						},
3044					},
3045				},
3046				WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3047			}
3048			resp := structs.ACLRole{}
3049
3050			err := acl.RoleSet(&req, &resp)
3051			if test.ok {
3052				require.NoError(t, err)
3053
3054				roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", resp.ID)
3055				require.NoError(t, err)
3056				role := roleResp.Role
3057				require.Equal(t, test.name, role.Name)
3058			} else {
3059				require.Error(t, err)
3060			}
3061		})
3062	}
3063}
3064
3065func TestACLEndpoint_RoleDelete(t *testing.T) {
3066	if testing.Short() {
3067		t.Skip("too slow for testing.Short")
3068	}
3069
3070	t.Parallel()
3071
3072	_, srv, codec := testACLServerWithConfig(t, nil, false)
3073	waitForLeaderEstablishment(t, srv)
3074	existingRole, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
3075
3076	require.NoError(t, err)
3077
3078	acl := ACL{srv: srv}
3079
3080	req := structs.ACLRoleDeleteRequest{
3081		Datacenter:   "dc1",
3082		RoleID:       existingRole.ID,
3083		WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3084	}
3085
3086	var resp string
3087
3088	err = acl.RoleDelete(&req, &resp)
3089	require.NoError(t, err)
3090
3091	// Make sure the role is gone
3092	roleResp, err := retrieveTestRole(codec, TestDefaultMasterToken, "dc1", existingRole.ID)
3093	require.NoError(t, err)
3094	require.Nil(t, roleResp.Role)
3095}
3096
3097func TestACLEndpoint_RoleList(t *testing.T) {
3098	if testing.Short() {
3099		t.Skip("too slow for testing.Short")
3100	}
3101
3102	t.Parallel()
3103
3104	_, srv, codec := testACLServerWithConfig(t, nil, false)
3105	waitForLeaderEstablishment(t, srv)
3106
3107	r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
3108	require.NoError(t, err)
3109
3110	r2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
3111	require.NoError(t, err)
3112
3113	acl := ACL{srv: srv}
3114
3115	req := structs.ACLRoleListRequest{
3116		Datacenter:   "dc1",
3117		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
3118	}
3119
3120	resp := structs.ACLRoleListResponse{}
3121
3122	err = acl.RoleList(&req, &resp)
3123	require.NoError(t, err)
3124	require.ElementsMatch(t, gatherIDs(t, resp.Roles), []string{r1.ID, r2.ID})
3125}
3126
3127func TestACLEndpoint_RoleResolve(t *testing.T) {
3128	if testing.Short() {
3129		t.Skip("too slow for testing.Short")
3130	}
3131
3132	t.Parallel()
3133
3134	_, srv, codec := testACLServerWithConfig(t, nil, false)
3135	waitForLeaderEstablishment(t, srv)
3136
3137	t.Run("Normal", func(t *testing.T) {
3138		r1, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
3139		require.NoError(t, err)
3140
3141		r2, err := upsertTestRole(codec, TestDefaultMasterToken, "dc1")
3142		require.NoError(t, err)
3143
3144		acl := ACL{srv: srv}
3145
3146		// Assign the roles to a token
3147		tokenUpsertReq := structs.ACLTokenSetRequest{
3148			Datacenter: "dc1",
3149			ACLToken: structs.ACLToken{
3150				Roles: []structs.ACLTokenRoleLink{
3151					{
3152						ID: r1.ID,
3153					},
3154					{
3155						ID: r2.ID,
3156					},
3157				},
3158			},
3159			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3160		}
3161		token := structs.ACLToken{}
3162		err = acl.TokenSet(&tokenUpsertReq, &token)
3163		require.NoError(t, err)
3164		require.NotEmpty(t, token.SecretID)
3165
3166		resp := structs.ACLRoleBatchResponse{}
3167		req := structs.ACLRoleBatchGetRequest{
3168			Datacenter:   "dc1",
3169			RoleIDs:      []string{r1.ID, r2.ID},
3170			QueryOptions: structs.QueryOptions{Token: token.SecretID},
3171		}
3172		err = acl.RoleResolve(&req, &resp)
3173		require.NoError(t, err)
3174		require.ElementsMatch(t, gatherIDs(t, resp.Roles), []string{r1.ID, r2.ID})
3175	})
3176}
3177
3178func TestACLEndpoint_AuthMethodSet(t *testing.T) {
3179	if testing.Short() {
3180		t.Skip("too slow for testing.Short")
3181	}
3182
3183	t.Parallel()
3184
3185	tempDir, err := ioutil.TempDir("", "consul")
3186	require.NoError(t, err)
3187	t.Cleanup(func() { os.RemoveAll(tempDir) })
3188	_, srv, codec := testACLServerWithConfig(t, nil, false)
3189
3190	waitForLeaderEstablishment(t, srv)
3191
3192	acl := ACL{srv: srv}
3193
3194	newAuthMethod := func(name string) structs.ACLAuthMethod {
3195		return structs.ACLAuthMethod{
3196			Name:        name,
3197			Description: "test",
3198			Type:        "testing",
3199		}
3200	}
3201
3202	t.Run("Create", func(t *testing.T) {
3203		reqMethod := newAuthMethod("test")
3204
3205		req := structs.ACLAuthMethodSetRequest{
3206			Datacenter:   "dc1",
3207			AuthMethod:   reqMethod,
3208			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3209		}
3210		resp := structs.ACLAuthMethod{}
3211
3212		err := acl.AuthMethodSet(&req, &resp)
3213		require.NoError(t, err)
3214
3215		// Get the method directly to validate that it exists
3216		methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name)
3217		require.NoError(t, err)
3218		method := methodResp.AuthMethod
3219
3220		require.Equal(t, method.Name, "test")
3221		require.Equal(t, method.Description, "test")
3222		require.Equal(t, method.Type, "testing")
3223	})
3224
3225	t.Run("Update fails; not allowed to change types", func(t *testing.T) {
3226		reqMethod := newAuthMethod("test")
3227		reqMethod.Type = "invalid"
3228
3229		req := structs.ACLAuthMethodSetRequest{
3230			Datacenter:   "dc1",
3231			AuthMethod:   reqMethod,
3232			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3233		}
3234		resp := structs.ACLAuthMethod{}
3235
3236		err := acl.AuthMethodSet(&req, &resp)
3237		require.Error(t, err)
3238	})
3239
3240	t.Run("Update - allow type to default", func(t *testing.T) {
3241		reqMethod := newAuthMethod("test")
3242		reqMethod.DisplayName = "updated display name 1"
3243		reqMethod.Description = "test modified 1"
3244		reqMethod.Type = "" // unset
3245
3246		req := structs.ACLAuthMethodSetRequest{
3247			Datacenter:   "dc1",
3248			AuthMethod:   reqMethod,
3249			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3250		}
3251		resp := structs.ACLAuthMethod{}
3252
3253		err := acl.AuthMethodSet(&req, &resp)
3254		require.NoError(t, err)
3255
3256		// Get the method directly to validate that it exists
3257		methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name)
3258		require.NoError(t, err)
3259		method := methodResp.AuthMethod
3260
3261		require.Equal(t, method.Name, "test")
3262		require.Equal(t, method.DisplayName, "updated display name 1")
3263		require.Equal(t, method.Description, "test modified 1")
3264		require.Equal(t, method.Type, "testing")
3265	})
3266
3267	t.Run("Update - specify type", func(t *testing.T) {
3268		reqMethod := newAuthMethod("test")
3269		reqMethod.DisplayName = "updated display name 2"
3270		reqMethod.Description = "test modified 2"
3271
3272		req := structs.ACLAuthMethodSetRequest{
3273			Datacenter:   "dc1",
3274			AuthMethod:   reqMethod,
3275			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3276		}
3277		resp := structs.ACLAuthMethod{}
3278
3279		err := acl.AuthMethodSet(&req, &resp)
3280		require.NoError(t, err)
3281
3282		// Get the method directly to validate that it exists
3283		methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name)
3284		require.NoError(t, err)
3285		method := methodResp.AuthMethod
3286
3287		require.Equal(t, method.Name, "test")
3288		require.Equal(t, method.DisplayName, "updated display name 2")
3289		require.Equal(t, method.Description, "test modified 2")
3290		require.Equal(t, method.Type, "testing")
3291	})
3292
3293	t.Run("Create with no name", func(t *testing.T) {
3294		req := structs.ACLAuthMethodSetRequest{
3295			Datacenter:   "dc1",
3296			AuthMethod:   newAuthMethod(""),
3297			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3298		}
3299		resp := structs.ACLAuthMethod{}
3300
3301		err := acl.AuthMethodSet(&req, &resp)
3302		require.Error(t, err)
3303	})
3304
3305	t.Run("Create with invalid type", func(t *testing.T) {
3306		req := structs.ACLAuthMethodSetRequest{
3307			Datacenter: "dc1",
3308			AuthMethod: structs.ACLAuthMethod{
3309				Name:        "invalid",
3310				Description: "invalid test",
3311				Type:        "invalid",
3312			},
3313			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3314		}
3315		resp := structs.ACLAuthMethod{}
3316
3317		err := acl.AuthMethodSet(&req, &resp)
3318		require.Error(t, err)
3319	})
3320
3321	for _, test := range []struct {
3322		name string
3323		ok   bool
3324	}{
3325		{strings.Repeat("x", 129), false},
3326		{strings.Repeat("x", 128), true},
3327		{"-abc", true},
3328		{"abc-", true},
3329		{"a-bc", true},
3330		{"_abc", true},
3331		{"abc_", true},
3332		{"a_bc", true},
3333		{":abc", false},
3334		{"abc:", false},
3335		{"a:bc", false},
3336		{"Abc", true},
3337		{"aBc", true},
3338		{"abC", true},
3339		{"0abc", true},
3340		{"abc0", true},
3341		{"a0bc", true},
3342	} {
3343		var testName string
3344		if test.ok {
3345			testName = "Create with valid name (by regex): " + test.name
3346		} else {
3347			testName = "Create with invalid name (by regex): " + test.name
3348		}
3349		t.Run(testName, func(t *testing.T) {
3350			req := structs.ACLAuthMethodSetRequest{
3351				Datacenter:   "dc1",
3352				AuthMethod:   newAuthMethod(test.name),
3353				WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3354			}
3355			resp := structs.ACLAuthMethod{}
3356
3357			err := acl.AuthMethodSet(&req, &resp)
3358
3359			if test.ok {
3360				require.NoError(t, err)
3361
3362				// Get the method directly to validate that it exists
3363				methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name)
3364				require.NoError(t, err)
3365				method := methodResp.AuthMethod
3366
3367				require.Equal(t, method.Name, test.name)
3368				require.Equal(t, method.Type, "testing")
3369			} else {
3370				require.Error(t, err)
3371			}
3372		})
3373	}
3374
3375	t.Run("Create with MaxTokenTTL", func(t *testing.T) {
3376		reqMethod := newAuthMethod("test")
3377		reqMethod.MaxTokenTTL = 5 * time.Minute
3378
3379		req := structs.ACLAuthMethodSetRequest{
3380			Datacenter:   "dc1",
3381			AuthMethod:   reqMethod,
3382			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3383		}
3384		resp := structs.ACLAuthMethod{}
3385
3386		err := acl.AuthMethodSet(&req, &resp)
3387		require.NoError(t, err)
3388
3389		// Get the method directly to validate that it exists
3390		methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name)
3391		require.NoError(t, err)
3392		method := methodResp.AuthMethod
3393
3394		require.Equal(t, method.Name, "test")
3395		require.Equal(t, method.Description, "test")
3396		require.Equal(t, method.Type, "testing")
3397		require.Equal(t, method.MaxTokenTTL, 5*time.Minute)
3398	})
3399
3400	t.Run("Update - change MaxTokenTTL", func(t *testing.T) {
3401		reqMethod := newAuthMethod("test")
3402		reqMethod.DisplayName = "updated display name 2"
3403		reqMethod.Description = "test modified 2"
3404		reqMethod.MaxTokenTTL = 8 * time.Minute
3405
3406		req := structs.ACLAuthMethodSetRequest{
3407			Datacenter:   "dc1",
3408			AuthMethod:   reqMethod,
3409			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3410		}
3411		resp := structs.ACLAuthMethod{}
3412
3413		err := acl.AuthMethodSet(&req, &resp)
3414		require.NoError(t, err)
3415
3416		// Get the method directly to validate that it exists
3417		methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", resp.Name)
3418		require.NoError(t, err)
3419		method := methodResp.AuthMethod
3420
3421		require.Equal(t, method.Name, "test")
3422		require.Equal(t, method.DisplayName, "updated display name 2")
3423		require.Equal(t, method.Description, "test modified 2")
3424		require.Equal(t, method.Type, "testing")
3425		require.Equal(t, method.MaxTokenTTL, 8*time.Minute)
3426	})
3427
3428	t.Run("Create with MaxTokenTTL too small", func(t *testing.T) {
3429		reqMethod := newAuthMethod("test")
3430		reqMethod.MaxTokenTTL = 1 * time.Millisecond
3431
3432		req := structs.ACLAuthMethodSetRequest{
3433			Datacenter:   "dc1",
3434			AuthMethod:   reqMethod,
3435			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3436		}
3437		resp := structs.ACLAuthMethod{}
3438
3439		err := acl.AuthMethodSet(&req, &resp)
3440		testutil.RequireErrorContains(t, err, "MaxTokenTTL 1ms cannot be less than")
3441	})
3442
3443	t.Run("Create with MaxTokenTTL too big", func(t *testing.T) {
3444		reqMethod := newAuthMethod("test")
3445		reqMethod.MaxTokenTTL = 25 * time.Hour
3446
3447		req := structs.ACLAuthMethodSetRequest{
3448			Datacenter:   "dc1",
3449			AuthMethod:   reqMethod,
3450			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3451		}
3452		resp := structs.ACLAuthMethod{}
3453
3454		err := acl.AuthMethodSet(&req, &resp)
3455		testutil.RequireErrorContains(t, err, "MaxTokenTTL 25h0m0s cannot be more than")
3456	})
3457}
3458
3459func TestACLEndpoint_AuthMethodDelete(t *testing.T) {
3460	if testing.Short() {
3461		t.Skip("too slow for testing.Short")
3462	}
3463
3464	t.Parallel()
3465
3466	_, srv, codec := testACLServerWithConfig(t, nil, false)
3467	waitForLeaderEstablishment(t, srv)
3468
3469	testSessionID := testauth.StartSession()
3470	defer testauth.ResetSession(testSessionID)
3471
3472	existingMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID)
3473	require.NoError(t, err)
3474
3475	acl := ACL{srv: srv}
3476
3477	t.Run("normal", func(t *testing.T) {
3478		req := structs.ACLAuthMethodDeleteRequest{
3479			Datacenter:     "dc1",
3480			AuthMethodName: existingMethod.Name,
3481			WriteRequest:   structs.WriteRequest{Token: TestDefaultMasterToken},
3482		}
3483
3484		var ignored bool
3485		err = acl.AuthMethodDelete(&req, &ignored)
3486		require.NoError(t, err)
3487
3488		// Make sure the method is gone
3489		methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", existingMethod.Name)
3490		require.NoError(t, err)
3491		require.Nil(t, methodResp.AuthMethod)
3492	})
3493
3494	t.Run("delete something that doesn't exist", func(t *testing.T) {
3495		req := structs.ACLAuthMethodDeleteRequest{
3496			Datacenter:     "dc1",
3497			AuthMethodName: "missing",
3498			WriteRequest:   structs.WriteRequest{Token: TestDefaultMasterToken},
3499		}
3500
3501		var ignored bool
3502		err = acl.AuthMethodDelete(&req, &ignored)
3503		require.NoError(t, err)
3504	})
3505}
3506
3507// Deleting an auth method atomically deletes all rules and tokens as well.
3508func TestACLEndpoint_AuthMethodDelete_RuleAndTokenCascade(t *testing.T) {
3509	if testing.Short() {
3510		t.Skip("too slow for testing.Short")
3511	}
3512
3513	t.Parallel()
3514
3515	_, srv, codec := testACLServerWithConfig(t, nil, false)
3516	waitForLeaderEstablishment(t, srv)
3517
3518	testSessionID1 := testauth.StartSession()
3519	defer testauth.ResetSession(testSessionID1)
3520	testauth.InstallSessionToken(testSessionID1, "fake-token1", "default", "abc", "abc123")
3521
3522	testSessionID2 := testauth.StartSession()
3523	defer testauth.ResetSession(testSessionID2)
3524	testauth.InstallSessionToken(testSessionID2, "fake-token2", "default", "abc", "abc123")
3525
3526	createToken := func(methodName, bearerToken string) *structs.ACLToken {
3527		acl := ACL{srv: srv}
3528
3529		resp := structs.ACLToken{}
3530
3531		require.NoError(t, acl.Login(&structs.ACLLoginRequest{
3532			Auth: &structs.ACLLoginParams{
3533				AuthMethod:  methodName,
3534				BearerToken: bearerToken,
3535			},
3536			Datacenter: "dc1",
3537		}, &resp))
3538
3539		return &resp
3540	}
3541
3542	method1, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID1)
3543	require.NoError(t, err)
3544	i1_r1, err := upsertTestBindingRule(
3545		codec, TestDefaultMasterToken, "dc1",
3546		method1.Name,
3547		"serviceaccount.name==abc",
3548		structs.BindingRuleBindTypeService,
3549		"abc",
3550	)
3551	require.NoError(t, err)
3552	i1_r2, err := upsertTestBindingRule(
3553		codec, TestDefaultMasterToken, "dc1",
3554		method1.Name,
3555		"serviceaccount.name==def",
3556		structs.BindingRuleBindTypeService,
3557		"def",
3558	)
3559	require.NoError(t, err)
3560	i1_t1 := createToken(method1.Name, "fake-token1")
3561	i1_t2 := createToken(method1.Name, "fake-token1")
3562
3563	method2, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID2)
3564	require.NoError(t, err)
3565	i2_r1, err := upsertTestBindingRule(
3566		codec, TestDefaultMasterToken, "dc1",
3567		method2.Name,
3568		"serviceaccount.name==abc",
3569		structs.BindingRuleBindTypeService,
3570		"abc",
3571	)
3572	require.NoError(t, err)
3573	i2_r2, err := upsertTestBindingRule(
3574		codec, TestDefaultMasterToken, "dc1",
3575		method2.Name,
3576		"serviceaccount.name==def",
3577		structs.BindingRuleBindTypeService,
3578		"def",
3579	)
3580	require.NoError(t, err)
3581	i2_t1 := createToken(method2.Name, "fake-token2")
3582	i2_t2 := createToken(method2.Name, "fake-token2")
3583
3584	acl := ACL{srv: srv}
3585
3586	req := structs.ACLAuthMethodDeleteRequest{
3587		Datacenter:     "dc1",
3588		AuthMethodName: method1.Name,
3589		WriteRequest:   structs.WriteRequest{Token: TestDefaultMasterToken},
3590	}
3591
3592	var ignored bool
3593	err = acl.AuthMethodDelete(&req, &ignored)
3594	require.NoError(t, err)
3595
3596	// Make sure the method is gone.
3597	methodResp, err := retrieveTestAuthMethod(codec, TestDefaultMasterToken, "dc1", method1.Name)
3598	require.NoError(t, err)
3599	require.Nil(t, methodResp.AuthMethod)
3600
3601	// Make sure the rules and tokens are gone.
3602	for _, id := range []string{i1_r1.ID, i1_r2.ID} {
3603		ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", id)
3604		require.NoError(t, err)
3605		require.Nil(t, ruleResp.BindingRule)
3606	}
3607	for _, id := range []string{i1_t1.AccessorID, i1_t2.AccessorID} {
3608		tokResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", id)
3609		require.NoError(t, err)
3610		require.Nil(t, tokResp.Token)
3611	}
3612
3613	// Make sure the rules and tokens for the untouched auth method are still there.
3614	for _, id := range []string{i2_r1.ID, i2_r2.ID} {
3615		ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", id)
3616		require.NoError(t, err)
3617		require.NotNil(t, ruleResp.BindingRule)
3618	}
3619	for _, id := range []string{i2_t1.AccessorID, i2_t2.AccessorID} {
3620		tokResp, err := retrieveTestToken(codec, TestDefaultMasterToken, "dc1", id)
3621		require.NoError(t, err)
3622		require.NotNil(t, tokResp.Token)
3623	}
3624}
3625
3626func TestACLEndpoint_AuthMethodList(t *testing.T) {
3627	if testing.Short() {
3628		t.Skip("too slow for testing.Short")
3629	}
3630
3631	t.Parallel()
3632
3633	_, srv, codec := testACLServerWithConfig(t, nil, false)
3634	waitForLeaderEstablishment(t, srv)
3635
3636	i1, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "")
3637	require.NoError(t, err)
3638
3639	i2, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "")
3640	require.NoError(t, err)
3641
3642	acl := ACL{srv: srv}
3643
3644	req := structs.ACLAuthMethodListRequest{
3645		Datacenter:   "dc1",
3646		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
3647	}
3648
3649	resp := structs.ACLAuthMethodListResponse{}
3650
3651	err = acl.AuthMethodList(&req, &resp)
3652	require.NoError(t, err)
3653	require.ElementsMatch(t, gatherIDs(t, resp.AuthMethods), []string{i1.Name, i2.Name})
3654}
3655
3656func TestACLEndpoint_BindingRuleSet(t *testing.T) {
3657	if testing.Short() {
3658		t.Skip("too slow for testing.Short")
3659	}
3660
3661	t.Parallel()
3662
3663	_, srv, codec := testACLServerWithConfig(t, nil, false)
3664	waitForLeaderEstablishment(t, srv)
3665	acl := ACL{srv: srv}
3666
3667	var ruleID string
3668
3669	testAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "")
3670	require.NoError(t, err)
3671
3672	otherTestAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "")
3673	require.NoError(t, err)
3674
3675	newRule := func() structs.ACLBindingRule {
3676		return structs.ACLBindingRule{
3677			Description: "foobar",
3678			AuthMethod:  testAuthMethod.Name,
3679			Selector:    "serviceaccount.name==abc",
3680			BindType:    structs.BindingRuleBindTypeService,
3681			BindName:    "abc",
3682		}
3683	}
3684
3685	requireSetErrors := func(t *testing.T, reqRule structs.ACLBindingRule) {
3686		req := structs.ACLBindingRuleSetRequest{
3687			Datacenter:   "dc1",
3688			BindingRule:  reqRule,
3689			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3690		}
3691		resp := structs.ACLBindingRule{}
3692
3693		err := acl.BindingRuleSet(&req, &resp)
3694		require.Error(t, err)
3695	}
3696
3697	requireOK := func(t *testing.T, reqRule structs.ACLBindingRule) *structs.ACLBindingRule {
3698		req := structs.ACLBindingRuleSetRequest{
3699			Datacenter:   "dc1",
3700			BindingRule:  reqRule,
3701			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3702		}
3703		resp := structs.ACLBindingRule{}
3704
3705		err := acl.BindingRuleSet(&req, &resp)
3706		require.NoError(t, err)
3707		require.NotEmpty(t, resp.ID)
3708		return &resp
3709	}
3710
3711	t.Run("Create it", func(t *testing.T) {
3712		reqRule := newRule()
3713
3714		req := structs.ACLBindingRuleSetRequest{
3715			Datacenter:   "dc1",
3716			BindingRule:  reqRule,
3717			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3718		}
3719		resp := structs.ACLBindingRule{}
3720
3721		err := acl.BindingRuleSet(&req, &resp)
3722		require.NoError(t, err)
3723		require.NotNil(t, resp.ID)
3724
3725		// Get the rule directly to validate that it exists
3726		ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID)
3727		require.NoError(t, err)
3728		rule := ruleResp.BindingRule
3729
3730		require.NotEmpty(t, rule.ID)
3731		require.Equal(t, rule.Description, "foobar")
3732		require.Equal(t, rule.AuthMethod, testAuthMethod.Name)
3733		require.Equal(t, "serviceaccount.name==abc", rule.Selector)
3734		require.Equal(t, structs.BindingRuleBindTypeService, rule.BindType)
3735		require.Equal(t, "abc", rule.BindName)
3736
3737		ruleID = rule.ID
3738	})
3739
3740	t.Run("Bind Node", func(t *testing.T) {
3741		req := structs.ACLBindingRuleSetRequest{
3742			Datacenter: "dc1",
3743			BindingRule: structs.ACLBindingRule{
3744				Description: "foobar",
3745				AuthMethod:  testAuthMethod.Name,
3746				Selector:    "serviceaccount.name==abc",
3747				BindType:    structs.BindingRuleBindTypeNode,
3748				BindName:    "test-node",
3749			},
3750			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3751		}
3752		var resp structs.ACLBindingRule
3753
3754		err := acl.BindingRuleSet(&req, &resp)
3755		require.NoError(t, err)
3756		require.NotNil(t, resp.ID)
3757
3758		// Get the rule directly to validate that it exists
3759		ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID)
3760		require.NoError(t, err)
3761		rule := ruleResp.BindingRule
3762
3763		require.NotEmpty(t, rule.ID)
3764		require.Equal(t, rule.Description, "foobar")
3765		require.Equal(t, rule.AuthMethod, testAuthMethod.Name)
3766		require.Equal(t, "serviceaccount.name==abc", rule.Selector)
3767		require.Equal(t, structs.BindingRuleBindTypeNode, rule.BindType)
3768		require.Equal(t, "test-node", rule.BindName)
3769	})
3770
3771	t.Run("Update fails; cannot change method name", func(t *testing.T) {
3772		reqRule := newRule()
3773		reqRule.ID = ruleID
3774		reqRule.AuthMethod = otherTestAuthMethod.Name
3775		requireSetErrors(t, reqRule)
3776	})
3777
3778	t.Run("Update it - omit method name", func(t *testing.T) {
3779		reqRule := newRule()
3780		reqRule.ID = ruleID
3781		reqRule.Description = "foobar modified 1"
3782		reqRule.Selector = "serviceaccount.namespace==def"
3783		reqRule.BindType = structs.BindingRuleBindTypeRole
3784		reqRule.BindName = "def"
3785		reqRule.AuthMethod = "" // clear
3786
3787		req := structs.ACLBindingRuleSetRequest{
3788			Datacenter:   "dc1",
3789			BindingRule:  reqRule,
3790			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3791		}
3792		resp := structs.ACLBindingRule{}
3793
3794		err := acl.BindingRuleSet(&req, &resp)
3795		require.NoError(t, err)
3796		require.NotNil(t, resp.ID)
3797
3798		// Get the rule directly to validate that it exists
3799		ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID)
3800		require.NoError(t, err)
3801		rule := ruleResp.BindingRule
3802
3803		require.NotEmpty(t, rule.ID)
3804		require.Equal(t, rule.Description, "foobar modified 1")
3805		require.Equal(t, rule.AuthMethod, testAuthMethod.Name)
3806		require.Equal(t, "serviceaccount.namespace==def", rule.Selector)
3807		require.Equal(t, structs.BindingRuleBindTypeRole, rule.BindType)
3808		require.Equal(t, "def", rule.BindName)
3809	})
3810
3811	t.Run("Update it - specify method name", func(t *testing.T) {
3812		reqRule := newRule()
3813		reqRule.ID = ruleID
3814		reqRule.Description = "foobar modified 2"
3815		reqRule.Selector = "serviceaccount.namespace==def"
3816		reqRule.BindType = structs.BindingRuleBindTypeRole
3817		reqRule.BindName = "def"
3818
3819		req := structs.ACLBindingRuleSetRequest{
3820			Datacenter:   "dc1",
3821			BindingRule:  reqRule,
3822			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
3823		}
3824		resp := structs.ACLBindingRule{}
3825
3826		err := acl.BindingRuleSet(&req, &resp)
3827		require.NoError(t, err)
3828		require.NotNil(t, resp.ID)
3829
3830		// Get the rule directly to validate that it exists
3831		ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", resp.ID)
3832		require.NoError(t, err)
3833		rule := ruleResp.BindingRule
3834
3835		require.NotEmpty(t, rule.ID)
3836		require.Equal(t, rule.Description, "foobar modified 2")
3837		require.Equal(t, rule.AuthMethod, testAuthMethod.Name)
3838		require.Equal(t, "serviceaccount.namespace==def", rule.Selector)
3839		require.Equal(t, structs.BindingRuleBindTypeRole, rule.BindType)
3840		require.Equal(t, "def", rule.BindName)
3841	})
3842
3843	t.Run("Create fails; empty method name", func(t *testing.T) {
3844		reqRule := newRule()
3845		reqRule.AuthMethod = ""
3846		requireSetErrors(t, reqRule)
3847	})
3848
3849	t.Run("Create fails; unknown method name", func(t *testing.T) {
3850		reqRule := newRule()
3851		reqRule.AuthMethod = "unknown"
3852		requireSetErrors(t, reqRule)
3853	})
3854
3855	t.Run("Create with no explicit selector", func(t *testing.T) {
3856		reqRule := newRule()
3857		reqRule.Selector = ""
3858
3859		rule := requireOK(t, reqRule)
3860		require.Empty(t, rule.Selector, 0)
3861	})
3862
3863	t.Run("Create fails; match selector with unknown vars", func(t *testing.T) {
3864		reqRule := newRule()
3865		reqRule.Selector = "serviceaccount.name==a and serviceaccount.bizarroname==b"
3866		requireSetErrors(t, reqRule)
3867	})
3868
3869	t.Run("Create fails; match selector invalid", func(t *testing.T) {
3870		reqRule := newRule()
3871		reqRule.Selector = "serviceaccount.name"
3872		requireSetErrors(t, reqRule)
3873	})
3874
3875	t.Run("Create fails; empty bind type", func(t *testing.T) {
3876		reqRule := newRule()
3877		reqRule.BindType = ""
3878		requireSetErrors(t, reqRule)
3879	})
3880
3881	t.Run("Create fails; empty bind name", func(t *testing.T) {
3882		reqRule := newRule()
3883		reqRule.BindName = ""
3884		requireSetErrors(t, reqRule)
3885	})
3886
3887	t.Run("Create fails; invalid bind type", func(t *testing.T) {
3888		reqRule := newRule()
3889		reqRule.BindType = "invalid"
3890		requireSetErrors(t, reqRule)
3891	})
3892
3893	t.Run("Create fails; bind name with unknown vars", func(t *testing.T) {
3894		reqRule := newRule()
3895		reqRule.BindName = "method-${serviceaccount.bizarroname}"
3896		requireSetErrors(t, reqRule)
3897	})
3898
3899	t.Run("Create fails; invalid bind name no template", func(t *testing.T) {
3900		reqRule := newRule()
3901		reqRule.BindName = "-abc:"
3902		requireSetErrors(t, reqRule)
3903	})
3904
3905	t.Run("Create fails; invalid bind name with template", func(t *testing.T) {
3906		reqRule := newRule()
3907		reqRule.BindName = "method-${serviceaccount.name"
3908		requireSetErrors(t, reqRule)
3909	})
3910	t.Run("Create fails; invalid bind name after template computed", func(t *testing.T) {
3911		reqRule := newRule()
3912		reqRule.BindName = "method-${serviceaccount.name}:blah-"
3913		requireSetErrors(t, reqRule)
3914	})
3915}
3916
3917func TestACLEndpoint_BindingRuleDelete(t *testing.T) {
3918	if testing.Short() {
3919		t.Skip("too slow for testing.Short")
3920	}
3921
3922	t.Parallel()
3923
3924	_, srv, codec := testACLServerWithConfig(t, nil, false)
3925	waitForLeaderEstablishment(t, srv)
3926
3927	testAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "")
3928	require.NoError(t, err)
3929
3930	existingRule, err := upsertTestBindingRule(
3931		codec, TestDefaultMasterToken, "dc1",
3932		testAuthMethod.Name,
3933		"serviceaccount.name==abc",
3934		structs.BindingRuleBindTypeService,
3935		"abc",
3936	)
3937	require.NoError(t, err)
3938
3939	acl := ACL{srv: srv}
3940
3941	t.Run("normal", func(t *testing.T) {
3942		req := structs.ACLBindingRuleDeleteRequest{
3943			Datacenter:    "dc1",
3944			BindingRuleID: existingRule.ID,
3945			WriteRequest:  structs.WriteRequest{Token: TestDefaultMasterToken},
3946		}
3947
3948		var ignored bool
3949		err = acl.BindingRuleDelete(&req, &ignored)
3950		require.NoError(t, err)
3951
3952		// Make sure the rule is gone
3953		ruleResp, err := retrieveTestBindingRule(codec, TestDefaultMasterToken, "dc1", existingRule.ID)
3954		require.NoError(t, err)
3955		require.Nil(t, ruleResp.BindingRule)
3956	})
3957
3958	t.Run("delete something that doesn't exist", func(t *testing.T) {
3959		fakeID, err := uuid.GenerateUUID()
3960		require.NoError(t, err)
3961
3962		req := structs.ACLBindingRuleDeleteRequest{
3963			Datacenter:    "dc1",
3964			BindingRuleID: fakeID,
3965			WriteRequest:  structs.WriteRequest{Token: TestDefaultMasterToken},
3966		}
3967
3968		var ignored bool
3969		err = acl.BindingRuleDelete(&req, &ignored)
3970		require.NoError(t, err)
3971	})
3972}
3973
3974func TestACLEndpoint_BindingRuleList(t *testing.T) {
3975	if testing.Short() {
3976		t.Skip("too slow for testing.Short")
3977	}
3978
3979	t.Parallel()
3980
3981	_, srv, codec := testACLServerWithConfig(t, nil, false)
3982	waitForLeaderEstablishment(t, srv)
3983
3984	testAuthMethod, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", "")
3985	require.NoError(t, err)
3986
3987	r1, err := upsertTestBindingRule(
3988		codec, TestDefaultMasterToken, "dc1",
3989		testAuthMethod.Name,
3990		"serviceaccount.name==abc",
3991		structs.BindingRuleBindTypeService,
3992		"abc",
3993	)
3994	require.NoError(t, err)
3995
3996	r2, err := upsertTestBindingRule(
3997		codec, TestDefaultMasterToken, "dc1",
3998		testAuthMethod.Name,
3999		"serviceaccount.name==def",
4000		structs.BindingRuleBindTypeService,
4001		"def",
4002	)
4003	require.NoError(t, err)
4004
4005	acl := ACL{srv: srv}
4006
4007	req := structs.ACLBindingRuleListRequest{
4008		Datacenter:   "dc1",
4009		QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
4010	}
4011
4012	resp := structs.ACLBindingRuleListResponse{}
4013
4014	err = acl.BindingRuleList(&req, &resp)
4015	require.NoError(t, err)
4016	require.ElementsMatch(t, gatherIDs(t, resp.BindingRules), []string{r1.ID, r2.ID})
4017}
4018
4019func TestACLEndpoint_SecureIntroEndpoints_LocalTokensDisabled(t *testing.T) {
4020	if testing.Short() {
4021		t.Skip("too slow for testing.Short")
4022	}
4023
4024	t.Parallel()
4025
4026	_, s1, _ := testACLServerWithConfig(t, func(c *Config) {
4027		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
4028		c.ACLTokenMaxExpirationTTL = 5 * time.Second
4029	}, false)
4030	waitForLeaderEstablishment(t, s1)
4031
4032	_, s2, _ := testACLServerWithConfig(t, func(c *Config) {
4033		c.Datacenter = "dc2"
4034		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
4035		c.ACLTokenMaxExpirationTTL = 5 * time.Second
4036		// disable local tokens
4037		c.ACLTokenReplication = false
4038	}, true)
4039	waitForLeaderEstablishment(t, s2)
4040
4041	// Try to join
4042	joinWAN(t, s2, s1)
4043
4044	waitForNewACLs(t, s1)
4045	waitForNewACLs(t, s2)
4046
4047	acl2 := ACL{srv: s2}
4048	var ignored bool
4049
4050	errString := errAuthMethodsRequireTokenReplication.Error()
4051
4052	t.Run("AuthMethodRead", func(t *testing.T) {
4053		testutil.RequireErrorContains(t,
4054			acl2.AuthMethodRead(&structs.ACLAuthMethodGetRequest{Datacenter: "dc2"},
4055				&structs.ACLAuthMethodResponse{}),
4056			errString,
4057		)
4058	})
4059	t.Run("AuthMethodSet", func(t *testing.T) {
4060		testutil.RequireErrorContains(t,
4061			acl2.AuthMethodSet(&structs.ACLAuthMethodSetRequest{Datacenter: "dc2"},
4062				&structs.ACLAuthMethod{}),
4063			errString,
4064		)
4065	})
4066	t.Run("AuthMethodDelete", func(t *testing.T) {
4067		testutil.RequireErrorContains(t,
4068			acl2.AuthMethodDelete(&structs.ACLAuthMethodDeleteRequest{Datacenter: "dc2"}, &ignored),
4069			errString,
4070		)
4071	})
4072	t.Run("AuthMethodList", func(t *testing.T) {
4073		testutil.RequireErrorContains(t,
4074			acl2.AuthMethodList(&structs.ACLAuthMethodListRequest{Datacenter: "dc2"},
4075				&structs.ACLAuthMethodListResponse{}),
4076			errString,
4077		)
4078	})
4079
4080	t.Run("BindingRuleRead", func(t *testing.T) {
4081		testutil.RequireErrorContains(t,
4082			acl2.BindingRuleRead(&structs.ACLBindingRuleGetRequest{Datacenter: "dc2"},
4083				&structs.ACLBindingRuleResponse{}),
4084			errString,
4085		)
4086	})
4087	t.Run("BindingRuleSet", func(t *testing.T) {
4088		testutil.RequireErrorContains(t,
4089			acl2.BindingRuleSet(&structs.ACLBindingRuleSetRequest{Datacenter: "dc2"},
4090				&structs.ACLBindingRule{}),
4091			errString,
4092		)
4093	})
4094	t.Run("BindingRuleDelete", func(t *testing.T) {
4095		testutil.RequireErrorContains(t,
4096			acl2.BindingRuleDelete(&structs.ACLBindingRuleDeleteRequest{Datacenter: "dc2"}, &ignored),
4097			errString,
4098		)
4099	})
4100	t.Run("BindingRuleList", func(t *testing.T) {
4101		testutil.RequireErrorContains(t,
4102			acl2.BindingRuleList(&structs.ACLBindingRuleListRequest{Datacenter: "dc2"},
4103				&structs.ACLBindingRuleListResponse{}),
4104			errString,
4105		)
4106	})
4107
4108	t.Run("Login", func(t *testing.T) {
4109		testutil.RequireErrorContains(t,
4110			acl2.Login(&structs.ACLLoginRequest{Datacenter: "dc2"},
4111				&structs.ACLToken{}),
4112			errString,
4113		)
4114	})
4115	t.Run("Logout", func(t *testing.T) {
4116		testutil.RequireErrorContains(t,
4117			acl2.Logout(&structs.ACLLogoutRequest{Datacenter: "dc2"}, &ignored),
4118			errString,
4119		)
4120	})
4121}
4122
4123func TestACLEndpoint_SecureIntroEndpoints_OnlyCreateLocalData(t *testing.T) {
4124	if testing.Short() {
4125		t.Skip("too slow for testing.Short")
4126	}
4127
4128	t.Parallel()
4129
4130	_, s1, codec1 := testACLServerWithConfig(t, func(c *Config) {
4131		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
4132		c.ACLTokenMaxExpirationTTL = 5 * time.Second
4133	}, false)
4134	waitForLeaderEstablishment(t, s1)
4135
4136	_, s2, codec2 := testACLServerWithConfig(t, func(c *Config) {
4137		c.Datacenter = "dc2"
4138		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
4139		c.ACLTokenMaxExpirationTTL = 5 * time.Second
4140		// enable token replication so secure intro works
4141		c.ACLTokenReplication = true
4142	}, true)
4143	waitForLeaderEstablishment(t, s2)
4144
4145	// Try to join
4146	joinWAN(t, s2, s1)
4147
4148	waitForNewACLs(t, s1)
4149	waitForNewACLs(t, s2)
4150
4151	// Ensure s2 is authoritative.
4152	waitForNewACLReplication(t, s2, structs.ACLReplicateTokens, 1, 1, 0)
4153
4154	acl := ACL{srv: s1}
4155	acl2 := ACL{srv: s2}
4156
4157	//
4158	// this order is specific so that we can do it in one pass
4159	//
4160
4161	testSessionID_1 := testauth.StartSession()
4162	defer testauth.ResetSession(testSessionID_1)
4163
4164	testSessionID_2 := testauth.StartSession()
4165	defer testauth.ResetSession(testSessionID_2)
4166
4167	testauth.InstallSessionToken(
4168		testSessionID_1,
4169		"fake-web1-token",
4170		"default", "web1", "abc123",
4171	)
4172	testauth.InstallSessionToken(
4173		testSessionID_2,
4174		"fake-web2-token",
4175		"default", "web2", "def456",
4176	)
4177
4178	t.Run("create auth method", func(t *testing.T) {
4179		req := structs.ACLAuthMethodSetRequest{
4180			Datacenter: "dc2",
4181			AuthMethod: structs.ACLAuthMethod{
4182				Name:        "testmethod",
4183				Description: "test original",
4184				Type:        "testing",
4185				Config: map[string]interface{}{
4186					"SessionID": testSessionID_2,
4187				},
4188			},
4189			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4190		}
4191		resp := structs.ACLAuthMethod{}
4192
4193		require.NoError(t, acl2.AuthMethodSet(&req, &resp))
4194
4195		// present in dc2
4196		resp2, err := retrieveTestAuthMethod(codec2, TestDefaultMasterToken, "dc2", "testmethod")
4197		require.NoError(t, err)
4198		require.NotNil(t, resp2.AuthMethod)
4199		require.Equal(t, "test original", resp2.AuthMethod.Description)
4200		// absent in dc1
4201		resp2, err = retrieveTestAuthMethod(codec1, TestDefaultMasterToken, "dc1", "testmethod")
4202		require.NoError(t, err)
4203		require.Nil(t, resp2.AuthMethod)
4204	})
4205
4206	t.Run("update auth method", func(t *testing.T) {
4207		req := structs.ACLAuthMethodSetRequest{
4208			Datacenter: "dc2",
4209			AuthMethod: structs.ACLAuthMethod{
4210				Name:        "testmethod",
4211				Description: "test updated",
4212				Config: map[string]interface{}{
4213					"SessionID": testSessionID_2,
4214				},
4215			},
4216			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4217		}
4218		resp := structs.ACLAuthMethod{}
4219
4220		require.NoError(t, acl2.AuthMethodSet(&req, &resp))
4221
4222		// present in dc2
4223		resp2, err := retrieveTestAuthMethod(codec2, TestDefaultMasterToken, "dc2", "testmethod")
4224		require.NoError(t, err)
4225		require.NotNil(t, resp2.AuthMethod)
4226		require.Equal(t, "test updated", resp2.AuthMethod.Description)
4227		// absent in dc1
4228		resp2, err = retrieveTestAuthMethod(codec1, TestDefaultMasterToken, "dc1", "testmethod")
4229		require.NoError(t, err)
4230		require.Nil(t, resp2.AuthMethod)
4231	})
4232
4233	t.Run("read auth method", func(t *testing.T) {
4234		// present in dc2
4235		req := structs.ACLAuthMethodGetRequest{
4236			Datacenter:     "dc2",
4237			AuthMethodName: "testmethod",
4238			QueryOptions:   structs.QueryOptions{Token: TestDefaultMasterToken},
4239		}
4240		resp := structs.ACLAuthMethodResponse{}
4241		require.NoError(t, acl2.AuthMethodRead(&req, &resp))
4242		require.NotNil(t, resp.AuthMethod)
4243		require.Equal(t, "test updated", resp.AuthMethod.Description)
4244
4245		// absent in dc1
4246		req = structs.ACLAuthMethodGetRequest{
4247			Datacenter:     "dc1",
4248			AuthMethodName: "testmethod",
4249			QueryOptions:   structs.QueryOptions{Token: TestDefaultMasterToken},
4250		}
4251		resp = structs.ACLAuthMethodResponse{}
4252		require.NoError(t, acl.AuthMethodRead(&req, &resp))
4253		require.Nil(t, resp.AuthMethod)
4254	})
4255
4256	t.Run("list auth method", func(t *testing.T) {
4257		// present in dc2
4258		req := structs.ACLAuthMethodListRequest{
4259			Datacenter:   "dc2",
4260			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
4261		}
4262		resp := structs.ACLAuthMethodListResponse{}
4263		require.NoError(t, acl2.AuthMethodList(&req, &resp))
4264		require.Len(t, resp.AuthMethods, 1)
4265
4266		// absent in dc1
4267		req = structs.ACLAuthMethodListRequest{
4268			Datacenter:   "dc1",
4269			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
4270		}
4271		resp = structs.ACLAuthMethodListResponse{}
4272		require.NoError(t, acl.AuthMethodList(&req, &resp))
4273		require.Len(t, resp.AuthMethods, 0)
4274	})
4275
4276	var ruleID string
4277	t.Run("create binding rule", func(t *testing.T) {
4278		req := structs.ACLBindingRuleSetRequest{
4279			Datacenter: "dc2",
4280			BindingRule: structs.ACLBindingRule{
4281				Description: "test original",
4282				AuthMethod:  "testmethod",
4283				BindType:    structs.BindingRuleBindTypeService,
4284				BindName:    "${serviceaccount.name}",
4285			},
4286			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4287		}
4288
4289		resp := structs.ACLBindingRule{}
4290
4291		require.NoError(t, acl2.BindingRuleSet(&req, &resp))
4292		ruleID = resp.ID
4293
4294		// present in dc2
4295		resp2, err := retrieveTestBindingRule(codec2, TestDefaultMasterToken, "dc2", ruleID)
4296		require.NoError(t, err)
4297		require.NotNil(t, resp2.BindingRule)
4298		require.Equal(t, "test original", resp2.BindingRule.Description)
4299		// absent in dc1
4300		resp2, err = retrieveTestBindingRule(codec1, TestDefaultMasterToken, "dc1", ruleID)
4301		require.NoError(t, err)
4302		require.Nil(t, resp2.BindingRule)
4303	})
4304
4305	t.Run("update binding rule", func(t *testing.T) {
4306		req := structs.ACLBindingRuleSetRequest{
4307			Datacenter: "dc2",
4308			BindingRule: structs.ACLBindingRule{
4309				ID:          ruleID,
4310				Description: "test updated",
4311				AuthMethod:  "testmethod",
4312				BindType:    structs.BindingRuleBindTypeService,
4313				BindName:    "${serviceaccount.name}",
4314			},
4315			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4316		}
4317
4318		resp := structs.ACLBindingRule{}
4319
4320		require.NoError(t, acl2.BindingRuleSet(&req, &resp))
4321		ruleID = resp.ID
4322
4323		// present in dc2
4324		resp2, err := retrieveTestBindingRule(codec2, TestDefaultMasterToken, "dc2", ruleID)
4325		require.NoError(t, err)
4326		require.NotNil(t, resp2.BindingRule)
4327		require.Equal(t, "test updated", resp2.BindingRule.Description)
4328		// absent in dc1
4329		resp2, err = retrieveTestBindingRule(codec1, TestDefaultMasterToken, "dc1", ruleID)
4330		require.NoError(t, err)
4331		require.Nil(t, resp2.BindingRule)
4332	})
4333
4334	t.Run("read binding rule", func(t *testing.T) {
4335		// present in dc2
4336		req := structs.ACLBindingRuleGetRequest{
4337			Datacenter:    "dc2",
4338			BindingRuleID: ruleID,
4339			QueryOptions:  structs.QueryOptions{Token: TestDefaultMasterToken},
4340		}
4341		resp := structs.ACLBindingRuleResponse{}
4342		require.NoError(t, acl2.BindingRuleRead(&req, &resp))
4343		require.NotNil(t, resp.BindingRule)
4344		require.Equal(t, "test updated", resp.BindingRule.Description)
4345
4346		// absent in dc1
4347		req = structs.ACLBindingRuleGetRequest{
4348			Datacenter:    "dc1",
4349			BindingRuleID: ruleID,
4350			QueryOptions:  structs.QueryOptions{Token: TestDefaultMasterToken},
4351		}
4352		resp = structs.ACLBindingRuleResponse{}
4353		require.NoError(t, acl.BindingRuleRead(&req, &resp))
4354		require.Nil(t, resp.BindingRule)
4355	})
4356
4357	t.Run("list binding rule", func(t *testing.T) {
4358		// present in dc2
4359		req := structs.ACLBindingRuleListRequest{
4360			Datacenter:   "dc2",
4361			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
4362		}
4363		resp := structs.ACLBindingRuleListResponse{}
4364		require.NoError(t, acl2.BindingRuleList(&req, &resp))
4365		require.Len(t, resp.BindingRules, 1)
4366
4367		// absent in dc1
4368		req = structs.ACLBindingRuleListRequest{
4369			Datacenter:   "dc1",
4370			QueryOptions: structs.QueryOptions{Token: TestDefaultMasterToken},
4371		}
4372		resp = structs.ACLBindingRuleListResponse{}
4373		require.NoError(t, acl.BindingRuleList(&req, &resp))
4374		require.Len(t, resp.BindingRules, 0)
4375	})
4376
4377	var remoteToken *structs.ACLToken
4378	t.Run("login in remote", func(t *testing.T) {
4379		req := structs.ACLLoginRequest{
4380			Datacenter: "dc2",
4381			Auth: &structs.ACLLoginParams{
4382				AuthMethod:  "testmethod",
4383				BearerToken: "fake-web2-token",
4384			},
4385		}
4386		resp := structs.ACLToken{}
4387
4388		require.NoError(t, acl2.Login(&req, &resp))
4389		remoteToken = &resp
4390
4391		// present in dc2
4392		resp2, err := retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", remoteToken.AccessorID)
4393		require.NoError(t, err)
4394		require.NotNil(t, resp2.Token)
4395		require.Len(t, resp2.Token.ServiceIdentities, 1)
4396		require.Equal(t, "web2", resp2.Token.ServiceIdentities[0].ServiceName)
4397		// absent in dc1
4398		resp2, err = retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", remoteToken.AccessorID)
4399		require.NoError(t, err)
4400		require.Nil(t, resp2.Token)
4401	})
4402
4403	// We delay until now to setup an auth method and binding rule in the
4404	// primary so our earlier listing tests were sane. We need to be able to
4405	// use auth methods in both datacenters in order to verify Logout is
4406	// properly scoped.
4407	t.Run("initialize primary so we can test logout", func(t *testing.T) {
4408		reqAM := structs.ACLAuthMethodSetRequest{
4409			Datacenter: "dc1",
4410			AuthMethod: structs.ACLAuthMethod{
4411				Name: "primarymethod",
4412				Type: "testing",
4413				Config: map[string]interface{}{
4414					"SessionID": testSessionID_1,
4415				},
4416			},
4417			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4418		}
4419		respAM := structs.ACLAuthMethod{}
4420		require.NoError(t, acl.AuthMethodSet(&reqAM, &respAM))
4421
4422		reqBR := structs.ACLBindingRuleSetRequest{
4423			Datacenter: "dc1",
4424			BindingRule: structs.ACLBindingRule{
4425				AuthMethod: "primarymethod",
4426				BindType:   structs.BindingRuleBindTypeService,
4427				BindName:   "${serviceaccount.name}",
4428			},
4429			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4430		}
4431
4432		respBR := structs.ACLBindingRule{}
4433		require.NoError(t, acl.BindingRuleSet(&reqBR, &respBR))
4434	})
4435
4436	var primaryToken *structs.ACLToken
4437	t.Run("login in primary", func(t *testing.T) {
4438		req := structs.ACLLoginRequest{
4439			Datacenter: "dc1",
4440			Auth: &structs.ACLLoginParams{
4441				AuthMethod:  "primarymethod",
4442				BearerToken: "fake-web1-token",
4443			},
4444		}
4445		resp := structs.ACLToken{}
4446
4447		require.NoError(t, acl.Login(&req, &resp))
4448		primaryToken = &resp
4449
4450		// present in dc1
4451		resp2, err := retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", primaryToken.AccessorID)
4452		require.NoError(t, err)
4453		require.NotNil(t, resp2.Token)
4454		require.Len(t, resp2.Token.ServiceIdentities, 1)
4455		require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName)
4456		// absent in dc2
4457		resp2, err = retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", primaryToken.AccessorID)
4458		require.NoError(t, err)
4459		require.Nil(t, resp2.Token)
4460	})
4461
4462	t.Run("logout of remote token in remote dc", func(t *testing.T) {
4463		// if the other test fails this one will to but will now not segfault
4464		require.NotNil(t, remoteToken)
4465
4466		req := structs.ACLLogoutRequest{
4467			Datacenter:   "dc2",
4468			WriteRequest: structs.WriteRequest{Token: remoteToken.SecretID},
4469		}
4470
4471		var ignored bool
4472		require.NoError(t, acl.Logout(&req, &ignored))
4473
4474		// absent in dc2
4475		resp2, err := retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", remoteToken.AccessorID)
4476		require.NoError(t, err)
4477		require.Nil(t, resp2.Token)
4478		// absent in dc1
4479		resp2, err = retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", remoteToken.AccessorID)
4480		require.NoError(t, err)
4481		require.Nil(t, resp2.Token)
4482	})
4483
4484	t.Run("logout of primary token in remote dc should not work", func(t *testing.T) {
4485		req := structs.ACLLogoutRequest{
4486			Datacenter:   "dc2",
4487			WriteRequest: structs.WriteRequest{Token: primaryToken.SecretID},
4488		}
4489
4490		var ignored bool
4491		testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "ACL not found")
4492
4493		// present in dc1
4494		resp2, err := retrieveTestToken(codec1, TestDefaultMasterToken, "dc1", primaryToken.AccessorID)
4495		require.NoError(t, err)
4496		require.NotNil(t, resp2.Token)
4497		require.Len(t, resp2.Token.ServiceIdentities, 1)
4498		require.Equal(t, "web1", resp2.Token.ServiceIdentities[0].ServiceName)
4499		// absent in dc2
4500		resp2, err = retrieveTestToken(codec2, TestDefaultMasterToken, "dc2", primaryToken.AccessorID)
4501		require.NoError(t, err)
4502		require.Nil(t, resp2.Token)
4503	})
4504
4505	// Don't trigger the auth method delete cascade so we know the individual
4506	// endpoints follow the rules.
4507
4508	t.Run("delete binding rule", func(t *testing.T) {
4509		req := structs.ACLBindingRuleDeleteRequest{
4510			Datacenter:    "dc2",
4511			BindingRuleID: ruleID,
4512			WriteRequest:  structs.WriteRequest{Token: TestDefaultMasterToken},
4513		}
4514
4515		var ignored bool
4516		require.NoError(t, acl2.BindingRuleDelete(&req, &ignored))
4517
4518		// absent in dc2
4519		resp2, err := retrieveTestBindingRule(codec2, TestDefaultMasterToken, "dc2", ruleID)
4520		require.NoError(t, err)
4521		require.Nil(t, resp2.BindingRule)
4522		// absent in dc1
4523		resp2, err = retrieveTestBindingRule(codec1, TestDefaultMasterToken, "dc1", ruleID)
4524		require.NoError(t, err)
4525		require.Nil(t, resp2.BindingRule)
4526	})
4527
4528	t.Run("delete auth method", func(t *testing.T) {
4529		req := structs.ACLAuthMethodDeleteRequest{
4530			Datacenter:     "dc2",
4531			AuthMethodName: "testmethod",
4532			WriteRequest:   structs.WriteRequest{Token: TestDefaultMasterToken},
4533		}
4534
4535		var ignored bool
4536		require.NoError(t, acl2.AuthMethodDelete(&req, &ignored))
4537
4538		// absent in dc2
4539		resp2, err := retrieveTestAuthMethod(codec2, TestDefaultMasterToken, "dc2", "testmethod")
4540		require.NoError(t, err)
4541		require.Nil(t, resp2.AuthMethod)
4542		// absent in dc1
4543		resp2, err = retrieveTestAuthMethod(codec1, TestDefaultMasterToken, "dc1", "testmethod")
4544		require.NoError(t, err)
4545		require.Nil(t, resp2.AuthMethod)
4546	})
4547}
4548
4549func TestACLEndpoint_Login(t *testing.T) {
4550	if testing.Short() {
4551		t.Skip("too slow for testing.Short")
4552	}
4553
4554	t.Parallel()
4555
4556	_, srv, codec := testACLServerWithConfig(t, nil, false)
4557	waitForLeaderEstablishment(t, srv)
4558
4559	acl := ACL{srv: srv}
4560
4561	testSessionID := testauth.StartSession()
4562	defer testauth.ResetSession(testSessionID)
4563
4564	testauth.InstallSessionToken(
4565		testSessionID,
4566		"fake-web", // no rules
4567		"default", "web", "abc123",
4568	)
4569	testauth.InstallSessionToken(
4570		testSessionID,
4571		"fake-db", // 1 rule (service)
4572		"default", "db", "def456",
4573	)
4574	testauth.InstallSessionToken(
4575		testSessionID,
4576		"fake-vault", // 1 rule (role)
4577		"default", "vault", "jkl012",
4578	)
4579	testauth.InstallSessionToken(
4580		testSessionID,
4581		"fake-monolith", // 2 rules (one of each)
4582		"default", "monolith", "ghi789",
4583	)
4584	testauth.InstallSessionToken(
4585		testSessionID,
4586		"fake-node",
4587		"default", "mynode", "jkl101",
4588	)
4589
4590	method, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID)
4591	require.NoError(t, err)
4592
4593	// 'fake-db' rules
4594	ruleDB, err := upsertTestBindingRule(
4595		codec, TestDefaultMasterToken, "dc1", method.Name,
4596		"serviceaccount.namespace==default and serviceaccount.name==db",
4597		structs.BindingRuleBindTypeService,
4598		"method-${serviceaccount.name}",
4599	)
4600	require.NoError(t, err)
4601
4602	// 'fake-vault' rules
4603	_, err = upsertTestBindingRule(
4604		codec, TestDefaultMasterToken, "dc1", method.Name,
4605		"serviceaccount.namespace==default and serviceaccount.name==vault",
4606		structs.BindingRuleBindTypeRole,
4607		"method-${serviceaccount.name}",
4608	)
4609	require.NoError(t, err)
4610
4611	// 'fake-monolith' rules
4612	_, err = upsertTestBindingRule(
4613		codec, TestDefaultMasterToken, "dc1", method.Name,
4614		"serviceaccount.namespace==default and serviceaccount.name==monolith",
4615		structs.BindingRuleBindTypeService,
4616		"method-${serviceaccount.name}",
4617	)
4618	require.NoError(t, err)
4619	_, err = upsertTestBindingRule(
4620		codec, TestDefaultMasterToken, "dc1", method.Name,
4621		"serviceaccount.namespace==default and serviceaccount.name==monolith",
4622		structs.BindingRuleBindTypeRole,
4623		"method-${serviceaccount.name}",
4624	)
4625	require.NoError(t, err)
4626
4627	// node identity rule
4628	_, err = upsertTestBindingRule(
4629		codec, TestDefaultMasterToken, "dc1", method.Name,
4630		"serviceaccount.namespace==default and serviceaccount.name==mynode",
4631		structs.BindingRuleBindTypeNode,
4632		"${serviceaccount.name}",
4633	)
4634	require.NoError(t, err)
4635
4636	t.Run("do not provide a token", func(t *testing.T) {
4637		req := structs.ACLLoginRequest{
4638			Auth: &structs.ACLLoginParams{
4639				AuthMethod:  method.Name,
4640				BearerToken: "fake-web",
4641				Meta:        map[string]string{"pod": "pod1"},
4642			},
4643			Datacenter: "dc1",
4644		}
4645		req.Token = "nope"
4646		resp := structs.ACLToken{}
4647
4648		testutil.RequireErrorContains(t, acl.Login(&req, &resp), "do not provide a token")
4649	})
4650
4651	t.Run("unknown method", func(t *testing.T) {
4652		req := structs.ACLLoginRequest{
4653			Auth: &structs.ACLLoginParams{
4654				AuthMethod:  method.Name + "-notexist",
4655				BearerToken: "fake-web",
4656				Meta:        map[string]string{"pod": "pod1"},
4657			},
4658			Datacenter: "dc1",
4659		}
4660		resp := structs.ACLToken{}
4661
4662		testutil.RequireErrorContains(t, acl.Login(&req, &resp), fmt.Sprintf("auth method %q not found", method.Name+"-notexist"))
4663	})
4664
4665	t.Run("invalid method token", func(t *testing.T) {
4666		req := structs.ACLLoginRequest{
4667			Auth: &structs.ACLLoginParams{
4668				AuthMethod:  method.Name,
4669				BearerToken: "invalid",
4670				Meta:        map[string]string{"pod": "pod1"},
4671			},
4672			Datacenter: "dc1",
4673		}
4674		resp := structs.ACLToken{}
4675
4676		require.Error(t, acl.Login(&req, &resp))
4677	})
4678
4679	t.Run("valid method token no bindings", func(t *testing.T) {
4680		req := structs.ACLLoginRequest{
4681			Auth: &structs.ACLLoginParams{
4682				AuthMethod:  method.Name,
4683				BearerToken: "fake-web",
4684				Meta:        map[string]string{"pod": "pod1"},
4685			},
4686			Datacenter: "dc1",
4687		}
4688		resp := structs.ACLToken{}
4689
4690		testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied")
4691	})
4692
4693	t.Run("valid method token 1 role binding and role does not exist", func(t *testing.T) {
4694		req := structs.ACLLoginRequest{
4695			Auth: &structs.ACLLoginParams{
4696				AuthMethod:  method.Name,
4697				BearerToken: "fake-vault",
4698				Meta:        map[string]string{"pod": "pod1"},
4699			},
4700			Datacenter: "dc1",
4701		}
4702		resp := structs.ACLToken{}
4703
4704		testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied")
4705	})
4706
4707	// create the role so that the bindtype=role login works
4708	var vaultRoleID string
4709	{
4710		arg := structs.ACLRoleSetRequest{
4711			Datacenter: "dc1",
4712			Role: structs.ACLRole{
4713				Name: "method-vault",
4714			},
4715			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4716		}
4717
4718		var out structs.ACLRole
4719		require.NoError(t, acl.RoleSet(&arg, &out))
4720
4721		vaultRoleID = out.ID
4722	}
4723
4724	t.Run("valid method token 1 role binding and role now exists", func(t *testing.T) {
4725		req := structs.ACLLoginRequest{
4726			Auth: &structs.ACLLoginParams{
4727				AuthMethod:  method.Name,
4728				BearerToken: "fake-vault",
4729				Meta:        map[string]string{"pod": "pod1"},
4730			},
4731			Datacenter: "dc1",
4732		}
4733		resp := structs.ACLToken{}
4734
4735		require.NoError(t, acl.Login(&req, &resp))
4736
4737		require.Equal(t, method.Name, resp.AuthMethod)
4738		require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description)
4739		require.True(t, resp.Local)
4740		require.Len(t, resp.ServiceIdentities, 0)
4741		require.Len(t, resp.Roles, 1)
4742		role := resp.Roles[0]
4743		require.Equal(t, vaultRoleID, role.ID)
4744		require.Equal(t, "method-vault", role.Name)
4745	})
4746
4747	t.Run("valid method token 1 service binding 1 role binding and role does not exist", func(t *testing.T) {
4748		req := structs.ACLLoginRequest{
4749			Auth: &structs.ACLLoginParams{
4750				AuthMethod:  method.Name,
4751				BearerToken: "fake-monolith",
4752				Meta:        map[string]string{"pod": "pod1"},
4753			},
4754			Datacenter: "dc1",
4755		}
4756		resp := structs.ACLToken{}
4757
4758		require.NoError(t, acl.Login(&req, &resp))
4759
4760		require.Equal(t, method.Name, resp.AuthMethod)
4761		require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description)
4762		require.True(t, resp.Local)
4763		require.Len(t, resp.ServiceIdentities, 1)
4764		require.Len(t, resp.Roles, 0)
4765		svcid := resp.ServiceIdentities[0]
4766		require.Len(t, svcid.Datacenters, 0)
4767		require.Equal(t, "method-monolith", svcid.ServiceName)
4768	})
4769
4770	// create the role so that the bindtype=role login works
4771	var monolithRoleID string
4772	{
4773		arg := structs.ACLRoleSetRequest{
4774			Datacenter: "dc1",
4775			Role: structs.ACLRole{
4776				Name: "method-monolith",
4777			},
4778			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4779		}
4780
4781		var out structs.ACLRole
4782		require.NoError(t, acl.RoleSet(&arg, &out))
4783
4784		monolithRoleID = out.ID
4785	}
4786
4787	t.Run("valid method token 1 service binding 1 role binding and role now exists", func(t *testing.T) {
4788		req := structs.ACLLoginRequest{
4789			Auth: &structs.ACLLoginParams{
4790				AuthMethod:  method.Name,
4791				BearerToken: "fake-monolith",
4792				Meta:        map[string]string{"pod": "pod1"},
4793			},
4794			Datacenter: "dc1",
4795		}
4796		resp := structs.ACLToken{}
4797
4798		require.NoError(t, acl.Login(&req, &resp))
4799
4800		require.Equal(t, method.Name, resp.AuthMethod)
4801		require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description)
4802		require.True(t, resp.Local)
4803		require.Len(t, resp.ServiceIdentities, 1)
4804		require.Len(t, resp.Roles, 1)
4805		role := resp.Roles[0]
4806		require.Equal(t, monolithRoleID, role.ID)
4807		require.Equal(t, "method-monolith", role.Name)
4808		svcid := resp.ServiceIdentities[0]
4809		require.Len(t, svcid.Datacenters, 0)
4810		require.Equal(t, "method-monolith", svcid.ServiceName)
4811	})
4812
4813	t.Run("valid bearer token 1 service binding", func(t *testing.T) {
4814		req := structs.ACLLoginRequest{
4815			Auth: &structs.ACLLoginParams{
4816				AuthMethod:  method.Name,
4817				BearerToken: "fake-db",
4818				Meta:        map[string]string{"pod": "pod1"},
4819			},
4820			Datacenter: "dc1",
4821		}
4822		resp := structs.ACLToken{}
4823
4824		require.NoError(t, acl.Login(&req, &resp))
4825
4826		require.Equal(t, method.Name, resp.AuthMethod)
4827		require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description)
4828		require.True(t, resp.Local)
4829		require.Len(t, resp.Roles, 0)
4830		require.Len(t, resp.ServiceIdentities, 1)
4831		svcid := resp.ServiceIdentities[0]
4832		require.Len(t, svcid.Datacenters, 0)
4833		require.Equal(t, "method-db", svcid.ServiceName)
4834	})
4835
4836	t.Run("valid bearer token 1 node binding", func(t *testing.T) {
4837		req := structs.ACLLoginRequest{
4838			Auth: &structs.ACLLoginParams{
4839				AuthMethod:  method.Name,
4840				BearerToken: "fake-node",
4841				Meta:        map[string]string{"node": "true"},
4842			},
4843			Datacenter: "dc1",
4844		}
4845		resp := structs.ACLToken{}
4846
4847		require.NoError(t, acl.Login(&req, &resp))
4848
4849		require.Equal(t, method.Name, resp.AuthMethod)
4850		require.Equal(t, `token created via login: {"node":"true"}`, resp.Description)
4851		require.True(t, resp.Local)
4852		require.Empty(t, resp.Roles)
4853		require.Empty(t, resp.ServiceIdentities)
4854		require.Len(t, resp.NodeIdentities, 1)
4855		nodeid := resp.NodeIdentities[0]
4856		require.Equal(t, "mynode", nodeid.NodeName)
4857		require.Equal(t, "dc1", nodeid.Datacenter)
4858	})
4859
4860	{
4861		req := structs.ACLBindingRuleSetRequest{
4862			Datacenter: "dc1",
4863			BindingRule: structs.ACLBindingRule{
4864				AuthMethod: ruleDB.AuthMethod,
4865				BindType:   structs.BindingRuleBindTypeService,
4866				BindName:   ruleDB.BindName,
4867				Selector:   "",
4868			},
4869			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4870		}
4871
4872		var out structs.ACLBindingRule
4873		require.NoError(t, acl.BindingRuleSet(&req, &out))
4874	}
4875
4876	t.Run("valid bearer token 1 binding (no selectors this time)", func(t *testing.T) {
4877		req := structs.ACLLoginRequest{
4878			Auth: &structs.ACLLoginParams{
4879				AuthMethod:  method.Name,
4880				BearerToken: "fake-db",
4881				Meta:        map[string]string{"pod": "pod1"},
4882			},
4883			Datacenter: "dc1",
4884		}
4885		resp := structs.ACLToken{}
4886
4887		require.NoError(t, acl.Login(&req, &resp))
4888
4889		require.Equal(t, method.Name, resp.AuthMethod)
4890		require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description)
4891		require.True(t, resp.Local)
4892		require.Len(t, resp.Roles, 0)
4893		require.Len(t, resp.ServiceIdentities, 1)
4894		svcid := resp.ServiceIdentities[0]
4895		require.Len(t, svcid.Datacenters, 0)
4896		require.Equal(t, "method-db", svcid.ServiceName)
4897	})
4898
4899	testSessionID_2 := testauth.StartSession()
4900	defer testauth.ResetSession(testSessionID_2)
4901	{
4902		// Update the method to force the cache to invalidate for the next
4903		// subtest.
4904		updated := *method
4905		updated.Description = "updated for the test"
4906		updated.Config = map[string]interface{}{
4907			"SessionID": testSessionID_2,
4908		}
4909
4910		req := structs.ACLAuthMethodSetRequest{
4911			Datacenter:   "dc1",
4912			AuthMethod:   updated,
4913			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
4914		}
4915
4916		var ignored structs.ACLAuthMethod
4917		require.NoError(t, acl.AuthMethodSet(&req, &ignored))
4918	}
4919
4920	t.Run("updating the method invalidates the cache", func(t *testing.T) {
4921		// We'll try to login with the 'fake-db' cred which DOES exist in the
4922		// old fake validator, but no longer exists in the new fake validator.
4923		req := structs.ACLLoginRequest{
4924			Auth: &structs.ACLLoginParams{
4925				AuthMethod:  method.Name,
4926				BearerToken: "fake-db",
4927				Meta:        map[string]string{"pod": "pod1"},
4928			},
4929			Datacenter: "dc1",
4930		}
4931		resp := structs.ACLToken{}
4932
4933		testutil.RequireErrorContains(t, acl.Login(&req, &resp), "ACL not found")
4934	})
4935}
4936
4937func TestACLEndpoint_Login_with_MaxTokenTTL(t *testing.T) {
4938	if testing.Short() {
4939		t.Skip("too slow for testing.Short")
4940	}
4941
4942	t.Parallel()
4943
4944	_, srv, codec := testACLServerWithConfig(t, nil, false)
4945	waitForLeaderEstablishment(t, srv)
4946
4947	acl := ACL{srv: srv}
4948
4949	testSessionID := testauth.StartSession()
4950	defer testauth.ResetSession(testSessionID)
4951
4952	testauth.InstallSessionToken(
4953		testSessionID,
4954		"fake-web", // no rules
4955		"default", "web", "abc123",
4956	)
4957
4958	method, err := upsertTestCustomizedAuthMethod(codec, TestDefaultMasterToken, "dc1", func(method *structs.ACLAuthMethod) {
4959		method.MaxTokenTTL = 5 * time.Minute
4960		method.Config = map[string]interface{}{
4961			"SessionID": testSessionID,
4962		}
4963	})
4964	require.NoError(t, err)
4965
4966	_, err = upsertTestBindingRule(
4967		codec, TestDefaultMasterToken, "dc1", method.Name,
4968		"",
4969		structs.BindingRuleBindTypeService,
4970		"web",
4971	)
4972	require.NoError(t, err)
4973
4974	// Create a token.
4975	req := structs.ACLLoginRequest{
4976		Auth: &structs.ACLLoginParams{
4977			AuthMethod:  method.Name,
4978			BearerToken: "fake-web",
4979			Meta:        map[string]string{"pod": "pod1"},
4980		},
4981		Datacenter: "dc1",
4982	}
4983
4984	resp := structs.ACLToken{}
4985	require.NoError(t, acl.Login(&req, &resp))
4986
4987	got := &resp
4988	got.CreateIndex = 0
4989	got.ModifyIndex = 0
4990	got.AccessorID = ""
4991	got.SecretID = ""
4992	got.Hash = nil
4993
4994	defaultEntMeta := structs.DefaultEnterpriseMeta()
4995	expect := &structs.ACLToken{
4996		AuthMethod:     method.Name,
4997		Description:    `token created via login: {"pod":"pod1"}`,
4998		Local:          true,
4999		CreateTime:     got.CreateTime,
5000		ExpirationTime: timePointer(got.CreateTime.Add(method.MaxTokenTTL)),
5001		ServiceIdentities: []*structs.ACLServiceIdentity{
5002			{ServiceName: "web"},
5003		},
5004		EnterpriseMeta: *defaultEntMeta,
5005	}
5006	expect.ACLAuthMethodEnterpriseMeta.FillWithEnterpriseMeta(defaultEntMeta)
5007	require.Equal(t, got, expect)
5008}
5009
5010func TestACLEndpoint_Login_with_TokenLocality(t *testing.T) {
5011	if testing.Short() {
5012		t.Skip("too slow for testing.Short")
5013	}
5014
5015	t.Parallel()
5016
5017	_, s1, codec := testACLServerWithConfig(t, func(c *Config) {
5018		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
5019		c.ACLTokenMaxExpirationTTL = 5 * time.Second
5020	}, false)
5021
5022	_, s2, _ := testACLServerWithConfig(t, func(c *Config) {
5023		c.Datacenter = "dc2"
5024		c.ACLTokenMinExpirationTTL = 10 * time.Millisecond
5025		c.ACLTokenMaxExpirationTTL = 5 * time.Second
5026		// token replication is required to test deleting non-local tokens in secondary dc
5027		c.ACLTokenReplication = true
5028	}, true)
5029
5030	waitForLeaderEstablishment(t, s1)
5031	waitForLeaderEstablishment(t, s2)
5032
5033	joinWAN(t, s2, s1)
5034
5035	waitForNewACLs(t, s1)
5036	waitForNewACLs(t, s2)
5037
5038	// Ensure s2 is authoritative.
5039	waitForNewACLReplication(t, s2, structs.ACLReplicateTokens, 1, 1, 0)
5040
5041	acl := ACL{srv: s1}
5042	acl2 := ACL{srv: s2}
5043
5044	testSessionID := testauth.StartSession()
5045	defer testauth.ResetSession(testSessionID)
5046
5047	testauth.InstallSessionToken(
5048		testSessionID,
5049		"fake-web", // no rules
5050		"default", "web", "abc123",
5051	)
5052
5053	cases := map[string]struct {
5054		tokenLocality     string
5055		expectLocal       bool
5056		deleteFromReplica bool
5057	}{
5058		"empty":             {tokenLocality: "", expectLocal: true},
5059		"local":             {tokenLocality: "local", expectLocal: true},
5060		"global dc1 delete": {tokenLocality: "global", expectLocal: false, deleteFromReplica: false},
5061		"global dc2 delete": {tokenLocality: "global", expectLocal: false, deleteFromReplica: true},
5062	}
5063
5064	for name, tc := range cases {
5065		tc := tc
5066		t.Run(name, func(t *testing.T) {
5067			method, err := upsertTestCustomizedAuthMethod(codec, TestDefaultMasterToken, "dc1", func(method *structs.ACLAuthMethod) {
5068				method.TokenLocality = tc.tokenLocality
5069				method.Config = map[string]interface{}{
5070					"SessionID": testSessionID,
5071				}
5072			})
5073			require.NoError(t, err)
5074
5075			_, err = upsertTestBindingRule(
5076				codec, TestDefaultMasterToken, "dc1", method.Name,
5077				"",
5078				structs.BindingRuleBindTypeService,
5079				"web",
5080			)
5081			require.NoError(t, err)
5082
5083			// Create a token.
5084			req := structs.ACLLoginRequest{
5085				Auth: &structs.ACLLoginParams{
5086					AuthMethod:  method.Name,
5087					BearerToken: "fake-web",
5088					Meta:        map[string]string{"pod": "pod1"},
5089				},
5090				Datacenter: "dc1",
5091			}
5092
5093			resp := structs.ACLToken{}
5094			require.NoError(t, acl.Login(&req, &resp))
5095
5096			secretID := resp.SecretID
5097
5098			got := resp.Clone()
5099			got.CreateIndex = 0
5100			got.ModifyIndex = 0
5101			got.AccessorID = ""
5102			got.SecretID = ""
5103			got.Hash = nil
5104
5105			defaultEntMeta := structs.DefaultEnterpriseMeta()
5106			expect := &structs.ACLToken{
5107				AuthMethod:  method.Name,
5108				Description: `token created via login: {"pod":"pod1"}`,
5109				Local:       tc.expectLocal,
5110				CreateTime:  got.CreateTime,
5111				ServiceIdentities: []*structs.ACLServiceIdentity{
5112					{ServiceName: "web"},
5113				},
5114				EnterpriseMeta: *defaultEntMeta,
5115			}
5116			expect.ACLAuthMethodEnterpriseMeta.FillWithEnterpriseMeta(defaultEntMeta)
5117			require.Equal(t, got, expect)
5118
5119			// Now turn around and nuke it.
5120			var (
5121				logoutACL ACL
5122				logoutDC  string
5123			)
5124			if tc.deleteFromReplica {
5125				// wait for it to show up
5126				retry.Run(t, func(r *retry.R) {
5127					var resp structs.ACLTokenResponse
5128					require.NoError(r, acl2.TokenRead(&structs.ACLTokenGetRequest{
5129						TokenID:        secretID,
5130						TokenIDType:    structs.ACLTokenSecret,
5131						Datacenter:     "dc2",
5132						EnterpriseMeta: *defaultEntMeta,
5133						QueryOptions:   structs.QueryOptions{Token: TestDefaultMasterToken},
5134					}, &resp))
5135					require.NotNil(r, resp.Token, "cannot lookup token with secretID %q", secretID)
5136				})
5137
5138				logoutACL = acl2
5139				logoutDC = "dc2"
5140			} else {
5141				logoutACL = acl
5142				logoutDC = "dc1"
5143			}
5144
5145			logoutReq := structs.ACLLogoutRequest{
5146				Datacenter:   logoutDC,
5147				WriteRequest: structs.WriteRequest{Token: secretID},
5148			}
5149
5150			var ignored bool
5151			require.NoError(t, logoutACL.Logout(&logoutReq, &ignored))
5152		})
5153	}
5154}
5155
5156func TestACLEndpoint_Login_k8s(t *testing.T) {
5157	if testing.Short() {
5158		t.Skip("too slow for testing.Short")
5159	}
5160
5161	t.Parallel()
5162
5163	_, srv, codec := testACLServerWithConfig(t, nil, false)
5164	waitForLeaderEstablishment(t, srv)
5165
5166	acl := ACL{srv: srv}
5167
5168	// spin up a fake api server
5169	testSrv := kubeauth.StartTestAPIServer(t)
5170	defer testSrv.Stop()
5171
5172	testSrv.AuthorizeJWT(goodJWT_A)
5173	testSrv.SetAllowedServiceAccount(
5174		"default",
5175		"demo",
5176		"76091af4-4b56-11e9-ac4b-708b11801cbe",
5177		"",
5178		goodJWT_B,
5179	)
5180
5181	method, err := upsertTestKubernetesAuthMethod(
5182		codec, TestDefaultMasterToken, "dc1",
5183		testSrv.CACert(),
5184		testSrv.Addr(),
5185		goodJWT_A,
5186	)
5187	require.NoError(t, err)
5188
5189	t.Run("invalid bearer token", func(t *testing.T) {
5190		req := structs.ACLLoginRequest{
5191			Auth: &structs.ACLLoginParams{
5192				AuthMethod:  method.Name,
5193				BearerToken: "invalid",
5194				Meta:        map[string]string{"pod": "pod1"},
5195			},
5196			Datacenter: "dc1",
5197		}
5198		resp := structs.ACLToken{}
5199
5200		require.Error(t, acl.Login(&req, &resp))
5201	})
5202
5203	t.Run("valid bearer token no bindings", func(t *testing.T) {
5204		req := structs.ACLLoginRequest{
5205			Auth: &structs.ACLLoginParams{
5206				AuthMethod:  method.Name,
5207				BearerToken: goodJWT_B,
5208				Meta:        map[string]string{"pod": "pod1"},
5209			},
5210			Datacenter: "dc1",
5211		}
5212		resp := structs.ACLToken{}
5213
5214		testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied")
5215	})
5216
5217	_, err = upsertTestBindingRule(
5218		codec, TestDefaultMasterToken, "dc1", method.Name,
5219		"serviceaccount.namespace==default",
5220		structs.BindingRuleBindTypeService,
5221		"${serviceaccount.name}",
5222	)
5223	require.NoError(t, err)
5224
5225	t.Run("valid bearer token 1 service binding", func(t *testing.T) {
5226		req := structs.ACLLoginRequest{
5227			Auth: &structs.ACLLoginParams{
5228				AuthMethod:  method.Name,
5229				BearerToken: goodJWT_B,
5230				Meta:        map[string]string{"pod": "pod1"},
5231			},
5232			Datacenter: "dc1",
5233		}
5234		resp := structs.ACLToken{}
5235
5236		require.NoError(t, acl.Login(&req, &resp))
5237
5238		require.Equal(t, method.Name, resp.AuthMethod)
5239		require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description)
5240		require.True(t, resp.Local)
5241		require.Len(t, resp.Roles, 0)
5242		require.Len(t, resp.ServiceIdentities, 1)
5243		svcid := resp.ServiceIdentities[0]
5244		require.Len(t, svcid.Datacenters, 0)
5245		require.Equal(t, "demo", svcid.ServiceName)
5246	})
5247
5248	// annotate the account
5249	testSrv.SetAllowedServiceAccount(
5250		"default",
5251		"demo",
5252		"76091af4-4b56-11e9-ac4b-708b11801cbe",
5253		"alternate-name",
5254		goodJWT_B,
5255	)
5256
5257	t.Run("valid bearer token 1 service binding - with annotation", func(t *testing.T) {
5258		req := structs.ACLLoginRequest{
5259			Auth: &structs.ACLLoginParams{
5260				AuthMethod:  method.Name,
5261				BearerToken: goodJWT_B,
5262				Meta:        map[string]string{"pod": "pod1"},
5263			},
5264			Datacenter: "dc1",
5265		}
5266		resp := structs.ACLToken{}
5267
5268		require.NoError(t, acl.Login(&req, &resp))
5269
5270		require.Equal(t, method.Name, resp.AuthMethod)
5271		require.Equal(t, `token created via login: {"pod":"pod1"}`, resp.Description)
5272		require.True(t, resp.Local)
5273		require.Len(t, resp.Roles, 0)
5274		require.Len(t, resp.ServiceIdentities, 1)
5275		svcid := resp.ServiceIdentities[0]
5276		require.Len(t, svcid.Datacenters, 0)
5277		require.Equal(t, "alternate-name", svcid.ServiceName)
5278	})
5279}
5280
5281func TestACLEndpoint_Login_jwt(t *testing.T) {
5282	if testing.Short() {
5283		t.Skip("too slow for testing.Short")
5284	}
5285
5286	t.Parallel()
5287
5288	_, srv, codec := testACLServerWithConfig(t, nil, false)
5289	waitForLeaderEstablishment(t, srv)
5290
5291	acl := ACL{srv: srv}
5292
5293	// spin up a fake oidc server
5294	oidcServer := startSSOTestServer(t)
5295	pubKey, privKey := oidcServer.SigningKeys()
5296
5297	type mConfig = map[string]interface{}
5298	cases := map[string]struct {
5299		f         func(config mConfig)
5300		issuer    string
5301		expectErr string
5302	}{
5303		"success - jwt static keys": {func(config mConfig) {
5304			config["BoundIssuer"] = "https://legit.issuer.internal/"
5305			config["JWTValidationPubKeys"] = []string{pubKey}
5306		},
5307			"https://legit.issuer.internal/",
5308			""},
5309		"success - jwt jwks": {func(config mConfig) {
5310			config["JWKSURL"] = oidcServer.Addr() + "/certs"
5311			config["JWKSCACert"] = oidcServer.CACert()
5312		},
5313			"https://legit.issuer.internal/",
5314			""},
5315		"success - jwt oidc discovery": {func(config mConfig) {
5316			config["OIDCDiscoveryURL"] = oidcServer.Addr()
5317			config["OIDCDiscoveryCACert"] = oidcServer.CACert()
5318		},
5319			oidcServer.Addr(),
5320			""},
5321	}
5322
5323	for name, tc := range cases {
5324		tc := tc
5325		t.Run(name, func(t *testing.T) {
5326			method, err := upsertTestCustomizedAuthMethod(codec, TestDefaultMasterToken, "dc1", func(method *structs.ACLAuthMethod) {
5327				method.Type = "jwt"
5328				method.Config = map[string]interface{}{
5329					"JWTSupportedAlgs": []string{"ES256"},
5330					"ClaimMappings": map[string]string{
5331						"first_name":   "name",
5332						"/org/primary": "primary_org",
5333					},
5334					"ListClaimMappings": map[string]string{
5335						"https://consul.test/groups": "groups",
5336					},
5337					"BoundAudiences": []string{"https://consul.test"},
5338				}
5339				if tc.f != nil {
5340					tc.f(method.Config)
5341				}
5342			})
5343			require.NoError(t, err)
5344
5345			t.Run("invalid bearer token", func(t *testing.T) {
5346				req := structs.ACLLoginRequest{
5347					Auth: &structs.ACLLoginParams{
5348						AuthMethod:  method.Name,
5349						BearerToken: "invalid",
5350					},
5351					Datacenter: "dc1",
5352				}
5353				resp := structs.ACLToken{}
5354
5355				require.Error(t, acl.Login(&req, &resp))
5356			})
5357
5358			cl := jwt.Claims{
5359				Subject:   "r3qXcK2bix9eFECzsU3Sbmh0K16fatW6@clients",
5360				Audience:  jwt.Audience{"https://consul.test"},
5361				Issuer:    tc.issuer,
5362				NotBefore: jwt.NewNumericDate(time.Now().Add(-5 * time.Second)),
5363				Expiry:    jwt.NewNumericDate(time.Now().Add(5 * time.Second)),
5364			}
5365
5366			type orgs struct {
5367				Primary string `json:"primary"`
5368			}
5369
5370			privateCl := struct {
5371				FirstName string   `json:"first_name"`
5372				Org       orgs     `json:"org"`
5373				Groups    []string `json:"https://consul.test/groups"`
5374			}{
5375				FirstName: "jeff2",
5376				Org:       orgs{"engineering"},
5377				Groups:    []string{"foo", "bar"},
5378			}
5379
5380			jwtData, err := oidcauthtest.SignJWT(privKey, cl, privateCl)
5381			require.NoError(t, err)
5382
5383			t.Run("valid bearer token no bindings", func(t *testing.T) {
5384				req := structs.ACLLoginRequest{
5385					Auth: &structs.ACLLoginParams{
5386						AuthMethod:  method.Name,
5387						BearerToken: jwtData,
5388					},
5389					Datacenter: "dc1",
5390				}
5391				resp := structs.ACLToken{}
5392
5393				testutil.RequireErrorContains(t, acl.Login(&req, &resp), "Permission denied")
5394			})
5395
5396			_, err = upsertTestBindingRule(
5397				codec, TestDefaultMasterToken, "dc1", method.Name,
5398				"value.name == jeff2 and value.primary_org == engineering and foo in list.groups",
5399				structs.BindingRuleBindTypeService,
5400				"test--${value.name}--${value.primary_org}",
5401			)
5402			require.NoError(t, err)
5403
5404			t.Run("valid bearer token 1 service binding", func(t *testing.T) {
5405				req := structs.ACLLoginRequest{
5406					Auth: &structs.ACLLoginParams{
5407						AuthMethod:  method.Name,
5408						BearerToken: jwtData,
5409					},
5410					Datacenter: "dc1",
5411				}
5412				resp := structs.ACLToken{}
5413
5414				require.NoError(t, acl.Login(&req, &resp))
5415
5416				require.Equal(t, method.Name, resp.AuthMethod)
5417				require.Equal(t, `token created via login`, resp.Description)
5418				require.True(t, resp.Local)
5419				require.Len(t, resp.Roles, 0)
5420				require.Len(t, resp.ServiceIdentities, 1)
5421				svcid := resp.ServiceIdentities[0]
5422				require.Len(t, svcid.Datacenters, 0)
5423				require.Equal(t, "test--jeff2--engineering", svcid.ServiceName)
5424			})
5425		})
5426	}
5427}
5428
5429func startSSOTestServer(t *testing.T) *oidcauthtest.Server {
5430	ports := freeport.MustTake(1)
5431	return oidcauthtest.Start(t, oidcauthtest.WithPort(
5432		ports[0],
5433		func() { freeport.Return(ports) },
5434	))
5435}
5436
5437func TestACLEndpoint_Logout(t *testing.T) {
5438	if testing.Short() {
5439		t.Skip("too slow for testing.Short")
5440	}
5441
5442	t.Parallel()
5443
5444	_, srv, codec := testACLServerWithConfig(t, nil, false)
5445	waitForLeaderEstablishment(t, srv)
5446
5447	acl := ACL{srv: srv}
5448
5449	testSessionID := testauth.StartSession()
5450	defer testauth.ResetSession(testSessionID)
5451	testauth.InstallSessionToken(
5452		testSessionID,
5453		"fake-db", // 1 rule
5454		"default", "db", "def456",
5455	)
5456
5457	method, err := upsertTestAuthMethod(codec, TestDefaultMasterToken, "dc1", testSessionID)
5458	require.NoError(t, err)
5459
5460	_, err = upsertTestBindingRule(
5461		codec, TestDefaultMasterToken, "dc1", method.Name,
5462		"",
5463		structs.BindingRuleBindTypeService,
5464		"method-${serviceaccount.name}",
5465	)
5466	require.NoError(t, err)
5467
5468	t.Run("you must provide a token", func(t *testing.T) {
5469		req := structs.ACLLogoutRequest{
5470			Datacenter: "dc1",
5471			// WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
5472		}
5473		req.Token = ""
5474		var ignored bool
5475
5476		testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "ACL not found")
5477	})
5478
5479	t.Run("logout from deleted token", func(t *testing.T) {
5480		req := structs.ACLLogoutRequest{
5481			Datacenter:   "dc1",
5482			WriteRequest: structs.WriteRequest{Token: "not-found"},
5483		}
5484		var ignored bool
5485		testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "ACL not found")
5486	})
5487
5488	t.Run("logout from non-auth method-linked token should fail", func(t *testing.T) {
5489		req := structs.ACLLogoutRequest{
5490			Datacenter:   "dc1",
5491			WriteRequest: structs.WriteRequest{Token: TestDefaultMasterToken},
5492		}
5493		var ignored bool
5494		testutil.RequireErrorContains(t, acl.Logout(&req, &ignored), "Permission denied")
5495	})
5496
5497	t.Run("login then logout", func(t *testing.T) {
5498		// Create a totally legit Login token.
5499		loginReq := structs.ACLLoginRequest{
5500			Auth: &structs.ACLLoginParams{
5501				AuthMethod:  method.Name,
5502				BearerToken: "fake-db",
5503			},
5504			Datacenter: "dc1",
5505		}
5506		loginToken := structs.ACLToken{}
5507
5508		require.NoError(t, acl.Login(&loginReq, &loginToken))
5509		require.NotEmpty(t, loginToken.SecretID)
5510
5511		// Now turn around and nuke it.
5512		req := structs.ACLLogoutRequest{
5513			Datacenter:   "dc1",
5514			WriteRequest: structs.WriteRequest{Token: loginToken.SecretID},
5515		}
5516
5517		var ignored bool
5518		require.NoError(t, acl.Logout(&req, &ignored))
5519	})
5520}
5521
5522func gatherIDs(t *testing.T, v interface{}) []string {
5523	t.Helper()
5524
5525	var out []string
5526	switch x := v.(type) {
5527	case []*structs.ACLRole:
5528		for _, r := range x {
5529			out = append(out, r.ID)
5530		}
5531	case structs.ACLRoles:
5532		for _, r := range x {
5533			out = append(out, r.ID)
5534		}
5535	case []*structs.ACLPolicy:
5536		for _, p := range x {
5537			out = append(out, p.ID)
5538		}
5539	case structs.ACLPolicyListStubs:
5540		for _, p := range x {
5541			out = append(out, p.ID)
5542		}
5543	case []*structs.ACLToken:
5544		for _, p := range x {
5545			out = append(out, p.AccessorID)
5546		}
5547	case structs.ACLTokenListStubs:
5548		for _, p := range x {
5549			out = append(out, p.AccessorID)
5550		}
5551	case []*structs.ACLAuthMethod:
5552		for _, p := range x {
5553			out = append(out, p.Name)
5554		}
5555	case structs.ACLAuthMethodListStubs:
5556		for _, p := range x {
5557			out = append(out, p.Name)
5558		}
5559	case []*structs.ACLBindingRule:
5560		for _, p := range x {
5561			out = append(out, p.ID)
5562		}
5563	case structs.ACLBindingRules:
5564		for _, p := range x {
5565			out = append(out, p.ID)
5566		}
5567	default:
5568		t.Fatalf("unknown type: %T", x)
5569	}
5570	return out
5571}
5572
5573func TestValidateBindingRuleBindName(t *testing.T) {
5574	t.Parallel()
5575
5576	type testcase struct {
5577		name     string
5578		bindType string
5579		bindName string
5580		fields   string
5581		valid    bool // valid HIL, invalid contents
5582		err      bool // invalid HIL
5583	}
5584
5585	for _, test := range []testcase{
5586		{"no bind type",
5587			"", "", "", false, false},
5588		{"bad bind type",
5589			"invalid", "blah", "", false, true},
5590		// valid HIL, invalid name
5591		{"empty",
5592			"both", "", "", false, false},
5593		{"just end",
5594			"both", "}", "", false, false},
5595		{"var without start",
5596			"both", " item }", "item", false, false},
5597		{"two vars missing second start",
5598			"both", "before-${ item }after--more }", "item,more", false, false},
5599		// names for the two types are validated differently
5600		{"@ is disallowed",
5601			"both", "bad@name", "", false, false},
5602		{"leading dash",
5603			"role", "-name", "", true, false},
5604		{"leading dash",
5605			"service", "-name", "", false, false},
5606		{"trailing dash",
5607			"role", "name-", "", true, false},
5608		{"trailing dash",
5609			"service", "name-", "", false, false},
5610		{"inner dash",
5611			"both", "name-end", "", true, false},
5612		{"upper case",
5613			"role", "NAME", "", true, false},
5614		{"upper case",
5615			"service", "NAME", "", false, false},
5616		// valid HIL, valid name
5617		{"no vars",
5618			"both", "nothing", "", true, false},
5619		{"just var",
5620			"both", "${item}", "item", true, false},
5621		{"var in middle",
5622			"both", "before-${item}after", "item", true, false},
5623		{"two vars",
5624			"both", "before-${item}after-${more}", "item,more", true, false},
5625		// bad
5626		{"no bind name",
5627			"both", "", "", false, false},
5628		{"just start",
5629			"both", "${", "", false, true},
5630		{"backwards",
5631			"both", "}${", "", false, true},
5632		{"no varname",
5633			"both", "${}", "", false, true},
5634		{"missing map key",
5635			"both", "${item}", "", false, true},
5636		{"var without end",
5637			"both", "${ item ", "item", false, true},
5638		{"two vars missing first end",
5639			"both", "before-${ item after-${ more }", "item,more", false, true},
5640	} {
5641		var cases []testcase
5642		if test.bindType == "both" {
5643			test1 := test
5644			test1.bindType = "role"
5645			test2 := test
5646			test2.bindType = "service"
5647			cases = []testcase{test1, test2}
5648		} else {
5649			cases = []testcase{test}
5650		}
5651
5652		for _, test := range cases {
5653			test := test
5654			t.Run(test.bindType+"--"+test.name, func(t *testing.T) {
5655				t.Parallel()
5656				valid, err := validateBindingRuleBindName(
5657					test.bindType,
5658					test.bindName,
5659					strings.Split(test.fields, ","),
5660				)
5661				if test.err {
5662					require.NotNil(t, err)
5663					require.False(t, valid)
5664				} else {
5665					require.NoError(t, err)
5666					require.Equal(t, test.valid, valid)
5667				}
5668			})
5669		}
5670	}
5671}
5672
5673// upsertTestToken creates a token for testing purposes
5674func upsertTestToken(codec rpc.ClientCodec, masterToken string, datacenter string,
5675	tokenModificationFn func(token *structs.ACLToken)) (*structs.ACLToken, error) {
5676	arg := structs.ACLTokenSetRequest{
5677		Datacenter: datacenter,
5678		ACLToken: structs.ACLToken{
5679			Description: "User token",
5680			Local:       false,
5681			Policies:    nil,
5682		},
5683		WriteRequest: structs.WriteRequest{Token: masterToken},
5684	}
5685
5686	if tokenModificationFn != nil {
5687		tokenModificationFn(&arg.ACLToken)
5688	}
5689
5690	var out structs.ACLToken
5691
5692	err := msgpackrpc.CallWithCodec(codec, "ACL.TokenSet", &arg, &out)
5693
5694	if err != nil {
5695		return nil, err
5696	}
5697
5698	if out.AccessorID == "" {
5699		return nil, fmt.Errorf("AccessorID is nil: %v", out)
5700	}
5701
5702	return &out, nil
5703}
5704
5705func upsertTestTokenWithPolicyRules(codec rpc.ClientCodec, masterToken string, datacenter string, rules string) (*structs.ACLToken, error) {
5706	policy, err := upsertTestPolicyWithRules(codec, masterToken, datacenter, rules)
5707	if err != nil {
5708		return nil, err
5709	}
5710
5711	token, err := upsertTestToken(codec, masterToken, datacenter, func(token *structs.ACLToken) {
5712		token.Policies = []structs.ACLTokenPolicyLink{{ID: policy.ID}}
5713	})
5714	if err != nil {
5715		return nil, err
5716	}
5717
5718	return token, nil
5719}
5720
5721func retrieveTestTokenAccessorForSecret(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (string, error) {
5722	arg := structs.ACLTokenGetRequest{
5723		TokenID:      id,
5724		TokenIDType:  structs.ACLTokenSecret,
5725		Datacenter:   datacenter,
5726		QueryOptions: structs.QueryOptions{Token: masterToken},
5727	}
5728
5729	var out structs.ACLTokenResponse
5730
5731	err := msgpackrpc.CallWithCodec(codec, "ACL.TokenRead", &arg, &out)
5732
5733	if err != nil {
5734		return "", err
5735	}
5736
5737	if out.Token == nil {
5738		return "", nil
5739	}
5740
5741	return out.Token.AccessorID, nil
5742}
5743
5744// retrieveTestToken returns a policy for testing purposes
5745func retrieveTestToken(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (*structs.ACLTokenResponse, error) {
5746	arg := structs.ACLTokenGetRequest{
5747		Datacenter:   datacenter,
5748		TokenID:      id,
5749		TokenIDType:  structs.ACLTokenAccessor,
5750		QueryOptions: structs.QueryOptions{Token: masterToken},
5751	}
5752
5753	var out structs.ACLTokenResponse
5754
5755	err := msgpackrpc.CallWithCodec(codec, "ACL.TokenRead", &arg, &out)
5756
5757	if err != nil {
5758		return nil, err
5759	}
5760
5761	return &out, nil
5762}
5763
5764func deleteTestToken(codec rpc.ClientCodec, masterToken string, datacenter string, tokenAccessor string) error {
5765	arg := structs.ACLTokenDeleteRequest{
5766		Datacenter:   datacenter,
5767		TokenID:      tokenAccessor,
5768		WriteRequest: structs.WriteRequest{Token: masterToken},
5769	}
5770
5771	var ignored string
5772	err := msgpackrpc.CallWithCodec(codec, "ACL.TokenDelete", &arg, &ignored)
5773	return err
5774}
5775
5776func deleteTestPolicy(codec rpc.ClientCodec, masterToken string, datacenter string, policyID string) error {
5777	arg := structs.ACLPolicyDeleteRequest{
5778		Datacenter:   datacenter,
5779		PolicyID:     policyID,
5780		WriteRequest: structs.WriteRequest{Token: masterToken},
5781	}
5782
5783	var ignored string
5784	err := msgpackrpc.CallWithCodec(codec, "ACL.PolicyDelete", &arg, &ignored)
5785	return err
5786}
5787
5788func upsertTestCustomizedPolicy(codec rpc.ClientCodec, masterToken string, datacenter string, policyModificationFn func(policy *structs.ACLPolicy)) (*structs.ACLPolicy, error) {
5789	// Make sure test policies can't collide
5790	policyUnq, err := uuid.GenerateUUID()
5791	if err != nil {
5792		return nil, err
5793	}
5794
5795	arg := structs.ACLPolicySetRequest{
5796		Datacenter: datacenter,
5797		Policy: structs.ACLPolicy{
5798			Name: fmt.Sprintf("test-policy-%s", policyUnq),
5799		},
5800		WriteRequest: structs.WriteRequest{Token: masterToken},
5801	}
5802
5803	if policyModificationFn != nil {
5804		policyModificationFn(&arg.Policy)
5805	}
5806
5807	var out structs.ACLPolicy
5808
5809	err = msgpackrpc.CallWithCodec(codec, "ACL.PolicySet", &arg, &out)
5810
5811	if err != nil {
5812		return nil, err
5813	}
5814
5815	if out.ID == "" {
5816		return nil, fmt.Errorf("ID is nil: %v", out)
5817	}
5818
5819	return &out, nil
5820}
5821
5822// upsertTestPolicy creates a policy for testing purposes
5823func upsertTestPolicy(codec rpc.ClientCodec, masterToken string, datacenter string) (*structs.ACLPolicy, error) {
5824	return upsertTestPolicyWithRules(codec, masterToken, datacenter, "")
5825}
5826
5827func upsertTestPolicyWithRules(codec rpc.ClientCodec, masterToken string, datacenter string, rules string) (*structs.ACLPolicy, error) {
5828	return upsertTestCustomizedPolicy(codec, masterToken, datacenter, func(policy *structs.ACLPolicy) {
5829		policy.Rules = rules
5830	})
5831}
5832
5833// retrieveTestPolicy returns a policy for testing purposes
5834func retrieveTestPolicy(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (*structs.ACLPolicyResponse, error) {
5835	arg := structs.ACLPolicyGetRequest{
5836		Datacenter:   datacenter,
5837		PolicyID:     id,
5838		QueryOptions: structs.QueryOptions{Token: masterToken},
5839	}
5840
5841	var out structs.ACLPolicyResponse
5842
5843	err := msgpackrpc.CallWithCodec(codec, "ACL.PolicyRead", &arg, &out)
5844
5845	if err != nil {
5846		return nil, err
5847	}
5848
5849	return &out, nil
5850}
5851
5852func deleteTestRole(codec rpc.ClientCodec, masterToken string, datacenter string, roleID string) error {
5853	arg := structs.ACLRoleDeleteRequest{
5854		Datacenter:   datacenter,
5855		RoleID:       roleID,
5856		WriteRequest: structs.WriteRequest{Token: masterToken},
5857	}
5858
5859	var ignored string
5860	err := msgpackrpc.CallWithCodec(codec, "ACL.RoleDelete", &arg, &ignored)
5861	return err
5862}
5863
5864func deleteTestRoleByName(codec rpc.ClientCodec, masterToken string, datacenter string, roleName string) error {
5865	resp, err := retrieveTestRoleByName(codec, masterToken, datacenter, roleName)
5866	if err != nil {
5867		return err
5868	}
5869	if resp.Role == nil {
5870		return nil
5871	}
5872
5873	return deleteTestRole(codec, masterToken, datacenter, resp.Role.ID)
5874}
5875
5876// upsertTestRole creates a role for testing purposes
5877func upsertTestRole(codec rpc.ClientCodec, masterToken string, datacenter string) (*structs.ACLRole, error) {
5878	return upsertTestCustomizedRole(codec, masterToken, datacenter, nil)
5879}
5880
5881func upsertTestCustomizedRole(codec rpc.ClientCodec, masterToken string, datacenter string, modify func(role *structs.ACLRole)) (*structs.ACLRole, error) {
5882	// Make sure test roles can't collide
5883	roleUnq, err := uuid.GenerateUUID()
5884	if err != nil {
5885		return nil, err
5886	}
5887
5888	arg := structs.ACLRoleSetRequest{
5889		Datacenter: datacenter,
5890		Role: structs.ACLRole{
5891			Name: fmt.Sprintf("test-role-%s", roleUnq),
5892		},
5893		WriteRequest: structs.WriteRequest{Token: masterToken},
5894	}
5895
5896	if modify != nil {
5897		modify(&arg.Role)
5898	}
5899
5900	var out structs.ACLRole
5901
5902	err = msgpackrpc.CallWithCodec(codec, "ACL.RoleSet", &arg, &out)
5903
5904	if err != nil {
5905		return nil, err
5906	}
5907
5908	if out.ID == "" {
5909		return nil, fmt.Errorf("ID is nil: %v", out)
5910	}
5911
5912	return &out, nil
5913}
5914
5915func retrieveTestRole(codec rpc.ClientCodec, masterToken string, datacenter string, id string) (*structs.ACLRoleResponse, error) {
5916	arg := structs.ACLRoleGetRequest{
5917		Datacenter:   datacenter,
5918		RoleID:       id,
5919		QueryOptions: structs.QueryOptions{Token: masterToken},
5920	}
5921
5922	var out structs.ACLRoleResponse
5923
5924	err := msgpackrpc.CallWithCodec(codec, "ACL.RoleRead", &arg, &out)
5925
5926	if err != nil {
5927		return nil, err
5928	}
5929
5930	return &out, nil
5931}
5932
5933func retrieveTestRoleByName(codec rpc.ClientCodec, masterToken string, datacenter string, name string) (*structs.ACLRoleResponse, error) {
5934	arg := structs.ACLRoleGetRequest{
5935		Datacenter:   datacenter,
5936		RoleName:     name,
5937		QueryOptions: structs.QueryOptions{Token: masterToken},
5938	}
5939
5940	var out structs.ACLRoleResponse
5941
5942	err := msgpackrpc.CallWithCodec(codec, "ACL.RoleRead", &arg, &out)
5943
5944	if err != nil {
5945		return nil, err
5946	}
5947
5948	return &out, nil
5949}
5950
5951func deleteTestAuthMethod(codec rpc.ClientCodec, masterToken string, datacenter string, methodName string) error {
5952	arg := structs.ACLAuthMethodDeleteRequest{
5953		Datacenter:     datacenter,
5954		AuthMethodName: methodName,
5955		WriteRequest:   structs.WriteRequest{Token: masterToken},
5956	}
5957
5958	var ignored string
5959	err := msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodDelete", &arg, &ignored)
5960	return err
5961}
5962func upsertTestAuthMethod(
5963	codec rpc.ClientCodec, masterToken string, datacenter string,
5964	sessionID string,
5965) (*structs.ACLAuthMethod, error) {
5966	return upsertTestCustomizedAuthMethod(codec, masterToken, datacenter, func(method *structs.ACLAuthMethod) {
5967		method.Config = map[string]interface{}{
5968			"SessionID": sessionID,
5969		}
5970	})
5971}
5972
5973func upsertTestCustomizedAuthMethod(
5974	codec rpc.ClientCodec, masterToken string, datacenter string,
5975	modify func(method *structs.ACLAuthMethod),
5976) (*structs.ACLAuthMethod, error) {
5977	name, err := uuid.GenerateUUID()
5978	if err != nil {
5979		return nil, err
5980	}
5981
5982	req := structs.ACLAuthMethodSetRequest{
5983		Datacenter: datacenter,
5984		AuthMethod: structs.ACLAuthMethod{
5985			Name: "test-method-" + name,
5986			Type: "testing",
5987		},
5988		WriteRequest: structs.WriteRequest{Token: masterToken},
5989	}
5990
5991	if modify != nil {
5992		modify(&req.AuthMethod)
5993	}
5994
5995	var out structs.ACLAuthMethod
5996
5997	err = msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodSet", &req, &out)
5998	if err != nil {
5999		return nil, err
6000	}
6001
6002	return &out, nil
6003}
6004
6005func upsertTestKubernetesAuthMethod(
6006	codec rpc.ClientCodec, masterToken string, datacenter string,
6007	caCert, kubeHost, kubeJWT string,
6008) (*structs.ACLAuthMethod, error) {
6009	name, err := uuid.GenerateUUID()
6010	if err != nil {
6011		return nil, err
6012	}
6013
6014	if kubeHost == "" {
6015		kubeHost = "https://abc:8443"
6016	}
6017	if kubeJWT == "" {
6018		kubeJWT = goodJWT_A
6019	}
6020
6021	req := structs.ACLAuthMethodSetRequest{
6022		Datacenter: datacenter,
6023		AuthMethod: structs.ACLAuthMethod{
6024			Name: "test-method-" + name,
6025			Type: "kubernetes",
6026			Config: map[string]interface{}{
6027				"Host":              kubeHost,
6028				"CACert":            caCert,
6029				"ServiceAccountJWT": kubeJWT,
6030			},
6031		},
6032		WriteRequest: structs.WriteRequest{Token: masterToken},
6033	}
6034
6035	var out structs.ACLAuthMethod
6036
6037	err = msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodSet", &req, &out)
6038	if err != nil {
6039		return nil, err
6040	}
6041
6042	return &out, nil
6043}
6044
6045func retrieveTestAuthMethod(codec rpc.ClientCodec, masterToken string, datacenter string, name string) (*structs.ACLAuthMethodResponse, error) {
6046	arg := structs.ACLAuthMethodGetRequest{
6047		Datacenter:     datacenter,
6048		AuthMethodName: name,
6049		QueryOptions:   structs.QueryOptions{Token: masterToken},
6050	}
6051
6052	var out structs.ACLAuthMethodResponse
6053
6054	err := msgpackrpc.CallWithCodec(codec, "ACL.AuthMethodRead", &arg, &out)
6055
6056	if err != nil {
6057		return nil, err
6058	}
6059
6060	return &out, nil
6061}
6062
6063func deleteTestBindingRule(codec rpc.ClientCodec, masterToken string, datacenter string, ruleID string) error {
6064	arg := structs.ACLBindingRuleDeleteRequest{
6065		Datacenter:    datacenter,
6066		BindingRuleID: ruleID,
6067		WriteRequest:  structs.WriteRequest{Token: masterToken},
6068	}
6069
6070	var ignored string
6071	err := msgpackrpc.CallWithCodec(codec, "ACL.BindingRuleDelete", &arg, &ignored)
6072	return err
6073}
6074
6075func upsertTestBindingRule(
6076	codec rpc.ClientCodec,
6077	masterToken string,
6078	datacenter string,
6079	methodName string,
6080	selector string,
6081	bindType string,
6082	bindName string,
6083) (*structs.ACLBindingRule, error) {
6084	return upsertTestCustomizedBindingRule(codec, masterToken, datacenter, func(rule *structs.ACLBindingRule) {
6085		rule.AuthMethod = methodName
6086		rule.BindType = bindType
6087		rule.BindName = bindName
6088		rule.Selector = selector
6089	})
6090}
6091
6092func upsertTestCustomizedBindingRule(codec rpc.ClientCodec, masterToken string, datacenter string, modify func(rule *structs.ACLBindingRule)) (*structs.ACLBindingRule, error) {
6093	req := structs.ACLBindingRuleSetRequest{
6094		Datacenter:   datacenter,
6095		BindingRule:  structs.ACLBindingRule{},
6096		WriteRequest: structs.WriteRequest{Token: masterToken},
6097	}
6098
6099	if modify != nil {
6100		modify(&req.BindingRule)
6101	}
6102
6103	var out structs.ACLBindingRule
6104
6105	err := msgpackrpc.CallWithCodec(codec, "ACL.BindingRuleSet", &req, &out)
6106	if err != nil {
6107		return nil, err
6108	}
6109
6110	return &out, nil
6111}
6112
6113func retrieveTestBindingRule(codec rpc.ClientCodec, masterToken string, datacenter string, ruleID string) (*structs.ACLBindingRuleResponse, error) {
6114	arg := structs.ACLBindingRuleGetRequest{
6115		Datacenter:    datacenter,
6116		BindingRuleID: ruleID,
6117		QueryOptions:  structs.QueryOptions{Token: masterToken},
6118	}
6119
6120	var out structs.ACLBindingRuleResponse
6121
6122	err := msgpackrpc.CallWithCodec(codec, "ACL.BindingRuleRead", &arg, &out)
6123
6124	if err != nil {
6125		return nil, err
6126	}
6127
6128	return &out, nil
6129}
6130
6131func requireTimeEquals(t *testing.T, expect, got *time.Time) {
6132	t.Helper()
6133	if expect == nil && got == nil {
6134		return
6135	} else if expect == nil && got != nil {
6136		t.Fatalf("expected=NIL != got=%q", *got)
6137	} else if expect != nil && got == nil {
6138		t.Fatalf("expected=%q != got=NIL", *expect)
6139	} else if !expect.Equal(*got) {
6140		t.Fatalf("expected=%q != got=%q", *expect, *got)
6141	}
6142}
6143
6144// 'default/admin'
6145const goodJWT_A = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFkbWluLXRva2VuLXFsejQyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNzM4YmMyNTEtNjUzMi0xMWU5LWI2N2YtNDhlNmM4YjhlY2I1Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6YWRtaW4ifQ.ixMlnWrAG7NVuTTKu8cdcYfM7gweS3jlKaEsIBNGOVEjPE7rtXtgMkAwjQTdYR08_0QBjkgzy5fQC5ZNyglSwONJ-bPaXGvhoH1cTnRi1dz9H_63CfqOCvQP1sbdkMeRxNTGVAyWZT76rXoCUIfHP4LY2I8aab0KN9FTIcgZRF0XPTtT70UwGIrSmRpxW38zjiy2ymWL01cc5VWGhJqVysmWmYk3wNp0h5N57H_MOrz4apQR4pKaamzskzjLxO55gpbmZFC76qWuUdexAR7DT2fpbHLOw90atN_NlLMY-VrXyW3-Ei5EhYaVreMB9PSpKwkrA4jULITohV-sxpa1LA"
6146
6147// 'default/demo'
6148const goodJWT_B = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlbW8tdG9rZW4ta21iOW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVtbyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6Ijc2MDkxYWY0LTRiNTYtMTFlOS1hYzRiLTcwOGIxMTgwMWNiZSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlbW8ifQ.ZiAHjijBAOsKdum0Aix6lgtkLkGo9_Tu87dWQ5Zfwnn3r2FejEWDAnftTft1MqqnMzivZ9Wyyki5ZjQRmTAtnMPJuHC-iivqY4Wh4S6QWCJ1SivBv5tMZR79t5t8mE7R1-OHwst46spru1pps9wt9jsA04d3LpV0eeKYgdPTVaQKklxTm397kIMUugA6yINIBQ3Rh8eQqBgNwEmL4iqyYubzHLVkGkoP9MJikFI05vfRiHtYr-piXz6JFDzXMQj9rW6xtMmrBSn79ChbyvC5nz-Nj2rJPnHsb_0rDUbmXY5PpnMhBpdSH-CbZ4j8jsiib6DtaGJhVZeEQ1GjsFAZwQ"
6149