From 49154850b5b2b8e4715befb55090196e3cfb5f8d Mon Sep 17 00:00:00 2001 From: Derek Menteer <105233703+hashi-derek@users.noreply.github.com> Date: Fri, 10 Feb 2023 13:06:40 -0600 Subject: [PATCH] Fix peering acceptors in secondary datacenters. (#16233) Prior to this commit, secondary datacenters could not be initialized as peering acceptors if ACLs were enabled. This is due to the fact that internal server-to-server API calls would fail because the management token was not generated. This PR makes it so that both primary and secondary datacenters generate their own management token whenever a leader is elected in their respective clusters. --- .changelog/16230.txt | 3 +++ agent/consul/leader.go | 26 ++++++++++----------- agent/consul/leader_test.go | 45 +++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 .changelog/16230.txt diff --git a/.changelog/16230.txt b/.changelog/16230.txt new file mode 100644 index 0000000000..81e574798a --- /dev/null +++ b/.changelog/16230.txt @@ -0,0 +1,3 @@ +```release-note:bug +peering: Fix issue where secondary wan-federated datacenters could not be used as peering acceptors. +``` diff --git a/agent/consul/leader.go b/agent/consul/leader.go index 94aeeb3bb4..ef2842e47e 100644 --- a/agent/consul/leader.go +++ b/agent/consul/leader.go @@ -529,25 +529,25 @@ func (s *Server) initializeACLs(ctx context.Context) error { s.logger.Info("Created ACL anonymous token from configuration") } - // Generate or rotate the server management token on leadership transitions. - // This token is used by Consul servers for authn/authz when making - // requests to themselves through public APIs such as the agent cache. - // It is stored as system metadata because it is internally - // managed and users are not meant to see it or interact with it. - secretID, err := lib.GenerateUUID(nil) - if err != nil { - return fmt.Errorf("failed to generate the secret ID for the server management token: %w", err) - } - if err := s.setSystemMetadataKey(structs.ServerManagementTokenAccessorID, secretID); err != nil { - return fmt.Errorf("failed to persist server management token: %w", err) - } - // launch the upgrade go routine to generate accessors for everything s.startACLUpgrade(ctx) } else { s.startACLReplication(ctx) } + // Generate or rotate the server management token on leadership transitions. + // This token is used by Consul servers for authn/authz when making + // requests to themselves through public APIs such as the agent cache. + // It is stored as system metadata because it is internally + // managed and users are not meant to see it or interact with it. + secretID, err := lib.GenerateUUID(nil) + if err != nil { + return fmt.Errorf("failed to generate the secret ID for the server management token: %w", err) + } + if err := s.setSystemMetadataKey(structs.ServerManagementTokenAccessorID, secretID); err != nil { + return fmt.Errorf("failed to persist server management token: %w", err) + } + s.startACLTokenReaping(ctx) return nil diff --git a/agent/consul/leader_test.go b/agent/consul/leader_test.go index 35bc924b7a..a73ee5988d 100644 --- a/agent/consul/leader_test.go +++ b/agent/consul/leader_test.go @@ -1308,6 +1308,51 @@ func TestLeader_ACL_Initialization(t *testing.T) { } } +func TestLeader_ACL_Initialization_SecondaryDC(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.Bootstrap = true + c.Datacenter = "dc1" + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + testrpc.WaitForTestAgent(t, s1.RPC, "dc1") + + dir2, s2 := testServerWithConfig(t, func(c *Config) { + c.Bootstrap = true + c.Datacenter = "dc2" + c.PrimaryDatacenter = "dc1" + c.ACLsEnabled = true + }) + defer os.RemoveAll(dir2) + defer s2.Shutdown() + testrpc.WaitForTestAgent(t, s2.RPC, "dc2") + + // Check dc1's management token + serverToken1, err := s1.getSystemMetadata(structs.ServerManagementTokenAccessorID) + require.NoError(t, err) + require.NotEmpty(t, serverToken1) + _, err = uuid.ParseUUID(serverToken1) + require.NoError(t, err) + + // Check dc2's management token + serverToken2, err := s2.getSystemMetadata(structs.ServerManagementTokenAccessorID) + require.NoError(t, err) + require.NotEmpty(t, serverToken2) + _, err = uuid.ParseUUID(serverToken2) + require.NoError(t, err) + + // Ensure the tokens were not replicated between clusters. + require.NotEqual(t, serverToken1, serverToken2) +} + func TestLeader_ACLUpgrade_IsStickyEvenIfSerfTagsRegress(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short")