mirror of https://github.com/hashicorp/consul
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
10 KiB
305 lines
10 KiB
// Copyright (c) HashiCorp, Inc. |
|
// SPDX-License-Identifier: BUSL-1.1 |
|
|
|
package token |
|
|
|
import ( |
|
"os" |
|
"path/filepath" |
|
"testing" |
|
|
|
"github.com/hashicorp/go-hclog" |
|
"github.com/stretchr/testify/require" |
|
|
|
"github.com/hashicorp/consul/sdk/testutil" |
|
) |
|
|
|
func TestStore_Load(t *testing.T) { |
|
dataDir := testutil.TempDir(t, "datadir") |
|
tokenFile := filepath.Join(dataDir, tokensPath) |
|
logger := hclog.New(nil) |
|
store := new(Store) |
|
|
|
t.Run("with empty store", func(t *testing.T) { |
|
cfg := Config{ |
|
DataDir: dataDir, |
|
ACLAgentToken: "alfa", |
|
ACLAgentRecoveryToken: "bravo", |
|
ACLDefaultToken: "charlie", |
|
ACLReplicationToken: "delta", |
|
ACLConfigFileRegistrationToken: "echo", |
|
ACLDNSToken: "foxtrot", |
|
} |
|
require.NoError(t, store.Load(cfg, logger)) |
|
require.Equal(t, "alfa", store.AgentToken()) |
|
require.Equal(t, "bravo", store.AgentRecoveryToken()) |
|
require.Equal(t, "charlie", store.UserToken()) |
|
require.Equal(t, "delta", store.ReplicationToken()) |
|
require.Equal(t, "echo", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "foxtrot", store.DNSToken()) |
|
}) |
|
|
|
t.Run("updated from Config", func(t *testing.T) { |
|
cfg := Config{ |
|
DataDir: dataDir, |
|
ACLDefaultToken: "sierra", |
|
ACLAgentToken: "tango", |
|
ACLAgentRecoveryToken: "uniform", |
|
ACLReplicationToken: "victor", |
|
ACLConfigFileRegistrationToken: "xray", |
|
ACLDNSToken: "zulu", |
|
} |
|
// ensures no error for missing persisted tokens file |
|
require.NoError(t, store.Load(cfg, logger)) |
|
require.Equal(t, "sierra", store.UserToken()) |
|
require.Equal(t, "tango", store.AgentToken()) |
|
require.Equal(t, "uniform", store.AgentRecoveryToken()) |
|
require.Equal(t, "victor", store.ReplicationToken()) |
|
require.Equal(t, "xray", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "zulu", store.DNSToken()) |
|
}) |
|
|
|
t.Run("with persisted tokens", func(t *testing.T) { |
|
cfg := Config{ |
|
DataDir: dataDir, |
|
ACLDefaultToken: "alpha", |
|
ACLAgentToken: "bravo", |
|
ACLAgentRecoveryToken: "charlie", |
|
ACLReplicationToken: "delta", |
|
ACLConfigFileRegistrationToken: "echo", |
|
ACLDNSToken: "foxtrot", |
|
} |
|
|
|
tokens := `{ |
|
"agent" : "golf", |
|
"agent_recovery" : "hotel", |
|
"default": "india", |
|
"replication": "juliet", |
|
"config_file_service_registration": "kilo", |
|
"dns": "lima" |
|
}` |
|
|
|
require.NoError(t, os.WriteFile(tokenFile, []byte(tokens), 0600)) |
|
require.NoError(t, store.Load(cfg, logger)) |
|
|
|
// no updates since token persistence is not enabled |
|
require.Equal(t, "alpha", store.UserToken()) |
|
require.Equal(t, "bravo", store.AgentToken()) |
|
require.Equal(t, "charlie", store.AgentRecoveryToken()) |
|
require.Equal(t, "delta", store.ReplicationToken()) |
|
require.Equal(t, "echo", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "foxtrot", store.DNSToken()) |
|
|
|
cfg.EnablePersistence = true |
|
require.NoError(t, store.Load(cfg, logger)) |
|
|
|
require.Equal(t, "golf", store.AgentToken()) |
|
require.Equal(t, "hotel", store.AgentRecoveryToken()) |
|
require.Equal(t, "india", store.UserToken()) |
|
require.Equal(t, "juliet", store.ReplicationToken()) |
|
require.Equal(t, "kilo", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "lima", store.DNSToken()) |
|
|
|
// check store persistence was enabled |
|
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, os.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) { |
|
tokens := `{ |
|
"agent" : "mike", |
|
"agent_recovery" : "november", |
|
"default": "oscar", |
|
"replication" : "papa", |
|
"config_file_service_registration" : "lima", |
|
"dns": "kilo" |
|
}` |
|
|
|
cfg := Config{ |
|
EnablePersistence: true, |
|
DataDir: dataDir, |
|
ACLDefaultToken: "quebec", |
|
ACLAgentToken: "romeo", |
|
ACLAgentRecoveryToken: "sierra", |
|
ACLReplicationToken: "tango", |
|
ACLConfigFileRegistrationToken: "uniform", |
|
ACLDNSToken: "victor", |
|
} |
|
|
|
require.NoError(t, os.WriteFile(tokenFile, []byte(tokens), 0600)) |
|
require.NoError(t, store.Load(cfg, logger)) |
|
|
|
require.Equal(t, "mike", store.AgentToken()) |
|
require.Equal(t, "november", store.AgentRecoveryToken()) |
|
require.Equal(t, "oscar", store.UserToken()) |
|
require.Equal(t, "papa", store.ReplicationToken()) |
|
require.Equal(t, "lima", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "kilo", store.DNSToken()) |
|
}) |
|
|
|
t.Run("with some persisted tokens", func(t *testing.T) { |
|
tokens := `{ |
|
"agent" : "xray", |
|
"agent_recovery" : "zulu" |
|
}` |
|
|
|
cfg := Config{ |
|
EnablePersistence: true, |
|
DataDir: dataDir, |
|
ACLDefaultToken: "alpha", |
|
ACLAgentToken: "bravo", |
|
ACLAgentRecoveryToken: "charlie", |
|
ACLReplicationToken: "delta", |
|
ACLConfigFileRegistrationToken: "echo", |
|
ACLDNSToken: "foxtrot", |
|
} |
|
|
|
require.NoError(t, os.WriteFile(tokenFile, []byte(tokens), 0600)) |
|
require.NoError(t, store.Load(cfg, logger)) |
|
|
|
require.Equal(t, "xray", store.AgentToken()) |
|
require.Equal(t, "zulu", store.AgentRecoveryToken()) |
|
|
|
require.Equal(t, "alpha", store.UserToken()) |
|
require.Equal(t, "delta", store.ReplicationToken()) |
|
require.Equal(t, "echo", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "foxtrot", store.DNSToken()) |
|
}) |
|
|
|
t.Run("persisted file contains invalid data", func(t *testing.T) { |
|
cfg := Config{ |
|
EnablePersistence: true, |
|
DataDir: dataDir, |
|
ACLDefaultToken: "alpha", |
|
ACLAgentToken: "bravo", |
|
ACLAgentRecoveryToken: "charlie", |
|
ACLReplicationToken: "delta", |
|
ACLConfigFileRegistrationToken: "echo", |
|
ACLDNSToken: "foxtrot", |
|
} |
|
|
|
require.NoError(t, os.WriteFile(tokenFile, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 0600)) |
|
err := store.Load(cfg, logger) |
|
require.Error(t, err) |
|
require.Contains(t, err.Error(), "failed to decode tokens file") |
|
|
|
require.Equal(t, "alpha", store.UserToken()) |
|
require.Equal(t, "bravo", store.AgentToken()) |
|
require.Equal(t, "charlie", store.AgentRecoveryToken()) |
|
require.Equal(t, "delta", store.ReplicationToken()) |
|
require.Equal(t, "echo", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "foxtrot", store.DNSToken()) |
|
}) |
|
|
|
t.Run("persisted file contains invalid json", func(t *testing.T) { |
|
cfg := Config{ |
|
EnablePersistence: true, |
|
DataDir: dataDir, |
|
ACLDefaultToken: "alfa", |
|
ACLAgentToken: "bravo", |
|
ACLAgentRecoveryToken: "charlie", |
|
ACLReplicationToken: "delta", |
|
ACLConfigFileRegistrationToken: "echo", |
|
ACLDNSToken: "foxtrot", |
|
} |
|
|
|
require.NoError(t, os.WriteFile(tokenFile, []byte("[1,2,3]"), 0600)) |
|
err := store.Load(cfg, logger) |
|
require.Error(t, err) |
|
require.Contains(t, err.Error(), "failed to decode tokens file") |
|
|
|
require.Equal(t, "alfa", store.UserToken()) |
|
require.Equal(t, "bravo", store.AgentToken()) |
|
require.Equal(t, "charlie", store.AgentRecoveryToken()) |
|
require.Equal(t, "delta", store.ReplicationToken()) |
|
require.Equal(t, "echo", store.ConfigFileRegistrationToken()) |
|
require.Equal(t, "foxtrot", store.DNSToken()) |
|
}) |
|
} |
|
|
|
func TestStore_WithPersistenceLock(t *testing.T) { |
|
// ACLDefaultToken: alpha --> sierra |
|
// ACLAgentToken: bravo --> tango |
|
// ACLAgentRecoveryToken: charlie --> uniform |
|
// ACLReplicationToken: delta --> victor |
|
// ACLConfigFileRegistrationToken: echo --> xray |
|
// ACLDNSToken: foxtrot --> zulu |
|
setupStore := func() (string, *Store) { |
|
dataDir := testutil.TempDir(t, "datadir") |
|
store := new(Store) |
|
cfg := Config{ |
|
EnablePersistence: true, |
|
DataDir: dataDir, |
|
ACLDefaultToken: "alpha", |
|
ACLAgentToken: "bravo", |
|
ACLAgentRecoveryToken: "charlie", |
|
ACLReplicationToken: "delta", |
|
ACLConfigFileRegistrationToken: "echo", |
|
ACLDNSToken: "foxtrot", |
|
} |
|
err := store.Load(cfg, hclog.New(nil)) |
|
require.NoError(t, err) |
|
|
|
return dataDir, store |
|
} |
|
|
|
requirePersistedTokens := func(t *testing.T, dataDir string, expected persistedTokens) { |
|
t.Helper() |
|
tokens, err := readPersistedFromFile(filepath.Join(dataDir, tokensPath)) |
|
require.NoError(t, err) |
|
require.Equal(t, expected, tokens) |
|
} |
|
|
|
t.Run("persist some tokens", func(t *testing.T) { |
|
dataDir, store := setupStore() |
|
err := store.WithPersistenceLock(func() error { |
|
require.True(t, store.UpdateUserToken("sierra", TokenSourceAPI)) |
|
require.True(t, store.UpdateAgentRecoveryToken("tango", TokenSourceAPI)) |
|
return nil |
|
}) |
|
require.NoError(t, err) |
|
|
|
// Only API-sourced tokens are persisted. |
|
requirePersistedTokens(t, dataDir, persistedTokens{ |
|
Default: "sierra", |
|
AgentRecovery: "tango", |
|
}) |
|
}) |
|
|
|
t.Run("persist all tokens", func(t *testing.T) { |
|
dataDir, store := setupStore() |
|
err := store.WithPersistenceLock(func() error { |
|
require.True(t, store.UpdateUserToken("sierra", TokenSourceAPI)) |
|
require.True(t, store.UpdateAgentToken("tango", TokenSourceAPI)) |
|
require.True(t, store.UpdateAgentRecoveryToken("uniform", TokenSourceAPI)) |
|
require.True(t, store.UpdateReplicationToken("victor", TokenSourceAPI)) |
|
require.True(t, store.UpdateConfigFileRegistrationToken("xray", TokenSourceAPI)) |
|
require.True(t, store.UpdateDNSToken("zulu", TokenSourceAPI)) |
|
return nil |
|
}) |
|
require.NoError(t, err) |
|
|
|
requirePersistedTokens(t, dataDir, persistedTokens{ |
|
Default: "sierra", |
|
Agent: "tango", |
|
AgentRecovery: "uniform", |
|
Replication: "victor", |
|
ConfigFileRegistration: "xray", |
|
DNS: "zulu", |
|
}) |
|
}) |
|
|
|
}
|
|
|