From 5bb87c0ccc856c1f8f1ef3a08dd9f487ed108c27 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Thu, 15 Sep 2022 17:36:19 -0400 Subject: [PATCH] Backport of connect/ca: Don't discard old roots on primaryInitialize into release/1.11.x (#14651) This pull request was automerged via backport-assistant --- .changelog/14598.txt | 3 ++ agent/consul/leader_connect_ca.go | 15 +------ agent/consul/leader_connect_test.go | 65 +++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 .changelog/14598.txt diff --git a/.changelog/14598.txt b/.changelog/14598.txt new file mode 100644 index 000000000000..f76b4958d164 --- /dev/null +++ b/.changelog/14598.txt @@ -0,0 +1,3 @@ +```release-note:bug +connect: Fixed a bug where old root CAs would be removed from the primary datacenter after switching providers and restarting the cluster. +``` diff --git a/agent/consul/leader_connect_ca.go b/agent/consul/leader_connect_ca.go index 30bcb937d7ef..4b482055f9b8 100644 --- a/agent/consul/leader_connect_ca.go +++ b/agent/consul/leader_connect_ca.go @@ -562,22 +562,9 @@ func (c *CAManager) primaryInitialize(provider ca.Provider, conf *structs.CAConf return nil } - // Get the highest index - idx, _, err := state.CARoots(nil) - if err != nil { + if err := c.persistNewRootAndConfig(provider, rootCA, conf); err != nil { return err } - - // Store the root cert in raft - _, err = c.delegate.ApplyCARequest(&structs.CARequest{ - Op: structs.CAOpSetRoots, - Index: idx, - Roots: []*structs.CARoot{rootCA}, - }) - if err != nil { - return fmt.Errorf("raft apply failed: %w", err) - } - c.setCAProvider(provider, rootCA) c.logger.Info("initialized primary datacenter CA with provider", "provider", conf.Provider) diff --git a/agent/consul/leader_connect_test.go b/agent/consul/leader_connect_test.go index 3b16a9450b39..7e1e8cee32f0 100644 --- a/agent/consul/leader_connect_test.go +++ b/agent/consul/leader_connect_test.go @@ -699,6 +699,71 @@ func TestConnectCA_ConfigurationSet_RootRotation_Secondary(t *testing.T) { require.NoError(err) } +func TestCAManager_Initialize_Vault_KeepOldRoots_Primary(t *testing.T) { + ca.SkipIfVaultNotPresent(t) + + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + testVault := ca.NewTestVaultServer(t) + defer testVault.Stop() + + dir1pre, s1pre := testServer(t) + defer os.RemoveAll(dir1pre) + defer s1pre.Shutdown() + codec := rpcClient(t, s1pre) + defer codec.Close() + + testrpc.WaitForLeader(t, s1pre.RPC, "dc1") + + // Update the CA config to use Vault - this should force the generation of a new root cert. + vaultCAConf := &structs.CAConfiguration{ + Provider: "vault", + Config: map[string]interface{}{ + "Address": testVault.Addr, + "Token": testVault.RootToken, + "RootPKIPath": "pki-root/", + "IntermediatePKIPath": "pki-intermediate/", + }, + } + + args := &structs.CARequest{ + Datacenter: "dc1", + Config: vaultCAConf, + } + var reply interface{} + + require.NoError(t, msgpackrpc.CallWithCodec(codec, "ConnectCA.ConfigurationSet", args, &reply)) + + // Should have 2 roots now. + _, roots, err := s1pre.fsm.State().CARoots(nil) + require.NoError(t, err) + require.Len(t, roots, 2) + + // Shutdown s1pre and restart it to trigger the primary CA init. + s1pre.Shutdown() + + dir1, s1 := testServerWithConfig(t, func(c *Config) { + c.DataDir = s1pre.config.DataDir + c.NodeName = s1pre.config.NodeName + c.NodeID = s1pre.config.NodeID + }) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // Roots should be unchanged + _, rootsAfterRestart, err := s1.fsm.State().CARoots(nil) + require.NoError(t, err) + require.Len(t, rootsAfterRestart, 2) + require.Equal(t, roots[0].ID, rootsAfterRestart[0].ID) + require.Equal(t, roots[1].ID, rootsAfterRestart[1].ID) +} + func TestCAManager_Initialize_Vault_FixesSigningKeyID_Primary(t *testing.T) { ca.SkipIfVaultNotPresent(t)