Skip to content

Commit 0d2a62a

Browse files
committed
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.
1 parent 08a2efa commit 0d2a62a

File tree

2 files changed

+70
-41
lines changed

2 files changed

+70
-41
lines changed

command/server.go

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,19 +1546,7 @@ func (c *ServerCommand) Run(args []string) int {
15461546
}
15471547

15481548
core.SetSealReloadFunc(func(ctx context.Context) error {
1549-
// This function performs the same seal reloading functionality as in the SIGHUP handler below.
1550-
config, _, err := c.reloadConfigFiles()
1551-
if err != nil {
1552-
return err
1553-
}
1554-
if config == nil {
1555-
return errors.New("no config found at reload time")
1556-
}
1557-
reloaded, err := c.reloadSeals(ctx, false, core, config)
1558-
if reloaded {
1559-
core.SetConfig(config)
1560-
}
1561-
return err
1549+
return c.reloadSealsOnLeaderActivation(ctx, core)
15621550
})
15631551

15641552
// Output the header that the server has started
@@ -1662,7 +1650,7 @@ func (c *ServerCommand) Run(args []string) int {
16621650

16631651
// Note that seal reloading can also be triggered via Core.TriggerSealReload.
16641652
// See the call to Core.SetSealReloadFunc above.
1665-
if reloaded, err := c.reloadSealsLocking(ctx, core, config); err != nil {
1653+
if reloaded, err := c.reloadSealsOnSigHup(ctx, core, config); err != nil {
16661654
c.UI.Error(fmt.Errorf("error reloading seal config: %s", err).Error())
16671655
config.Seals = core.GetCoreConfigInternal().Seals
16681656
goto RUNRELOADFUNCS
@@ -3376,7 +3364,46 @@ func startHttpServers(c *ServerCommand, core *vault.Core, config *server.Config,
33763364
return nil
33773365
}
33783366

3379-
func (c *ServerCommand) reloadSealsLocking(ctx context.Context, core *vault.Core, config *server.Config) (bool, error) {
3367+
// reloadSealsOnLeaderActivation checks to see if the in-memory seal generation info is stale, and if so,
3368+
// reloads the seal configuration.
3369+
func (c *ServerCommand) reloadSealsOnLeaderActivation(ctx context.Context, core *vault.Core) error {
3370+
existingSealGenerationInfo, err := vault.PhysicalSealGenInfo(ctx, core.PhysicalAccess())
3371+
if err != nil {
3372+
return fmt.Errorf("error checking for stale seal generation info: %w", err)
3373+
}
3374+
if existingSealGenerationInfo == nil {
3375+
c.logger.Debug("not reloading seals config since there is no seal generation info in storage")
3376+
return nil
3377+
}
3378+
3379+
currentSealGenerationInfo := core.SealAccess().GetAccess().GetSealGenerationInfo()
3380+
if currentSealGenerationInfo == nil {
3381+
c.logger.Debug("not reloading seal config since there is no current generation info (the seal has not been initialized)")
3382+
return nil
3383+
}
3384+
if currentSealGenerationInfo.Generation >= existingSealGenerationInfo.Generation {
3385+
c.logger.Debug("seal generation info is up to date, not reloading seal configuration")
3386+
return nil
3387+
}
3388+
3389+
// Reload seal configuration
3390+
3391+
config, _, err := c.reloadConfigFiles()
3392+
if err != nil {
3393+
return fmt.Errorf("error reading configuration files while reloading seal configuration: %w", err)
3394+
}
3395+
if config == nil {
3396+
return errors.New("no configuration files found while reloading seal configuration")
3397+
}
3398+
reloaded, err := c.reloadSeals(ctx, false, core, config)
3399+
if reloaded {
3400+
core.SetConfig(config)
3401+
}
3402+
return err
3403+
}
3404+
3405+
// reloadSealsOnSigHup will reload seal configurtion as a result of receiving a SIGHUP signal.
3406+
func (c *ServerCommand) reloadSealsOnSigHup(ctx context.Context, core *vault.Core, config *server.Config) (bool, error) {
33803407
return c.reloadSeals(ctx, true, core, config)
33813408
}
33823409

@@ -3385,63 +3412,63 @@ func (c *ServerCommand) reloadSealsLocking(ctx context.Context, core *vault.Core
33853412
// in the seal configuration files.
33863413
// This function returns true if the newConfig was used to re-create the Seal.Access() objects. In other words,
33873414
// if false is returned, there were no changes done to the seals.
3388-
func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, core *vault.Core, newConfig *server.Config) (ret bool, err error) {
3389-
defer func() {
3390-
if err != nil {
3391-
// We do not log here, as the error will be logged higher in the call chain
3392-
return
3393-
}
3394-
if ret {
3395-
c.logger.Info("seal configuration reloaded successfully")
3396-
} else {
3397-
c.logger.Info("seal configuration was not reloaded")
3398-
}
3399-
}()
3400-
3415+
func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, core *vault.Core, newConfig *server.Config) (bool, error) {
34013416
if core.IsInSealMigrationMode(grabStateLock) {
3417+
c.logger.Debug("not reloading seal configuration since Vault is in migration mode")
34023418
return false, nil
34033419
}
34043420

34053421
currentConfig := core.GetCoreConfigInternal()
34063422

3407-
// we need to persist seal information if multiseal is being enabled
3408-
addEnableMultiseal := !currentConfig.IsMultisealEnabled() && newConfig.IsMultisealEnabled()
3423+
// We only want to reload if multiseal is currently enabled, or it is being enabled
3424+
if !(currentConfig.IsMultisealEnabled() || newConfig.IsMultisealEnabled()) {
3425+
c.logger.Debug("not reloading seal configuration since enable_multiseal is not set, nor is it being disabled")
3426+
return false, nil
3427+
}
3428+
3429+
if conf, err := core.PhysicalBarrierSealConfig(ctx); err != nil {
3430+
return false, fmt.Errorf("error reading barrier seal configuration from storage while reloading seals: %w", err)
3431+
} else if conf == nil {
3432+
c.logger.Debug("not reloading seal configuration since there is no barrier config in storage (the seal has not been initialized)")
3433+
return false, nil
3434+
}
34093435

34103436
if core.SealAccess().BarrierSealConfigType() == vault.SealConfigTypeShamir {
34113437
switch {
34123438
case len(newConfig.Seals) == 0:
34133439
// We are fine, our ServerCommand.reloadConfigFiles() does not do the "automagic" creation
34143440
// of the Shamir seal configuration.
3441+
c.logger.Debug("not reloading seal configuration since the new one has no seal stanzas")
34153442
return false, nil
34163443

34173444
case len(newConfig.Seals) == 1 && newConfig.Seals[0].Disabled:
34183445
// If we have only one seal and it is disabled, it means that the newConfig wants to migrate
34193446
// to Shamir, which is not supported by seal reloading.
3447+
c.logger.Debug("not reloading seal configuration since the new one specifies migration to Shamir")
34203448
return false, nil
34213449

34223450
case len(newConfig.Seals) == 1 && newConfig.Seals[0].Type == vault.SealConfigTypeShamir.String():
34233451
// Having a single Shamir seal in newConfig is not really possible, since a Shamir seal
34243452
// is specified in configuration by *not* having a seal stanza. If we were to hit this
34253453
// case, though, it is equivalent to trying to migrate to Shamir, which is not supported
34263454
// by seal reloading.
3455+
c.logger.Debug("not reloading seal configuration since the new one has single Shamir stanza")
34273456
return false, nil
34283457
}
34293458
}
34303459

3431-
if cmp.Equal(currentConfig.Seals, newConfig.Seals) && !addEnableMultiseal {
3432-
return false, nil
3433-
}
3434-
34353460
// Verify that the new config we picked up is not trying to migrate from autoseal to shamir
34363461
if len(newConfig.Seals) == 1 && newConfig.Seals[0].Disabled {
34373462
// If we get here, it means the node was not started in migration mode, but the new config says
3438-
// we should go into migration mode.
3439-
return false, errors.New("moving from autoseal to shamir requires seal migration")
3463+
// we should go into migration mode. This case should be caught by the core.IsInSealMigrationMode()
3464+
// above.
3465+
3466+
return false, errors.New("not reloading seal configuration: moving from autoseal to shamir requires seal migration")
34403467
}
34413468

34423469
// Verify that the new config we picked up is not trying to migrate shamir to autoseal
34433470
if core.SealAccess().BarrierSealConfigType() == vault.SealConfigTypeShamir {
3444-
return false, errors.New("moving from shamir to autoseal requires seal migration")
3471+
return false, errors.New("not reloading seal configuration: moving from Shamir to autoseal requires seal migration")
34453472
}
34463473

34473474
infoKeysReload := make([]string, 0)
@@ -3450,10 +3477,10 @@ func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, cor
34503477
core.SetMultisealEnabled(newConfig.IsMultisealEnabled())
34513478
setSealResponse, secureRandomReader, err := c.configureSeals(ctx, newConfig, core.PhysicalAccess(), infoKeysReload, infoReload)
34523479
if err != nil {
3453-
return false, err
3480+
return false, fmt.Errorf("error reloading seal configuration: %w", err)
34543481
}
34553482
if setSealResponse.sealConfigError != nil {
3456-
return false, err
3483+
return false, fmt.Errorf("error reloading seal configuration: %w", setSealResponse.sealConfigError)
34573484
}
34583485

34593486
newGen := setSealResponse.barrierSeal.GetAccess().GetSealGenerationInfo()
@@ -3470,6 +3497,8 @@ func (c *ServerCommand) reloadSeals(ctx context.Context, grabStateLock bool, cor
34703497
// finalize the old seals and set the new seals as the current ones
34713498
c.setSealsToFinalize(setSealResponse.getCreatedSeals())
34723499

3500+
c.logger.Debug("seal configuration reloaded successfully")
3501+
34733502
return true, nil
34743503
}
34753504

command/server_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,12 @@ func TestReloadSeals(t *testing.T) {
414414

415415
testCommand.logger = corehelpers.NewTestLogger(t)
416416
ctx := context.Background()
417-
reloaded, err := testCommand.reloadSealsLocking(ctx, testCore, &testConfig)
417+
reloaded, err := testCommand.reloadSealsOnSigHup(ctx, testCore, &testConfig)
418418
require.NoError(t, err)
419419
require.False(t, reloaded, "reloadSeals does not support Shamir seals")
420420

421421
testConfig = server.Config{SharedConfig: &configutil.SharedConfig{Seals: []*configutil.KMS{{Disabled: true}}}}
422-
reloaded, err = testCommand.reloadSealsLocking(ctx, testCore, &testConfig)
422+
reloaded, err = testCommand.reloadSealsOnSigHup(ctx, testCore, &testConfig)
423423
require.NoError(t, err)
424424
require.False(t, reloaded, "reloadSeals does not support Shamir seals")
425425
}

0 commit comments

Comments
 (0)