1package api
2
3import (
4	"strings"
5	"testing"
6
7	"github.com/hashicorp/consul/sdk/testutil/retry"
8
9	"github.com/stretchr/testify/require"
10)
11
12func TestAPI_ACLBootstrap(t *testing.T) {
13	// TODO (slackpad) We currently can't inject the version, and the
14	// version in the binary depends on Git tags, so we can't reliably
15	// test this until we are just running an agent in-process here and
16	// have full control over the config.
17}
18
19func TestAPI_ACLCreateDestroy(t *testing.T) {
20	t.Parallel()
21	c, s := makeACLClient(t)
22	defer s.Stop()
23	s.WaitForSerfCheck(t)
24
25	acl := c.ACL()
26
27	ae := ACLEntry{
28		Name:  "API test",
29		Type:  ACLClientType,
30		Rules: `key "" { policy = "deny" }`,
31	}
32
33	id, wm, err := acl.Create(&ae, nil)
34	if err != nil {
35		t.Fatalf("err: %v", err)
36	}
37
38	if wm.RequestTime == 0 {
39		t.Fatalf("bad: %v", wm)
40	}
41
42	if id == "" {
43		t.Fatalf("invalid: %v", id)
44	}
45
46	ae2, _, err := acl.Info(id, nil)
47	if err != nil {
48		t.Fatalf("err: %v", err)
49	}
50
51	if ae2.Name != ae.Name || ae2.Type != ae.Type || ae2.Rules != ae.Rules {
52		t.Fatalf("Bad: %#v", ae2)
53	}
54
55	wm, err = acl.Destroy(id, nil)
56	if err != nil {
57		t.Fatalf("err: %v", err)
58	}
59
60	if wm.RequestTime == 0 {
61		t.Fatalf("bad: %v", wm)
62	}
63}
64
65func TestAPI_ACLCloneDestroy(t *testing.T) {
66	t.Parallel()
67	c, s := makeACLClient(t)
68	defer s.Stop()
69
70	acl := c.ACL()
71
72	id, wm, err := acl.Clone(c.config.Token, nil)
73	if err != nil {
74		t.Fatalf("err: %v", err)
75	}
76
77	if wm.RequestTime == 0 {
78		t.Fatalf("bad: %v", wm)
79	}
80
81	if id == "" {
82		t.Fatalf("invalid: %v", id)
83	}
84
85	wm, err = acl.Destroy(id, nil)
86	if err != nil {
87		t.Fatalf("err: %v", err)
88	}
89
90	if wm.RequestTime == 0 {
91		t.Fatalf("bad: %v", wm)
92	}
93}
94
95func TestAPI_ACLInfo(t *testing.T) {
96	t.Parallel()
97	c, s := makeACLClient(t)
98	defer s.Stop()
99
100	acl := c.ACL()
101
102	ae, qm, err := acl.Info(c.config.Token, nil)
103	if err != nil {
104		t.Fatalf("err: %v", err)
105	}
106
107	if qm.LastIndex == 0 {
108		t.Fatalf("bad: %v", qm)
109	}
110	if !qm.KnownLeader {
111		t.Fatalf("bad: %v", qm)
112	}
113
114	if ae == nil || ae.ID != c.config.Token || ae.Type != ACLManagementType {
115		t.Fatalf("bad: %#v", ae)
116	}
117}
118
119func TestAPI_ACLList(t *testing.T) {
120	t.Parallel()
121	c, s := makeACLClient(t)
122	defer s.Stop()
123
124	acl := c.ACL()
125
126	acls, qm, err := acl.List(nil)
127	if err != nil {
128		t.Fatalf("err: %v", err)
129	}
130
131	// anon token is a new token
132	if len(acls) < 1 {
133		t.Fatalf("bad: %v", acls)
134	}
135
136	if qm.LastIndex == 0 {
137		t.Fatalf("bad: %v", qm)
138	}
139	if !qm.KnownLeader {
140		t.Fatalf("bad: %v", qm)
141	}
142}
143
144func TestAPI_ACLReplication(t *testing.T) {
145	t.Parallel()
146	c, s := makeACLClient(t)
147	defer s.Stop()
148
149	acl := c.ACL()
150
151	repl, qm, err := acl.Replication(nil)
152	if err != nil {
153		t.Fatalf("err: %v", err)
154	}
155
156	if repl == nil {
157		t.Fatalf("bad: %v", repl)
158	}
159
160	if repl.Running {
161		t.Fatal("bad: repl should not be running")
162	}
163
164	if repl.Enabled {
165		t.Fatal("bad: repl should not be enabled")
166	}
167
168	if qm.RequestTime == 0 {
169		t.Fatalf("bad: %v", qm)
170	}
171}
172
173func TestAPI_ACLPolicy_CreateReadDelete(t *testing.T) {
174	t.Parallel()
175	c, s := makeACLClient(t)
176	defer s.Stop()
177
178	acl := c.ACL()
179
180	created, wm, err := acl.PolicyCreate(&ACLPolicy{
181		Name:        "test-policy",
182		Description: "test-policy description",
183		Rules:       `node_prefix "" { policy = "read" }`,
184		Datacenters: []string{"dc1"},
185	}, nil)
186
187	require.NoError(t, err)
188	require.NotNil(t, created)
189	require.NotEqual(t, "", created.ID)
190	require.NotEqual(t, 0, wm.RequestTime)
191
192	read, qm, err := acl.PolicyRead(created.ID, nil)
193	require.NoError(t, err)
194	require.NotEqual(t, 0, qm.LastIndex)
195	require.True(t, qm.KnownLeader)
196
197	require.Equal(t, created, read)
198
199	wm, err = acl.PolicyDelete(created.ID, nil)
200	require.NoError(t, err)
201	require.NotEqual(t, 0, wm.RequestTime)
202
203	read, _, err = acl.PolicyRead(created.ID, nil)
204	require.Nil(t, read)
205	require.Error(t, err)
206}
207
208func TestAPI_ACLPolicy_CreateReadByNameDelete(t *testing.T) {
209	t.Parallel()
210	c, s := makeACLClient(t)
211	defer s.Stop()
212
213	acl := c.ACL()
214
215	created, wm, err := acl.PolicyCreate(&ACLPolicy{
216		Name:        "test-policy",
217		Description: "test-policy description",
218		Rules:       `node_prefix "" { policy = "read" }`,
219		Datacenters: []string{"dc1"},
220	}, nil)
221
222	require.NoError(t, err)
223	require.NotNil(t, created)
224	require.NotEqual(t, "", created.ID)
225	require.NotEqual(t, 0, wm.RequestTime)
226
227	read, qm, err := acl.PolicyReadByName(created.Name, nil)
228	require.NoError(t, err)
229	require.NotEqual(t, 0, qm.LastIndex)
230	require.True(t, qm.KnownLeader)
231
232	require.Equal(t, created, read)
233
234	wm, err = acl.PolicyDelete(created.ID, nil)
235	require.NoError(t, err)
236	require.NotEqual(t, 0, wm.RequestTime)
237
238	read, _, err = acl.PolicyRead(created.ID, nil)
239	require.Nil(t, read)
240	require.Error(t, err)
241}
242
243func TestAPI_ACLPolicy_CreateUpdate(t *testing.T) {
244	t.Parallel()
245	c, s := makeACLClient(t)
246	defer s.Stop()
247
248	acl := c.ACL()
249
250	created, _, err := acl.PolicyCreate(&ACLPolicy{
251		Name:        "test-policy",
252		Description: "test-policy description",
253		Rules:       `node_prefix "" { policy = "read" }`,
254		Datacenters: []string{"dc1"},
255	}, nil)
256
257	require.NoError(t, err)
258	require.NotNil(t, created)
259	require.NotEqual(t, "", created.ID)
260
261	read, _, err := acl.PolicyRead(created.ID, nil)
262	require.NoError(t, err)
263	require.Equal(t, created, read)
264
265	read.Rules += ` service_prefix "" { policy = "read" }`
266	read.Datacenters = nil
267
268	updated, wm, err := acl.PolicyUpdate(read, nil)
269	require.NoError(t, err)
270	require.Equal(t, created.ID, updated.ID)
271	require.Equal(t, created.Description, updated.Description)
272	require.Equal(t, read.Rules, updated.Rules)
273	require.Equal(t, created.CreateIndex, updated.CreateIndex)
274	require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex)
275	require.Nil(t, updated.Datacenters)
276	require.NotEqual(t, 0, wm.RequestTime)
277
278	updated_read, _, err := acl.PolicyRead(created.ID, nil)
279	require.NoError(t, err)
280	require.Equal(t, updated, updated_read)
281}
282
283func TestAPI_ACLPolicy_List(t *testing.T) {
284	t.Parallel()
285	c, s := makeACLClient(t)
286	defer s.Stop()
287
288	acl := c.ACL()
289
290	created1, _, err := acl.PolicyCreate(&ACLPolicy{
291		Name:        "policy1",
292		Description: "policy1 description",
293		Rules:       `node_prefix "" { policy = "read" }`,
294		Datacenters: []string{"dc1"},
295	}, nil)
296
297	require.NoError(t, err)
298	require.NotNil(t, created1)
299	require.NotEqual(t, "", created1.ID)
300
301	created2, _, err := acl.PolicyCreate(&ACLPolicy{
302		Name:        "policy2",
303		Description: "policy2 description",
304		Rules:       `service "app" { policy = "write" }`,
305		Datacenters: []string{"dc1", "dc2"},
306	}, nil)
307
308	require.NoError(t, err)
309	require.NotNil(t, created2)
310	require.NotEqual(t, "", created2.ID)
311
312	created3, _, err := acl.PolicyCreate(&ACLPolicy{
313		Name:        "policy3",
314		Description: "policy3 description",
315		Rules:       `acl = "read"`,
316	}, nil)
317
318	require.NoError(t, err)
319	require.NotNil(t, created3)
320	require.NotEqual(t, "", created3.ID)
321
322	policies, qm, err := acl.PolicyList(nil)
323	require.NoError(t, err)
324	require.Len(t, policies, 4)
325	require.NotEqual(t, 0, qm.LastIndex)
326	require.True(t, qm.KnownLeader)
327
328	policyMap := make(map[string]*ACLPolicyListEntry)
329	for _, policy := range policies {
330		policyMap[policy.ID] = policy
331	}
332
333	policy1, ok := policyMap[created1.ID]
334	require.True(t, ok)
335	require.NotNil(t, policy1)
336	require.Equal(t, created1.Name, policy1.Name)
337	require.Equal(t, created1.Description, policy1.Description)
338	require.Equal(t, created1.CreateIndex, policy1.CreateIndex)
339	require.Equal(t, created1.ModifyIndex, policy1.ModifyIndex)
340	require.Equal(t, created1.Hash, policy1.Hash)
341	require.ElementsMatch(t, created1.Datacenters, policy1.Datacenters)
342
343	policy2, ok := policyMap[created2.ID]
344	require.True(t, ok)
345	require.NotNil(t, policy2)
346	require.Equal(t, created2.Name, policy2.Name)
347	require.Equal(t, created2.Description, policy2.Description)
348	require.Equal(t, created2.CreateIndex, policy2.CreateIndex)
349	require.Equal(t, created2.ModifyIndex, policy2.ModifyIndex)
350	require.Equal(t, created2.Hash, policy2.Hash)
351	require.ElementsMatch(t, created2.Datacenters, policy2.Datacenters)
352
353	policy3, ok := policyMap[created3.ID]
354	require.True(t, ok)
355	require.NotNil(t, policy3)
356	require.Equal(t, created3.Name, policy3.Name)
357	require.Equal(t, created3.Description, policy3.Description)
358	require.Equal(t, created3.CreateIndex, policy3.CreateIndex)
359	require.Equal(t, created3.ModifyIndex, policy3.ModifyIndex)
360	require.Equal(t, created3.Hash, policy3.Hash)
361	require.ElementsMatch(t, created3.Datacenters, policy3.Datacenters)
362
363	// make sure the 4th policy is the global management
364	policy4, ok := policyMap["00000000-0000-0000-0000-000000000001"]
365	require.True(t, ok)
366	require.NotNil(t, policy4)
367}
368
369func prepTokenPolicies(t *testing.T, acl *ACL) (policies []*ACLPolicy) {
370	policy, _, err := acl.PolicyCreate(&ACLPolicy{
371		Name:        "one",
372		Description: "one description",
373		Rules:       `acl = "read"`,
374		Datacenters: []string{"dc1", "dc2"},
375	}, nil)
376
377	require.NoError(t, err)
378	require.NotNil(t, policy)
379	policies = append(policies, policy)
380
381	policy, _, err = acl.PolicyCreate(&ACLPolicy{
382		Name:        "two",
383		Description: "two description",
384		Rules:       `node_prefix "" { policy = "read" }`,
385		Datacenters: []string{"dc1", "dc2"},
386	}, nil)
387
388	require.NoError(t, err)
389	require.NotNil(t, policy)
390	policies = append(policies, policy)
391
392	policy, _, err = acl.PolicyCreate(&ACLPolicy{
393		Name:        "three",
394		Description: "three description",
395		Rules:       `service_prefix "" { policy = "read" }`,
396	}, nil)
397
398	require.NoError(t, err)
399	require.NotNil(t, policy)
400	policies = append(policies, policy)
401
402	policy, _, err = acl.PolicyCreate(&ACLPolicy{
403		Name:        "four",
404		Description: "four description",
405		Rules:       `agent "foo" { policy = "write" }`,
406	}, nil)
407
408	require.NoError(t, err)
409	require.NotNil(t, policy)
410	policies = append(policies, policy)
411	return
412}
413
414func TestAPI_ACLToken_CreateReadDelete(t *testing.T) {
415	t.Parallel()
416	c, s := makeACLClient(t)
417	defer s.Stop()
418
419	acl := c.ACL()
420
421	policies := prepTokenPolicies(t, acl)
422
423	created, wm, err := acl.TokenCreate(&ACLToken{
424		Description: "token created",
425		Policies: []*ACLTokenPolicyLink{
426			&ACLTokenPolicyLink{
427				ID: policies[0].ID,
428			},
429			&ACLTokenPolicyLink{
430				ID: policies[1].ID,
431			},
432			&ACLTokenPolicyLink{
433				Name: policies[2].Name,
434			},
435			&ACLTokenPolicyLink{
436				Name: policies[3].Name,
437			},
438		},
439	}, nil)
440
441	require.NoError(t, err)
442	require.NotNil(t, created)
443	require.NotEqual(t, "", created.AccessorID)
444	require.NotEqual(t, "", created.SecretID)
445	require.NotEqual(t, 0, wm.RequestTime)
446
447	read, qm, err := acl.TokenRead(created.AccessorID, nil)
448	require.NoError(t, err)
449	require.Equal(t, created, read)
450	require.NotEqual(t, 0, qm.LastIndex)
451	require.True(t, qm.KnownLeader)
452
453	acl.c.config.Token = created.SecretID
454	self, _, err := acl.TokenReadSelf(nil)
455	require.NoError(t, err)
456	require.Equal(t, created, self)
457	acl.c.config.Token = "root"
458
459	_, err = acl.TokenDelete(created.AccessorID, nil)
460	require.NoError(t, err)
461
462	read, _, err = acl.TokenRead(created.AccessorID, nil)
463	require.Nil(t, read)
464	require.Error(t, err)
465}
466
467func TestAPI_ACLToken_CreateUpdate(t *testing.T) {
468	t.Parallel()
469	c, s := makeACLClient(t)
470	defer s.Stop()
471
472	acl := c.ACL()
473
474	policies := prepTokenPolicies(t, acl)
475
476	created, _, err := acl.TokenCreate(&ACLToken{
477		Description: "token created",
478		Policies: []*ACLTokenPolicyLink{
479			&ACLTokenPolicyLink{
480				ID: policies[0].ID,
481			},
482			&ACLTokenPolicyLink{
483				Name: policies[2].Name,
484			},
485		},
486	}, nil)
487
488	require.NoError(t, err)
489	require.NotNil(t, created)
490	require.NotEqual(t, "", created.AccessorID)
491	require.NotEqual(t, "", created.SecretID)
492
493	read, _, err := acl.TokenRead(created.AccessorID, nil)
494	require.NoError(t, err)
495	require.Equal(t, created, read)
496
497	read.Policies = append(read.Policies, &ACLTokenPolicyLink{ID: policies[1].ID})
498	read.Policies = append(read.Policies, &ACLTokenPolicyLink{Name: policies[2].Name})
499
500	expectedPolicies := []*ACLTokenPolicyLink{
501		&ACLTokenPolicyLink{
502			ID:   policies[0].ID,
503			Name: policies[0].Name,
504		},
505		&ACLTokenPolicyLink{
506			ID:   policies[1].ID,
507			Name: policies[1].Name,
508		},
509		&ACLTokenPolicyLink{
510			ID:   policies[2].ID,
511			Name: policies[2].Name,
512		},
513	}
514
515	updated, wm, err := acl.TokenUpdate(read, nil)
516	require.NoError(t, err)
517	require.Equal(t, created.AccessorID, updated.AccessorID)
518	require.Equal(t, created.SecretID, updated.SecretID)
519	require.Equal(t, created.Description, updated.Description)
520	require.Equal(t, created.CreateIndex, updated.CreateIndex)
521	require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex)
522	require.ElementsMatch(t, expectedPolicies, updated.Policies)
523	require.NotEqual(t, 0, wm.RequestTime)
524
525	updated_read, _, err := acl.TokenRead(created.AccessorID, nil)
526	require.NoError(t, err)
527	require.Equal(t, updated, updated_read)
528}
529
530func TestAPI_ACLToken_List(t *testing.T) {
531	t.Parallel()
532	c, s := makeACLClient(t)
533	defer s.Stop()
534
535	acl := c.ACL()
536	s.WaitForSerfCheck(t)
537
538	policies := prepTokenPolicies(t, acl)
539
540	created1, _, err := acl.TokenCreate(&ACLToken{
541		Description: "token created1",
542		Policies: []*ACLTokenPolicyLink{
543			&ACLTokenPolicyLink{
544				ID: policies[0].ID,
545			},
546		},
547	}, nil)
548
549	require.NoError(t, err)
550	require.NotNil(t, created1)
551	require.NotEqual(t, "", created1.AccessorID)
552	require.NotEqual(t, "", created1.SecretID)
553
554	created2, _, err := acl.TokenCreate(&ACLToken{
555		Description: "token created2",
556		Policies: []*ACLTokenPolicyLink{
557			&ACLTokenPolicyLink{
558				ID: policies[1].ID,
559			},
560		},
561	}, nil)
562
563	require.NoError(t, err)
564	require.NotNil(t, created2)
565	require.NotEqual(t, "", created2.AccessorID)
566	require.NotEqual(t, "", created2.SecretID)
567
568	created3, _, err := acl.TokenCreate(&ACLToken{
569		Description: "token created3",
570		Policies: []*ACLTokenPolicyLink{
571			&ACLTokenPolicyLink{
572				ID: policies[2].ID,
573			},
574		},
575	}, nil)
576
577	require.NoError(t, err)
578	require.NotNil(t, created3)
579	require.NotEqual(t, "", created3.AccessorID)
580	require.NotEqual(t, "", created3.SecretID)
581
582	tokens, qm, err := acl.TokenList(nil)
583	require.NoError(t, err)
584	// 3 + anon + master
585	require.Len(t, tokens, 5)
586	require.NotEqual(t, 0, qm.LastIndex)
587	require.True(t, qm.KnownLeader)
588
589	tokenMap := make(map[string]*ACLTokenListEntry)
590	for _, token := range tokens {
591		tokenMap[token.AccessorID] = token
592	}
593
594	token1, ok := tokenMap[created1.AccessorID]
595	require.True(t, ok)
596	require.NotNil(t, token1)
597	require.Equal(t, created1.Description, token1.Description)
598	require.Equal(t, created1.CreateIndex, token1.CreateIndex)
599	require.Equal(t, created1.ModifyIndex, token1.ModifyIndex)
600	require.Equal(t, created1.Hash, token1.Hash)
601	require.ElementsMatch(t, created1.Policies, token1.Policies)
602
603	token2, ok := tokenMap[created2.AccessorID]
604	require.True(t, ok)
605	require.NotNil(t, token2)
606	require.Equal(t, created2.Description, token2.Description)
607	require.Equal(t, created2.CreateIndex, token2.CreateIndex)
608	require.Equal(t, created2.ModifyIndex, token2.ModifyIndex)
609	require.Equal(t, created2.Hash, token2.Hash)
610	require.ElementsMatch(t, created2.Policies, token2.Policies)
611
612	token3, ok := tokenMap[created3.AccessorID]
613	require.True(t, ok)
614	require.NotNil(t, token3)
615	require.Equal(t, created3.Description, token3.Description)
616	require.Equal(t, created3.CreateIndex, token3.CreateIndex)
617	require.Equal(t, created3.ModifyIndex, token3.ModifyIndex)
618	require.Equal(t, created3.Hash, token3.Hash)
619	require.ElementsMatch(t, created3.Policies, token3.Policies)
620
621	// make sure the there is an anon token
622	token4, ok := tokenMap["00000000-0000-0000-0000-000000000002"]
623	require.True(t, ok)
624	require.NotNil(t, token4)
625
626	// ensure the 5th token is the root master token
627	root, _, err := acl.TokenReadSelf(nil)
628	require.NoError(t, err)
629	require.NotNil(t, root)
630	token5, ok := tokenMap[root.AccessorID]
631	require.True(t, ok)
632	require.NotNil(t, token5)
633}
634
635func TestAPI_ACLToken_Clone(t *testing.T) {
636	t.Parallel()
637	c, s := makeACLClient(t)
638	defer s.Stop()
639
640	acl := c.ACL()
641
642	master, _, err := acl.TokenReadSelf(nil)
643	require.NoError(t, err)
644	require.NotNil(t, master)
645
646	cloned, _, err := acl.TokenClone(master.AccessorID, "cloned", nil)
647	require.NoError(t, err)
648	require.NotNil(t, cloned)
649	require.NotEqual(t, master.AccessorID, cloned.AccessorID)
650	require.NotEqual(t, master.SecretID, cloned.SecretID)
651	require.Equal(t, "cloned", cloned.Description)
652	require.ElementsMatch(t, master.Policies, cloned.Policies)
653
654	read, _, err := acl.TokenRead(cloned.AccessorID, nil)
655	require.NoError(t, err)
656	require.NotNil(t, read)
657	require.Equal(t, cloned, read)
658}
659
660func TestAPI_RulesTranslate_FromToken(t *testing.T) {
661	t.Parallel()
662	c, s := makeACLClient(t)
663	defer s.Stop()
664
665	acl := c.ACL()
666
667	ae := ACLEntry{
668		Name:  "API test",
669		Type:  ACLClientType,
670		Rules: `key "" { policy = "deny" }`,
671	}
672
673	id, _, err := acl.Create(&ae, nil)
674	require.NoError(t, err)
675
676	var accessor string
677	acl.c.config.Token = id
678
679	// This relies on the token upgrade loop running in the background
680	// to assign an accessor
681	retry.Run(t, func(r *retry.R) {
682		token, _, err := acl.TokenReadSelf(nil)
683		require.NoError(r, err)
684		require.NotEqual(r, "", token.AccessorID)
685		accessor = token.AccessorID
686	})
687	acl.c.config.Token = "root"
688
689	rules, err := acl.RulesTranslateToken(accessor)
690	require.NoError(t, err)
691	require.Equal(t, "key_prefix \"\" {\n  policy = \"deny\"\n}", rules)
692}
693
694func TestAPI_RulesTranslate_Raw(t *testing.T) {
695	t.Parallel()
696	c, s := makeACLClient(t)
697	defer s.Stop()
698
699	acl := c.ACL()
700
701	input := `#start of policy
702agent "" {
703   policy = "read"
704}
705
706node "" {
707   policy = "read"
708}
709
710service "" {
711   policy = "read"
712}
713
714key "" {
715   policy = "read"
716}
717
718session "" {
719   policy = "read"
720}
721
722event "" {
723   policy = "read"
724}
725
726query "" {
727   policy = "read"
728}`
729
730	expected := `#start of policy
731agent_prefix "" {
732  policy = "read"
733}
734
735node_prefix "" {
736  policy = "read"
737}
738
739service_prefix "" {
740  policy = "read"
741}
742
743key_prefix "" {
744  policy = "read"
745}
746
747session_prefix "" {
748  policy = "read"
749}
750
751event_prefix "" {
752  policy = "read"
753}
754
755query_prefix "" {
756  policy = "read"
757}`
758
759	rules, err := acl.RulesTranslate(strings.NewReader(input))
760	require.NoError(t, err)
761	require.Equal(t, expected, rules)
762}
763