mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 11:08:10 +00:00
Only reload seal config when enable_multiseal is set, or is being disabled (#26166)
Fix reloading of seal configuration when a node gains leadership. Verify that the in-memory seal generation information is stale and only reload seal configuration when that is the case. When reloading seal configuration, only do it when enable_multiseal is currently set to true, or the new configuration is attempting to set it to true.
This commit is contained in:
3
changelog/26166.txt
Normal file
3
changelog/26166.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:bug
|
||||||
|
core: Only reload seal configuration when enable_multiseal is set to true.
|
||||||
|
```
|
||||||
@@ -1546,19 +1546,7 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
core.SetSealReloadFunc(func(ctx context.Context) error {
|
core.SetSealReloadFunc(func(ctx context.Context) error {
|
||||||
// This function performs the same seal reloading functionality as in the SIGHUP handler below.
|
return c.reloadSealsOnLeaderActivation(ctx, core)
|
||||||
config, _, err := c.reloadConfigFiles()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if config == nil {
|
|
||||||
return errors.New("no config found at reload time")
|
|
||||||
}
|
|
||||||
reloaded, err := c.reloadSeals(ctx, false, core, config)
|
|
||||||
if reloaded {
|
|
||||||
core.SetConfig(config)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Output the header that the server has started
|
// Output the header that the server has started
|
||||||
@@ -1662,7 +1650,7 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
|
|
||||||
// Note that seal reloading can also be triggered via Core.TriggerSealReload.
|
// Note that seal reloading can also be triggered via Core.TriggerSealReload.
|
||||||
// See the call to Core.SetSealReloadFunc above.
|
// See the call to Core.SetSealReloadFunc above.
|
||||||
if reloaded, err := c.reloadSealsLocking(ctx, core, config); err != nil {
|
if reloaded, err := c.reloadSealsOnSigHup(ctx, core, config); err != nil {
|
||||||
c.UI.Error(fmt.Errorf("error reloading seal config: %s", err).Error())
|
c.UI.Error(fmt.Errorf("error reloading seal config: %s", err).Error())
|
||||||
config.Seals = core.GetCoreConfigInternal().Seals
|
config.Seals = core.GetCoreConfigInternal().Seals
|
||||||
goto RUNRELOADFUNCS
|
goto RUNRELOADFUNCS
|
||||||
@@ -3376,7 +3364,46 @@ func startHttpServers(c *ServerCommand, core *vault.Core, config *server.Config,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ServerCommand) reloadSealsLocking(ctx context.Context, core *vault.Core, config *server.Config) (bool, error) {
|
// reloadSealsOnLeaderActivation checks to see if the in-memory seal generation info is stale, and if so,
|
||||||
|
// reloads the seal configuration.
|
||||||
|
func (c *ServerCommand) reloadSealsOnLeaderActivation(ctx context.Context, core *vault.Core) error {
|
||||||
|
existingSealGenerationInfo, err := vault.PhysicalSealGenInfo(ctx, core.PhysicalAccess())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error checking for stale seal generation info: %w", err)
|
||||||
|
}
|
||||||
|
if existingSealGenerationInfo == nil {
|
||||||
|
c.logger.Debug("not reloading seals config since there is no seal generation info in storage")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSealGenerationInfo := core.SealAccess().GetAccess().GetSealGenerationInfo()
|
||||||
|
if currentSealGenerationInfo == nil {
|
||||||
|
c.logger.Debug("not reloading seal config since there is no current generation info (the seal has not been initialized)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if currentSealGenerationInfo.Generation >= existingSealGenerationInfo.Generation {
|
||||||
|
c.logger.Debug("seal generation info is up to date, not reloading seal configuration")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload seal configuration
|
||||||
|
|
||||||
|
config, _, err := c.reloadConfigFiles()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading configuration files while reloading seal configuration: %w", err)
|
||||||
|
}
|
||||||
|
if config == nil {
|
||||||
|
return errors.New("no configuration files found while reloading seal configuration")
|
||||||
|
}
|
||||||
|
reloaded, err := c.reloadSeals(ctx, false, core, config)
|
||||||
|
if reloaded {
|
||||||
|
core.SetConfig(config)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// reloadSealsOnSigHup will reload seal configurtion as a result of receiving a SIGHUP signal.
|
||||||
|
func (c *ServerCommand) reloadSealsOnSigHup(ctx context.Context, core *vault.Core, config *server.Config) (bool, error) {
|
||||||
return c.reloadSeals(ctx, true, core, config)
|
return c.reloadSeals(ctx, true, core, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3385,38 +3412,39 @@ func (c *ServerCommand) reloadSealsLocking(ctx context.Context, core *vault.Core
|
|||||||
// in the seal configuration files.
|
// in the seal configuration files.
|
||||||
// This function returns true if the newConfig was used to re-create the Seal.Access() objects. In other words,
|
// This function returns true if the newConfig was used to re-create the Seal.Access() objects. In other words,
|
||||||
// if false is returned, there were no changes done to the seals.
|
// if false is returned, there were no changes done to the seals.
|
||||||
func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, core *vault.Core, newConfig *server.Config) (ret bool, err error) {
|
func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, core *vault.Core, newConfig *server.Config) (bool, error) {
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
// We do not log here, as the error will be logged higher in the call chain
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ret {
|
|
||||||
c.logger.Info("seal configuration reloaded successfully")
|
|
||||||
} else {
|
|
||||||
c.logger.Info("seal configuration was not reloaded")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if core.IsInSealMigrationMode(grabStateLock) {
|
if core.IsInSealMigrationMode(grabStateLock) {
|
||||||
|
c.logger.Debug("not reloading seal configuration since Vault is in migration mode")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
currentConfig := core.GetCoreConfigInternal()
|
currentConfig := core.GetCoreConfigInternal()
|
||||||
|
|
||||||
// we need to persist seal information if multiseal is being enabled
|
// We only want to reload if multiseal is currently enabled, or it is being enabled
|
||||||
addEnableMultiseal := !currentConfig.IsMultisealEnabled() && newConfig.IsMultisealEnabled()
|
if !(currentConfig.IsMultisealEnabled() || newConfig.IsMultisealEnabled()) {
|
||||||
|
c.logger.Debug("not reloading seal configuration since enable_multiseal is not set, nor is it being disabled")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf, err := core.PhysicalBarrierSealConfig(ctx); err != nil {
|
||||||
|
return false, fmt.Errorf("error reading barrier seal configuration from storage while reloading seals: %w", err)
|
||||||
|
} else if conf == nil {
|
||||||
|
c.logger.Debug("not reloading seal configuration since there is no barrier config in storage (the seal has not been initialized)")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
if core.SealAccess().BarrierSealConfigType() == vault.SealConfigTypeShamir {
|
if core.SealAccess().BarrierSealConfigType() == vault.SealConfigTypeShamir {
|
||||||
switch {
|
switch {
|
||||||
case len(newConfig.Seals) == 0:
|
case len(newConfig.Seals) == 0:
|
||||||
// We are fine, our ServerCommand.reloadConfigFiles() does not do the "automagic" creation
|
// We are fine, our ServerCommand.reloadConfigFiles() does not do the "automagic" creation
|
||||||
// of the Shamir seal configuration.
|
// of the Shamir seal configuration.
|
||||||
|
c.logger.Debug("not reloading seal configuration since the new one has no seal stanzas")
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
||||||
case len(newConfig.Seals) == 1 && newConfig.Seals[0].Disabled:
|
case len(newConfig.Seals) == 1 && newConfig.Seals[0].Disabled:
|
||||||
// If we have only one seal and it is disabled, it means that the newConfig wants to migrate
|
// If we have only one seal and it is disabled, it means that the newConfig wants to migrate
|
||||||
// to Shamir, which is not supported by seal reloading.
|
// to Shamir, which is not supported by seal reloading.
|
||||||
|
c.logger.Debug("not reloading seal configuration since the new one specifies migration to Shamir")
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
||||||
case len(newConfig.Seals) == 1 && newConfig.Seals[0].Type == vault.SealConfigTypeShamir.String():
|
case len(newConfig.Seals) == 1 && newConfig.Seals[0].Type == vault.SealConfigTypeShamir.String():
|
||||||
@@ -3424,24 +3452,23 @@ func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, cor
|
|||||||
// is specified in configuration by *not* having a seal stanza. If we were to hit this
|
// is specified in configuration by *not* having a seal stanza. If we were to hit this
|
||||||
// case, though, it is equivalent to trying to migrate to Shamir, which is not supported
|
// case, though, it is equivalent to trying to migrate to Shamir, which is not supported
|
||||||
// by seal reloading.
|
// by seal reloading.
|
||||||
|
c.logger.Debug("not reloading seal configuration since the new one has single Shamir stanza")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmp.Equal(currentConfig.Seals, newConfig.Seals) && !addEnableMultiseal {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the new config we picked up is not trying to migrate from autoseal to shamir
|
// Verify that the new config we picked up is not trying to migrate from autoseal to shamir
|
||||||
if len(newConfig.Seals) == 1 && newConfig.Seals[0].Disabled {
|
if len(newConfig.Seals) == 1 && newConfig.Seals[0].Disabled {
|
||||||
// If we get here, it means the node was not started in migration mode, but the new config says
|
// If we get here, it means the node was not started in migration mode, but the new config says
|
||||||
// we should go into migration mode.
|
// we should go into migration mode. This case should be caught by the core.IsInSealMigrationMode()
|
||||||
return false, errors.New("moving from autoseal to shamir requires seal migration")
|
// above.
|
||||||
|
|
||||||
|
return false, errors.New("not reloading seal configuration: moving from autoseal to shamir requires seal migration")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the new config we picked up is not trying to migrate shamir to autoseal
|
// Verify that the new config we picked up is not trying to migrate shamir to autoseal
|
||||||
if core.SealAccess().BarrierSealConfigType() == vault.SealConfigTypeShamir {
|
if core.SealAccess().BarrierSealConfigType() == vault.SealConfigTypeShamir {
|
||||||
return false, errors.New("moving from shamir to autoseal requires seal migration")
|
return false, errors.New("not reloading seal configuration: moving from Shamir to autoseal requires seal migration")
|
||||||
}
|
}
|
||||||
|
|
||||||
infoKeysReload := make([]string, 0)
|
infoKeysReload := make([]string, 0)
|
||||||
@@ -3450,10 +3477,10 @@ func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, cor
|
|||||||
core.SetMultisealEnabled(newConfig.IsMultisealEnabled())
|
core.SetMultisealEnabled(newConfig.IsMultisealEnabled())
|
||||||
setSealResponse, secureRandomReader, err := c.configureSeals(ctx, newConfig, core.PhysicalAccess(), infoKeysReload, infoReload)
|
setSealResponse, secureRandomReader, err := c.configureSeals(ctx, newConfig, core.PhysicalAccess(), infoKeysReload, infoReload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, fmt.Errorf("error reloading seal configuration: %w", err)
|
||||||
}
|
}
|
||||||
if setSealResponse.sealConfigError != nil {
|
if setSealResponse.sealConfigError != nil {
|
||||||
return false, err
|
return false, fmt.Errorf("error reloading seal configuration: %w", setSealResponse.sealConfigError)
|
||||||
}
|
}
|
||||||
|
|
||||||
newGen := setSealResponse.barrierSeal.GetAccess().GetSealGenerationInfo()
|
newGen := setSealResponse.barrierSeal.GetAccess().GetSealGenerationInfo()
|
||||||
@@ -3470,6 +3497,8 @@ func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, cor
|
|||||||
// finalize the old seals and set the new seals as the current ones
|
// finalize the old seals and set the new seals as the current ones
|
||||||
c.setSealsToFinalize(setSealResponse.getCreatedSeals())
|
c.setSealsToFinalize(setSealResponse.getCreatedSeals())
|
||||||
|
|
||||||
|
c.logger.Debug("seal configuration reloaded successfully")
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -414,12 +414,12 @@ func TestReloadSeals(t *testing.T) {
|
|||||||
|
|
||||||
testCommand.logger = corehelpers.NewTestLogger(t)
|
testCommand.logger = corehelpers.NewTestLogger(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
reloaded, err := testCommand.reloadSealsLocking(ctx, testCore, &testConfig)
|
reloaded, err := testCommand.reloadSealsOnSigHup(ctx, testCore, &testConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.False(t, reloaded, "reloadSeals does not support Shamir seals")
|
require.False(t, reloaded, "reloadSeals does not support Shamir seals")
|
||||||
|
|
||||||
testConfig = server.Config{SharedConfig: &configutil.SharedConfig{Seals: []*configutil.KMS{{Disabled: true}}}}
|
testConfig = server.Config{SharedConfig: &configutil.SharedConfig{Seals: []*configutil.KMS{{Disabled: true}}}}
|
||||||
reloaded, err = testCommand.reloadSealsLocking(ctx, testCore, &testConfig)
|
reloaded, err = testCommand.reloadSealsOnSigHup(ctx, testCore, &testConfig)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.False(t, reloaded, "reloadSeals does not support Shamir seals")
|
require.False(t, reloaded, "reloadSeals does not support Shamir seals")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user