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.
337 lines
12 KiB
337 lines
12 KiB
// Copyright (c) HashiCorp, Inc. |
|
// SPDX-License-Identifier: BUSL-1.1 |
|
|
|
package token |
|
|
|
import ( |
|
"testing" |
|
|
|
"github.com/stretchr/testify/require" |
|
) |
|
|
|
func TestStore_RegularTokens(t *testing.T) { |
|
type tokens struct { |
|
userSource TokenSource |
|
user string |
|
agent string |
|
agentSource TokenSource |
|
recovery string |
|
recoverySource TokenSource |
|
repl string |
|
replSource TokenSource |
|
registration string |
|
registrationSource TokenSource |
|
dns string |
|
dnsSource TokenSource |
|
} |
|
|
|
tests := []struct { |
|
name string |
|
set tokens |
|
raw tokens |
|
effective tokens |
|
}{ |
|
{ |
|
name: "set user - config", |
|
set: tokens{user: "U", userSource: TokenSourceConfig}, |
|
raw: tokens{user: "U", userSource: TokenSourceConfig}, |
|
effective: tokens{user: "U", agent: "U"}, |
|
}, |
|
{ |
|
name: "set user - api", |
|
set: tokens{user: "U", userSource: TokenSourceAPI}, |
|
raw: tokens{user: "U", userSource: TokenSourceAPI}, |
|
effective: tokens{user: "U", agent: "U"}, |
|
}, |
|
{ |
|
name: "set agent - config", |
|
set: tokens{agent: "A", agentSource: TokenSourceConfig}, |
|
raw: tokens{agent: "A", agentSource: TokenSourceConfig}, |
|
effective: tokens{agent: "A"}, |
|
}, |
|
{ |
|
name: "set agent - api", |
|
set: tokens{agent: "A", agentSource: TokenSourceAPI}, |
|
raw: tokens{agent: "A", agentSource: TokenSourceAPI}, |
|
effective: tokens{agent: "A"}, |
|
}, |
|
{ |
|
name: "set user and agent", |
|
set: tokens{agent: "A", user: "U"}, |
|
raw: tokens{agent: "A", user: "U"}, |
|
effective: tokens{agent: "A", user: "U"}, |
|
}, |
|
{ |
|
name: "set repl - config", |
|
set: tokens{repl: "R", replSource: TokenSourceConfig}, |
|
raw: tokens{repl: "R", replSource: TokenSourceConfig}, |
|
effective: tokens{repl: "R"}, |
|
}, |
|
{ |
|
name: "set repl - api", |
|
set: tokens{repl: "R", replSource: TokenSourceAPI}, |
|
raw: tokens{repl: "R", replSource: TokenSourceAPI}, |
|
effective: tokens{repl: "R"}, |
|
}, |
|
{ |
|
name: "set recovery - config", |
|
set: tokens{recovery: "M", recoverySource: TokenSourceConfig}, |
|
raw: tokens{recovery: "M", recoverySource: TokenSourceConfig}, |
|
effective: tokens{recovery: "M"}, |
|
}, |
|
{ |
|
name: "set recovery - api", |
|
set: tokens{recovery: "M", recoverySource: TokenSourceAPI}, |
|
raw: tokens{recovery: "M", recoverySource: TokenSourceAPI}, |
|
effective: tokens{recovery: "M"}, |
|
}, |
|
{ |
|
name: "set registration - config", |
|
set: tokens{registration: "G", registrationSource: TokenSourceConfig}, |
|
raw: tokens{registration: "G", registrationSource: TokenSourceConfig}, |
|
effective: tokens{registration: "G"}, |
|
}, |
|
{ |
|
name: "set registration - api", |
|
set: tokens{registration: "G", registrationSource: TokenSourceAPI}, |
|
raw: tokens{registration: "G", registrationSource: TokenSourceAPI}, |
|
effective: tokens{registration: "G"}, |
|
}, |
|
{ |
|
name: "set dns - config", |
|
set: tokens{dns: "D", dnsSource: TokenSourceConfig}, |
|
raw: tokens{dns: "D", dnsSource: TokenSourceConfig}, |
|
effective: tokens{dns: "D"}, |
|
}, |
|
{ |
|
name: "set dns - api", |
|
set: tokens{dns: "D", dnsSource: TokenSourceAPI}, |
|
raw: tokens{dns: "D", dnsSource: TokenSourceAPI}, |
|
effective: tokens{dns: "D"}, |
|
}, |
|
{ |
|
name: "set all", |
|
set: tokens{user: "U", agent: "A", repl: "R", recovery: "M", registration: "G", dns: "D"}, |
|
raw: tokens{user: "U", agent: "A", repl: "R", recovery: "M", registration: "G", dns: "D"}, |
|
effective: tokens{user: "U", agent: "A", repl: "R", recovery: "M", registration: "G", dns: "D"}, |
|
}, |
|
} |
|
for _, tt := range tests { |
|
t.Run(tt.name, func(t *testing.T) { |
|
s := new(Store) |
|
if tt.set.user != "" { |
|
require.True(t, s.UpdateUserToken(tt.set.user, tt.set.userSource)) |
|
} |
|
|
|
if tt.set.agent != "" { |
|
require.True(t, s.UpdateAgentToken(tt.set.agent, tt.set.agentSource)) |
|
} |
|
|
|
if tt.set.repl != "" { |
|
require.True(t, s.UpdateReplicationToken(tt.set.repl, tt.set.replSource)) |
|
} |
|
|
|
if tt.set.recovery != "" { |
|
require.True(t, s.UpdateAgentRecoveryToken(tt.set.recovery, tt.set.recoverySource)) |
|
} |
|
|
|
if tt.set.registration != "" { |
|
require.True(t, s.UpdateConfigFileRegistrationToken(tt.set.registration, tt.set.registrationSource)) |
|
} |
|
|
|
if tt.set.dns != "" { |
|
require.True(t, s.UpdateDNSToken(tt.set.dns, tt.set.dnsSource)) |
|
} |
|
|
|
// If they don't change then they return false. |
|
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.UpdateReplicationToken(tt.set.repl, tt.set.replSource)) |
|
require.False(t, s.UpdateAgentRecoveryToken(tt.set.recovery, tt.set.recoverySource)) |
|
require.False(t, s.UpdateConfigFileRegistrationToken(tt.set.registration, tt.set.registrationSource)) |
|
require.False(t, s.UpdateDNSToken(tt.set.dns, tt.set.dnsSource)) |
|
|
|
require.Equal(t, tt.effective.user, s.UserToken()) |
|
require.Equal(t, tt.effective.agent, s.AgentToken()) |
|
require.Equal(t, tt.effective.recovery, s.AgentRecoveryToken()) |
|
require.Equal(t, tt.effective.repl, s.ReplicationToken()) |
|
require.Equal(t, tt.effective.registration, s.ConfigFileRegistrationToken()) |
|
require.Equal(t, tt.effective.dns, s.DNSToken()) |
|
|
|
tok, src := s.UserTokenAndSource() |
|
require.Equal(t, tt.raw.user, tok) |
|
require.Equal(t, tt.raw.userSource, src) |
|
|
|
tok, src = s.AgentTokenAndSource() |
|
require.Equal(t, tt.raw.agent, tok) |
|
require.Equal(t, tt.raw.agentSource, src) |
|
|
|
tok, src = s.AgentRecoveryTokenAndSource() |
|
require.Equal(t, tt.raw.recovery, tok) |
|
require.Equal(t, tt.raw.recoverySource, src) |
|
|
|
tok, src = s.ReplicationTokenAndSource() |
|
require.Equal(t, tt.raw.repl, tok) |
|
require.Equal(t, tt.raw.replSource, src) |
|
|
|
tok, src = s.ConfigFileRegistrationTokenAndSource() |
|
require.Equal(t, tt.raw.registration, tok) |
|
require.Equal(t, tt.raw.registrationSource, src) |
|
|
|
tok, src = s.DNSTokenAndSource() |
|
require.Equal(t, tt.raw.dns, tok) |
|
require.Equal(t, tt.raw.dnsSource, src) |
|
}) |
|
} |
|
} |
|
|
|
func TestStore_AgentRecoveryToken(t *testing.T) { |
|
s := new(Store) |
|
|
|
verify := func(want bool, toks ...string) { |
|
for _, tok := range toks { |
|
require.Equal(t, want, s.IsAgentRecoveryToken(tok)) |
|
} |
|
} |
|
|
|
verify(false, "", "nope") |
|
|
|
s.UpdateAgentRecoveryToken("recovery", TokenSourceConfig) |
|
verify(true, "recovery") |
|
verify(false, "", "nope") |
|
|
|
s.UpdateAgentRecoveryToken("another", TokenSourceConfig) |
|
verify(true, "another") |
|
verify(false, "", "nope", "recovery") |
|
|
|
s.UpdateAgentRecoveryToken("", TokenSourceConfig) |
|
verify(false, "", "nope", "recovery", "another") |
|
} |
|
|
|
func TestStore_Notify(t *testing.T) { |
|
s := new(Store) |
|
|
|
newNotification := func(t *testing.T, s *Store, kind TokenKind) Notifier { |
|
n := s.Notify(kind) |
|
require.NotNil(t, n.Ch) |
|
return n |
|
} |
|
|
|
requireNotNotified := func(t *testing.T, ch <-chan struct{}) { |
|
require.Empty(t, ch) |
|
} |
|
|
|
requireNotifiedOnce := func(t *testing.T, ch <-chan struct{}) { |
|
require.Len(t, ch, 1) |
|
// drain the channel |
|
<-ch |
|
// just to be safe |
|
require.Empty(t, ch) |
|
} |
|
|
|
agentNotifier := newNotification(t, s, TokenKindAgent) |
|
userNotifier := newNotification(t, s, TokenKindUser) |
|
agentRecoveryNotifier := newNotification(t, s, TokenKindAgentRecovery) |
|
replicationNotifier := newNotification(t, s, TokenKindReplication) |
|
replicationNotifier2 := newNotification(t, s, TokenKindReplication) |
|
registrationNotifier := newNotification(t, s, TokenKindConfigFileRegistration) |
|
dnsNotifier := newNotification(t, s, TokenKindDNS) |
|
|
|
// perform an update of the user token |
|
require.True(t, s.UpdateUserToken("edcae2a2-3b51-4864-b412-c7a568f49cb1", TokenSourceConfig)) |
|
// do it again to ensure it doesn't block even though nothing has read from the 1 buffered chan yet |
|
require.True(t, s.UpdateUserToken("47788919-f944-476a-bda5-446d64be1df8", TokenSourceAPI)) |
|
|
|
// ensure notifications were sent to the user notifier and all other notifiers were not notified. |
|
requireNotNotified(t, agentNotifier.Ch) |
|
requireNotifiedOnce(t, userNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier.Ch) |
|
requireNotNotified(t, agentRecoveryNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier2.Ch) |
|
requireNotNotified(t, registrationNotifier.Ch) |
|
requireNotNotified(t, dnsNotifier.Ch) |
|
|
|
// update the agent token which should send a notification to the agent notifier. |
|
require.True(t, s.UpdateAgentToken("5d748ec2-d536-461f-8e2a-1f7eae98d559", TokenSourceAPI)) |
|
|
|
requireNotifiedOnce(t, agentNotifier.Ch) |
|
requireNotNotified(t, userNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier.Ch) |
|
requireNotNotified(t, agentRecoveryNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier2.Ch) |
|
requireNotNotified(t, registrationNotifier.Ch) |
|
requireNotNotified(t, dnsNotifier.Ch) |
|
|
|
// update the agent recovery token which should send a notification to the agent recovery notifier. |
|
require.True(t, s.UpdateAgentRecoveryToken("789badc8-f850-43e1-8742-9b9f484957cc", TokenSourceAPI)) |
|
|
|
requireNotNotified(t, agentNotifier.Ch) |
|
requireNotNotified(t, userNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier.Ch) |
|
requireNotifiedOnce(t, agentRecoveryNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier2.Ch) |
|
requireNotNotified(t, registrationNotifier.Ch) |
|
requireNotNotified(t, dnsNotifier.Ch) |
|
|
|
// update the replication token which should send a notification to the replication notifier. |
|
require.True(t, s.UpdateReplicationToken("789badc8-f850-43e1-8742-9b9f484957cc", TokenSourceAPI)) |
|
|
|
requireNotNotified(t, agentNotifier.Ch) |
|
requireNotNotified(t, userNotifier.Ch) |
|
requireNotifiedOnce(t, replicationNotifier.Ch) |
|
requireNotNotified(t, agentRecoveryNotifier.Ch) |
|
requireNotifiedOnce(t, replicationNotifier2.Ch) |
|
requireNotNotified(t, registrationNotifier.Ch) |
|
requireNotNotified(t, dnsNotifier.Ch) |
|
|
|
s.StopNotify(replicationNotifier2) |
|
|
|
// update the replication token which should send a notification to the replication notifier. |
|
require.True(t, s.UpdateReplicationToken("eb0b56b9-fa65-4ae1-902a-c64457c62ac6", TokenSourceAPI)) |
|
|
|
requireNotNotified(t, agentNotifier.Ch) |
|
requireNotNotified(t, userNotifier.Ch) |
|
requireNotifiedOnce(t, replicationNotifier.Ch) |
|
requireNotNotified(t, agentRecoveryNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier2.Ch) |
|
requireNotNotified(t, registrationNotifier.Ch) |
|
requireNotNotified(t, dnsNotifier.Ch) |
|
|
|
// update the config file registration token which should send a notification to the replication notifier. |
|
require.True(t, s.UpdateConfigFileRegistrationToken("82fe7362-7d83-4f43-bb27-c35f1f15083c", TokenSourceAPI)) |
|
|
|
requireNotNotified(t, agentNotifier.Ch) |
|
requireNotNotified(t, userNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier.Ch) |
|
requireNotNotified(t, agentRecoveryNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier2.Ch) |
|
requireNotifiedOnce(t, registrationNotifier.Ch) |
|
requireNotNotified(t, dnsNotifier.Ch) |
|
|
|
// update the dns token which should send a notification to the replication notifier. |
|
require.True(t, s.UpdateDNSToken("ce8e829f-dc45-4ba7-9dd3-1dbbe070f573", TokenSourceAPI)) |
|
|
|
requireNotNotified(t, agentNotifier.Ch) |
|
requireNotNotified(t, userNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier.Ch) |
|
requireNotNotified(t, agentRecoveryNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier2.Ch) |
|
requireNotNotified(t, registrationNotifier.Ch) |
|
requireNotifiedOnce(t, dnsNotifier.Ch) |
|
|
|
// request updates that are not changes |
|
require.False(t, s.UpdateAgentToken("5d748ec2-d536-461f-8e2a-1f7eae98d559", 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.UpdateReplicationToken("eb0b56b9-fa65-4ae1-902a-c64457c62ac6", TokenSourceAPI)) |
|
require.False(t, s.UpdateConfigFileRegistrationToken("82fe7362-7d83-4f43-bb27-c35f1f15083c", TokenSourceAPI)) |
|
require.False(t, s.UpdateDNSToken("ce8e829f-dc45-4ba7-9dd3-1dbbe070f573", TokenSourceAPI)) |
|
|
|
// ensure that notifications were not sent |
|
requireNotNotified(t, agentNotifier.Ch) |
|
requireNotNotified(t, userNotifier.Ch) |
|
requireNotNotified(t, replicationNotifier.Ch) |
|
requireNotNotified(t, agentRecoveryNotifier.Ch) |
|
requireNotNotified(t, registrationNotifier.Ch) |
|
requireNotNotified(t, dnsNotifier.Ch) |
|
}
|
|
|