Adds support for a new "acl_agent_token" which is used for internal
catalog operations.
This commit is contained in:
parent
99a5ae2737
commit
67f1fe8d0b
|
@ -227,8 +227,8 @@ func Create(config *Config, logOutput io.Writer, logWriter *logger.LogWriter,
|
|||
Port: agent.config.Ports.Server,
|
||||
Tags: []string{},
|
||||
}
|
||||
// TODO (slackpad) - Plumb the "acl_agent_token" into here.
|
||||
agent.state.AddService(&consulService, "")
|
||||
|
||||
agent.state.AddService(&consulService, agent.config.GetTokenForAgent())
|
||||
} else {
|
||||
err = agent.setupClient()
|
||||
agent.state.SetIface(agent.client)
|
||||
|
@ -364,6 +364,9 @@ func (a *Agent) consulConfig() *consul.Config {
|
|||
if a.config.ACLToken != "" {
|
||||
base.ACLToken = a.config.ACLToken
|
||||
}
|
||||
if a.config.ACLAgentToken != "" {
|
||||
base.ACLAgentToken = a.config.ACLAgentToken
|
||||
}
|
||||
if a.config.ACLMasterToken != "" {
|
||||
base.ACLMasterToken = a.config.ACLMasterToken
|
||||
}
|
||||
|
|
|
@ -488,6 +488,11 @@ type Config struct {
|
|||
// token is not provided. If not configured the 'anonymous' token is used.
|
||||
ACLToken string `mapstructure:"acl_token" json:"-"`
|
||||
|
||||
// ACLAgentToken is the default token used to make requests for the agent
|
||||
// itself, such as for registering itself with the catalog. If not
|
||||
// configured, the 'acl_token' will be used.
|
||||
ACLAgentToken string `mapstructure:"acl_agent_token" json:"-"`
|
||||
|
||||
// ACLMasterToken is used to bootstrap the ACL system. It should be specified
|
||||
// on the servers in the ACLDatacenter. When the leader comes online, it ensures
|
||||
// that the Master token is available. This provides the initial token.
|
||||
|
@ -756,6 +761,18 @@ func (c *Config) ClientListener(override string, port int) (net.Addr, error) {
|
|||
return &net.TCPAddr{IP: ip, Port: port}, nil
|
||||
}
|
||||
|
||||
// GetTokenForAgent returns the token the agent should use for its own internal
|
||||
// operations, such as registering itself with the catalog.
|
||||
func (c *Config) GetTokenForAgent() string {
|
||||
if c.ACLAgentToken != "" {
|
||||
return c.ACLAgentToken
|
||||
} else if c.ACLToken != "" {
|
||||
return c.ACLToken
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeConfig reads the configuration from the given reader in JSON
|
||||
// format and decodes it into a proper Config structure.
|
||||
func DecodeConfig(r io.Reader) (*Config, error) {
|
||||
|
@ -1466,6 +1483,9 @@ func MergeConfig(a, b *Config) *Config {
|
|||
if b.ACLToken != "" {
|
||||
result.ACLToken = b.ACLToken
|
||||
}
|
||||
if b.ACLAgentToken != "" {
|
||||
result.ACLAgentToken = b.ACLAgentToken
|
||||
}
|
||||
if b.ACLMasterToken != "" {
|
||||
result.ACLMasterToken = b.ACLMasterToken
|
||||
}
|
||||
|
|
|
@ -643,7 +643,7 @@ func TestDecodeConfig(t *testing.T) {
|
|||
}
|
||||
|
||||
// ACLs
|
||||
input = `{"acl_token": "1234", "acl_datacenter": "dc2",
|
||||
input = `{"acl_token": "1234", "acl_agent_token": "5678", "acl_datacenter": "dc2",
|
||||
"acl_ttl": "60s", "acl_down_policy": "deny",
|
||||
"acl_default_policy": "deny", "acl_master_token": "2345",
|
||||
"acl_replication_token": "8675309"}`
|
||||
|
@ -655,6 +655,9 @@ func TestDecodeConfig(t *testing.T) {
|
|||
if config.ACLToken != "1234" {
|
||||
t.Fatalf("bad: %#v", config)
|
||||
}
|
||||
if config.ACLAgentToken != "5678" {
|
||||
t.Fatalf("bad: %#v", config)
|
||||
}
|
||||
if config.ACLMasterToken != "2345" {
|
||||
t.Fatalf("bad: %#v", config)
|
||||
}
|
||||
|
@ -674,6 +677,32 @@ func TestDecodeConfig(t *testing.T) {
|
|||
t.Fatalf("bad: %#v", config)
|
||||
}
|
||||
|
||||
// ACL token precedence.
|
||||
input = `{}`
|
||||
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if token := config.GetTokenForAgent(); token != "" {
|
||||
t.Fatalf("bad: %s", token)
|
||||
}
|
||||
input = `{"acl_token": "hello"}`
|
||||
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if token := config.GetTokenForAgent(); token != "hello" {
|
||||
t.Fatalf("bad: %s", token)
|
||||
}
|
||||
input = `{"acl_agent_token": "world", "acl_token": "hello"}`
|
||||
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if token := config.GetTokenForAgent(); token != "world" {
|
||||
t.Fatalf("bad: %s", token)
|
||||
}
|
||||
|
||||
// ACL flag for Consul version 0.8 features (broken out since we will
|
||||
// eventually remove this). We first verify this is opt-out.
|
||||
config = DefaultConfig()
|
||||
|
@ -1561,6 +1590,7 @@ func TestMergeConfig(t *testing.T) {
|
|||
CheckUpdateInterval: 8 * time.Minute,
|
||||
CheckUpdateIntervalRaw: "8m",
|
||||
ACLToken: "1234",
|
||||
ACLAgentToken: "5678",
|
||||
ACLMasterToken: "2345",
|
||||
ACLDatacenter: "dc2",
|
||||
ACLTTL: 15 * time.Second,
|
||||
|
|
|
@ -400,7 +400,7 @@ func (l *localState) setSyncState() error {
|
|||
req := structs.NodeSpecificRequest{
|
||||
Datacenter: l.config.Datacenter,
|
||||
Node: l.config.NodeName,
|
||||
QueryOptions: structs.QueryOptions{Token: l.config.ACLToken},
|
||||
QueryOptions: structs.QueryOptions{Token: l.config.GetTokenForAgent()},
|
||||
}
|
||||
var out1 structs.IndexedNodeServices
|
||||
var out2 structs.IndexedHealthChecks
|
||||
|
@ -709,7 +709,7 @@ func (l *localState) syncNodeInfo() error {
|
|||
Node: l.config.NodeName,
|
||||
Address: l.config.AdvertiseAddr,
|
||||
TaggedAddresses: l.config.TaggedAddresses,
|
||||
WriteRequest: structs.WriteRequest{Token: l.config.ACLToken},
|
||||
WriteRequest: structs.WriteRequest{Token: l.config.GetTokenForAgent()},
|
||||
}
|
||||
var out struct{}
|
||||
err := l.iface.RPC("Catalog.Register", &req, &out)
|
||||
|
|
|
@ -155,6 +155,11 @@ type Config struct {
|
|||
// backwards compatibility as well.
|
||||
ACLToken string
|
||||
|
||||
// ACLAgentToken is the default token used to make requests for the agent
|
||||
// itself, such as for registering itself with the catalog. If not
|
||||
// configured, the ACLToken will be used.
|
||||
ACLAgentToken string
|
||||
|
||||
// ACLMasterToken is used to bootstrap the ACL system. It should be specified
|
||||
// on the servers in the ACLDatacenter. When the leader comes online, it ensures
|
||||
// that the Master token is available. This provides the initial token.
|
||||
|
@ -370,6 +375,7 @@ func (c *Config) ScaleRaft(raftMultRaw uint) {
|
|||
c.RaftConfig.LeaderLeaseTimeout = raftMult * def.LeaderLeaseTimeout
|
||||
}
|
||||
|
||||
// tlsConfig maps this config into a tlsutil config.
|
||||
func (c *Config) tlsConfig() *tlsutil.Config {
|
||||
tlsConf := &tlsutil.Config{
|
||||
VerifyIncoming: c.VerifyIncoming,
|
||||
|
@ -384,3 +390,15 @@ func (c *Config) tlsConfig() *tlsutil.Config {
|
|||
}
|
||||
return tlsConf
|
||||
}
|
||||
|
||||
// GetTokenForAgent returns the token the agent should use for its own internal
|
||||
// operations, such as registering itself with the catalog.
|
||||
func (c *Config) GetTokenForAgent() string {
|
||||
if c.ACLAgentToken != "" {
|
||||
return c.ACLAgentToken
|
||||
} else if c.ACLToken != "" {
|
||||
return c.ACLToken
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package consul
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConfig_GetTokenForAgent(t *testing.T) {
|
||||
config := DefaultConfig()
|
||||
if token := config.GetTokenForAgent(); token != "" {
|
||||
t.Fatalf("bad: %s", token)
|
||||
}
|
||||
config.ACLToken = "hello"
|
||||
if token := config.GetTokenForAgent(); token != "hello" {
|
||||
t.Fatalf("bad: %s", token)
|
||||
}
|
||||
config.ACLAgentToken = "world"
|
||||
if token := config.GetTokenForAgent(); token != "world" {
|
||||
t.Fatalf("bad: %s", token)
|
||||
}
|
||||
}
|
|
@ -428,7 +428,7 @@ AFTER_CHECK:
|
|||
Status: structs.HealthPassing,
|
||||
Output: SerfCheckAliveOutput,
|
||||
},
|
||||
WriteRequest: structs.WriteRequest{Token: s.config.ACLToken},
|
||||
WriteRequest: structs.WriteRequest{Token: s.config.GetTokenForAgent()},
|
||||
}
|
||||
var out struct{}
|
||||
return s.endpoints.Catalog.Register(&req, &out)
|
||||
|
@ -469,7 +469,7 @@ func (s *Server) handleFailedMember(member serf.Member) error {
|
|||
Status: structs.HealthCritical,
|
||||
Output: SerfCheckFailedOutput,
|
||||
},
|
||||
WriteRequest: structs.WriteRequest{Token: s.config.ACLToken},
|
||||
WriteRequest: structs.WriteRequest{Token: s.config.GetTokenForAgent()},
|
||||
}
|
||||
var out struct{}
|
||||
return s.endpoints.Catalog.Register(&req, &out)
|
||||
|
@ -612,7 +612,7 @@ func (s *Server) reapTombstones(index uint64) {
|
|||
Datacenter: s.config.Datacenter,
|
||||
Op: structs.TombstoneReap,
|
||||
ReapIndex: index,
|
||||
WriteRequest: structs.WriteRequest{Token: s.config.ACLToken},
|
||||
WriteRequest: structs.WriteRequest{Token: s.config.GetTokenForAgent()},
|
||||
}
|
||||
_, err := s.raftApply(structs.TombstoneRequestType, &req)
|
||||
if err != nil {
|
||||
|
|
|
@ -377,6 +377,14 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
|
|||
all operations, and "extend-cache" allows any cached ACLs to be used, ignoring their TTL
|
||||
values. If a non-cached ACL is used, "extend-cache" acts like "deny".
|
||||
|
||||
* <a name"acl_agent_token"></a><a href="#acl_agent_token">`acl_agent_token`</a> - Used for clients
|
||||
and servers to perform internal operations to the service catalog. If this isn't specified, then
|
||||
the <a href="#acl_token">`acl_token`</a> will be used. This was added in Consul 0.7.2.
|
||||
<br><br>
|
||||
For clients, this token must at least have write access to the node name it will register as. For
|
||||
servers, this must have write access to all nodes that are expected to join the cluster, as well
|
||||
as write access to the "consul" service, which will be registered automatically on its behalf.
|
||||
|
||||
* <a name="acl_enforce_version_8"></a><a href="#acl_enforce_version_8">`acl_enforce_version_8`</a> -
|
||||
Used for clients and servers to determine if enforcement should occur for new ACL policies being
|
||||
previewed before Consul 0.8. Added in Consul 0.7.2, this will default to false in versions of
|
||||
|
|
Loading…
Reference in New Issue