1package agent
2
3import (
4	"fmt"
5	"os"
6	"strings"
7	"testing"
8	"time"
9
10	rawacl "github.com/hashicorp/consul/acl"
11	"github.com/hashicorp/consul/agent/config"
12	"github.com/hashicorp/consul/agent/structs"
13	"github.com/hashicorp/consul/testutil"
14	"github.com/hashicorp/consul/types"
15	"github.com/hashicorp/serf/serf"
16)
17
18func TestACL_Bad_Config(t *testing.T) {
19	t.Parallel()
20
21	dataDir := testutil.TempDir(t, "agent")
22	defer os.Remove(dataDir)
23
24	cfg := TestConfig(config.Source{
25		Name:   "acl",
26		Format: "hcl",
27		Data: `
28			acl_down_policy = "nope"
29			data_dir = "` + dataDir + `"
30		`,
31	})
32
33	// do not use TestAgent here since we want
34	// the agent to fail during startup.
35	_, err := New(cfg)
36	if err == nil || !strings.Contains(err.Error(), "invalid ACL down policy") {
37		t.Fatalf("err: %v", err)
38	}
39}
40
41type MockServer struct {
42	getPolicyFn func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error
43}
44
45func (m *MockServer) GetPolicy(args *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
46	if m.getPolicyFn != nil {
47		return m.getPolicyFn(args, reply)
48	}
49	return fmt.Errorf("should not have called GetPolicy")
50}
51
52func TestACL_Version8(t *testing.T) {
53	t.Parallel()
54
55	t.Run("version 8 disabled", func(t *testing.T) {
56		a := NewTestAgent(t.Name(), TestACLConfig()+`
57 		acl_enforce_version_8 = false
58 	`)
59		defer a.Shutdown()
60
61		m := MockServer{
62			getPolicyFn: func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
63				t.Fatalf("should not have called to server")
64				return nil
65			},
66		}
67		if err := a.registerEndpoint("ACL", &m); err != nil {
68			t.Fatalf("err: %v", err)
69		}
70
71		if token, err := a.resolveToken("nope"); token != nil || err != nil {
72			t.Fatalf("bad: %v err: %v", token, err)
73		}
74	})
75
76	t.Run("version 8 enabled", func(t *testing.T) {
77		a := NewTestAgent(t.Name(), TestACLConfig()+`
78 		acl_enforce_version_8 = true
79 	`)
80		defer a.Shutdown()
81
82		var called bool
83		m := MockServer{
84			getPolicyFn: func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
85				called = true
86				return fmt.Errorf("token not found")
87			},
88		}
89		if err := a.registerEndpoint("ACL", &m); err != nil {
90			t.Fatalf("err: %v", err)
91		}
92
93		if _, err := a.resolveToken("nope"); err != nil {
94			t.Fatalf("err: %v", err)
95		}
96
97		if !called {
98			t.Fatalf("bad")
99		}
100	})
101}
102
103func TestACL_Disabled(t *testing.T) {
104	t.Parallel()
105	a := NewTestAgent(t.Name(), TestACLConfig()+`
106		acl_disabled_ttl = "10ms"
107		acl_enforce_version_8 = true
108	`)
109	defer a.Shutdown()
110
111	m := MockServer{
112		// Fetch a token without ACLs enabled and make sure the manager sees it.
113		getPolicyFn: func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
114			return rawacl.ErrDisabled
115		},
116	}
117	if err := a.registerEndpoint("ACL", &m); err != nil {
118		t.Fatalf("err: %v", err)
119	}
120
121	if a.acls.isDisabled() {
122		t.Fatalf("should not be disabled yet")
123	}
124	if token, err := a.resolveToken("nope"); token != nil || err != nil {
125		t.Fatalf("bad: %v err: %v", token, err)
126	}
127	if !a.acls.isDisabled() {
128		t.Fatalf("should be disabled")
129	}
130
131	// Now turn on ACLs and check right away, it should still think ACLs are
132	// disabled since we don't check again right away.
133	m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
134		return rawacl.ErrNotFound
135	}
136	if token, err := a.resolveToken("nope"); token != nil || err != nil {
137		t.Fatalf("bad: %v err: %v", token, err)
138	}
139	if !a.acls.isDisabled() {
140		t.Fatalf("should be disabled")
141	}
142
143	// Wait the waiting period and make sure it checks again. Do a few tries
144	// to make sure we don't think it's disabled.
145	time.Sleep(2 * 10 * time.Millisecond)
146	for i := 0; i < 10; i++ {
147		_, err := a.resolveToken("nope")
148		if !rawacl.IsErrNotFound(err) {
149			t.Fatalf("err: %v", err)
150		}
151		if a.acls.isDisabled() {
152			t.Fatalf("should not be disabled")
153		}
154	}
155}
156
157func TestACL_Special_IDs(t *testing.T) {
158	t.Parallel()
159	a := NewTestAgent(t.Name(), TestACLConfig()+`
160 		acl_enforce_version_8 = true
161 		acl_agent_master_token = "towel"
162 	`)
163	defer a.Shutdown()
164
165	m := MockServer{
166		// An empty ID should get mapped to the anonymous token.
167		getPolicyFn: func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
168			if req.ACL != "anonymous" {
169				t.Fatalf("bad: %#v", *req)
170			}
171			return rawacl.ErrNotFound
172		},
173	}
174	if err := a.registerEndpoint("ACL", &m); err != nil {
175		t.Fatalf("err: %v", err)
176	}
177	_, err := a.resolveToken("")
178	if !rawacl.IsErrNotFound(err) {
179		t.Fatalf("err: %v", err)
180	}
181
182	// A root ACL request should get rejected and not call the server.
183	m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
184		t.Fatalf("should not have called to server")
185		return nil
186	}
187	_, err = a.resolveToken("deny")
188	if !rawacl.IsErrRootDenied(err) {
189		t.Fatalf("err: %v", err)
190	}
191
192	// The ACL master token should also not call the server, but should give
193	// us a working agent token.
194	acl, err := a.resolveToken("towel")
195	if err != nil {
196		t.Fatalf("err: %v", err)
197	}
198	if acl == nil {
199		t.Fatalf("should not be nil")
200	}
201	if !acl.AgentRead(a.config.NodeName) {
202		t.Fatalf("should be able to read agent")
203	}
204	if !acl.AgentWrite(a.config.NodeName) {
205		t.Fatalf("should be able to write agent")
206	}
207	if !acl.NodeRead("hello") {
208		t.Fatalf("should be able to read any node")
209	}
210	if acl.NodeWrite("hello", nil) {
211		t.Fatalf("should not be able to write any node")
212	}
213}
214
215func TestACL_Down_Deny(t *testing.T) {
216	t.Parallel()
217	a := NewTestAgent(t.Name(), TestACLConfig()+`
218		acl_down_policy = "deny"
219		acl_enforce_version_8 = true
220	`)
221	defer a.Shutdown()
222
223	m := MockServer{
224		// Resolve with ACLs down.
225		getPolicyFn: func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
226			return fmt.Errorf("ACLs are broken")
227		},
228	}
229	if err := a.registerEndpoint("ACL", &m); err != nil {
230		t.Fatalf("err: %v", err)
231	}
232
233	acl, err := a.resolveToken("nope")
234	if err != nil {
235		t.Fatalf("err: %v", err)
236	}
237	if acl == nil {
238		t.Fatalf("should not be nil")
239	}
240	if acl.AgentRead(a.config.NodeName) {
241		t.Fatalf("should deny")
242	}
243}
244
245func TestACL_Down_Allow(t *testing.T) {
246	t.Parallel()
247	a := NewTestAgent(t.Name(), TestACLConfig()+`
248		acl_down_policy = "allow"
249		acl_enforce_version_8 = true
250	`)
251	defer a.Shutdown()
252
253	m := MockServer{
254		// Resolve with ACLs down.
255		getPolicyFn: func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
256			return fmt.Errorf("ACLs are broken")
257		},
258	}
259	if err := a.registerEndpoint("ACL", &m); err != nil {
260		t.Fatalf("err: %v", err)
261	}
262
263	acl, err := a.resolveToken("nope")
264	if err != nil {
265		t.Fatalf("err: %v", err)
266	}
267	if acl == nil {
268		t.Fatalf("should not be nil")
269	}
270	if !acl.AgentRead(a.config.NodeName) {
271		t.Fatalf("should allow")
272	}
273}
274
275func TestACL_Down_Extend(t *testing.T) {
276	t.Parallel()
277	a := NewTestAgent(t.Name(), TestACLConfig()+`
278		acl_down_policy = "extend-cache"
279		acl_enforce_version_8 = true
280	`)
281	defer a.Shutdown()
282
283	m := MockServer{
284		// Populate the cache for one of the tokens.
285		getPolicyFn: func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
286			*reply = structs.ACLPolicy{
287				Parent: "allow",
288				Policy: &rawacl.Policy{
289					Agents: []*rawacl.AgentPolicy{
290						&rawacl.AgentPolicy{
291							Node:   a.config.NodeName,
292							Policy: "read",
293						},
294					},
295				},
296			}
297			return nil
298		},
299	}
300	if err := a.registerEndpoint("ACL", &m); err != nil {
301		t.Fatalf("err: %v", err)
302	}
303
304	acl, err := a.resolveToken("yep")
305	if err != nil {
306		t.Fatalf("err: %v", err)
307	}
308	if acl == nil {
309		t.Fatalf("should not be nil")
310	}
311	if !acl.AgentRead(a.config.NodeName) {
312		t.Fatalf("should allow")
313	}
314	if acl.AgentWrite(a.config.NodeName) {
315		t.Fatalf("should deny")
316	}
317
318	// Now take down ACLs and make sure a new token fails to resolve.
319	m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
320		return fmt.Errorf("ACLs are broken")
321	}
322	acl, err = a.resolveToken("nope")
323	if err != nil {
324		t.Fatalf("err: %v", err)
325	}
326	if acl == nil {
327		t.Fatalf("should not be nil")
328	}
329	if acl.AgentRead(a.config.NodeName) {
330		t.Fatalf("should deny")
331	}
332	if acl.AgentWrite(a.config.NodeName) {
333		t.Fatalf("should deny")
334	}
335
336	// Read the token from the cache while ACLs are broken, which should
337	// extend.
338	acl, err = a.resolveToken("yep")
339	if err != nil {
340		t.Fatalf("err: %v", err)
341	}
342	if acl == nil {
343		t.Fatalf("should not be nil")
344	}
345	if !acl.AgentRead(a.config.NodeName) {
346		t.Fatalf("should allow")
347	}
348	if acl.AgentWrite(a.config.NodeName) {
349		t.Fatalf("should deny")
350	}
351}
352
353func TestACL_Cache(t *testing.T) {
354	t.Parallel()
355	a := NewTestAgent(t.Name(), TestACLConfig()+`
356		acl_enforce_version_8 = true
357	`)
358	defer a.Shutdown()
359
360	m := MockServer{
361		// Populate the cache for one of the tokens.
362		getPolicyFn: func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
363			*reply = structs.ACLPolicy{
364				ETag:   "hash1",
365				Parent: "deny",
366				Policy: &rawacl.Policy{
367					Agents: []*rawacl.AgentPolicy{
368						&rawacl.AgentPolicy{
369							Node:   a.config.NodeName,
370							Policy: "read",
371						},
372					},
373				},
374				TTL: 10 * time.Millisecond,
375			}
376			return nil
377		},
378	}
379	if err := a.registerEndpoint("ACL", &m); err != nil {
380		t.Fatalf("err: %v", err)
381	}
382
383	rule, err := a.resolveToken("yep")
384	if err != nil {
385		t.Fatalf("err: %v", err)
386	}
387	if rule == nil {
388		t.Fatalf("should not be nil")
389	}
390	if !rule.AgentRead(a.config.NodeName) {
391		t.Fatalf("should allow")
392	}
393	if rule.AgentWrite(a.config.NodeName) {
394		t.Fatalf("should deny")
395	}
396	if rule.NodeRead("nope") {
397		t.Fatalf("should deny")
398	}
399
400	// Fetch right away and make sure it uses the cache.
401	m.getPolicyFn = func(*structs.ACLPolicyRequest, *structs.ACLPolicy) error {
402		t.Fatalf("should not have called to server")
403		return nil
404	}
405	rule, err = a.resolveToken("yep")
406	if err != nil {
407		t.Fatalf("err: %v", err)
408	}
409	if rule == nil {
410		t.Fatalf("should not be nil")
411	}
412	if !rule.AgentRead(a.config.NodeName) {
413		t.Fatalf("should allow")
414	}
415	if rule.AgentWrite(a.config.NodeName) {
416		t.Fatalf("should deny")
417	}
418	if rule.NodeRead("nope") {
419		t.Fatalf("should deny")
420	}
421
422	// Wait for the TTL to expire and try again. This time the token will be
423	// gone.
424	time.Sleep(20 * time.Millisecond)
425	m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
426		return rawacl.ErrNotFound
427	}
428	_, err = a.resolveToken("yep")
429	if !rawacl.IsErrNotFound(err) {
430		t.Fatalf("err: %v", err)
431	}
432
433	// Page it back in with a new tag and different policy
434	m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
435		*reply = structs.ACLPolicy{
436			ETag:   "hash2",
437			Parent: "deny",
438			Policy: &rawacl.Policy{
439				Agents: []*rawacl.AgentPolicy{
440					&rawacl.AgentPolicy{
441						Node:   a.config.NodeName,
442						Policy: "write",
443					},
444				},
445			},
446			TTL: 10 * time.Millisecond,
447		}
448		return nil
449	}
450	rule, err = a.resolveToken("yep")
451	if err != nil {
452		t.Fatalf("err: %v", err)
453	}
454	if rule == nil {
455		t.Fatalf("should not be nil")
456	}
457	if !rule.AgentRead(a.config.NodeName) {
458		t.Fatalf("should allow")
459	}
460	if !rule.AgentWrite(a.config.NodeName) {
461		t.Fatalf("should allow")
462	}
463	if rule.NodeRead("nope") {
464		t.Fatalf("should deny")
465	}
466
467	// Wait for the TTL to expire and try again. This will match the tag
468	// and not send the policy back, but we should have the old token
469	// behavior.
470	time.Sleep(20 * time.Millisecond)
471	var didRefresh bool
472	m.getPolicyFn = func(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
473		*reply = structs.ACLPolicy{
474			ETag: "hash2",
475			TTL:  10 * time.Millisecond,
476		}
477		didRefresh = true
478		return nil
479	}
480	rule, err = a.resolveToken("yep")
481	if err != nil {
482		t.Fatalf("err: %v", err)
483	}
484	if rule == nil {
485		t.Fatalf("should not be nil")
486	}
487	if !rule.AgentRead(a.config.NodeName) {
488		t.Fatalf("should allow")
489	}
490	if !rule.AgentWrite(a.config.NodeName) {
491		t.Fatalf("should allow")
492	}
493	if rule.NodeRead("nope") {
494		t.Fatalf("should deny")
495	}
496	if !didRefresh {
497		t.Fatalf("should refresh")
498	}
499}
500
501// catalogPolicy supplies some standard policies to help with testing the
502// catalog-related vet and filter functions.
503func catalogPolicy(req *structs.ACLPolicyRequest, reply *structs.ACLPolicy) error {
504	reply.Policy = &rawacl.Policy{}
505
506	switch req.ACL {
507
508	case "node-ro":
509		reply.Policy.Nodes = append(reply.Policy.Nodes,
510			&rawacl.NodePolicy{Name: "Node", Policy: "read"})
511
512	case "node-rw":
513		reply.Policy.Nodes = append(reply.Policy.Nodes,
514			&rawacl.NodePolicy{Name: "Node", Policy: "write"})
515
516	case "service-ro":
517		reply.Policy.Services = append(reply.Policy.Services,
518			&rawacl.ServicePolicy{Name: "service", Policy: "read"})
519
520	case "service-rw":
521		reply.Policy.Services = append(reply.Policy.Services,
522			&rawacl.ServicePolicy{Name: "service", Policy: "write"})
523
524	case "other-rw":
525		reply.Policy.Services = append(reply.Policy.Services,
526			&rawacl.ServicePolicy{Name: "other", Policy: "write"})
527
528	default:
529		return fmt.Errorf("unknown token %q", req.ACL)
530	}
531
532	return nil
533}
534
535func TestACL_vetServiceRegister(t *testing.T) {
536	t.Parallel()
537	a := NewTestAgent(t.Name(), TestACLConfig()+`
538		acl_enforce_version_8 = true
539	`)
540	defer a.Shutdown()
541
542	m := MockServer{catalogPolicy}
543	if err := a.registerEndpoint("ACL", &m); err != nil {
544		t.Fatalf("err: %v", err)
545	}
546
547	// Register a new service, with permission.
548	err := a.vetServiceRegister("service-rw", &structs.NodeService{
549		ID:      "my-service",
550		Service: "service",
551	})
552	if err != nil {
553		t.Fatalf("err: %v", err)
554	}
555
556	// Register a new service without write privs.
557	err = a.vetServiceRegister("service-ro", &structs.NodeService{
558		ID:      "my-service",
559		Service: "service",
560	})
561	if !rawacl.IsErrPermissionDenied(err) {
562		t.Fatalf("err: %v", err)
563	}
564
565	// Try to register over a service without write privs to the existing
566	// service.
567	a.State.AddService(&structs.NodeService{
568		ID:      "my-service",
569		Service: "other",
570	}, "")
571	err = a.vetServiceRegister("service-rw", &structs.NodeService{
572		ID:      "my-service",
573		Service: "service",
574	})
575	if !rawacl.IsErrPermissionDenied(err) {
576		t.Fatalf("err: %v", err)
577	}
578}
579
580func TestACL_vetServiceUpdate(t *testing.T) {
581	t.Parallel()
582	a := NewTestAgent(t.Name(), TestACLConfig()+`
583		acl_enforce_version_8 = true
584	`)
585	defer a.Shutdown()
586
587	m := MockServer{catalogPolicy}
588	if err := a.registerEndpoint("ACL", &m); err != nil {
589		t.Fatalf("err: %v", err)
590	}
591
592	// Update a service that doesn't exist.
593	err := a.vetServiceUpdate("service-rw", "my-service")
594	if err == nil || !strings.Contains(err.Error(), "Unknown service") {
595		t.Fatalf("err: %v", err)
596	}
597
598	// Update with write privs.
599	a.State.AddService(&structs.NodeService{
600		ID:      "my-service",
601		Service: "service",
602	}, "")
603	err = a.vetServiceUpdate("service-rw", "my-service")
604	if err != nil {
605		t.Fatalf("err: %v", err)
606	}
607
608	// Update without write privs.
609	err = a.vetServiceUpdate("service-ro", "my-service")
610	if !rawacl.IsErrPermissionDenied(err) {
611		t.Fatalf("err: %v", err)
612	}
613}
614
615func TestACL_vetCheckRegister(t *testing.T) {
616	t.Parallel()
617	a := NewTestAgent(t.Name(), TestACLConfig()+`
618		acl_enforce_version_8 = true
619	`)
620	defer a.Shutdown()
621
622	m := MockServer{catalogPolicy}
623	if err := a.registerEndpoint("ACL", &m); err != nil {
624		t.Fatalf("err: %v", err)
625	}
626
627	// Register a new service check with write privs.
628	err := a.vetCheckRegister("service-rw", &structs.HealthCheck{
629		CheckID:     types.CheckID("my-check"),
630		ServiceID:   "my-service",
631		ServiceName: "service",
632	})
633	if err != nil {
634		t.Fatalf("err: %v", err)
635	}
636
637	// Register a new service check without write privs.
638	err = a.vetCheckRegister("service-ro", &structs.HealthCheck{
639		CheckID:     types.CheckID("my-check"),
640		ServiceID:   "my-service",
641		ServiceName: "service",
642	})
643	if !rawacl.IsErrPermissionDenied(err) {
644		t.Fatalf("err: %v", err)
645	}
646
647	// Register a new node check with write privs.
648	err = a.vetCheckRegister("node-rw", &structs.HealthCheck{
649		CheckID: types.CheckID("my-check"),
650	})
651	if err != nil {
652		t.Fatalf("err: %v", err)
653	}
654
655	// Register a new node check without write privs.
656	err = a.vetCheckRegister("node-ro", &structs.HealthCheck{
657		CheckID: types.CheckID("my-check"),
658	})
659	if !rawacl.IsErrPermissionDenied(err) {
660		t.Fatalf("err: %v", err)
661	}
662
663	// Try to register over a service check without write privs to the
664	// existing service.
665	a.State.AddService(&structs.NodeService{
666		ID:      "my-service",
667		Service: "service",
668	}, "")
669	a.State.AddCheck(&structs.HealthCheck{
670		CheckID:     types.CheckID("my-check"),
671		ServiceID:   "my-service",
672		ServiceName: "other",
673	}, "")
674	err = a.vetCheckRegister("service-rw", &structs.HealthCheck{
675		CheckID:     types.CheckID("my-check"),
676		ServiceID:   "my-service",
677		ServiceName: "service",
678	})
679	if !rawacl.IsErrPermissionDenied(err) {
680		t.Fatalf("err: %v", err)
681	}
682
683	// Try to register over a node check without write privs to the node.
684	a.State.AddCheck(&structs.HealthCheck{
685		CheckID: types.CheckID("my-node-check"),
686	}, "")
687	err = a.vetCheckRegister("service-rw", &structs.HealthCheck{
688		CheckID:     types.CheckID("my-node-check"),
689		ServiceID:   "my-service",
690		ServiceName: "service",
691	})
692	if !rawacl.IsErrPermissionDenied(err) {
693		t.Fatalf("err: %v", err)
694	}
695}
696
697func TestACL_vetCheckUpdate(t *testing.T) {
698	t.Parallel()
699	a := NewTestAgent(t.Name(), TestACLConfig()+`
700		acl_enforce_version_8 = true
701	`)
702	defer a.Shutdown()
703
704	m := MockServer{catalogPolicy}
705	if err := a.registerEndpoint("ACL", &m); err != nil {
706		t.Fatalf("err: %v", err)
707	}
708
709	// Update a check that doesn't exist.
710	err := a.vetCheckUpdate("node-rw", "my-check")
711	if err == nil || !strings.Contains(err.Error(), "Unknown check") {
712		t.Fatalf("err: %v", err)
713	}
714
715	// Update service check with write privs.
716	a.State.AddService(&structs.NodeService{
717		ID:      "my-service",
718		Service: "service",
719	}, "")
720	a.State.AddCheck(&structs.HealthCheck{
721		CheckID:     types.CheckID("my-service-check"),
722		ServiceID:   "my-service",
723		ServiceName: "service",
724	}, "")
725	err = a.vetCheckUpdate("service-rw", "my-service-check")
726	if err != nil {
727		t.Fatalf("err: %v", err)
728	}
729
730	// Update service check without write privs.
731	err = a.vetCheckUpdate("service-ro", "my-service-check")
732	if !rawacl.IsErrPermissionDenied(err) {
733		t.Fatalf("err: %v", err)
734	}
735
736	// Update node check with write privs.
737	a.State.AddCheck(&structs.HealthCheck{
738		CheckID: types.CheckID("my-node-check"),
739	}, "")
740	err = a.vetCheckUpdate("node-rw", "my-node-check")
741	if err != nil {
742		t.Fatalf("err: %v", err)
743	}
744
745	// Update without write privs.
746	err = a.vetCheckUpdate("node-ro", "my-node-check")
747	if !rawacl.IsErrPermissionDenied(err) {
748		t.Fatalf("err: %v", err)
749	}
750}
751
752func TestACL_filterMembers(t *testing.T) {
753	t.Parallel()
754	a := NewTestAgent(t.Name(), TestACLConfig()+`
755		acl_enforce_version_8 = true
756	`)
757	defer a.Shutdown()
758
759	m := MockServer{catalogPolicy}
760	if err := a.registerEndpoint("ACL", &m); err != nil {
761		t.Fatalf("err: %v", err)
762	}
763
764	var members []serf.Member
765	if err := a.filterMembers("node-ro", &members); err != nil {
766		t.Fatalf("err: %v", err)
767	}
768	if len(members) != 0 {
769		t.Fatalf("bad: %#v", members)
770	}
771
772	members = []serf.Member{
773		serf.Member{Name: "Node 1"},
774		serf.Member{Name: "Nope"},
775		serf.Member{Name: "Node 2"},
776	}
777	if err := a.filterMembers("node-ro", &members); err != nil {
778		t.Fatalf("err: %v", err)
779	}
780	if len(members) != 2 ||
781		members[0].Name != "Node 1" ||
782		members[1].Name != "Node 2" {
783		t.Fatalf("bad: %#v", members)
784	}
785}
786
787func TestACL_filterServices(t *testing.T) {
788	t.Parallel()
789	a := NewTestAgent(t.Name(), TestACLConfig()+`
790		acl_enforce_version_8 = true
791	`)
792	defer a.Shutdown()
793
794	m := MockServer{catalogPolicy}
795	if err := a.registerEndpoint("ACL", &m); err != nil {
796		t.Fatalf("err: %v", err)
797	}
798
799	services := make(map[string]*structs.NodeService)
800	if err := a.filterServices("node-ro", &services); err != nil {
801		t.Fatalf("err: %v", err)
802	}
803
804	services["my-service"] = &structs.NodeService{ID: "my-service", Service: "service"}
805	services["my-other"] = &structs.NodeService{ID: "my-other", Service: "other"}
806	if err := a.filterServices("service-ro", &services); err != nil {
807		t.Fatalf("err: %v", err)
808	}
809	if _, ok := services["my-service"]; !ok {
810		t.Fatalf("bad: %#v", services)
811	}
812	if _, ok := services["my-other"]; ok {
813		t.Fatalf("bad: %#v", services)
814	}
815}
816
817func TestACL_filterChecks(t *testing.T) {
818	t.Parallel()
819	a := NewTestAgent(t.Name(), TestACLConfig()+`
820		acl_enforce_version_8 = true
821	`)
822	defer a.Shutdown()
823
824	m := MockServer{catalogPolicy}
825	if err := a.registerEndpoint("ACL", &m); err != nil {
826		t.Fatalf("err: %v", err)
827	}
828
829	checks := make(map[types.CheckID]*structs.HealthCheck)
830	if err := a.filterChecks("node-ro", &checks); err != nil {
831		t.Fatalf("err: %v", err)
832	}
833
834	checks["my-node"] = &structs.HealthCheck{}
835	checks["my-service"] = &structs.HealthCheck{ServiceName: "service"}
836	checks["my-other"] = &structs.HealthCheck{ServiceName: "other"}
837	if err := a.filterChecks("service-ro", &checks); err != nil {
838		t.Fatalf("err: %v", err)
839	}
840	if _, ok := checks["my-node"]; ok {
841		t.Fatalf("bad: %#v", checks)
842	}
843	if _, ok := checks["my-service"]; !ok {
844		t.Fatalf("bad: %#v", checks)
845	}
846	if _, ok := checks["my-other"]; ok {
847		t.Fatalf("bad: %#v", checks)
848	}
849
850	checks["my-node"] = &structs.HealthCheck{}
851	checks["my-service"] = &structs.HealthCheck{ServiceName: "service"}
852	checks["my-other"] = &structs.HealthCheck{ServiceName: "other"}
853	if err := a.filterChecks("node-ro", &checks); err != nil {
854		t.Fatalf("err: %v", err)
855	}
856	if _, ok := checks["my-node"]; !ok {
857		t.Fatalf("bad: %#v", checks)
858	}
859	if _, ok := checks["my-service"]; ok {
860		t.Fatalf("bad: %#v", checks)
861	}
862	if _, ok := checks["my-other"]; ok {
863		t.Fatalf("bad: %#v", checks)
864	}
865}
866