consul: Enable ACL lookup

pull/291/head
Armon Dadgar 2014-08-08 15:52:52 -07:00
parent 97a737b1ee
commit 338f11c6cf
3 changed files with 57 additions and 6 deletions

View File

@ -1,10 +1,17 @@
package consul package consul
import ( import (
"fmt" "errors"
"strings"
"time" "time"
"github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/consul/structs"
)
const (
// aclNotFound indicates there is no matching ACL
aclNotFound = "ACL not found"
) )
// aclCacheEntry is used to cache non-authoritative ACL's // aclCacheEntry is used to cache non-authoritative ACL's
@ -23,7 +30,7 @@ func (s *Server) aclFault(id string) (string, error) {
return "", err return "", err
} }
if acl == nil { if acl == nil {
return "", fmt.Errorf("ACL not found: %s", id) return "", errors.New(aclNotFound)
} }
return acl.Rules, nil return acl.Rules, nil
} }
@ -43,12 +50,12 @@ func (s *Server) resolveToken(id string) (acl.ACL, error) {
} }
// Use our non-authoritative cache // Use our non-authoritative cache
return s.lookupACL(id) return s.lookupACL(id, authDC)
} }
// lookupACL is used when we are non-authoritative, and need // lookupACL is used when we are non-authoritative, and need
// to resolve an ACL // to resolve an ACL
func (s *Server) lookupACL(id string) (acl.ACL, error) { func (s *Server) lookupACL(id, authDC string) (acl.ACL, error) {
// Check the cache for the ACL // Check the cache for the ACL
var cached *aclCacheEntry var cached *aclCacheEntry
raw, ok := s.aclCache.Get(id) raw, ok := s.aclCache.Get(id)
@ -62,7 +69,48 @@ func (s *Server) lookupACL(id string) (acl.ACL, error) {
} }
// Attempt to refresh the policy // Attempt to refresh the policy
// TODO: GetPolicy... args := structs.ACLSpecificRequest{
Datacenter: authDC,
ACL: id,
}
var out structs.ACLPolicy
err := s.RPC("ACL.GetPolicy", &args, &out)
// 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
}
// Check for not-found
if strings.Contains(err.Error(), aclNotFound) {
return nil, errors.New(aclNotFound)
} else {
s.logger.Printf("[ERR] consul.acl: Failed to get policy for '%s': %v", id, err)
}
// Unable to refresh, apply the down policy // Unable to refresh, apply the down policy
switch s.config.ACLDownPolicy { switch s.config.ACLDownPolicy {

View File

@ -95,8 +95,10 @@ func (a *ACL) GetPolicy(args *structs.ACLSpecificRequest, reply *structs.ACLPoli
} }
// Setup the response // Setup the response
conf := a.srv.config
reply.Policy = policy reply.Policy = policy
reply.TTL = a.srv.config.ACLTTL reply.Root = conf.ACLDefaultPolicy
reply.TTL = conf.ACLTTL
a.srv.setQueryMeta(&reply.QueryMeta) a.srv.setQueryMeta(&reply.QueryMeta)
return nil return nil
} }

View File

@ -472,6 +472,7 @@ type IndexedACLs struct {
} }
type ACLPolicy struct { type ACLPolicy struct {
Root string
Policy *acl.Policy Policy *acl.Policy
TTL time.Duration TTL time.Duration
QueryMeta QueryMeta