Skip to content

Commit

Permalink
refactor core migration
Browse files Browse the repository at this point in the history
  • Loading branch information
mjarmy committed May 26, 2020
1 parent deced65 commit a776452
Show file tree
Hide file tree
Showing 2 changed files with 239 additions and 110 deletions.
110 changes: 110 additions & 0 deletions command/server_util.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package command

import (
"context"
"errors"
"fmt"

log "github.com/hashicorp/go-hclog"
aeadwrapper "github.com/hashicorp/go-kms-wrapping/wrappers/aead"
"github.com/hashicorp/vault/command/server"
"github.com/hashicorp/vault/vault"
vaultseal "github.com/hashicorp/vault/vault/seal"
)

var (
Expand All @@ -11,3 +18,106 @@ var (

func adjustCoreConfigForEntNoop(config *server.Config, coreConfig *vault.CoreConfig) {
}

func AdjustCoreForSealMigration(logger log.Logger, core *vault.Core, barrierSeal, unwrapSeal vault.Seal) error {
existBarrierSealConfig, existRecoverySealConfig, err := core.PhysicalSealConfigs(context.Background())
if err != nil {
return fmt.Errorf("Error checking for existing seal: %s", err)
}

// If we don't have an existing config or if it's the deprecated auto seal
// which needs an upgrade, skip out
if existBarrierSealConfig == nil || existBarrierSealConfig.Type == wrapping.HSMAutoDeprecated {
return nil
}

if unwrapSeal == nil {
// We have the same barrier type and the unwrap seal is nil so we're not
// migrating from same to same, IOW we assume it's not a migration
if existBarrierSealConfig.Type == barrierSeal.BarrierType() {
return nil
}

// If we're not coming from Shamir, and the existing type doesn't match
// the barrier type, we need both the migration seal and the new seal
if existBarrierSealConfig.Type != wrapping.Shamir && barrierSeal.BarrierType() != wrapping.Shamir {
return errors.New(`Trying to migrate from auto-seal to auto-seal but no "disabled" seal stanza found`)
}
} else {
if unwrapSeal.BarrierType() == wrapping.Shamir {
return errors.New("Shamir seals cannot be set disabled (they should simply not be set)")
}
}

if existBarrierSealConfig.Type != wrapping.Shamir && existRecoverySealConfig == nil {
return errors.New(`Recovery seal configuration not found for existing seal`)
}

var migrationSeal vault.Seal
var newSeal vault.Seal

// Determine the migrationSeal. This is either going to be an instance of
// shamir or the unwrapSeal.
switch existBarrierSealConfig.Type {
case wrapping.Shamir:
// The value reflected in config is what we're going to
migrationSeal = vault.NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(&wrapping.WrapperOptions{
Logger: logger.Named("shamir"),
}),
})

default:
// If we're not coming from Shamir we expect the previous seal to be
// in the config and disabled.
migrationSeal = unwrapSeal
}

// newSeal will be the barrierSeal
newSeal = barrierSeal

if migrationSeal != nil && newSeal != nil && migrationSeal.BarrierType() == newSeal.BarrierType() {
return errors.New("Migrating between same seal types is currently not supported")
}

if unwrapSeal != nil && existBarrierSealConfig.Type == barrierSeal.BarrierType() {
// In this case our migration seal is set so we are using it
// (potentially) for unwrapping. Set it on core for that purpose then
// exit.
core.SetSealsForMigration(nil, nil, unwrapSeal)
return nil
}

// Set the appropriate barrier and recovery configs.
switch {
case migrationSeal != nil && newSeal != nil && migrationSeal.RecoveryKeySupported() && newSeal.RecoveryKeySupported():
// Migrating from auto->auto, copy the configs over
newSeal.SetCachedBarrierConfig(existBarrierSealConfig)
newSeal.SetCachedRecoveryConfig(existRecoverySealConfig)
case migrationSeal != nil && newSeal != nil && migrationSeal.RecoveryKeySupported():
// Migrating from auto->shamir, clone auto's recovery config and set
// stored keys to 1.
newSealConfig := existRecoverySealConfig.Clone()
newSealConfig.StoredShares = 1
newSeal.SetCachedBarrierConfig(newSealConfig)
case newSeal != nil && newSeal.RecoveryKeySupported():
// Migrating from shamir->auto, set a new barrier config and set
// recovery config to a clone of shamir's barrier config with stored
// keys set to 0.
newBarrierSealConfig := &vault.SealConfig{
Type: newSeal.BarrierType(),
SecretShares: 1,
SecretThreshold: 1,
StoredShares: 1,
}
newSeal.SetCachedBarrierConfig(newBarrierSealConfig)

newRecoveryConfig := existBarrierSealConfig.Clone()
newRecoveryConfig.StoredShares = 0
newSeal.SetCachedRecoveryConfig(newRecoveryConfig)
}

core.SetSealsForMigration(migrationSeal, newSeal, unwrapSeal)

return nil
}
239 changes: 129 additions & 110 deletions vault/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -943,10 +943,10 @@ func NewCore(conf *CoreConfig) (*Core, error) {

c.clusterListener.Store((*cluster.Listener)(nil))

err = c.adjustForSealMigration(conf.UnwrapSeal)
if err != nil {
return nil, err
}
//err = c.adjustForSealMigration(conf.UnwrapSeal)
//if err != nil {
// return nil, err
//}

return c, nil
}
Expand Down Expand Up @@ -2232,115 +2232,134 @@ func (c *Core) PhysicalSealConfigs(ctx context.Context) (*SealConfig, *SealConfi
return barrierConf, recoveryConf, nil
}

func (c *Core) adjustForSealMigration(unwrapSeal Seal) error {
existBarrierSealConfig, existRecoverySealConfig, err := c.PhysicalSealConfigs(context.Background())
if err != nil {
return fmt.Errorf("Error checking for existing seal: %s", err)
}

// If we don't have an existing config or if it's the deprecated auto seal
// which needs an upgrade, skip out
if existBarrierSealConfig == nil || existBarrierSealConfig.Type == wrapping.HSMAutoDeprecated {
return nil
}

if unwrapSeal == nil {
// We have the same barrier type and the unwrap seal is nil so we're not
// migrating from same to same, IOW we assume it's not a migration
if existBarrierSealConfig.Type == c.seal.BarrierType() {
return nil
}

// If we're not coming from Shamir, and the existing type doesn't match
// the barrier type, we need both the migration seal and the new seal
if existBarrierSealConfig.Type != wrapping.Shamir && c.seal.BarrierType() != wrapping.Shamir {
return errors.New(`Trying to migrate from auto-seal to auto-seal but no "disabled" seal stanza found`)
}
} else {
if unwrapSeal.BarrierType() == wrapping.Shamir {
return errors.New("Shamir seals cannot be set disabled (they should simply not be set)")
}
}

if existBarrierSealConfig.Type != wrapping.Shamir && existRecoverySealConfig == nil {
return errors.New(`Recovery seal configuration not found for existing seal`)
}

var migrationSeal Seal
var newSeal Seal

// Determine the migrationSeal. This is either going to be an instance of
// shamir or the unwrapSeal.
switch existBarrierSealConfig.Type {
case wrapping.Shamir:
// The value reflected in config is what we're going to
migrationSeal = NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewWrapper(&wrapping.WrapperOptions{
Logger: c.logger.Named("shamir"),
}),
})

default:
// If we're not coming from Shamir we expect the previous seal to be
// in the config and disabled.
migrationSeal = unwrapSeal
}

// newSeal will be the barrierSeal
newSeal = c.seal

if migrationSeal != nil && newSeal != nil && migrationSeal.BarrierType() == newSeal.BarrierType() {
return errors.New("Migrating between same seal types is currently not supported")
}

if unwrapSeal != nil && existBarrierSealConfig.Type == c.seal.BarrierType() {
// In this case our migration seal is set so we are using it
// (potentially) for unwrapping. Set it on core for that purpose then
// exit.
c.setSealsForMigration(nil, nil, unwrapSeal)
return nil
}

// Set the appropriate barrier and recovery configs.
switch {
case migrationSeal != nil && newSeal != nil && migrationSeal.RecoveryKeySupported() && newSeal.RecoveryKeySupported():
// Migrating from auto->auto, copy the configs over
newSeal.SetCachedBarrierConfig(existBarrierSealConfig)
newSeal.SetCachedRecoveryConfig(existRecoverySealConfig)
case migrationSeal != nil && newSeal != nil && migrationSeal.RecoveryKeySupported():
// Migrating from auto->shamir, clone auto's recovery config and set
// stored keys to 1.
newSealConfig := existRecoverySealConfig.Clone()
newSealConfig.StoredShares = 1
newSeal.SetCachedBarrierConfig(newSealConfig)
case newSeal != nil && newSeal.RecoveryKeySupported():
// Migrating from shamir->auto, set a new barrier config and set
// recovery config to a clone of shamir's barrier config with stored
// keys set to 0.
newBarrierSealConfig := &SealConfig{
Type: newSeal.BarrierType(),
SecretShares: 1,
SecretThreshold: 1,
StoredShares: 1,
}
newSeal.SetCachedBarrierConfig(newBarrierSealConfig)

newRecoveryConfig := existBarrierSealConfig.Clone()
newRecoveryConfig.StoredShares = 0
newSeal.SetCachedRecoveryConfig(newRecoveryConfig)
}

c.setSealsForMigration(migrationSeal, newSeal, unwrapSeal)

return nil
}
//func (c *Core) adjustForSealMigration(unwrapSeal Seal) error {
// existBarrierSealConfig, existRecoverySealConfig, err := c.PhysicalSealConfigs(context.Background())
// if err != nil {
// return fmt.Errorf("Error checking for existing seal: %s", err)
// }
//
// // If we don't have an existing config or if it's the deprecated auto seal
// // which needs an upgrade, skip out
// if existBarrierSealConfig == nil || existBarrierSealConfig.Type == wrapping.HSMAutoDeprecated {
// return nil
// }
//
// if unwrapSeal == nil {
// // We have the same barrier type and the unwrap seal is nil so we're not
// // migrating from same to same, IOW we assume it's not a migration
// if existBarrierSealConfig.Type == c.seal.BarrierType() {
// return nil
// }
//
// // If we're not coming from Shamir, and the existing type doesn't match
// // the barrier type, we need both the migration seal and the new seal
// if existBarrierSealConfig.Type != wrapping.Shamir && c.seal.BarrierType() != wrapping.Shamir {
// return errors.New(`Trying to migrate from auto-seal to auto-seal but no "disabled" seal stanza found`)
// }
// } else {
// if unwrapSeal.BarrierType() == wrapping.Shamir {
// return errors.New("Shamir seals cannot be set disabled (they should simply not be set)")
// }
// }
//
// if existBarrierSealConfig.Type != wrapping.Shamir && existRecoverySealConfig == nil {
// return errors.New(`Recovery seal configuration not found for existing seal`)
// }
//
// var migrationSeal Seal
// var newSeal Seal
//
// // Determine the migrationSeal. This is either going to be an instance of
// // shamir or the unwrapSeal.
// switch existBarrierSealConfig.Type {
// case wrapping.Shamir:
// // The value reflected in config is what we're going to
// migrationSeal = NewDefaultSeal(&vaultseal.Access{
// Wrapper: aeadwrapper.NewWrapper(&wrapping.WrapperOptions{
// Logger: c.logger.Named("shamir"),
// }),
// })
//
// default:
// // If we're not coming from Shamir we expect the previous seal to be
// // in the config and disabled.
// migrationSeal = unwrapSeal
// }
//
// // newSeal will be the barrierSeal
// newSeal = c.seal
//
// if migrationSeal != nil && newSeal != nil && migrationSeal.BarrierType() == newSeal.BarrierType() {
// return errors.New("Migrating between same seal types is currently not supported")
// }
//
// if unwrapSeal != nil && existBarrierSealConfig.Type == c.seal.BarrierType() {
// // In this case our migration seal is set so we are using it
// // (potentially) for unwrapping. Set it on core for that purpose then
// // exit.
// c.setSealsForMigration(nil, nil, unwrapSeal)
// return nil
// }
//
// // Set the appropriate barrier and recovery configs.
// switch {
// case migrationSeal != nil && newSeal != nil && migrationSeal.RecoveryKeySupported() && newSeal.RecoveryKeySupported():
// // Migrating from auto->auto, copy the configs over
// newSeal.SetCachedBarrierConfig(existBarrierSealConfig)
// newSeal.SetCachedRecoveryConfig(existRecoverySealConfig)
// case migrationSeal != nil && newSeal != nil && migrationSeal.RecoveryKeySupported():
// // Migrating from auto->shamir, clone auto's recovery config and set
// // stored keys to 1.
// newSealConfig := existRecoverySealConfig.Clone()
// newSealConfig.StoredShares = 1
// newSeal.SetCachedBarrierConfig(newSealConfig)
// case newSeal != nil && newSeal.RecoveryKeySupported():
// // Migrating from shamir->auto, set a new barrier config and set
// // recovery config to a clone of shamir's barrier config with stored
// // keys set to 0.
// newBarrierSealConfig := &SealConfig{
// Type: newSeal.BarrierType(),
// SecretShares: 1,
// SecretThreshold: 1,
// StoredShares: 1,
// }
// newSeal.SetCachedBarrierConfig(newBarrierSealConfig)
//
// newRecoveryConfig := existBarrierSealConfig.Clone()
// newRecoveryConfig.StoredShares = 0
// newSeal.SetCachedRecoveryConfig(newRecoveryConfig)
// }
//
// c.setSealsForMigration(migrationSeal, newSeal, unwrapSeal)
//
// return nil
//}

func (c *Core) setSealsForMigration(migrationSeal, newSeal, unwrapSeal Seal) {
//func (c *Core) setSealsForMigration(migrationSeal, newSeal, unwrapSeal Seal) {
// c.stateLock.Lock()
// defer c.stateLock.Unlock()
//
// fmt.Printf("test-debug (c *Core) setSealsForMigration %T %T %T\n", migrationSeal, newSeal, unwrapSeal)
//
// c.unwrapSeal = unwrapSeal
// if c.unwrapSeal != nil {
// c.unwrapSeal.SetCore(c)
// }
// if newSeal != nil && migrationSeal != nil {
// c.migrationInfo = &migrationInformation{
// seal: migrationSeal,
// }
// c.migrationInfo.seal.SetCore(c)
// c.seal = newSeal
// c.seal.SetCore(c)
// c.logger.Warn("entering seal migration mode; Vault will not automatically unseal even if using an autoseal", "from_barrier_type", c.migrationInfo.seal.BarrierType(), "to_barrier_type", c.seal.BarrierType())
// c.initSealsForMigration()
// }
//}

func (c *Core) SetSealsForMigration(migrationSeal, newSeal, unwrapSeal Seal) {
c.stateLock.Lock()
defer c.stateLock.Unlock()

fmt.Printf("test-debug (c *Core) setSealsForMigration %T %T %T\n", migrationSeal, newSeal, unwrapSeal)

c.unwrapSeal = unwrapSeal
if c.unwrapSeal != nil {
c.unwrapSeal.SetCore(c)
Expand Down

0 comments on commit a776452

Please sign in to comment.