1package api
2
3import (
4	"strings"
5	"testing"
6
7	"github.com/hashicorp/consul/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_CreateUpdate(t *testing.T) {
209	t.Parallel()
210	c, s := makeACLClient(t)
211	defer s.Stop()
212
213	acl := c.ACL()
214
215	created, _, 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
226	read, _, err := acl.PolicyRead(created.ID, nil)
227	require.NoError(t, err)
228	require.Equal(t, created, read)
229
230	read.Rules += ` service_prefix "" { policy = "read" }`
231	read.Datacenters = nil
232
233	updated, wm, err := acl.PolicyUpdate(read, nil)
234	require.NoError(t, err)
235	require.Equal(t, created.ID, updated.ID)
236	require.Equal(t, created.Description, updated.Description)
237	require.Equal(t, read.Rules, updated.Rules)
238	require.Equal(t, created.CreateIndex, updated.CreateIndex)
239	require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex)
240	require.Nil(t, updated.Datacenters)
241	require.NotEqual(t, 0, wm.RequestTime)
242
243	updated_read, _, err := acl.PolicyRead(created.ID, nil)
244	require.NoError(t, err)
245	require.Equal(t, updated, updated_read)
246}
247
248func TestAPI_ACLPolicy_List(t *testing.T) {
249	t.Parallel()
250	c, s := makeACLClient(t)
251	defer s.Stop()
252
253	acl := c.ACL()
254
255	created1, _, err := acl.PolicyCreate(&ACLPolicy{
256		Name:        "policy1",
257		Description: "policy1 description",
258		Rules:       `node_prefix "" { policy = "read" }`,
259		Datacenters: []string{"dc1"},
260	}, nil)
261
262	require.NoError(t, err)
263	require.NotNil(t, created1)
264	require.NotEqual(t, "", created1.ID)
265
266	created2, _, err := acl.PolicyCreate(&ACLPolicy{
267		Name:        "policy2",
268		Description: "policy2 description",
269		Rules:       `service "app" { policy = "write" }`,
270		Datacenters: []string{"dc1", "dc2"},
271	}, nil)
272
273	require.NoError(t, err)
274	require.NotNil(t, created2)
275	require.NotEqual(t, "", created2.ID)
276
277	created3, _, err := acl.PolicyCreate(&ACLPolicy{
278		Name:        "policy3",
279		Description: "policy3 description",
280		Rules:       `acl = "read"`,
281	}, nil)
282
283	require.NoError(t, err)
284	require.NotNil(t, created3)
285	require.NotEqual(t, "", created3.ID)
286
287	policies, qm, err := acl.PolicyList(nil)
288	require.NoError(t, err)
289	require.Len(t, policies, 4)
290	require.NotEqual(t, 0, qm.LastIndex)
291	require.True(t, qm.KnownLeader)
292
293	policyMap := make(map[string]*ACLPolicyListEntry)
294	for _, policy := range policies {
295		policyMap[policy.ID] = policy
296	}
297
298	policy1, ok := policyMap[created1.ID]
299	require.True(t, ok)
300	require.NotNil(t, policy1)
301	require.Equal(t, created1.Name, policy1.Name)
302	require.Equal(t, created1.Description, policy1.Description)
303	require.Equal(t, created1.CreateIndex, policy1.CreateIndex)
304	require.Equal(t, created1.ModifyIndex, policy1.ModifyIndex)
305	require.Equal(t, created1.Hash, policy1.Hash)
306	require.ElementsMatch(t, created1.Datacenters, policy1.Datacenters)
307
308	policy2, ok := policyMap[created2.ID]
309	require.True(t, ok)
310	require.NotNil(t, policy2)
311	require.Equal(t, created2.Name, policy2.Name)
312	require.Equal(t, created2.Description, policy2.Description)
313	require.Equal(t, created2.CreateIndex, policy2.CreateIndex)
314	require.Equal(t, created2.ModifyIndex, policy2.ModifyIndex)
315	require.Equal(t, created2.Hash, policy2.Hash)
316	require.ElementsMatch(t, created2.Datacenters, policy2.Datacenters)
317
318	policy3, ok := policyMap[created3.ID]
319	require.True(t, ok)
320	require.NotNil(t, policy3)
321	require.Equal(t, created3.Name, policy3.Name)
322	require.Equal(t, created3.Description, policy3.Description)
323	require.Equal(t, created3.CreateIndex, policy3.CreateIndex)
324	require.Equal(t, created3.ModifyIndex, policy3.ModifyIndex)
325	require.Equal(t, created3.Hash, policy3.Hash)
326	require.ElementsMatch(t, created3.Datacenters, policy3.Datacenters)
327
328	// make sure the 4th policy is the global management
329	policy4, ok := policyMap["00000000-0000-0000-0000-000000000001"]
330	require.True(t, ok)
331	require.NotNil(t, policy4)
332}
333
334func prepTokenPolicies(t *testing.T, acl *ACL) (policies []*ACLPolicy) {
335	policy, _, err := acl.PolicyCreate(&ACLPolicy{
336		Name:        "one",
337		Description: "one description",
338		Rules:       `acl = "read"`,
339		Datacenters: []string{"dc1", "dc2"},
340	}, nil)
341
342	require.NoError(t, err)
343	require.NotNil(t, policy)
344	policies = append(policies, policy)
345
346	policy, _, err = acl.PolicyCreate(&ACLPolicy{
347		Name:        "two",
348		Description: "two description",
349		Rules:       `node_prefix "" { policy = "read" }`,
350		Datacenters: []string{"dc1", "dc2"},
351	}, nil)
352
353	require.NoError(t, err)
354	require.NotNil(t, policy)
355	policies = append(policies, policy)
356
357	policy, _, err = acl.PolicyCreate(&ACLPolicy{
358		Name:        "three",
359		Description: "three description",
360		Rules:       `service_prefix "" { policy = "read" }`,
361	}, nil)
362
363	require.NoError(t, err)
364	require.NotNil(t, policy)
365	policies = append(policies, policy)
366
367	policy, _, err = acl.PolicyCreate(&ACLPolicy{
368		Name:        "four",
369		Description: "four description",
370		Rules:       `agent "foo" { policy = "write" }`,
371	}, nil)
372
373	require.NoError(t, err)
374	require.NotNil(t, policy)
375	policies = append(policies, policy)
376	return
377}
378
379func TestAPI_ACLToken_CreateReadDelete(t *testing.T) {
380	t.Parallel()
381	c, s := makeACLClient(t)
382	defer s.Stop()
383
384	acl := c.ACL()
385
386	policies := prepTokenPolicies(t, acl)
387
388	created, wm, err := acl.TokenCreate(&ACLToken{
389		Description: "token created",
390		Policies: []*ACLTokenPolicyLink{
391			&ACLTokenPolicyLink{
392				ID: policies[0].ID,
393			},
394			&ACLTokenPolicyLink{
395				ID: policies[1].ID,
396			},
397			&ACLTokenPolicyLink{
398				Name: policies[2].Name,
399			},
400			&ACLTokenPolicyLink{
401				Name: policies[3].Name,
402			},
403		},
404	}, nil)
405
406	require.NoError(t, err)
407	require.NotNil(t, created)
408	require.NotEqual(t, "", created.AccessorID)
409	require.NotEqual(t, "", created.SecretID)
410	require.NotEqual(t, 0, wm.RequestTime)
411
412	read, qm, err := acl.TokenRead(created.AccessorID, nil)
413	require.NoError(t, err)
414	require.Equal(t, created, read)
415	require.NotEqual(t, 0, qm.LastIndex)
416	require.True(t, qm.KnownLeader)
417
418	acl.c.config.Token = created.SecretID
419	self, _, err := acl.TokenReadSelf(nil)
420	require.NoError(t, err)
421	require.Equal(t, created, self)
422	acl.c.config.Token = "root"
423
424	_, err = acl.TokenDelete(created.AccessorID, nil)
425	require.NoError(t, err)
426
427	read, _, err = acl.TokenRead(created.AccessorID, nil)
428	require.Nil(t, read)
429	require.Error(t, err)
430}
431
432func TestAPI_ACLToken_CreateUpdate(t *testing.T) {
433	t.Parallel()
434	c, s := makeACLClient(t)
435	defer s.Stop()
436
437	acl := c.ACL()
438
439	policies := prepTokenPolicies(t, acl)
440
441	created, _, err := acl.TokenCreate(&ACLToken{
442		Description: "token created",
443		Policies: []*ACLTokenPolicyLink{
444			&ACLTokenPolicyLink{
445				ID: policies[0].ID,
446			},
447			&ACLTokenPolicyLink{
448				Name: policies[2].Name,
449			},
450		},
451	}, nil)
452
453	require.NoError(t, err)
454	require.NotNil(t, created)
455	require.NotEqual(t, "", created.AccessorID)
456	require.NotEqual(t, "", created.SecretID)
457
458	read, _, err := acl.TokenRead(created.AccessorID, nil)
459	require.NoError(t, err)
460	require.Equal(t, created, read)
461
462	read.Policies = append(read.Policies, &ACLTokenPolicyLink{ID: policies[1].ID})
463	read.Policies = append(read.Policies, &ACLTokenPolicyLink{Name: policies[2].Name})
464
465	expectedPolicies := []*ACLTokenPolicyLink{
466		&ACLTokenPolicyLink{
467			ID:   policies[0].ID,
468			Name: policies[0].Name,
469		},
470		&ACLTokenPolicyLink{
471			ID:   policies[1].ID,
472			Name: policies[1].Name,
473		},
474		&ACLTokenPolicyLink{
475			ID:   policies[2].ID,
476			Name: policies[2].Name,
477		},
478	}
479
480	updated, wm, err := acl.TokenUpdate(read, nil)
481	require.NoError(t, err)
482	require.Equal(t, created.AccessorID, updated.AccessorID)
483	require.Equal(t, created.SecretID, updated.SecretID)
484	require.Equal(t, created.Description, updated.Description)
485	require.Equal(t, created.CreateIndex, updated.CreateIndex)
486	require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex)
487	require.ElementsMatch(t, expectedPolicies, updated.Policies)
488	require.NotEqual(t, 0, wm.RequestTime)
489
490	updated_read, _, err := acl.TokenRead(created.AccessorID, nil)
491	require.NoError(t, err)
492	require.Equal(t, updated, updated_read)
493}
494
495func TestAPI_ACLToken_List(t *testing.T) {
496	t.Parallel()
497	c, s := makeACLClient(t)
498	defer s.Stop()
499
500	acl := c.ACL()
501
502	policies := prepTokenPolicies(t, acl)
503
504	created1, _, err := acl.TokenCreate(&ACLToken{
505		Description: "token created1",
506		Policies: []*ACLTokenPolicyLink{
507			&ACLTokenPolicyLink{
508				ID: policies[0].ID,
509			},
510		},
511	}, nil)
512
513	require.NoError(t, err)
514	require.NotNil(t, created1)
515	require.NotEqual(t, "", created1.AccessorID)
516	require.NotEqual(t, "", created1.SecretID)
517
518	created2, _, err := acl.TokenCreate(&ACLToken{
519		Description: "token created2",
520		Policies: []*ACLTokenPolicyLink{
521			&ACLTokenPolicyLink{
522				ID: policies[1].ID,
523			},
524		},
525	}, nil)
526
527	require.NoError(t, err)
528	require.NotNil(t, created2)
529	require.NotEqual(t, "", created2.AccessorID)
530	require.NotEqual(t, "", created2.SecretID)
531
532	created3, _, err := acl.TokenCreate(&ACLToken{
533		Description: "token created3",
534		Policies: []*ACLTokenPolicyLink{
535			&ACLTokenPolicyLink{
536				ID: policies[2].ID,
537			},
538		},
539	}, nil)
540
541	require.NoError(t, err)
542	require.NotNil(t, created3)
543	require.NotEqual(t, "", created3.AccessorID)
544	require.NotEqual(t, "", created3.SecretID)
545
546	tokens, qm, err := acl.TokenList(nil)
547	require.NoError(t, err)
548	// 3 + anon + master
549	require.Len(t, tokens, 5)
550	require.NotEqual(t, 0, qm.LastIndex)
551	require.True(t, qm.KnownLeader)
552
553	tokenMap := make(map[string]*ACLTokenListEntry)
554	for _, token := range tokens {
555		tokenMap[token.AccessorID] = token
556	}
557
558	token1, ok := tokenMap[created1.AccessorID]
559	require.True(t, ok)
560	require.NotNil(t, token1)
561	require.Equal(t, created1.Description, token1.Description)
562	require.Equal(t, created1.CreateIndex, token1.CreateIndex)
563	require.Equal(t, created1.ModifyIndex, token1.ModifyIndex)
564	require.Equal(t, created1.Hash, token1.Hash)
565	require.ElementsMatch(t, created1.Policies, token1.Policies)
566
567	token2, ok := tokenMap[created2.AccessorID]
568	require.True(t, ok)
569	require.NotNil(t, token2)
570	require.Equal(t, created2.Description, token2.Description)
571	require.Equal(t, created2.CreateIndex, token2.CreateIndex)
572	require.Equal(t, created2.ModifyIndex, token2.ModifyIndex)
573	require.Equal(t, created2.Hash, token2.Hash)
574	require.ElementsMatch(t, created2.Policies, token2.Policies)
575
576	token3, ok := tokenMap[created3.AccessorID]
577	require.True(t, ok)
578	require.NotNil(t, token3)
579	require.Equal(t, created3.Description, token3.Description)
580	require.Equal(t, created3.CreateIndex, token3.CreateIndex)
581	require.Equal(t, created3.ModifyIndex, token3.ModifyIndex)
582	require.Equal(t, created3.Hash, token3.Hash)
583	require.ElementsMatch(t, created3.Policies, token3.Policies)
584
585	// make sure the there is an anon token
586	token4, ok := tokenMap["00000000-0000-0000-0000-000000000002"]
587	require.True(t, ok)
588	require.NotNil(t, token4)
589
590	// ensure the 5th token is the root master token
591	root, _, err := acl.TokenReadSelf(nil)
592	require.NoError(t, err)
593	require.NotNil(t, root)
594	token5, ok := tokenMap[root.AccessorID]
595	require.True(t, ok)
596	require.NotNil(t, token5)
597}
598
599func TestAPI_ACLToken_Clone(t *testing.T) {
600	t.Parallel()
601	c, s := makeACLClient(t)
602	defer s.Stop()
603
604	acl := c.ACL()
605
606	master, _, err := acl.TokenReadSelf(nil)
607	require.NoError(t, err)
608	require.NotNil(t, master)
609
610	cloned, _, err := acl.TokenClone(master.AccessorID, "cloned", nil)
611	require.NoError(t, err)
612	require.NotNil(t, cloned)
613	require.NotEqual(t, master.AccessorID, cloned.AccessorID)
614	require.NotEqual(t, master.SecretID, cloned.SecretID)
615	require.Equal(t, "cloned", cloned.Description)
616	require.ElementsMatch(t, master.Policies, cloned.Policies)
617
618	read, _, err := acl.TokenRead(cloned.AccessorID, nil)
619	require.NoError(t, err)
620	require.NotNil(t, read)
621	require.Equal(t, cloned, read)
622}
623
624func TestAPI_RulesTranslate_FromToken(t *testing.T) {
625	t.Parallel()
626	c, s := makeACLClient(t)
627	defer s.Stop()
628
629	acl := c.ACL()
630
631	ae := ACLEntry{
632		Name:  "API test",
633		Type:  ACLClientType,
634		Rules: `key "" { policy = "deny" }`,
635	}
636
637	id, _, err := acl.Create(&ae, nil)
638	require.NoError(t, err)
639
640	var accessor string
641	acl.c.config.Token = id
642
643	// This relies on the token upgrade loop running in the background
644	// to assign an accessor
645	retry.Run(t, func(t *retry.R) {
646		token, _, err := acl.TokenReadSelf(nil)
647		require.NoError(t, err)
648		require.NotEqual(t, "", token.AccessorID)
649		accessor = token.AccessorID
650	})
651	acl.c.config.Token = "root"
652
653	rules, err := acl.RulesTranslateToken(accessor)
654	require.NoError(t, err)
655	require.Equal(t, "key_prefix \"\" {\n  policy = \"deny\"\n}", rules)
656}
657
658func TestAPI_RulesTranslate_Raw(t *testing.T) {
659	t.Parallel()
660	c, s := makeACLClient(t)
661	defer s.Stop()
662
663	acl := c.ACL()
664
665	input := `#start of policy
666agent "" {
667   policy = "read"
668}
669
670node "" {
671   policy = "read"
672}
673
674service "" {
675   policy = "read"
676}
677
678key "" {
679   policy = "read"
680}
681
682session "" {
683   policy = "read"
684}
685
686event "" {
687   policy = "read"
688}
689
690query "" {
691   policy = "read"
692}`
693
694	expected := `#start of policy
695agent_prefix "" {
696  policy = "read"
697}
698
699node_prefix "" {
700  policy = "read"
701}
702
703service_prefix "" {
704  policy = "read"
705}
706
707key_prefix "" {
708  policy = "read"
709}
710
711session_prefix "" {
712  policy = "read"
713}
714
715event_prefix "" {
716  policy = "read"
717}
718
719query_prefix "" {
720  policy = "read"
721}`
722
723	rules, err := acl.RulesTranslate(strings.NewReader(input))
724	require.NoError(t, err)
725	require.Equal(t, expected, rules)
726}
727