Passthrough replication token for token/policy replication

This commit is contained in:
Armon Dadgar 2017-08-20 20:51:30 -07:00
parent 855240b1b5
commit 3e46094cee
10 changed files with 47 additions and 15 deletions

View File

@ -146,6 +146,9 @@ func convertServerConfig(agentConfig *Config, logOutput io.Writer) (*nomad.Confi
if agentConfig.ACL.Enabled {
conf.ACLEnabled = true
}
if agentConfig.ACL.ReplicationToken != "" {
conf.ReplicationToken = agentConfig.ACL.ReplicationToken
}
// Set up the bind addresses
rpcAddr, err := net.ResolveTCPAddr("tcp", agentConfig.normalizedAddrs.RPC)

View File

@ -87,6 +87,7 @@ acl {
enabled = true
token_ttl = "60s"
policy_ttl = "60s"
replication_token = "foobar"
}
telemetry {
statsite_address = "127.0.0.1:1234"

View File

@ -247,6 +247,11 @@ type ACLConfig struct {
// to "30s". Reducing this impacts performance by forcing more
// frequent resolution.
PolicyTTL time.Duration `mapstructure:"policy_ttl"`
// ReplicationToken is used by servers to replicate tokens and policies
// from the authoritative region. This must be a valid management token
// within the authoritative region.
ReplicationToken string `mapstructure:"replication_token"`
}
// ServerConfig is configuration specific to the server mode
@ -953,6 +958,9 @@ func (a *ACLConfig) Merge(b *ACLConfig) *ACLConfig {
if b.PolicyTTL != 0 {
result.PolicyTTL = b.PolicyTTL
}
if b.ReplicationToken != "" {
result.ReplicationToken = b.ReplicationToken
}
return &result
}

View File

@ -573,6 +573,7 @@ func parseACL(result **ACLConfig, list *ast.ObjectList) error {
"enabled",
"token_ttl",
"policy_ttl",
"replication_token",
}
if err := checkHCLKeys(listVal, valid); err != nil {
return err

View File

@ -105,9 +105,10 @@ func TestConfig_Parse(t *testing.T) {
EncryptKey: "abc",
},
ACL: &ACLConfig{
Enabled: true,
TokenTTL: 60 * time.Second,
PolicyTTL: 60 * time.Second,
Enabled: true,
TokenTTL: 60 * time.Second,
PolicyTTL: 60 * time.Second,
ReplicationToken: "foobar",
},
Telemetry: &Telemetry{
StatsiteAddr: "127.0.0.1:1234",

View File

@ -103,9 +103,10 @@ func TestConfig_Merge(t *testing.T) {
MaxHeartbeatsPerSecond: 30.0,
},
ACL: &ACLConfig{
Enabled: true,
TokenTTL: 60 * time.Second,
PolicyTTL: 60 * time.Second,
Enabled: true,
TokenTTL: 60 * time.Second,
PolicyTTL: 60 * time.Second,
ReplicationToken: "foo",
},
Ports: &Ports{
HTTP: 4646,
@ -247,9 +248,10 @@ func TestConfig_Merge(t *testing.T) {
retryInterval: time.Second * 10,
},
ACL: &ACLConfig{
Enabled: true,
TokenTTL: 20 * time.Second,
PolicyTTL: 20 * time.Second,
Enabled: true,
TokenTTL: 20 * time.Second,
PolicyTTL: 20 * time.Second,
ReplicationToken: "foobar",
},
Ports: &Ports{
HTTP: 20000,

View File

@ -235,6 +235,10 @@ type Config struct {
// ReplicationBackoff is how much we backoff when replication errors.
// This is a tunable knob for testing primarily.
ReplicationBackoff time.Duration
// ReplicationToken is the ACL Token Secret ID used to fetch from
// the Authoritative Region.
ReplicationToken string
}
// CheckVersion is used to check if the ProtocolVersion is valid

View File

@ -691,6 +691,7 @@ START:
// Fetch the list of policies
var resp structs.ACLPolicyListResponse
req.SecretID = s.ReplicationToken()
err := s.forwardRegion(s.config.AuthoritativeRegion,
"ACL.ListPolicies", &req, &resp)
if err != nil {
@ -719,7 +720,8 @@ START:
req := structs.ACLPolicySetRequest{
Names: update,
QueryOptions: structs.QueryOptions{
Region: s.config.AuthoritativeRegion,
Region: s.config.AuthoritativeRegion,
SecretID: s.ReplicationToken(),
},
}
var reply structs.ACLPolicySetResponse
@ -831,6 +833,7 @@ START:
// Fetch the list of tokens
var resp structs.ACLTokenListResponse
req.SecretID = s.ReplicationToken()
err := s.forwardRegion(s.config.AuthoritativeRegion,
"ACL.ListTokens", &req, &resp)
if err != nil {
@ -859,7 +862,8 @@ START:
req := structs.ACLTokenSetRequest{
AccessorIDS: update,
QueryOptions: structs.QueryOptions{
Region: s.config.AuthoritativeRegion,
Region: s.config.AuthoritativeRegion,
SecretID: s.ReplicationToken(),
},
}
var reply structs.ACLTokenSetResponse

View File

@ -629,17 +629,18 @@ func TestLeader_RestoreVaultAccessors(t *testing.T) {
func TestLeader_ReplicateACLPolicies(t *testing.T) {
t.Parallel()
s1 := testServer(t, func(c *Config) {
s1, root := testACLServer(t, func(c *Config) {
c.Region = "region1"
c.AuthoritativeRegion = "region1"
c.ACLEnabled = true
})
defer s1.Shutdown()
s2 := testServer(t, func(c *Config) {
s2, _ := testACLServer(t, func(c *Config) {
c.Region = "region2"
c.AuthoritativeRegion = "region1"
c.ACLEnabled = true
c.ReplicationBackoff = 20 * time.Millisecond
c.ReplicationToken = root.SecretID
})
defer s2.Shutdown()
testJoin(t, s1, s2)
@ -699,17 +700,18 @@ func TestLeader_DiffACLPolicies(t *testing.T) {
func TestLeader_ReplicateACLTokens(t *testing.T) {
t.Parallel()
s1 := testServer(t, func(c *Config) {
s1, root := testACLServer(t, func(c *Config) {
c.Region = "region1"
c.AuthoritativeRegion = "region1"
c.ACLEnabled = true
})
defer s1.Shutdown()
s2 := testServer(t, func(c *Config) {
s2, _ := testACLServer(t, func(c *Config) {
c.Region = "region2"
c.AuthoritativeRegion = "region1"
c.ACLEnabled = true
c.ReplicationBackoff = 20 * time.Millisecond
c.ReplicationToken = root.SecretID
})
defer s2.Shutdown()
testJoin(t, s1, s2)

View File

@ -1147,6 +1147,12 @@ func (s *Server) GetConfig() *Config {
return s.config
}
// ReplicationToken returns the token used for replication. We use a method to support
// dynamic reloading of this value later.
func (s *Server) ReplicationToken() string {
return s.config.ReplicationToken
}
// peersInfoContent is used to help operators understand what happened to the
// peers.json file. This is written to a file called peers.info in the same
// location.