This file is indexed.

/usr/share/gocode/src/github.com/hashicorp/consul/acl/cache.go is in golang-github-hashicorp-consul-dev 0.6.4~dfsg-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package acl

import (
	"crypto/md5"
	"fmt"

	"github.com/hashicorp/golang-lru"
)

// FaultFunc is a function used to fault in the parent,
// rules for an  ACL given it's ID
type FaultFunc func(id string) (string, string, error)

// aclEntry allows us to store the ACL with it's policy ID
type aclEntry struct {
	ACL    ACL
	Parent string
	RuleID string
}

// Cache is used to implement policy and ACL caching
type Cache struct {
	faultfn     FaultFunc
	aclCache    *lru.Cache // Cache id -> acl
	policyCache *lru.Cache // Cache policy -> acl
	ruleCache   *lru.Cache // Cache rules -> policy
}

// NewCache constructs a new policy and ACL cache of a given size
func NewCache(size int, faultfn FaultFunc) (*Cache, error) {
	if size <= 0 {
		return nil, fmt.Errorf("Must provide positive cache size")
	}
	rc, _ := lru.New(size)
	pc, _ := lru.New(size)
	ac, _ := lru.New(size)
	c := &Cache{
		faultfn:     faultfn,
		aclCache:    ac,
		policyCache: pc,
		ruleCache:   rc,
	}
	return c, nil
}

// GetPolicy is used to get a potentially cached policy set.
// If not cached, it will be parsed, and then cached.
func (c *Cache) GetPolicy(rules string) (*Policy, error) {
	return c.getPolicy(c.ruleID(rules), rules)
}

// getPolicy is an internal method to get a cached policy,
// but it assumes a pre-computed ID
func (c *Cache) getPolicy(id, rules string) (*Policy, error) {
	raw, ok := c.ruleCache.Get(id)
	if ok {
		return raw.(*Policy), nil
	}
	policy, err := Parse(rules)
	if err != nil {
		return nil, err
	}
	policy.ID = id
	c.ruleCache.Add(id, policy)
	return policy, nil

}

// ruleID is used to generate an ID for a rule
func (c *Cache) ruleID(rules string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(rules)))
}

// policyID returns the cache ID for a policy
func (c *Cache) policyID(parent, ruleID string) string {
	return parent + ":" + ruleID
}

// GetACLPolicy is used to get the potentially cached ACL
// policy. If not cached, it will be generated and then cached.
func (c *Cache) GetACLPolicy(id string) (string, *Policy, error) {
	// Check for a cached acl
	if raw, ok := c.aclCache.Get(id); ok {
		cached := raw.(aclEntry)
		if raw, ok := c.ruleCache.Get(cached.RuleID); ok {
			return cached.Parent, raw.(*Policy), nil
		}
	}

	// Fault in the rules
	parent, rules, err := c.faultfn(id)
	if err != nil {
		return "", nil, err
	}

	// Get cached
	policy, err := c.GetPolicy(rules)
	return parent, policy, err
}

// GetACL is used to get a potentially cached ACL policy.
// If not cached, it will be generated and then cached.
func (c *Cache) GetACL(id string) (ACL, error) {
	// Look for the ACL directly
	raw, ok := c.aclCache.Get(id)
	if ok {
		return raw.(aclEntry).ACL, nil
	}

	// Get the rules
	parentID, rules, err := c.faultfn(id)
	if err != nil {
		return nil, err
	}
	ruleID := c.ruleID(rules)

	// Check for a compiled ACL
	policyID := c.policyID(parentID, ruleID)
	var compiled ACL
	if raw, ok := c.policyCache.Get(policyID); ok {
		compiled = raw.(ACL)
	} else {
		// Get the policy
		policy, err := c.getPolicy(ruleID, rules)
		if err != nil {
			return nil, err
		}

		// Get the parent ACL
		parent := RootACL(parentID)
		if parent == nil {
			parent, err = c.GetACL(parentID)
			if err != nil {
				return nil, err
			}
		}

		// Compile the ACL
		acl, err := New(parent, policy)
		if err != nil {
			return nil, err
		}

		// Cache the compiled ACL
		c.policyCache.Add(policyID, acl)
		compiled = acl
	}

	// Cache and return the ACL
	c.aclCache.Add(id, aclEntry{compiled, parentID, ruleID})
	return compiled, nil
}

// ClearACL is used to clear the ACL cache if any
func (c *Cache) ClearACL(id string) {
	c.aclCache.Remove(id)
}

// Purge is used to clear all the ACL caches. The
// rule and policy caches are not purged, since they
// are content-hashed anyways.
func (c *Cache) Purge() {
	c.aclCache.Purge()
}