agent/token: rename `agent_master` to `agent_recovery` (internally) (#11744)

This commit is contained in:
Dan Upton 2021-12-07 12:12:47 +00:00 committed by GitHub
parent cfabdbba21
commit 0230ebb4ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 194 additions and 167 deletions

3
.changelog/11744.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:note
Renamed the `agent_master` field to `agent_recovery` in the `acl-tokens.json` file in which tokens are persisted on-disk (when `acl.enable_token_persistence` is enabled)
```

View File

@ -1510,7 +1510,7 @@ func (s *HTTPHandlers) AgentToken(resp http.ResponseWriter, req *http.Request) (
} }
case "acl_agent_master_token", "agent_master", "agent_recovery": case "acl_agent_master_token", "agent_master", "agent_recovery":
s.agent.tokens.UpdateAgentMasterToken(args.Token, token_store.TokenSourceAPI) s.agent.tokens.UpdateAgentRecoveryToken(args.Token, token_store.TokenSourceAPI)
case "acl_replication_token", "replication": case "acl_replication_token", "replication":
s.agent.tokens.UpdateReplicationToken(args.Token, token_store.TokenSourceAPI) s.agent.tokens.UpdateReplicationToken(args.Token, token_store.TokenSourceAPI)

View File

@ -5396,7 +5396,7 @@ func TestAgent_Token(t *testing.T) {
resetTokens := func(init tokens) { resetTokens := func(init tokens) {
a.tokens.UpdateUserToken(init.user, init.userSource) a.tokens.UpdateUserToken(init.user, init.userSource)
a.tokens.UpdateAgentToken(init.agent, init.agentSource) a.tokens.UpdateAgentToken(init.agent, init.agentSource)
a.tokens.UpdateAgentMasterToken(init.master, init.masterSource) a.tokens.UpdateAgentRecoveryToken(init.master, init.masterSource)
a.tokens.UpdateReplicationToken(init.repl, init.replSource) a.tokens.UpdateReplicationToken(init.repl, init.replSource)
} }
@ -5614,7 +5614,7 @@ func TestAgent_Token(t *testing.T) {
} }
require.Equal(t, tt.effective.user, a.tokens.UserToken()) require.Equal(t, tt.effective.user, a.tokens.UserToken())
require.Equal(t, tt.effective.agent, a.tokens.AgentToken()) require.Equal(t, tt.effective.agent, a.tokens.AgentToken())
require.Equal(t, tt.effective.master, a.tokens.AgentMasterToken()) require.Equal(t, tt.effective.master, a.tokens.AgentRecoveryToken())
require.Equal(t, tt.effective.repl, a.tokens.ReplicationToken()) require.Equal(t, tt.effective.repl, a.tokens.ReplicationToken())
tok, src := a.tokens.UserTokenAndSource() tok, src := a.tokens.UserTokenAndSource()
@ -5625,7 +5625,7 @@ func TestAgent_Token(t *testing.T) {
require.Equal(t, tt.raw.agent, tok) require.Equal(t, tt.raw.agent, tok)
require.Equal(t, tt.raw.agentSource, src) require.Equal(t, tt.raw.agentSource, src)
tok, src = a.tokens.AgentMasterTokenAndSource() tok, src = a.tokens.AgentRecoveryTokenAndSource()
require.Equal(t, tt.raw.master, tok) require.Equal(t, tt.raw.master, tok)
require.Equal(t, tt.raw.masterSource, src) require.Equal(t, tt.raw.masterSource, src)

View File

@ -226,7 +226,7 @@ func TestAgent_TokenStore(t *testing.T) {
if got, want := a.tokens.AgentToken(), "agent"; got != want { if got, want := a.tokens.AgentToken(), "agent"; got != want {
t.Fatalf("got %q want %q", got, want) t.Fatalf("got %q want %q", got, want)
} }
if got, want := a.tokens.IsAgentMasterToken("master"), true; got != want { if got, want := a.tokens.IsAgentRecoveryToken("master"), true; got != want {
t.Fatalf("got %v want %v", got, want) t.Fatalf("got %v want %v", got, want)
} }
} }

View File

@ -866,12 +866,12 @@ func (b *builder) build() (rt RuntimeConfig, err error) {
ACLTokenReplication: boolVal(c.ACL.TokenReplication), ACLTokenReplication: boolVal(c.ACL.TokenReplication),
ACLTokens: token.Config{ ACLTokens: token.Config{
DataDir: dataDir, DataDir: dataDir,
EnablePersistence: boolValWithDefault(c.ACL.EnableTokenPersistence, false), EnablePersistence: boolValWithDefault(c.ACL.EnableTokenPersistence, false),
ACLDefaultToken: stringVal(c.ACL.Tokens.Default), ACLDefaultToken: stringVal(c.ACL.Tokens.Default),
ACLAgentToken: stringVal(c.ACL.Tokens.Agent), ACLAgentToken: stringVal(c.ACL.Tokens.Agent),
ACLAgentMasterToken: stringVal(c.ACL.Tokens.AgentRecovery), ACLAgentRecoveryToken: stringVal(c.ACL.Tokens.AgentRecovery),
ACLReplicationToken: stringVal(c.ACL.Tokens.Replication), ACLReplicationToken: stringVal(c.ACL.Tokens.Replication),
}, },
// Autopilot // Autopilot

View File

@ -111,7 +111,7 @@ func TestLoad_DeprecatedConfig_ACLMasterTokens(t *testing.T) {
rt := result.RuntimeConfig rt := result.RuntimeConfig
require.Equal("token1", rt.ACLMasterToken) require.Equal("token1", rt.ACLMasterToken)
require.Equal("token2", rt.ACLTokens.ACLAgentMasterToken) require.Equal("token2", rt.ACLTokens.ACLAgentRecoveryToken)
}) })
t.Run("embedded in tokens struct", func(t *testing.T) { t.Run("embedded in tokens struct", func(t *testing.T) {
@ -142,7 +142,7 @@ func TestLoad_DeprecatedConfig_ACLMasterTokens(t *testing.T) {
rt := result.RuntimeConfig rt := result.RuntimeConfig
require.Equal("token1", rt.ACLMasterToken) require.Equal("token1", rt.ACLMasterToken)
require.Equal("token2", rt.ACLTokens.ACLAgentMasterToken) require.Equal("token2", rt.ACLTokens.ACLAgentRecoveryToken)
}) })
t.Run("both", func(t *testing.T) { t.Run("both", func(t *testing.T) {
@ -170,6 +170,6 @@ func TestLoad_DeprecatedConfig_ACLMasterTokens(t *testing.T) {
rt := result.RuntimeConfig rt := result.RuntimeConfig
require.Equal("token3", rt.ACLMasterToken) require.Equal("token3", rt.ACLMasterToken)
require.Equal("token4", rt.ACLTokens.ACLAgentMasterToken) require.Equal("token4", rt.ACLTokens.ACLAgentRecoveryToken)
}) })
} }

View File

@ -5341,12 +5341,12 @@ func TestLoad_FullConfig(t *testing.T) {
// user configurable values // user configurable values
ACLTokens: token.Config{ ACLTokens: token.Config{
EnablePersistence: true, EnablePersistence: true,
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "418fdff1", ACLDefaultToken: "418fdff1",
ACLAgentToken: "bed2377c", ACLAgentToken: "bed2377c",
ACLAgentMasterToken: "1dba6aba", ACLAgentRecoveryToken: "1dba6aba",
ACLReplicationToken: "5795983a", ACLReplicationToken: "5795983a",
}, },
ACLsEnabled: true, ACLsEnabled: true,

View File

@ -14,7 +14,7 @@
}, },
"ACLTokenReplication": false, "ACLTokenReplication": false,
"ACLTokens": { "ACLTokens": {
"ACLAgentMasterToken": "hidden", "ACLAgentRecoveryToken": "hidden",
"ACLAgentToken": "hidden", "ACLAgentToken": "hidden",
"ACLDefaultToken": "hidden", "ACLDefaultToken": "hidden",
"ACLReplicationToken": "hidden", "ACLReplicationToken": "hidden",

View File

@ -1053,7 +1053,7 @@ func (r *ACLResolver) resolveLocallyManagedToken(token string) (structs.ACLIdent
return nil, nil, false return nil, nil, false
} }
if r.tokens.IsAgentMasterToken(token) { if r.tokens.IsAgentRecoveryToken(token) {
return structs.NewAgentMasterTokenIdentity(r.config.NodeName, token), r.agentMasterAuthz, true return structs.NewAgentMasterTokenIdentity(r.config.NodeName, token), r.agentMasterAuthz, true
} }

View File

@ -4020,7 +4020,7 @@ func TestACLResolver_AgentMaster(t *testing.T) {
cfg.DisableDuration = 0 cfg.DisableDuration = 0
}) })
tokens.UpdateAgentMasterToken("9a184a11-5599-459e-b71a-550e5f9a5a23", token.TokenSourceConfig) tokens.UpdateAgentRecoveryToken("9a184a11-5599-459e-b71a-550e5f9a5a23", token.TokenSourceConfig)
ident, authz, err := r.ResolveTokenToIdentityAndAuthorizer("9a184a11-5599-459e-b71a-550e5f9a5a23") ident, authz, err := r.ResolveTokenToIdentityAndAuthorizer("9a184a11-5599-459e-b71a-550e5f9a5a23")
require.NoError(t, err) require.NoError(t, err)

View File

@ -17,12 +17,12 @@ type Logger interface {
// Config used by Store.Load, which includes tokens and settings for persistence. // Config used by Store.Load, which includes tokens and settings for persistence.
type Config struct { type Config struct {
EnablePersistence bool EnablePersistence bool
DataDir string DataDir string
ACLDefaultToken string ACLDefaultToken string
ACLAgentToken string ACLAgentToken string
ACLAgentMasterToken string ACLAgentRecoveryToken string
ACLReplicationToken string ACLReplicationToken string
EnterpriseConfig EnterpriseConfig
} }
@ -69,10 +69,10 @@ func (t *Store) WithPersistenceLock(f func() error) error {
} }
type persistedTokens struct { type persistedTokens struct {
Replication string `json:"replication,omitempty"` Replication string `json:"replication,omitempty"`
AgentMaster string `json:"agent_master,omitempty"` AgentRecovery string `json:"agent_recovery,omitempty"`
Default string `json:"default,omitempty"` Default string `json:"default,omitempty"`
Agent string `json:"agent,omitempty"` Agent string `json:"agent,omitempty"`
} }
type fileStore struct { type fileStore struct {
@ -110,14 +110,14 @@ func loadTokens(s *Store, cfg Config, tokens persistedTokens, logger Logger) {
s.UpdateAgentToken(cfg.ACLAgentToken, TokenSourceConfig) s.UpdateAgentToken(cfg.ACLAgentToken, TokenSourceConfig)
} }
if tokens.AgentMaster != "" { if tokens.AgentRecovery != "" {
s.UpdateAgentMasterToken(tokens.AgentMaster, TokenSourceAPI) s.UpdateAgentRecoveryToken(tokens.AgentRecovery, TokenSourceAPI)
if cfg.ACLAgentMasterToken != "" { if cfg.ACLAgentRecoveryToken != "" {
logger.Warn("\"agent_master\" token present in both the configuration and persisted token store, using the persisted token") logger.Warn("\"agent_recovery\" token present in both the configuration and persisted token store, using the persisted token")
} }
} else { } else {
s.UpdateAgentMasterToken(cfg.ACLAgentMasterToken, TokenSourceConfig) s.UpdateAgentRecoveryToken(cfg.ACLAgentRecoveryToken, TokenSourceConfig)
} }
if tokens.Replication != "" { if tokens.Replication != "" {
@ -134,22 +134,32 @@ func loadTokens(s *Store, cfg Config, tokens persistedTokens, logger Logger) {
} }
func readPersistedFromFile(filename string) (persistedTokens, error) { func readPersistedFromFile(filename string) (persistedTokens, error) {
tokens := persistedTokens{} var tokens struct {
persistedTokens
// Support reading tokens persisted by versions <1.11, where agent_master was
// renamed to agent_recovery.
LegacyAgentMaster string `json:"agent_master"`
}
buf, err := ioutil.ReadFile(filename) buf, err := ioutil.ReadFile(filename)
switch { switch {
case os.IsNotExist(err): case os.IsNotExist(err):
// non-existence is not an error we care about // non-existence is not an error we care about
return tokens, nil return tokens.persistedTokens, nil
case err != nil: case err != nil:
return tokens, fmt.Errorf("failed reading tokens file %q: %w", filename, err) return tokens.persistedTokens, fmt.Errorf("failed reading tokens file %q: %w", filename, err)
} }
if err := json.Unmarshal(buf, &tokens); err != nil { if err := json.Unmarshal(buf, &tokens); err != nil {
return tokens, fmt.Errorf("failed to decode tokens file %q: %w", filename, err) return tokens.persistedTokens, fmt.Errorf("failed to decode tokens file %q: %w", filename, err)
} }
return tokens, nil if tokens.AgentRecovery == "" {
tokens.AgentRecovery = tokens.LegacyAgentMaster
}
return tokens.persistedTokens, nil
} }
func (p *fileStore) withPersistenceLock(s *Store, f func() error) error { func (p *fileStore) withPersistenceLock(s *Store, f func() error) error {
@ -170,8 +180,8 @@ func (p *fileStore) saveToFile(s *Store) error {
tokens.Agent = tok tokens.Agent = tok
} }
if tok, source := s.AgentMasterTokenAndSource(); tok != "" && source == TokenSourceAPI { if tok, source := s.AgentRecoveryTokenAndSource(); tok != "" && source == TokenSourceAPI {
tokens.AgentMaster = tok tokens.AgentRecovery = tok
} }
if tok, source := s.ReplicationTokenAndSource(); tok != "" && source == TokenSourceAPI { if tok, source := s.ReplicationTokenAndSource(); tok != "" && source == TokenSourceAPI {

View File

@ -18,47 +18,47 @@ func TestStore_Load(t *testing.T) {
t.Run("with empty store", func(t *testing.T) { t.Run("with empty store", func(t *testing.T) {
cfg := Config{ cfg := Config{
DataDir: dataDir, DataDir: dataDir,
ACLAgentToken: "alfa", ACLAgentToken: "alfa",
ACLAgentMasterToken: "bravo", ACLAgentRecoveryToken: "bravo",
ACLDefaultToken: "charlie", ACLDefaultToken: "charlie",
ACLReplicationToken: "delta", ACLReplicationToken: "delta",
} }
require.NoError(t, store.Load(cfg, logger)) require.NoError(t, store.Load(cfg, logger))
require.Equal(t, "alfa", store.AgentToken()) require.Equal(t, "alfa", store.AgentToken())
require.Equal(t, "bravo", store.AgentMasterToken()) require.Equal(t, "bravo", store.AgentRecoveryToken())
require.Equal(t, "charlie", store.UserToken()) require.Equal(t, "charlie", store.UserToken())
require.Equal(t, "delta", store.ReplicationToken()) require.Equal(t, "delta", store.ReplicationToken())
}) })
t.Run("updated from Config", func(t *testing.T) { t.Run("updated from Config", func(t *testing.T) {
cfg := Config{ cfg := Config{
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "echo", ACLDefaultToken: "echo",
ACLAgentToken: "foxtrot", ACLAgentToken: "foxtrot",
ACLAgentMasterToken: "golf", ACLAgentRecoveryToken: "golf",
ACLReplicationToken: "hotel", ACLReplicationToken: "hotel",
} }
// ensures no error for missing persisted tokens file // ensures no error for missing persisted tokens file
require.NoError(t, store.Load(cfg, logger)) require.NoError(t, store.Load(cfg, logger))
require.Equal(t, "echo", store.UserToken()) require.Equal(t, "echo", store.UserToken())
require.Equal(t, "foxtrot", store.AgentToken()) require.Equal(t, "foxtrot", store.AgentToken())
require.Equal(t, "golf", store.AgentMasterToken()) require.Equal(t, "golf", store.AgentRecoveryToken())
require.Equal(t, "hotel", store.ReplicationToken()) require.Equal(t, "hotel", store.ReplicationToken())
}) })
t.Run("with persisted tokens", func(t *testing.T) { t.Run("with persisted tokens", func(t *testing.T) {
cfg := Config{ cfg := Config{
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "echo", ACLDefaultToken: "echo",
ACLAgentToken: "foxtrot", ACLAgentToken: "foxtrot",
ACLAgentMasterToken: "golf", ACLAgentRecoveryToken: "golf",
ACLReplicationToken: "hotel", ACLReplicationToken: "hotel",
} }
tokens := `{ tokens := `{
"agent" : "india", "agent" : "india",
"agent_master" : "juliett", "agent_recovery" : "juliett",
"default": "kilo", "default": "kilo",
"replication" : "lima" "replication" : "lima"
}` }`
@ -69,14 +69,14 @@ func TestStore_Load(t *testing.T) {
// no updates since token persistence is not enabled // no updates since token persistence is not enabled
require.Equal(t, "echo", store.UserToken()) require.Equal(t, "echo", store.UserToken())
require.Equal(t, "foxtrot", store.AgentToken()) require.Equal(t, "foxtrot", store.AgentToken())
require.Equal(t, "golf", store.AgentMasterToken()) require.Equal(t, "golf", store.AgentRecoveryToken())
require.Equal(t, "hotel", store.ReplicationToken()) require.Equal(t, "hotel", store.ReplicationToken())
cfg.EnablePersistence = true cfg.EnablePersistence = true
require.NoError(t, store.Load(cfg, logger)) require.NoError(t, store.Load(cfg, logger))
require.Equal(t, "india", store.AgentToken()) require.Equal(t, "india", store.AgentToken())
require.Equal(t, "juliett", store.AgentMasterToken()) require.Equal(t, "juliett", store.AgentRecoveryToken())
require.Equal(t, "kilo", store.UserToken()) require.Equal(t, "kilo", store.UserToken())
require.Equal(t, "lima", store.ReplicationToken()) require.Equal(t, "lima", store.ReplicationToken())
@ -84,28 +84,42 @@ func TestStore_Load(t *testing.T) {
require.NotNil(t, store.persistence) require.NotNil(t, store.persistence)
}) })
t.Run("persisted tokens include pre-1.11 agent_master naming", func(t *testing.T) {
cfg := Config{
EnablePersistence: true,
DataDir: dataDir,
ACLAgentRecoveryToken: "golf",
}
tokens := `{"agent_master": "juliett"}`
require.NoError(t, ioutil.WriteFile(tokenFile, []byte(tokens), 0600))
require.NoError(t, store.Load(cfg, logger))
require.Equal(t, "juliett", store.AgentRecoveryToken())
})
t.Run("with persisted tokens, persisted tokens override config", func(t *testing.T) { t.Run("with persisted tokens, persisted tokens override config", func(t *testing.T) {
tokens := `{ tokens := `{
"agent" : "mike", "agent" : "mike",
"agent_master" : "november", "agent_recovery" : "november",
"default": "oscar", "default": "oscar",
"replication" : "papa" "replication" : "papa"
}` }`
cfg := Config{ cfg := Config{
EnablePersistence: true, EnablePersistence: true,
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "quebec", ACLDefaultToken: "quebec",
ACLAgentToken: "romeo", ACLAgentToken: "romeo",
ACLAgentMasterToken: "sierra", ACLAgentRecoveryToken: "sierra",
ACLReplicationToken: "tango", ACLReplicationToken: "tango",
} }
require.NoError(t, ioutil.WriteFile(tokenFile, []byte(tokens), 0600)) require.NoError(t, ioutil.WriteFile(tokenFile, []byte(tokens), 0600))
require.NoError(t, store.Load(cfg, logger)) require.NoError(t, store.Load(cfg, logger))
require.Equal(t, "mike", store.AgentToken()) require.Equal(t, "mike", store.AgentToken())
require.Equal(t, "november", store.AgentMasterToken()) require.Equal(t, "november", store.AgentRecoveryToken())
require.Equal(t, "oscar", store.UserToken()) require.Equal(t, "oscar", store.UserToken())
require.Equal(t, "papa", store.ReplicationToken()) require.Equal(t, "papa", store.ReplicationToken())
}) })
@ -113,35 +127,35 @@ func TestStore_Load(t *testing.T) {
t.Run("with some persisted tokens", func(t *testing.T) { t.Run("with some persisted tokens", func(t *testing.T) {
tokens := `{ tokens := `{
"agent" : "uniform", "agent" : "uniform",
"agent_master" : "victor" "agent_recovery" : "victor"
}` }`
cfg := Config{ cfg := Config{
EnablePersistence: true, EnablePersistence: true,
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "whiskey", ACLDefaultToken: "whiskey",
ACLAgentToken: "xray", ACLAgentToken: "xray",
ACLAgentMasterToken: "yankee", ACLAgentRecoveryToken: "yankee",
ACLReplicationToken: "zulu", ACLReplicationToken: "zulu",
} }
require.NoError(t, ioutil.WriteFile(tokenFile, []byte(tokens), 0600)) require.NoError(t, ioutil.WriteFile(tokenFile, []byte(tokens), 0600))
require.NoError(t, store.Load(cfg, logger)) require.NoError(t, store.Load(cfg, logger))
require.Equal(t, "uniform", store.AgentToken()) require.Equal(t, "uniform", store.AgentToken())
require.Equal(t, "victor", store.AgentMasterToken()) require.Equal(t, "victor", store.AgentRecoveryToken())
require.Equal(t, "whiskey", store.UserToken()) require.Equal(t, "whiskey", store.UserToken())
require.Equal(t, "zulu", store.ReplicationToken()) require.Equal(t, "zulu", store.ReplicationToken())
}) })
t.Run("persisted file contains invalid data", func(t *testing.T) { t.Run("persisted file contains invalid data", func(t *testing.T) {
cfg := Config{ cfg := Config{
EnablePersistence: true, EnablePersistence: true,
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "one", ACLDefaultToken: "one",
ACLAgentToken: "two", ACLAgentToken: "two",
ACLAgentMasterToken: "three", ACLAgentRecoveryToken: "three",
ACLReplicationToken: "four", ACLReplicationToken: "four",
} }
require.NoError(t, ioutil.WriteFile(tokenFile, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 0600)) require.NoError(t, ioutil.WriteFile(tokenFile, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 0600))
@ -151,18 +165,18 @@ func TestStore_Load(t *testing.T) {
require.Equal(t, "one", store.UserToken()) require.Equal(t, "one", store.UserToken())
require.Equal(t, "two", store.AgentToken()) require.Equal(t, "two", store.AgentToken())
require.Equal(t, "three", store.AgentMasterToken()) require.Equal(t, "three", store.AgentRecoveryToken())
require.Equal(t, "four", store.ReplicationToken()) require.Equal(t, "four", store.ReplicationToken())
}) })
t.Run("persisted file contains invalid json", func(t *testing.T) { t.Run("persisted file contains invalid json", func(t *testing.T) {
cfg := Config{ cfg := Config{
EnablePersistence: true, EnablePersistence: true,
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "alfa", ACLDefaultToken: "alfa",
ACLAgentToken: "bravo", ACLAgentToken: "bravo",
ACLAgentMasterToken: "charlie", ACLAgentRecoveryToken: "charlie",
ACLReplicationToken: "foxtrot", ACLReplicationToken: "foxtrot",
} }
require.NoError(t, ioutil.WriteFile(tokenFile, []byte("[1,2,3]"), 0600)) require.NoError(t, ioutil.WriteFile(tokenFile, []byte("[1,2,3]"), 0600))
@ -172,7 +186,7 @@ func TestStore_Load(t *testing.T) {
require.Equal(t, "alfa", store.UserToken()) require.Equal(t, "alfa", store.UserToken())
require.Equal(t, "bravo", store.AgentToken()) require.Equal(t, "bravo", store.AgentToken())
require.Equal(t, "charlie", store.AgentMasterToken()) require.Equal(t, "charlie", store.AgentRecoveryToken())
require.Equal(t, "foxtrot", store.ReplicationToken()) require.Equal(t, "foxtrot", store.ReplicationToken())
}) })
} }
@ -181,12 +195,12 @@ func TestStore_WithPersistenceLock(t *testing.T) {
dataDir := testutil.TempDir(t, "datadir") dataDir := testutil.TempDir(t, "datadir")
store := new(Store) store := new(Store)
cfg := Config{ cfg := Config{
EnablePersistence: true, EnablePersistence: true,
DataDir: dataDir, DataDir: dataDir,
ACLDefaultToken: "default-token", ACLDefaultToken: "default-token",
ACLAgentToken: "agent-token", ACLAgentToken: "agent-token",
ACLAgentMasterToken: "master-token", ACLAgentRecoveryToken: "recovery-token",
ACLReplicationToken: "replication-token", ACLReplicationToken: "replication-token",
} }
err := store.Load(cfg, hclog.New(nil)) err := store.Load(cfg, hclog.New(nil))
require.NoError(t, err) require.NoError(t, err)
@ -195,7 +209,7 @@ func TestStore_WithPersistenceLock(t *testing.T) {
updated := store.UpdateUserToken("the-new-token", TokenSourceAPI) updated := store.UpdateUserToken("the-new-token", TokenSourceAPI)
require.True(t, updated) require.True(t, updated)
updated = store.UpdateAgentMasterToken("the-new-master-token", TokenSourceAPI) updated = store.UpdateAgentRecoveryToken("the-new-recovery-token", TokenSourceAPI)
require.True(t, updated) require.True(t, updated)
return nil return nil
} }
@ -206,8 +220,8 @@ func TestStore_WithPersistenceLock(t *testing.T) {
tokens, err := readPersistedFromFile(filepath.Join(dataDir, tokensPath)) tokens, err := readPersistedFromFile(filepath.Join(dataDir, tokensPath))
require.NoError(t, err) require.NoError(t, err)
expected := persistedTokens{ expected := persistedTokens{
Default: "the-new-token", Default: "the-new-token",
AgentMaster: "the-new-master-token", AgentRecovery: "the-new-recovery-token",
} }
require.Equal(t, expected, tokens) require.Equal(t, expected, tokens)
} }

View File

@ -17,7 +17,7 @@ type TokenKind int
const ( const (
TokenKindAgent TokenKind = iota TokenKindAgent TokenKind = iota
TokenKindAgentMaster TokenKindAgentRecovery
TokenKindUser TokenKindUser
TokenKindReplication TokenKindReplication
) )
@ -59,13 +59,13 @@ type Store struct {
// agentTokenSource indicates where this token originated from // agentTokenSource indicates where this token originated from
agentTokenSource TokenSource agentTokenSource TokenSource
// agentMasterToken is a special token that's only used locally for // agentRecoveryToken is a special token that's only used locally for
// access to the /v1/agent utility operations if the servers aren't // access to the /v1/agent utility operations if the servers aren't
// available. // available.
agentMasterToken string agentRecoveryToken string
// agentMasterTokenSource indicates where this token originated from // agentRecoveryTokenSource indicates where this token originated from
agentMasterTokenSource TokenSource agentRecoveryTokenSource TokenSource
// replicationToken is a special token that's used by servers to // replicationToken is a special token that's used by servers to
// replicate data from the primary datacenter. // replicate data from the primary datacenter.
@ -188,15 +188,15 @@ func (t *Store) UpdateAgentToken(token string, source TokenSource) bool {
return changed return changed
} }
// UpdateAgentMasterToken replaces the current agent master token in the store. // UpdateAgentRecoveryToken replaces the current agent recovery token in the store.
// Returns true if it was changed. // Returns true if it was changed.
func (t *Store) UpdateAgentMasterToken(token string, source TokenSource) bool { func (t *Store) UpdateAgentRecoveryToken(token string, source TokenSource) bool {
t.l.Lock() t.l.Lock()
changed := t.agentMasterToken != token || t.agentMasterTokenSource != source changed := t.agentRecoveryToken != token || t.agentRecoveryTokenSource != source
t.agentMasterToken = token t.agentRecoveryToken = token
t.agentMasterTokenSource = source t.agentRecoveryTokenSource = source
if changed { if changed {
t.sendNotificationLocked(TokenKindAgentMaster) t.sendNotificationLocked(TokenKindAgentRecovery)
} }
t.l.Unlock() t.l.Unlock()
return changed return changed
@ -239,11 +239,11 @@ func (t *Store) AgentToken() string {
return t.userToken return t.userToken
} }
func (t *Store) AgentMasterToken() string { func (t *Store) AgentRecoveryToken() string {
t.l.RLock() t.l.RLock()
defer t.l.RUnlock() defer t.l.RUnlock()
return t.agentMasterToken return t.agentRecoveryToken
} }
// ReplicationToken returns the replication token. // ReplicationToken returns the replication token.
@ -270,11 +270,11 @@ func (t *Store) AgentTokenAndSource() (string, TokenSource) {
return t.agentToken, t.agentTokenSource return t.agentToken, t.agentTokenSource
} }
func (t *Store) AgentMasterTokenAndSource() (string, TokenSource) { func (t *Store) AgentRecoveryTokenAndSource() (string, TokenSource) {
t.l.RLock() t.l.RLock()
defer t.l.RUnlock() defer t.l.RUnlock()
return t.agentMasterToken, t.agentMasterTokenSource return t.agentRecoveryToken, t.agentRecoveryTokenSource
} }
// ReplicationToken returns the replication token. // ReplicationToken returns the replication token.
@ -285,11 +285,11 @@ func (t *Store) ReplicationTokenAndSource() (string, TokenSource) {
return t.replicationToken, t.replicationTokenSource return t.replicationToken, t.replicationTokenSource
} }
// IsAgentMasterToken checks to see if a given token is the agent master token. // IsAgentRecoveryToken checks to see if a given token is the agent recovery token.
// This will never match an empty token for safety. // This will never match an empty token for safety.
func (t *Store) IsAgentMasterToken(token string) bool { func (t *Store) IsAgentRecoveryToken(token string) bool {
t.l.RLock() t.l.RLock()
defer t.l.RUnlock() defer t.l.RUnlock()
return (token != "") && (subtle.ConstantTimeCompare([]byte(token), []byte(t.agentMasterToken)) == 1) return (token != "") && (subtle.ConstantTimeCompare([]byte(token), []byte(t.agentRecoveryToken)) == 1)
} }

View File

@ -8,14 +8,14 @@ import (
func TestStore_RegularTokens(t *testing.T) { func TestStore_RegularTokens(t *testing.T) {
type tokens struct { type tokens struct {
userSource TokenSource userSource TokenSource
user string user string
agent string agent string
agentSource TokenSource agentSource TokenSource
master string recovery string
masterSource TokenSource recoverySource TokenSource
repl string repl string
replSource TokenSource replSource TokenSource
} }
tests := []struct { tests := []struct {
@ -67,22 +67,22 @@ func TestStore_RegularTokens(t *testing.T) {
effective: tokens{repl: "R"}, effective: tokens{repl: "R"},
}, },
{ {
name: "set master - config", name: "set recovery - config",
set: tokens{master: "M", masterSource: TokenSourceConfig}, set: tokens{recovery: "M", recoverySource: TokenSourceConfig},
raw: tokens{master: "M", masterSource: TokenSourceConfig}, raw: tokens{recovery: "M", recoverySource: TokenSourceConfig},
effective: tokens{master: "M"}, effective: tokens{recovery: "M"},
}, },
{ {
name: "set master - api", name: "set recovery - api",
set: tokens{master: "M", masterSource: TokenSourceAPI}, set: tokens{recovery: "M", recoverySource: TokenSourceAPI},
raw: tokens{master: "M", masterSource: TokenSourceAPI}, raw: tokens{recovery: "M", recoverySource: TokenSourceAPI},
effective: tokens{master: "M"}, effective: tokens{recovery: "M"},
}, },
{ {
name: "set all", name: "set all",
set: tokens{user: "U", agent: "A", repl: "R", master: "M"}, set: tokens{user: "U", agent: "A", repl: "R", recovery: "M"},
raw: tokens{user: "U", agent: "A", repl: "R", master: "M"}, raw: tokens{user: "U", agent: "A", repl: "R", recovery: "M"},
effective: tokens{user: "U", agent: "A", repl: "R", master: "M"}, effective: tokens{user: "U", agent: "A", repl: "R", recovery: "M"},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -100,19 +100,19 @@ func TestStore_RegularTokens(t *testing.T) {
require.True(t, s.UpdateReplicationToken(tt.set.repl, tt.set.replSource)) require.True(t, s.UpdateReplicationToken(tt.set.repl, tt.set.replSource))
} }
if tt.set.master != "" { if tt.set.recovery != "" {
require.True(t, s.UpdateAgentMasterToken(tt.set.master, tt.set.masterSource)) require.True(t, s.UpdateAgentRecoveryToken(tt.set.recovery, tt.set.recoverySource))
} }
// If they don't change then they return false. // If they don't change then they return false.
require.False(t, s.UpdateUserToken(tt.set.user, tt.set.userSource)) require.False(t, s.UpdateUserToken(tt.set.user, tt.set.userSource))
require.False(t, s.UpdateAgentToken(tt.set.agent, tt.set.agentSource)) require.False(t, s.UpdateAgentToken(tt.set.agent, tt.set.agentSource))
require.False(t, s.UpdateReplicationToken(tt.set.repl, tt.set.replSource)) require.False(t, s.UpdateReplicationToken(tt.set.repl, tt.set.replSource))
require.False(t, s.UpdateAgentMasterToken(tt.set.master, tt.set.masterSource)) require.False(t, s.UpdateAgentRecoveryToken(tt.set.recovery, tt.set.recoverySource))
require.Equal(t, tt.effective.user, s.UserToken()) require.Equal(t, tt.effective.user, s.UserToken())
require.Equal(t, tt.effective.agent, s.AgentToken()) require.Equal(t, tt.effective.agent, s.AgentToken())
require.Equal(t, tt.effective.master, s.AgentMasterToken()) require.Equal(t, tt.effective.recovery, s.AgentRecoveryToken())
require.Equal(t, tt.effective.repl, s.ReplicationToken()) require.Equal(t, tt.effective.repl, s.ReplicationToken())
tok, src := s.UserTokenAndSource() tok, src := s.UserTokenAndSource()
@ -123,9 +123,9 @@ func TestStore_RegularTokens(t *testing.T) {
require.Equal(t, tt.raw.agent, tok) require.Equal(t, tt.raw.agent, tok)
require.Equal(t, tt.raw.agentSource, src) require.Equal(t, tt.raw.agentSource, src)
tok, src = s.AgentMasterTokenAndSource() tok, src = s.AgentRecoveryTokenAndSource()
require.Equal(t, tt.raw.master, tok) require.Equal(t, tt.raw.recovery, tok)
require.Equal(t, tt.raw.masterSource, src) require.Equal(t, tt.raw.recoverySource, src)
tok, src = s.ReplicationTokenAndSource() tok, src = s.ReplicationTokenAndSource()
require.Equal(t, tt.raw.repl, tok) require.Equal(t, tt.raw.repl, tok)
@ -134,27 +134,27 @@ func TestStore_RegularTokens(t *testing.T) {
} }
} }
func TestStore_AgentMasterToken(t *testing.T) { func TestStore_AgentRecoveryToken(t *testing.T) {
s := new(Store) s := new(Store)
verify := func(want bool, toks ...string) { verify := func(want bool, toks ...string) {
for _, tok := range toks { for _, tok := range toks {
require.Equal(t, want, s.IsAgentMasterToken(tok)) require.Equal(t, want, s.IsAgentRecoveryToken(tok))
} }
} }
verify(false, "", "nope") verify(false, "", "nope")
s.UpdateAgentMasterToken("master", TokenSourceConfig) s.UpdateAgentRecoveryToken("recovery", TokenSourceConfig)
verify(true, "master") verify(true, "recovery")
verify(false, "", "nope") verify(false, "", "nope")
s.UpdateAgentMasterToken("another", TokenSourceConfig) s.UpdateAgentRecoveryToken("another", TokenSourceConfig)
verify(true, "another") verify(true, "another")
verify(false, "", "nope", "master") verify(false, "", "nope", "recovery")
s.UpdateAgentMasterToken("", TokenSourceConfig) s.UpdateAgentRecoveryToken("", TokenSourceConfig)
verify(false, "", "nope", "master", "another") verify(false, "", "nope", "recovery", "another")
} }
func TestStore_Notify(t *testing.T) { func TestStore_Notify(t *testing.T) {
@ -180,7 +180,7 @@ func TestStore_Notify(t *testing.T) {
agentNotifier := newNotification(t, s, TokenKindAgent) agentNotifier := newNotification(t, s, TokenKindAgent)
userNotifier := newNotification(t, s, TokenKindUser) userNotifier := newNotification(t, s, TokenKindUser)
agentMasterNotifier := newNotification(t, s, TokenKindAgentMaster) agentRecoveryNotifier := newNotification(t, s, TokenKindAgentRecovery)
replicationNotifier := newNotification(t, s, TokenKindReplication) replicationNotifier := newNotification(t, s, TokenKindReplication)
replicationNotifier2 := newNotification(t, s, TokenKindReplication) replicationNotifier2 := newNotification(t, s, TokenKindReplication)
@ -193,7 +193,7 @@ func TestStore_Notify(t *testing.T) {
requireNotNotified(t, agentNotifier.Ch) requireNotNotified(t, agentNotifier.Ch)
requireNotifiedOnce(t, userNotifier.Ch) requireNotifiedOnce(t, userNotifier.Ch)
requireNotNotified(t, replicationNotifier.Ch) requireNotNotified(t, replicationNotifier.Ch)
requireNotNotified(t, agentMasterNotifier.Ch) requireNotNotified(t, agentRecoveryNotifier.Ch)
requireNotNotified(t, replicationNotifier2.Ch) requireNotNotified(t, replicationNotifier2.Ch)
// now update the agent token which should send notificaitons to the agent and all notifier // now update the agent token which should send notificaitons to the agent and all notifier
@ -202,16 +202,16 @@ func TestStore_Notify(t *testing.T) {
requireNotifiedOnce(t, agentNotifier.Ch) requireNotifiedOnce(t, agentNotifier.Ch)
requireNotNotified(t, userNotifier.Ch) requireNotNotified(t, userNotifier.Ch)
requireNotNotified(t, replicationNotifier.Ch) requireNotNotified(t, replicationNotifier.Ch)
requireNotNotified(t, agentMasterNotifier.Ch) requireNotNotified(t, agentRecoveryNotifier.Ch)
requireNotNotified(t, replicationNotifier2.Ch) requireNotNotified(t, replicationNotifier2.Ch)
// now update the agent master token which should send notificaitons to the agent master and all notifier // now update the agent recovery token which should send notificaitons to the agent recovery and all notifier
require.True(t, s.UpdateAgentMasterToken("789badc8-f850-43e1-8742-9b9f484957cc", TokenSourceAPI)) require.True(t, s.UpdateAgentRecoveryToken("789badc8-f850-43e1-8742-9b9f484957cc", TokenSourceAPI))
requireNotNotified(t, agentNotifier.Ch) requireNotNotified(t, agentNotifier.Ch)
requireNotNotified(t, userNotifier.Ch) requireNotNotified(t, userNotifier.Ch)
requireNotNotified(t, replicationNotifier.Ch) requireNotNotified(t, replicationNotifier.Ch)
requireNotifiedOnce(t, agentMasterNotifier.Ch) requireNotifiedOnce(t, agentRecoveryNotifier.Ch)
requireNotNotified(t, replicationNotifier2.Ch) requireNotNotified(t, replicationNotifier2.Ch)
// now update the replication token which should send notificaitons to the replication and all notifier // now update the replication token which should send notificaitons to the replication and all notifier
@ -220,7 +220,7 @@ func TestStore_Notify(t *testing.T) {
requireNotNotified(t, agentNotifier.Ch) requireNotNotified(t, agentNotifier.Ch)
requireNotNotified(t, userNotifier.Ch) requireNotNotified(t, userNotifier.Ch)
requireNotifiedOnce(t, replicationNotifier.Ch) requireNotifiedOnce(t, replicationNotifier.Ch)
requireNotNotified(t, agentMasterNotifier.Ch) requireNotNotified(t, agentRecoveryNotifier.Ch)
requireNotifiedOnce(t, replicationNotifier2.Ch) requireNotifiedOnce(t, replicationNotifier2.Ch)
s.StopNotify(replicationNotifier2) s.StopNotify(replicationNotifier2)
@ -231,12 +231,12 @@ func TestStore_Notify(t *testing.T) {
requireNotNotified(t, agentNotifier.Ch) requireNotNotified(t, agentNotifier.Ch)
requireNotNotified(t, userNotifier.Ch) requireNotNotified(t, userNotifier.Ch)
requireNotifiedOnce(t, replicationNotifier.Ch) requireNotifiedOnce(t, replicationNotifier.Ch)
requireNotNotified(t, agentMasterNotifier.Ch) requireNotNotified(t, agentRecoveryNotifier.Ch)
requireNotNotified(t, replicationNotifier2.Ch) requireNotNotified(t, replicationNotifier2.Ch)
// request updates but that are not changes // request updates but that are not changes
require.False(t, s.UpdateAgentToken("5d748ec2-d536-461f-8e2a-1f7eae98d559", TokenSourceAPI)) require.False(t, s.UpdateAgentToken("5d748ec2-d536-461f-8e2a-1f7eae98d559", TokenSourceAPI))
require.False(t, s.UpdateAgentMasterToken("789badc8-f850-43e1-8742-9b9f484957cc", TokenSourceAPI)) require.False(t, s.UpdateAgentRecoveryToken("789badc8-f850-43e1-8742-9b9f484957cc", TokenSourceAPI))
require.False(t, s.UpdateUserToken("47788919-f944-476a-bda5-446d64be1df8", TokenSourceAPI)) require.False(t, s.UpdateUserToken("47788919-f944-476a-bda5-446d64be1df8", TokenSourceAPI))
require.False(t, s.UpdateReplicationToken("eb0b56b9-fa65-4ae1-902a-c64457c62ac6", TokenSourceAPI)) require.False(t, s.UpdateReplicationToken("eb0b56b9-fa65-4ae1-902a-c64457c62ac6", TokenSourceAPI))
@ -244,5 +244,5 @@ func TestStore_Notify(t *testing.T) {
requireNotNotified(t, agentNotifier.Ch) requireNotNotified(t, agentNotifier.Ch)
requireNotNotified(t, userNotifier.Ch) requireNotNotified(t, userNotifier.Ch)
requireNotNotified(t, replicationNotifier.Ch) requireNotNotified(t, replicationNotifier.Ch)
requireNotNotified(t, agentMasterNotifier.Ch) requireNotNotified(t, agentRecoveryNotifier.Ch)
} }