1package vault
2
3import (
4	"context"
5	"fmt"
6	"path"
7	"strings"
8	"sync"
9	"time"
10
11	metrics "github.com/armon/go-metrics"
12	"github.com/hashicorp/errwrap"
13	log "github.com/hashicorp/go-hclog"
14	lru "github.com/hashicorp/golang-lru"
15	"github.com/hashicorp/vault/helper/identity"
16	"github.com/hashicorp/vault/helper/namespace"
17	"github.com/hashicorp/vault/sdk/helper/consts"
18	"github.com/hashicorp/vault/sdk/helper/strutil"
19	"github.com/hashicorp/vault/sdk/logical"
20)
21
22const (
23	// policySubPath is the sub-path used for the policy store view. This is
24	// nested under the system view. policyRGPSubPath/policyEGPSubPath are
25	// similar but for RGPs/EGPs.
26	policyACLSubPath = "policy/"
27	policyRGPSubPath = "policy-rgp/"
28	policyEGPSubPath = "policy-egp/"
29
30	// policyCacheSize is the number of policies that are kept cached
31	policyCacheSize = 1024
32
33	// defaultPolicyName is the name of the default policy
34	defaultPolicyName = "default"
35
36	// responseWrappingPolicyName is the name of the fixed policy
37	responseWrappingPolicyName = "response-wrapping"
38
39	// controlGroupPolicyName is the name of the fixed policy for control group
40	// tokens
41	controlGroupPolicyName = "control-group"
42
43	// responseWrappingPolicy is the policy that ensures cubbyhole response
44	// wrapping can always succeed.
45	responseWrappingPolicy = `
46path "cubbyhole/response" {
47    capabilities = ["create", "read"]
48}
49
50path "sys/wrapping/unwrap" {
51    capabilities = ["update"]
52}
53`
54	// controlGroupPolicy is the policy that ensures control group requests can
55	// commit themselves
56	controlGroupPolicy = `
57path "cubbyhole/control-group" {
58    capabilities = ["update", "create", "read"]
59}
60
61path "sys/wrapping/unwrap" {
62    capabilities = ["update"]
63}
64`
65	// defaultPolicy is the "default" policy
66	defaultPolicy = `
67# Allow tokens to look up their own properties
68path "auth/token/lookup-self" {
69    capabilities = ["read"]
70}
71
72# Allow tokens to renew themselves
73path "auth/token/renew-self" {
74    capabilities = ["update"]
75}
76
77# Allow tokens to revoke themselves
78path "auth/token/revoke-self" {
79    capabilities = ["update"]
80}
81
82# Allow a token to look up its own capabilities on a path
83path "sys/capabilities-self" {
84    capabilities = ["update"]
85}
86
87# Allow a token to look up its own entity by id or name
88path "identity/entity/id/{{identity.entity.id}}" {
89  capabilities = ["read"]
90}
91path "identity/entity/name/{{identity.entity.name}}" {
92  capabilities = ["read"]
93}
94
95
96# Allow a token to look up its resultant ACL from all policies. This is useful
97# for UIs. It is an internal path because the format may change at any time
98# based on how the internal ACL features and capabilities change.
99path "sys/internal/ui/resultant-acl" {
100    capabilities = ["read"]
101}
102
103# Allow a token to renew a lease via lease_id in the request body; old path for
104# old clients, new path for newer
105path "sys/renew" {
106    capabilities = ["update"]
107}
108path "sys/leases/renew" {
109    capabilities = ["update"]
110}
111
112# Allow looking up lease properties. This requires knowing the lease ID ahead
113# of time and does not divulge any sensitive information.
114path "sys/leases/lookup" {
115    capabilities = ["update"]
116}
117
118# Allow a token to manage its own cubbyhole
119path "cubbyhole/*" {
120    capabilities = ["create", "read", "update", "delete", "list"]
121}
122
123# Allow a token to wrap arbitrary values in a response-wrapping token
124path "sys/wrapping/wrap" {
125    capabilities = ["update"]
126}
127
128# Allow a token to look up the creation time and TTL of a given
129# response-wrapping token
130path "sys/wrapping/lookup" {
131    capabilities = ["update"]
132}
133
134# Allow a token to unwrap a response-wrapping token. This is a convenience to
135# avoid client token swapping since this is also part of the response wrapping
136# policy.
137path "sys/wrapping/unwrap" {
138    capabilities = ["update"]
139}
140
141# Allow general purpose tools
142path "sys/tools/hash" {
143    capabilities = ["update"]
144}
145path "sys/tools/hash/*" {
146    capabilities = ["update"]
147}
148
149# Allow checking the status of a Control Group request if the user has the
150# accessor
151path "sys/control-group/request" {
152    capabilities = ["update"]
153}
154`
155)
156
157var (
158	immutablePolicies = []string{
159		"root",
160		responseWrappingPolicyName,
161		controlGroupPolicyName,
162	}
163	nonAssignablePolicies = []string{
164		responseWrappingPolicyName,
165		controlGroupPolicyName,
166	}
167)
168
169// PolicyStore is used to provide durable storage of policy, and to
170// manage ACLs associated with them.
171type PolicyStore struct {
172	entPolicyStore
173
174	core    *Core
175	aclView *BarrierView
176	rgpView *BarrierView
177	egpView *BarrierView
178
179	tokenPoliciesLRU *lru.TwoQueueCache
180	egpLRU           *lru.TwoQueueCache
181
182	// This is used to ensure that writes to the store (acl/rgp) or to the egp
183	// path tree don't happen concurrently. We are okay reading stale data so
184	// long as there aren't concurrent writes.
185	modifyLock *sync.RWMutex
186
187	// Stores whether a token policy is ACL or RGP
188	policyTypeMap sync.Map
189
190	// logger is the server logger copied over from core
191	logger log.Logger
192}
193
194// PolicyEntry is used to store a policy by name
195type PolicyEntry struct {
196	sentinelPolicy
197
198	Version   int
199	Raw       string
200	Templated bool
201	Type      PolicyType
202}
203
204// NewPolicyStore creates a new PolicyStore that is backed
205// using a given view. It used used to durable store and manage named policy.
206func NewPolicyStore(ctx context.Context, core *Core, baseView *BarrierView, system logical.SystemView, logger log.Logger) (*PolicyStore, error) {
207	ps := &PolicyStore{
208		aclView:    baseView.SubView(policyACLSubPath),
209		rgpView:    baseView.SubView(policyRGPSubPath),
210		egpView:    baseView.SubView(policyEGPSubPath),
211		modifyLock: new(sync.RWMutex),
212		logger:     logger,
213		core:       core,
214	}
215
216	ps.extraInit()
217
218	if !system.CachingDisabled() {
219		cache, _ := lru.New2Q(policyCacheSize)
220		ps.tokenPoliciesLRU = cache
221		cache, _ = lru.New2Q(policyCacheSize)
222		ps.egpLRU = cache
223	}
224
225	aclView := ps.getACLView(namespace.RootNamespace)
226	keys, err := logical.CollectKeys(namespace.RootContext(ctx), aclView)
227	if err != nil {
228		ps.logger.Error("error collecting acl policy keys", "error", err)
229		return nil, err
230	}
231	for _, key := range keys {
232		index := ps.cacheKey(namespace.RootNamespace, ps.sanitizeName(key))
233		ps.policyTypeMap.Store(index, PolicyTypeACL)
234	}
235
236	if err := ps.loadNamespacePolicies(ctx, core); err != nil {
237		return nil, err
238	}
239
240	// Special-case root; doesn't exist on disk but does need to be found
241	ps.policyTypeMap.Store(ps.cacheKey(namespace.RootNamespace, "root"), PolicyTypeACL)
242	return ps, nil
243}
244
245// setupPolicyStore is used to initialize the policy store
246// when the vault is being unsealed.
247func (c *Core) setupPolicyStore(ctx context.Context) error {
248	// Create the policy store
249	var err error
250	sysView := &dynamicSystemView{core: c}
251	psLogger := c.baseLogger.Named("policy")
252	c.AddLogger(psLogger)
253	c.policyStore, err = NewPolicyStore(ctx, c, c.systemBarrierView, sysView, psLogger)
254	if err != nil {
255		return err
256	}
257
258	if c.ReplicationState().HasState(consts.ReplicationPerformanceSecondary | consts.ReplicationDRSecondary) {
259		// Policies will sync from the primary
260		return nil
261	}
262
263	// Ensure that the default policy exists, and if not, create it
264	if err := c.policyStore.loadACLPolicy(ctx, defaultPolicyName, defaultPolicy); err != nil {
265		return err
266	}
267	// Ensure that the response wrapping policy exists
268	if err := c.policyStore.loadACLPolicy(ctx, responseWrappingPolicyName, responseWrappingPolicy); err != nil {
269		return err
270	}
271	// Ensure that the control group policy exists
272	if err := c.policyStore.loadACLPolicy(ctx, controlGroupPolicyName, controlGroupPolicy); err != nil {
273		return err
274	}
275
276	return nil
277}
278
279// teardownPolicyStore is used to reverse setupPolicyStore
280// when the vault is being sealed.
281func (c *Core) teardownPolicyStore() error {
282	c.policyStore = nil
283	return nil
284}
285
286func (ps *PolicyStore) invalidate(ctx context.Context, name string, policyType PolicyType) {
287	ns, err := namespace.FromContext(ctx)
288	if err != nil {
289		ps.logger.Error("unable to invalidate key, no namespace info passed", "key", name)
290		return
291	}
292
293	// This may come with a prefixed "/" due to joining the file path
294	saneName := strings.TrimPrefix(name, "/")
295	index := ps.cacheKey(ns, saneName)
296
297	ps.modifyLock.Lock()
298	defer ps.modifyLock.Unlock()
299
300	// We don't lock before removing from the LRU here because the worst that
301	// can happen is we load again if something since added it
302	switch policyType {
303	case PolicyTypeACL, PolicyTypeRGP:
304		if ps.tokenPoliciesLRU != nil {
305			ps.tokenPoliciesLRU.Remove(index)
306		}
307
308	case PolicyTypeEGP:
309		if ps.egpLRU != nil {
310			ps.egpLRU.Remove(index)
311		}
312
313	default:
314		// Can't do anything
315		return
316	}
317
318	// Force a reload
319	out, err := ps.switchedGetPolicy(ctx, name, policyType, false)
320	if err != nil {
321		ps.logger.Error("error fetching policy after invalidation", "name", saneName)
322	}
323
324	// If true, the invalidation was actually a delete, so we may need to
325	// perform further deletion tasks. We skip the physical deletion just in
326	// case another process has re-written the policy; instead next time Get is
327	// called the values will be loaded back in.
328	if out == nil {
329		ps.switchedDeletePolicy(ctx, name, policyType, false, true)
330	}
331
332	return
333}
334
335// SetPolicy is used to create or update the given policy
336func (ps *PolicyStore) SetPolicy(ctx context.Context, p *Policy) error {
337	defer metrics.MeasureSince([]string{"policy", "set_policy"}, time.Now())
338	if p == nil {
339		return fmt.Errorf("nil policy passed in for storage")
340	}
341	if p.Name == "" {
342		return fmt.Errorf("policy name missing")
343	}
344	// Policies are normalized to lower-case
345	p.Name = ps.sanitizeName(p.Name)
346	if strutil.StrListContains(immutablePolicies, p.Name) {
347		return fmt.Errorf("cannot update %q policy", p.Name)
348	}
349
350	return ps.setPolicyInternal(ctx, p)
351}
352
353func (ps *PolicyStore) setPolicyInternal(ctx context.Context, p *Policy) error {
354	ps.modifyLock.Lock()
355	defer ps.modifyLock.Unlock()
356
357	// Get the appropriate view based on policy type and namespace
358	view := ps.getBarrierView(p.namespace, p.Type)
359	if view == nil {
360		return fmt.Errorf("unable to get the barrier subview for policy type %q", p.Type)
361	}
362
363	if err := ps.parseEGPPaths(p); err != nil {
364		return err
365	}
366
367	// Create the entry
368	entry, err := logical.StorageEntryJSON(p.Name, &PolicyEntry{
369		Version:        2,
370		Raw:            p.Raw,
371		Type:           p.Type,
372		Templated:      p.Templated,
373		sentinelPolicy: p.sentinelPolicy,
374	})
375	if err != nil {
376		return errwrap.Wrapf("failed to create entry: {{err}}", err)
377	}
378
379	// Construct the cache key
380	index := ps.cacheKey(p.namespace, p.Name)
381
382	switch p.Type {
383	case PolicyTypeACL:
384		rgpView := ps.getRGPView(p.namespace)
385		rgp, err := rgpView.Get(ctx, entry.Key)
386		if err != nil {
387			return errwrap.Wrapf("failed looking up conflicting policy: {{err}}", err)
388		}
389		if rgp != nil {
390			return fmt.Errorf("cannot reuse policy names between ACLs and RGPs")
391		}
392
393		if err := view.Put(ctx, entry); err != nil {
394			return errwrap.Wrapf("failed to persist policy: {{err}}", err)
395		}
396
397		ps.policyTypeMap.Store(index, PolicyTypeACL)
398
399		if ps.tokenPoliciesLRU != nil {
400			ps.tokenPoliciesLRU.Add(index, p)
401		}
402
403	case PolicyTypeRGP:
404		aclView := ps.getACLView(p.namespace)
405		acl, err := aclView.Get(ctx, entry.Key)
406		if err != nil {
407			return errwrap.Wrapf("failed looking up conflicting policy: {{err}}", err)
408		}
409		if acl != nil {
410			return fmt.Errorf("cannot reuse policy names between ACLs and RGPs")
411		}
412
413		if err := ps.handleSentinelPolicy(ctx, p, view, entry); err != nil {
414			return err
415		}
416
417		ps.policyTypeMap.Store(index, PolicyTypeRGP)
418
419		// We load here after successfully loading into Sentinel so that on
420		// error we will try loading again on the next get
421		if ps.tokenPoliciesLRU != nil {
422			ps.tokenPoliciesLRU.Add(index, p)
423		}
424
425	case PolicyTypeEGP:
426		if err := ps.handleSentinelPolicy(ctx, p, view, entry); err != nil {
427			return err
428		}
429
430		// We load here after successfully loading into Sentinel so that on
431		// error we will try loading again on the next get
432		if ps.egpLRU != nil {
433			ps.egpLRU.Add(index, p)
434		}
435
436	default:
437		return fmt.Errorf("unknown policy type, cannot set")
438	}
439
440	return nil
441}
442
443// GetPolicy is used to fetch the named policy
444func (ps *PolicyStore) GetPolicy(ctx context.Context, name string, policyType PolicyType) (*Policy, error) {
445	return ps.switchedGetPolicy(ctx, name, policyType, true)
446}
447
448func (ps *PolicyStore) switchedGetPolicy(ctx context.Context, name string, policyType PolicyType, grabLock bool) (*Policy, error) {
449	defer metrics.MeasureSince([]string{"policy", "get_policy"}, time.Now())
450
451	ns, err := namespace.FromContext(ctx)
452	if err != nil {
453		return nil, err
454	}
455	// Policies are normalized to lower-case
456	name = ps.sanitizeName(name)
457	index := ps.cacheKey(ns, name)
458
459	var cache *lru.TwoQueueCache
460	var view *BarrierView
461
462	switch policyType {
463	case PolicyTypeACL:
464		cache = ps.tokenPoliciesLRU
465		view = ps.getACLView(ns)
466	case PolicyTypeRGP:
467		cache = ps.tokenPoliciesLRU
468		view = ps.getRGPView(ns)
469	case PolicyTypeEGP:
470		cache = ps.egpLRU
471		view = ps.getEGPView(ns)
472	case PolicyTypeToken:
473		cache = ps.tokenPoliciesLRU
474		val, ok := ps.policyTypeMap.Load(index)
475		if !ok {
476			// Doesn't exist
477			return nil, nil
478		}
479		policyType = val.(PolicyType)
480		switch policyType {
481		case PolicyTypeACL:
482			view = ps.getACLView(ns)
483		case PolicyTypeRGP:
484			view = ps.getRGPView(ns)
485		default:
486			return nil, fmt.Errorf("invalid type of policy in type map: %q", policyType)
487		}
488	}
489
490	if cache != nil {
491		// Check for cached policy
492		if raw, ok := cache.Get(index); ok {
493			return raw.(*Policy), nil
494		}
495	}
496
497	// Special case the root policy
498	if policyType == PolicyTypeACL && name == "root" && ns.ID == namespace.RootNamespaceID {
499		p := &Policy{
500			Name:      "root",
501			namespace: namespace.RootNamespace,
502		}
503		if cache != nil {
504			cache.Add(index, p)
505		}
506		return p, nil
507	}
508
509	if grabLock {
510		ps.modifyLock.Lock()
511		defer ps.modifyLock.Unlock()
512	}
513
514	// See if anything has added it since we got the lock
515	if cache != nil {
516		if raw, ok := cache.Get(index); ok {
517			return raw.(*Policy), nil
518		}
519	}
520
521	// Nil-check on the view before proceeding to retrieve from storage
522	if view == nil {
523		return nil, fmt.Errorf("unable to get the barrier subview for policy type %q", policyType)
524	}
525
526	out, err := view.Get(ctx, name)
527	if err != nil {
528		return nil, errwrap.Wrapf("failed to read policy: {{err}}", err)
529	}
530
531	if out == nil {
532		return nil, nil
533	}
534
535	policyEntry := new(PolicyEntry)
536	policy := new(Policy)
537	err = out.DecodeJSON(policyEntry)
538	if err != nil {
539		return nil, errwrap.Wrapf("failed to parse policy: {{err}}", err)
540	}
541
542	// Set these up here so that they're available for loading into
543	// Sentinel
544	policy.Name = name
545	policy.Raw = policyEntry.Raw
546	policy.Type = policyEntry.Type
547	policy.Templated = policyEntry.Templated
548	policy.sentinelPolicy = policyEntry.sentinelPolicy
549	policy.namespace = ns
550	switch policyEntry.Type {
551	case PolicyTypeACL:
552		// Parse normally
553		p, err := ParseACLPolicy(ns, policyEntry.Raw)
554		if err != nil {
555			return nil, errwrap.Wrapf("failed to parse policy: {{err}}", err)
556		}
557		policy.Paths = p.Paths
558
559		// Reset this in case they set the name in the policy itself
560		policy.Name = name
561
562		ps.policyTypeMap.Store(index, PolicyTypeACL)
563
564	case PolicyTypeRGP:
565		if err := ps.handleSentinelPolicy(ctx, policy, nil, nil); err != nil {
566			return nil, err
567		}
568
569		ps.policyTypeMap.Store(index, PolicyTypeRGP)
570
571	case PolicyTypeEGP:
572		if err := ps.handleSentinelPolicy(ctx, policy, nil, nil); err != nil {
573			return nil, err
574		}
575
576	default:
577		return nil, fmt.Errorf("unknown policy type %q", policyEntry.Type.String())
578	}
579
580	if cache != nil {
581		// Update the LRU cache
582		cache.Add(index, policy)
583	}
584
585	return policy, nil
586}
587
588// ListPolicies is used to list the available policies
589func (ps *PolicyStore) ListPolicies(ctx context.Context, policyType PolicyType) ([]string, error) {
590	defer metrics.MeasureSince([]string{"policy", "list_policies"}, time.Now())
591
592	ns, err := namespace.FromContext(ctx)
593	if err != nil {
594		return nil, err
595	}
596	if ns == nil {
597		return nil, namespace.ErrNoNamespace
598	}
599
600	// Get the appropriate view based on policy type and namespace
601	view := ps.getBarrierView(ns, policyType)
602	if view == nil {
603		return []string{}, fmt.Errorf("unable to get the barrier subview for policy type %q", policyType)
604	}
605
606	// Scan the view, since the policy names are the same as the
607	// key names.
608	var keys []string
609	switch policyType {
610	case PolicyTypeACL:
611		keys, err = logical.CollectKeys(ctx, view)
612	case PolicyTypeRGP:
613		return logical.CollectKeys(ctx, view)
614	case PolicyTypeEGP:
615		return logical.CollectKeys(ctx, view)
616	default:
617		return nil, fmt.Errorf("unknown policy type %q", policyType)
618	}
619
620	// We only have non-assignable ACL policies at the moment
621	for _, nonAssignable := range nonAssignablePolicies {
622		deleteIndex := -1
623		// Find indices of non-assignable policies in keys
624		for index, key := range keys {
625			if key == nonAssignable {
626				// Delete collection outside the loop
627				deleteIndex = index
628				break
629			}
630		}
631		// Remove non-assignable policies when found
632		if deleteIndex != -1 {
633			keys = append(keys[:deleteIndex], keys[deleteIndex+1:]...)
634		}
635	}
636
637	return keys, err
638}
639
640// DeletePolicy is used to delete the named policy
641func (ps *PolicyStore) DeletePolicy(ctx context.Context, name string, policyType PolicyType) error {
642	return ps.switchedDeletePolicy(ctx, name, policyType, true, false)
643}
644
645// deletePolicyForce is used to delete the named policy and force it even if
646// default or a singleton. It's used for invalidations or namespace deletion
647// where we internally need to actually remove a policy that the user normally
648// isn't allowed to remove.
649func (ps *PolicyStore) deletePolicyForce(ctx context.Context, name string, policyType PolicyType) error {
650	return ps.switchedDeletePolicy(ctx, name, policyType, true, true)
651}
652
653func (ps *PolicyStore) switchedDeletePolicy(ctx context.Context, name string, policyType PolicyType, physicalDeletion, force bool) error {
654	defer metrics.MeasureSince([]string{"policy", "delete_policy"}, time.Now())
655
656	ns, err := namespace.FromContext(ctx)
657	if err != nil {
658		return err
659	}
660	// If not set, the call comes from invalidation, where we'll already have
661	// grabbed the lock
662	if physicalDeletion {
663		ps.modifyLock.Lock()
664		defer ps.modifyLock.Unlock()
665	}
666
667	// Policies are normalized to lower-case
668	name = ps.sanitizeName(name)
669	index := ps.cacheKey(ns, name)
670
671	view := ps.getBarrierView(ns, policyType)
672	if view == nil {
673		return fmt.Errorf("unable to get the barrier subview for policy type %q", policyType)
674	}
675
676	switch policyType {
677	case PolicyTypeACL:
678		if !force {
679			if strutil.StrListContains(immutablePolicies, name) {
680				return fmt.Errorf("cannot delete %q policy", name)
681			}
682			if name == "default" {
683				return fmt.Errorf("cannot delete default policy")
684			}
685		}
686
687		if physicalDeletion {
688			err := view.Delete(ctx, name)
689			if err != nil {
690				return errwrap.Wrapf("failed to delete policy: {{err}}", err)
691			}
692		}
693
694		if ps.tokenPoliciesLRU != nil {
695			// Clear the cache
696			ps.tokenPoliciesLRU.Remove(index)
697		}
698
699		ps.policyTypeMap.Delete(index)
700
701	case PolicyTypeRGP:
702		if physicalDeletion {
703			err := view.Delete(ctx, name)
704			if err != nil {
705				return errwrap.Wrapf("failed to delete policy: {{err}}", err)
706			}
707		}
708
709		if ps.tokenPoliciesLRU != nil {
710			// Clear the cache
711			ps.tokenPoliciesLRU.Remove(index)
712		}
713
714		ps.policyTypeMap.Delete(index)
715
716		defer ps.core.invalidateSentinelPolicy(policyType, index)
717
718	case PolicyTypeEGP:
719		if physicalDeletion {
720			err := view.Delete(ctx, name)
721			if err != nil {
722				return errwrap.Wrapf("failed to delete policy: {{err}}", err)
723			}
724		}
725
726		if ps.egpLRU != nil {
727			// Clear the cache
728			ps.egpLRU.Remove(index)
729		}
730
731		defer ps.core.invalidateSentinelPolicy(policyType, index)
732
733		ps.invalidateEGPTreePath(index)
734	}
735
736	return nil
737}
738
739type TemplateError struct {
740	Err error
741}
742
743func (t *TemplateError) WrappedErrors() []error {
744	return []error{t.Err}
745}
746
747func (t *TemplateError) Error() string {
748	return t.Err.Error()
749}
750
751// ACL is used to return an ACL which is built using the
752// named policies.
753func (ps *PolicyStore) ACL(ctx context.Context, entity *identity.Entity, policyNames map[string][]string) (*ACL, error) {
754	var policies []*Policy
755	// Fetch the policies
756	for nsID, nsPolicyNames := range policyNames {
757		policyNS, err := NamespaceByID(ctx, nsID, ps.core)
758		if err != nil {
759			return nil, err
760		}
761		if policyNS == nil {
762			return nil, namespace.ErrNoNamespace
763		}
764		policyCtx := namespace.ContextWithNamespace(ctx, policyNS)
765		for _, nsPolicyName := range nsPolicyNames {
766			p, err := ps.GetPolicy(policyCtx, nsPolicyName, PolicyTypeToken)
767			if err != nil {
768				return nil, errwrap.Wrapf("failed to get policy: {{err}}", err)
769			}
770			if p != nil {
771				policies = append(policies, p)
772			}
773		}
774	}
775
776	var fetchedGroups bool
777	var groups []*identity.Group
778	for i, policy := range policies {
779		if policy.Type == PolicyTypeACL && policy.Templated {
780			if !fetchedGroups {
781				fetchedGroups = true
782				if entity != nil {
783					directGroups, inheritedGroups, err := ps.core.identityStore.groupsByEntityID(entity.ID)
784					if err != nil {
785						return nil, errwrap.Wrapf("failed to fetch group memberships: {{err}}", err)
786					}
787					groups = append(directGroups, inheritedGroups...)
788				}
789			}
790			p, err := parseACLPolicyWithTemplating(policy.namespace, policy.Raw, true, entity, groups)
791			if err != nil {
792				return nil, errwrap.Wrapf(fmt.Sprintf("error parsing templated policy %q: {{err}}", policy.Name), err)
793			}
794			p.Name = policy.Name
795			policies[i] = p
796		}
797	}
798
799	// Construct the ACL
800	acl, err := NewACL(ctx, policies)
801	if err != nil {
802		return nil, errwrap.Wrapf("failed to construct ACL: {{err}}", err)
803	}
804
805	return acl, nil
806}
807
808// loadACLPolicy is used to load default ACL policies. The default policies will
809// be loaded to all namespaces.
810func (ps *PolicyStore) loadACLPolicy(ctx context.Context, policyName, policyText string) error {
811	return ps.loadACLPolicyNamespaces(ctx, policyName, policyText)
812}
813
814// loadACLPolicyInternal is used to load default ACL policies in a specific
815// namespace.
816func (ps *PolicyStore) loadACLPolicyInternal(ctx context.Context, policyName, policyText string) error {
817	ns, err := namespace.FromContext(ctx)
818	if err != nil {
819		return err
820	}
821
822	// Check if the policy already exists
823	policy, err := ps.GetPolicy(ctx, policyName, PolicyTypeACL)
824	if err != nil {
825		return errwrap.Wrapf(fmt.Sprintf("error fetching %s policy from store: {{err}}", policyName), err)
826	}
827	if policy != nil {
828		if !strutil.StrListContains(immutablePolicies, policyName) || policyText == policy.Raw {
829			return nil
830		}
831	}
832
833	policy, err = ParseACLPolicy(ns, policyText)
834	if err != nil {
835		return errwrap.Wrapf(fmt.Sprintf("error parsing %s policy: {{err}}", policyName), err)
836	}
837
838	if policy == nil {
839		return fmt.Errorf("parsing %q policy resulted in nil policy", policyName)
840	}
841
842	policy.Name = policyName
843	policy.Type = PolicyTypeACL
844	return ps.setPolicyInternal(ctx, policy)
845}
846
847func (ps *PolicyStore) sanitizeName(name string) string {
848	return strings.ToLower(strings.TrimSpace(name))
849}
850
851func (ps *PolicyStore) cacheKey(ns *namespace.Namespace, name string) string {
852	return path.Join(ns.ID, name)
853}
854