consul: Use Etag for policy caching
This commit is contained in:
parent
bee6e4e559
commit
61b80e912c
|
@ -18,8 +18,8 @@ const (
|
|||
// If non-authoritative, then we must respect a TTL
|
||||
type aclCacheEntry struct {
|
||||
ACL acl.ACL
|
||||
TTL time.Duration
|
||||
Expires time.Time
|
||||
ETag string
|
||||
}
|
||||
|
||||
// aclFault is used to fault in the rules for an ACL if we take a miss
|
||||
|
@ -78,31 +78,7 @@ func (s *Server) lookupACL(id, authDC string) (acl.ACL, error) {
|
|||
|
||||
// Handle the happy path
|
||||
if err == nil {
|
||||
// Determine the root
|
||||
var root acl.ACL
|
||||
switch out.Root {
|
||||
case "allow":
|
||||
root = acl.AllowAll()
|
||||
default:
|
||||
root = acl.DenyAll()
|
||||
}
|
||||
|
||||
// Compile the ACL
|
||||
acl, err := acl.New(root, out.Policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Cache the ACL
|
||||
cached := &aclCacheEntry{
|
||||
ACL: acl,
|
||||
TTL: out.TTL,
|
||||
}
|
||||
if out.TTL > 0 {
|
||||
cached.Expires = time.Now().Add(out.TTL)
|
||||
}
|
||||
s.aclCache.Add(id, cached)
|
||||
return acl, nil
|
||||
return s.useACLPolicy(id, cached, &out)
|
||||
}
|
||||
|
||||
// Check for not-found
|
||||
|
@ -125,3 +101,51 @@ func (s *Server) lookupACL(id, authDC string) (acl.ACL, error) {
|
|||
return acl.DenyAll(), nil
|
||||
}
|
||||
}
|
||||
|
||||
// useACLPolicy handles an ACLPolicy response
|
||||
func (s *Server) useACLPolicy(id string, cached *aclCacheEntry, p *structs.ACLPolicy) (acl.ACL, error) {
|
||||
// Check if we can used the cached policy
|
||||
if cached != nil && cached.ETag == p.ETag {
|
||||
if p.TTL > 0 {
|
||||
cached.Expires = time.Now().Add(p.TTL)
|
||||
}
|
||||
return cached.ACL, nil
|
||||
}
|
||||
|
||||
// Check for a cached compiled policy
|
||||
var compiled acl.ACL
|
||||
raw, ok := s.aclPolicyCache.Get(cached.ETag)
|
||||
if ok {
|
||||
compiled = raw.(acl.ACL)
|
||||
} else {
|
||||
// Determine the root policy
|
||||
var root acl.ACL
|
||||
switch p.Root {
|
||||
case "allow":
|
||||
root = acl.AllowAll()
|
||||
default:
|
||||
root = acl.DenyAll()
|
||||
}
|
||||
|
||||
// Compile the ACL
|
||||
acl, err := acl.New(root, p.Policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Cache the policy
|
||||
s.aclPolicyCache.Add(p.ETag, acl)
|
||||
compiled = acl
|
||||
}
|
||||
|
||||
// Cache the ACL
|
||||
cached = &aclCacheEntry{
|
||||
ACL: compiled,
|
||||
ETag: p.ETag,
|
||||
}
|
||||
if p.TTL > 0 {
|
||||
cached.Expires = time.Now().Add(p.TTL)
|
||||
}
|
||||
s.aclCache.Add(id, cached)
|
||||
return acl, nil
|
||||
}
|
||||
|
|
|
@ -59,6 +59,9 @@ type Server struct {
|
|||
// aclCache is a non-authoritative ACL cache
|
||||
aclCache *lru.Cache
|
||||
|
||||
// aclPolicyCache is a policy cache
|
||||
aclPolicyCache *lru.Cache
|
||||
|
||||
// Consul configuration
|
||||
config *Config
|
||||
|
||||
|
@ -216,6 +219,13 @@ func NewServer(config *Config) (*Server, error) {
|
|||
return nil, fmt.Errorf("Failed to create ACL cache: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the ACL policy cache
|
||||
s.aclPolicyCache, err = lru.New(aclCacheSize)
|
||||
if err != nil {
|
||||
s.Shutdown()
|
||||
return nil, fmt.Errorf("Failed to create ACL policy cache: %v", err)
|
||||
}
|
||||
|
||||
// Initialize the RPC layer
|
||||
if err := s.setupRPC(tlsConfig); err != nil {
|
||||
s.Shutdown()
|
||||
|
|
Loading…
Reference in New Issue