From ef171ca344dfefd96cf75f527cb59c6be7754a25 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Tue, 12 Aug 2014 10:38:57 -0700 Subject: [PATCH] consul: Support management tokens --- consul/acl.go | 15 +++++++++++---- consul/acl_test.go | 28 ++++++++++++++++++++++++++++ consul/server.go | 11 +---------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/consul/acl.go b/consul/acl.go index 8921047dc6..f9609611b8 100644 --- a/consul/acl.go +++ b/consul/acl.go @@ -28,17 +28,24 @@ type aclCacheEntry struct { } // aclFault is used to fault in the rules for an ACL if we take a miss -func (s *Server) aclFault(id string) (string, error) { +func (s *Server) aclFault(id string) (string, string, error) { defer metrics.MeasureSince([]string{"consul", "acl", "fault"}, time.Now()) state := s.fsm.State() _, acl, err := state.ACLGet(id) if err != nil { - return "", err + return "", "", err } if acl == nil { - return "", errors.New(aclNotFound) + return "", "", errors.New(aclNotFound) } - return acl.Rules, nil + + // Management tokens have no policy and inherit from allow + if acl.Type == structs.ACLTypeManagement { + return "allow", "", nil + } + + // Otherwise use the base policy + return s.config.ACLDefaultPolicy, acl.Rules, nil } // resolveToken is used to resolve an ACL is any is appropriate diff --git a/consul/acl_test.go b/consul/acl_test.go index b0dca39871..85bcb907c7 100644 --- a/consul/acl_test.go +++ b/consul/acl_test.go @@ -146,6 +146,34 @@ func TestACL_Authority_Master_Found(t *testing.T) { } } +func TestACL_Authority_Management(t *testing.T) { + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.ACLDatacenter = "dc1" // Enable ACLs! + c.ACLMasterToken = "foobar" + c.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + client := rpcClient(t, s1) + defer client.Close() + + testutil.WaitForLeader(t, client.Call, "dc1") + + // Resolve the token + acl, err := s1.resolveToken("foobar") + if err != nil { + t.Fatalf("err: %v", err) + } + if acl == nil { + t.Fatalf("missing acl") + } + + // Check the policy, should allow all + if !acl.KeyRead("foo/test") { + t.Fatalf("unexpected failed read") + } +} + func TestACL_NonAuthority_NotFound(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" diff --git a/consul/server.go b/consul/server.go index dc30308293..d3fe6da924 100644 --- a/consul/server.go +++ b/consul/server.go @@ -196,17 +196,8 @@ func NewServer(config *Config) (*Server, error) { shutdownCh: make(chan struct{}), } - // Determine the ACL root policy - var aclRoot acl.ACL - switch config.ACLDefaultPolicy { - case "allow": - aclRoot = acl.AllowAll() - case "deny": - aclRoot = acl.DenyAll() - } - // Initialize the authoritative ACL cache - s.aclAuthCache, err = acl.NewCache(aclCacheSize, aclRoot, s.aclFault) + s.aclAuthCache, err = acl.NewCache(aclCacheSize, s.aclFault) if err != nil { s.Shutdown() return nil, fmt.Errorf("Failed to create ACL cache: %v", err)