Clean up the logic in persistNewRootAndConfig

This commit is contained in:
Kyle Havlovitz 2020-11-20 15:54:44 -08:00
parent 0bfda4481f
commit 13c31ccfce
3 changed files with 27 additions and 29 deletions

View File

@ -535,6 +535,7 @@ func (c *CAManager) persistNewRootAndConfig(provider ca.Provider, newActiveRoot
return err return err
} }
// Look up the existing CA config if a new one wasn't provided.
var newConf structs.CAConfiguration var newConf structs.CAConfiguration
_, storedConfig, err := state.CAConfig(nil) _, storedConfig, err := state.CAConfig(nil)
if err != nil { if err != nil {
@ -543,14 +544,28 @@ func (c *CAManager) persistNewRootAndConfig(provider ca.Provider, newActiveRoot
if storedConfig == nil { if storedConfig == nil {
return fmt.Errorf("local CA not initialized yet") return fmt.Errorf("local CA not initialized yet")
} }
// Exit early if the change is a no-op.
if newActiveRoot == nil && config != nil && config.Provider == storedConfig.Provider && reflect.DeepEqual(config.Config, storedConfig.Config) {
return nil
}
if config != nil { if config != nil {
newConf = *config newConf = *config
} else { } else {
newConf = *storedConfig newConf = *storedConfig
} }
// Update the trust domain for the config if there's a new root, or keep the old
// one if the root isn't being updated.
newConf.ModifyIndex = storedConfig.ModifyIndex newConf.ModifyIndex = storedConfig.ModifyIndex
if newActiveRoot != nil { if newActiveRoot != nil {
newConf.ClusterID = newActiveRoot.ExternalTrustDomain newConf.ClusterID = newActiveRoot.ExternalTrustDomain
} else {
_, activeRoot, err := state.CARootActive(nil)
if err != nil {
return err
}
newConf.ClusterID = activeRoot.ExternalTrustDomain
} }
// Persist any state the provider needs us to // Persist any state the provider needs us to
@ -562,21 +577,19 @@ func (c *CAManager) persistNewRootAndConfig(provider ca.Provider, newActiveRoot
// If there's a new active root, copy the root list and append it, updating // If there's a new active root, copy the root list and append it, updating
// the old root with the time it was rotated out. // the old root with the time it was rotated out.
var newRoots structs.CARoots var newRoots structs.CARoots
if newActiveRoot != nil { for _, r := range oldRoots {
for _, r := range oldRoots { newRoot := *r
newRoot := *r if newRoot.Active {
if newRoot.Active { newRoot.Active = false
newRoot.Active = false newRoot.RotatedOutAt = time.Now()
newRoot.RotatedOutAt = time.Now()
}
if newRoot.ExternalTrustDomain == "" {
newRoot.ExternalTrustDomain = newConf.ClusterID
}
newRoots = append(newRoots, &newRoot)
} }
if newRoot.ExternalTrustDomain == "" {
newRoot.ExternalTrustDomain = newConf.ClusterID
}
newRoots = append(newRoots, &newRoot)
}
if newActiveRoot != nil {
newRoots = append(newRoots, newActiveRoot) newRoots = append(newRoots, newActiveRoot)
} else {
newRoots = oldRoots
} }
args := &structs.CARequest{ args := &structs.CARequest{

View File

@ -100,6 +100,7 @@ func (m *mockCAServerDelegate) raftApply(t structs.MessageType, msg interface{})
act, err = m.store.CACheckAndSetConfig(1, req.Config.ModifyIndex, req.Config) act, err = m.store.CACheckAndSetConfig(1, req.Config.ModifyIndex, req.Config)
require.NoError(m.t, err) require.NoError(m.t, err)
require.True(m.t, act)
} }
m.callbackCh <- fmt.Sprintf("raftApply/%s", t) m.callbackCh <- fmt.Sprintf("raftApply/%s", t)
return nil, nil return nil, nil

View File

@ -700,22 +700,6 @@ func TestLeader_SecondaryCA_TransitionFromPrimary(t *testing.T) {
require.NoError(t, s2.RPC("ConnectCA.Roots", &args, &dc2PrimaryRoots)) require.NoError(t, s2.RPC("ConnectCA.Roots", &args, &dc2PrimaryRoots))
require.Len(t, dc2PrimaryRoots.Roots, 1) require.Len(t, dc2PrimaryRoots.Roots, 1)
// Set the ExternalTrustDomain to a blank string to simulate an old version (pre-1.4.0)
// it's fine to change the roots struct directly here because the RPC endpoint already
// makes a copy to return.
dc2PrimaryRoots.Roots[0].ExternalTrustDomain = ""
rootSetArgs := structs.CARequest{
Op: structs.CAOpSetRoots,
Datacenter: "dc2",
Index: dc2PrimaryRoots.Index,
Roots: dc2PrimaryRoots.Roots,
}
resp, err := s2.raftApply(structs.ConnectCARequestType, rootSetArgs)
require.NoError(t, err)
if respErr, ok := resp.(error); ok {
t.Fatal(respErr)
}
// Shutdown s2 and restart it with the dc1 as the primary // Shutdown s2 and restart it with the dc1 as the primary
s2.Shutdown() s2.Shutdown()
dir3, s3 := testServerWithConfig(t, func(c *Config) { dir3, s3 := testServerWithConfig(t, func(c *Config) {