Removes the exception for the "consul" service in the catalog.

This commit is contained in:
James Phillips 2016-12-07 17:58:23 -08:00
parent 7fa4ab3fd1
commit 66b437ca33
No known key found for this signature in database
GPG Key ID: 77183E682AC5FC11
4 changed files with 38 additions and 10 deletions

View File

@ -227,6 +227,7 @@ func Create(config *Config, logOutput io.Writer, logWriter *logger.LogWriter,
Port: agent.config.Ports.Server, Port: agent.config.Ports.Server,
Tags: []string{}, Tags: []string{},
} }
// TODO (slackpad) - Plumb the "acl_agent_token" into here.
agent.state.AddService(&consulService, "") agent.state.AddService(&consulService, "")
} else { } else {
err = agent.setupClient() err = agent.setupClient()
@ -381,6 +382,9 @@ func (a *Agent) consulConfig() *consul.Config {
if a.config.ACLReplicationToken != "" { if a.config.ACLReplicationToken != "" {
base.ACLReplicationToken = a.config.ACLReplicationToken base.ACLReplicationToken = a.config.ACLReplicationToken
} }
if a.config.ACLEnforceVersion8 != nil {
base.ACLEnforceVersion8 = *a.config.ACLEnforceVersion8
}
if a.config.SessionTTLMinRaw != "" { if a.config.SessionTTLMinRaw != "" {
base.SessionTTLMin = a.config.SessionTTLMin base.SessionTTLMin = a.config.SessionTTLMin
} }

View File

@ -26,6 +26,12 @@ func (c *Catalog) Register(args *structs.RegisterRequest, reply *struct{}) error
return fmt.Errorf("Must provide node and address") return fmt.Errorf("Must provide node and address")
} }
// Fetch the ACL token, if any.
acl, err := c.srv.resolveToken(args.Token)
if err != nil {
return err
}
if args.Service != nil { if args.Service != nil {
// If no service id, but service name, use default // If no service id, but service name, use default
if args.Service.ID == "" && args.Service.Service != "" { if args.Service.ID == "" && args.Service.Service != "" {
@ -37,14 +43,12 @@ func (c *Catalog) Register(args *structs.RegisterRequest, reply *struct{}) error
return fmt.Errorf("Must provide service name with ID") return fmt.Errorf("Must provide service name with ID")
} }
// Apply the ACL policy if any // Apply the ACL policy if any. The 'consul' service is excluded
// The 'consul' service is excluded since it is managed // since it is managed automatically internally (that behavior
// automatically internally. // is going away after version 0.8).
if args.Service.Service != ConsulServiceName { if c.srv.config.ACLEnforceVersion8 ||
acl, err := c.srv.resolveToken(args.Token) (args.Service.Service != ConsulServiceName) {
if err != nil { if acl != nil && !acl.ServiceWrite(args.Service.Service) {
return err
} else if acl != nil && !acl.ServiceWrite(args.Service.Service) {
c.srv.logger.Printf("[WARN] consul.catalog: Register of service '%s' on '%s' denied due to ACLs", c.srv.logger.Printf("[WARN] consul.catalog: Register of service '%s' on '%s' denied due to ACLs",
args.Service.Service, args.Node) args.Service.Service, args.Node)
return permissionDeniedErr return permissionDeniedErr
@ -65,7 +69,7 @@ func (c *Catalog) Register(args *structs.RegisterRequest, reply *struct{}) error
} }
} }
_, err := c.srv.raftApply(structs.RegisterRequestType, args) _, err = c.srv.raftApply(structs.RegisterRequestType, args)
if err != nil { if err != nil {
c.srv.logger.Printf("[ERR] consul.catalog: Register failed: %v", err) c.srv.logger.Printf("[ERR] consul.catalog: Register failed: %v", err)
return err return err

View File

@ -46,11 +46,12 @@ func TestCatalogRegister(t *testing.T) {
}) })
} }
func TestCatalogRegister_ACLDeny(t *testing.T) { func TestCatalogRegister_ACLDeny_Service(t *testing.T) {
dir1, s1 := testServerWithConfig(t, func(c *Config) { dir1, s1 := testServerWithConfig(t, func(c *Config) {
c.ACLDatacenter = "dc1" c.ACLDatacenter = "dc1"
c.ACLMasterToken = "root" c.ACLMasterToken = "root"
c.ACLDefaultPolicy = "deny" c.ACLDefaultPolicy = "deny"
c.ACLEnforceVersion8 = false
}) })
defer os.RemoveAll(dir1) defer os.RemoveAll(dir1)
defer s1.Shutdown() defer s1.Shutdown()
@ -99,6 +100,21 @@ func TestCatalogRegister_ACLDeny(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
// Try the special case for the "consul" service.
argR.Service.Service = "consul"
err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR)
if err != nil {
t.Fatalf("err: %v", err)
}
// Make sure the exception goes away when we turn on version 8 ACL
// enforcement.
s1.config.ACLEnforceVersion8 = true
err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR)
if err == nil || !strings.Contains(err.Error(), permissionDenied) {
t.Fatalf("err: %v", err)
}
} }
func TestCatalogRegister_ForwardLeader(t *testing.T) { func TestCatalogRegister_ForwardLeader(t *testing.T) {

View File

@ -200,6 +200,10 @@ type Config struct {
// used to limit the amount of Raft bandwidth used for replication. // used to limit the amount of Raft bandwidth used for replication.
ACLReplicationApplyLimit int ACLReplicationApplyLimit int
// ACLEnforceVersion8 is used to gate a set of ACL policy features that
// are opt-in prior to Consul 0.8 and opt-out in Consul 0.8 and later.
ACLEnforceVersion8 bool
// TombstoneTTL is used to control how long KV tombstones are retained. // TombstoneTTL is used to control how long KV tombstones are retained.
// This provides a window of time where the X-Consul-Index is monotonic. // This provides a window of time where the X-Consul-Index is monotonic.
// Outside this window, the index may not be monotonic. This is a result // Outside this window, the index may not be monotonic. This is a result