mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-05 04:16:31 +02:00
Backport Provide more information around seal migrations into ce/main (#14345)
This commit is contained in:
parent
1d4d9bc61c
commit
ceada1d29a
@ -96,25 +96,26 @@ func sealStatusRequestWithContext(ctx context.Context, c *Sys, r *Request) (*Sea
|
||||
}
|
||||
|
||||
type SealStatusResponse struct {
|
||||
Type string `json:"type"`
|
||||
Initialized bool `json:"initialized"`
|
||||
Sealed bool `json:"sealed"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Nonce string `json:"nonce"`
|
||||
Version string `json:"version"`
|
||||
BuildDate string `json:"build_date"`
|
||||
Migration bool `json:"migration"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
RecoverySeal bool `json:"recovery_seal"`
|
||||
RecoverySealType string `json:"recovery_seal_type,omitempty"`
|
||||
StorageType string `json:"storage_type,omitempty"`
|
||||
HCPLinkStatus string `json:"hcp_link_status,omitempty"`
|
||||
HCPLinkResourceID string `json:"hcp_link_resource_ID,omitempty"`
|
||||
RemovedFromCluster *bool `json:"removed_from_cluster,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Initialized bool `json:"initialized"`
|
||||
Sealed bool `json:"sealed"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Nonce string `json:"nonce"`
|
||||
Version string `json:"version"`
|
||||
BuildDate string `json:"build_date"`
|
||||
Migration bool `json:"migration"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
RecoverySeal bool `json:"recovery_seal"`
|
||||
RecoverySealType string `json:"recovery_seal_type,omitempty"`
|
||||
StorageType string `json:"storage_type,omitempty"`
|
||||
HCPLinkStatus string `json:"hcp_link_status,omitempty"`
|
||||
HCPLinkResourceID string `json:"hcp_link_resource_ID,omitempty"`
|
||||
RemovedFromCluster *bool `json:"removed_from_cluster,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
MigrationDoneAtEpoch int64 `json:"migration_done_at_epoch,omitempty"`
|
||||
}
|
||||
|
||||
type UnsealOpts struct {
|
||||
|
||||
3
changelog/_14334.txt
Normal file
3
changelog/_14334.txt
Normal file
@ -0,0 +1,3 @@
|
||||
```release-note:improvement
|
||||
api: Add migration_done_at_epoch to sys/seal-status response.
|
||||
```
|
||||
@ -1337,7 +1337,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
|
||||
|
||||
// For recovery mode we've now configured enough to return early.
|
||||
if c.recoveryMode {
|
||||
checkResult, err := c.checkForSealMigration(context.Background(), conf.UnwrapSeal)
|
||||
checkResult, _, err := c.checkForSealMigration(context.Background(), conf.UnwrapSeal)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error checking if a seal migration is needed: %w", err)
|
||||
}
|
||||
@ -1840,7 +1840,7 @@ func (c *Core) unsealFragment(key []byte, migrate bool) error {
|
||||
return fmt.Errorf("can't perform a seal migration while joining a raft cluster")
|
||||
}
|
||||
if !migrate && c.migrationInfo != nil {
|
||||
done, err := c.sealMigrated(ctx)
|
||||
done, _, err := c.sealMigrated(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking to see if seal is migrated: %w", err)
|
||||
}
|
||||
@ -2072,26 +2072,28 @@ func (c *Core) getUnsealKey(ctx context.Context, seal Seal) ([]byte, error) {
|
||||
// For the auto->auto same seal migration scenario, it will return false even
|
||||
// if the preceding conditions are true but we cannot decrypt the master key
|
||||
// in storage using the configured seal.
|
||||
func (c *Core) sealMigrated(ctx context.Context) (bool, error) {
|
||||
// When no error is returned, returns a string that gives more information about
|
||||
// why the bool return value is set as it is.
|
||||
func (c *Core) sealMigrated(ctx context.Context) (bool, string, error) {
|
||||
sealMigDone := c.sealMigrationDone.Load()
|
||||
if sealMigDone != nil && !sealMigDone.IsZero() {
|
||||
return true, nil
|
||||
return true, "sealMigrationDone nonzero", nil
|
||||
}
|
||||
|
||||
existBarrierSealConfig, existRecoverySealConfig, err := c.PhysicalSealConfigs(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, "", err
|
||||
}
|
||||
|
||||
if !c.seal.BarrierSealConfigType().IsSameAs(existBarrierSealConfig.Type) {
|
||||
return false, nil
|
||||
return false, "barrier seal config type in seal matches what's in storage", nil
|
||||
}
|
||||
if c.seal.RecoveryKeySupported() && !SealConfigTypeRecovery.IsSameAs(existRecoverySealConfig.Type) {
|
||||
return false, nil
|
||||
return false, "recovery seal config type in seal matches what's in storage", nil
|
||||
}
|
||||
|
||||
if c.seal.BarrierSealConfigType() != c.migrationInfo.seal.BarrierSealConfigType() {
|
||||
return true, nil
|
||||
return true, "barrier seal config type in seal doesn't match what's in storage", nil
|
||||
}
|
||||
|
||||
// The above checks can handle the auto->shamir and shamir->auto
|
||||
@ -2103,13 +2105,13 @@ func (c *Core) sealMigrated(ctx context.Context) (bool, error) {
|
||||
|
||||
switch {
|
||||
case len(keys) > 0 && err == nil:
|
||||
return true, nil
|
||||
return true, "seal has stored keys", nil
|
||||
case len(keysMig) > 0 && errMig == nil:
|
||||
return false, nil
|
||||
return false, "migration seal has stored keys", nil
|
||||
case errors.Is(err, &ErrDecrypt{}) && errors.Is(errMig, &ErrDecrypt{}):
|
||||
return false, fmt.Errorf("decrypt error, neither the old nor new seal can read stored keys: old seal err=%v, new seal err=%v", errMig, err)
|
||||
return false, "", fmt.Errorf("decrypt error, neither the old nor new seal can read stored keys: old seal err=%v, new seal err=%v", errMig, err)
|
||||
default:
|
||||
return false, fmt.Errorf("neither the old nor new seal can read stored keys: old seal err=%v, new seal err=%v", errMig, err)
|
||||
return false, "", fmt.Errorf("neither the old nor new seal can read stored keys: old seal err=%v, new seal err=%v", errMig, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2121,17 +2123,17 @@ func (c *Core) migrateSeal(ctx context.Context) error {
|
||||
return c.migrateMultiSealConfig(ctx)
|
||||
}
|
||||
|
||||
ok, err := c.sealMigrated(ctx)
|
||||
ok, info, err := c.sealMigrated(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking if seal is migrated or not: %w", err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
c.logger.Info("migration is already performed")
|
||||
c.logger.Info("migration is already performed", "info", info)
|
||||
return nil
|
||||
}
|
||||
|
||||
c.logger.Info("seal migration initiated")
|
||||
c.logger.Info("seal migration initiated", "info", info)
|
||||
|
||||
switch {
|
||||
case c.migrationInfo.seal.RecoveryKeySupported() && c.seal.RecoveryKeySupported():
|
||||
@ -3345,16 +3347,16 @@ const (
|
||||
sealMigrationCheckDoNotAjust
|
||||
)
|
||||
|
||||
func (c *Core) checkForSealMigration(ctx context.Context, unwrapSeal Seal) (sealMigrationCheckResult, error) {
|
||||
func (c *Core) checkForSealMigration(ctx context.Context, unwrapSeal Seal) (sealMigrationCheckResult, string, error) {
|
||||
existBarrierSealConfig, _, err := c.PhysicalSealConfigs(ctx)
|
||||
if err != nil {
|
||||
return sealMigrationCheckError, fmt.Errorf("Error checking for existing seal: %s", err)
|
||||
return sealMigrationCheckError, "", 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 == WrapperTypeHsmAutoDeprecated.String() {
|
||||
return sealMigrationCheckSkip, nil
|
||||
return sealMigrationCheckSkip, "no seal config or deprecated", nil
|
||||
}
|
||||
|
||||
if unwrapSeal == nil {
|
||||
@ -3368,28 +3370,28 @@ func (c *Core) checkForSealMigration(ctx context.Context, unwrapSeal Seal) (seal
|
||||
case storedType == configuredType:
|
||||
// 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.
|
||||
return sealMigrationCheckDoNotAjust, nil
|
||||
return sealMigrationCheckDoNotAjust, "same barrier and unwrap seal is nil", nil
|
||||
case configuredType == SealConfigTypeShamir:
|
||||
// The stored barrier config is not shamir, there is no disabled seal
|
||||
// in config, and either no configured seal (which equates to Shamir)
|
||||
// or an explicitly configured Shamir seal.
|
||||
return sealMigrationCheckError, fmt.Errorf("cannot seal migrate from %q to Shamir, no disabled seal in configuration",
|
||||
return sealMigrationCheckError, "", fmt.Errorf("cannot seal migrate from %q to Shamir, no disabled seal in configuration",
|
||||
existBarrierSealConfig.Type)
|
||||
case storedType == SealConfigTypeShamir:
|
||||
// The configured seal is not Shamir, the stored seal config is Shamir.
|
||||
// This is a migration away from Shamir.
|
||||
|
||||
return sealMigrationCheckAdjust, nil
|
||||
return sealMigrationCheckAdjust, "configured seal is not shamir and stored seal config is", nil
|
||||
case configuredType == SealConfigTypeMultiseal && c.IsMultisealEnabled():
|
||||
// We are going from a single non-shamir seal to multiseal, and multi seal is supported.
|
||||
// This scenario is not considered a migration in the sense of requiring an unwrapSeal,
|
||||
// but we will update the stored SealConfig later (see Core.migrateMultiSealConfig).
|
||||
|
||||
return sealMigrationCheckDoNotAjust, nil
|
||||
return sealMigrationCheckDoNotAjust, "single non-shamir to multiseal", nil
|
||||
case configuredType == SealConfigTypeMultiseal:
|
||||
// The configured seal is multiseal and we know the stored type is not shamir, thus
|
||||
// we are going from auto seal to multiseal.
|
||||
return sealMigrationCheckError, fmt.Errorf("cannot seal migrate from %q to %q, multiple seals are not supported",
|
||||
return sealMigrationCheckError, "", fmt.Errorf("cannot seal migrate from %q to %q, multiple seals are not supported",
|
||||
existBarrierSealConfig.Type, c.seal.BarrierSealConfigType())
|
||||
case storedType == SealConfigTypeMultiseal:
|
||||
// The stored type is multiseal and we know the type the configured type is not shamir,
|
||||
@ -3398,12 +3400,12 @@ func (c *Core) checkForSealMigration(ctx context.Context, unwrapSeal Seal) (seal
|
||||
// This scenario is not considered a migration in the sense of requiring an unwrapSeal,
|
||||
// but we will update the stored SealConfig later (see Core.migrateMultiSealConfig).
|
||||
|
||||
return sealMigrationCheckDoNotAjust, nil
|
||||
return sealMigrationCheckDoNotAjust, "multiseal to autoseal", nil
|
||||
default:
|
||||
// We know at this point that there is a configured non-Shamir seal,
|
||||
// that it does not match the stored non-Shamir seal config, and that
|
||||
// there is no explicitly disabled seal stanza.
|
||||
return sealMigrationCheckError, fmt.Errorf("cannot seal migrate from %q to %q, no disabled seal in configuration",
|
||||
return sealMigrationCheckError, "", fmt.Errorf("cannot seal migrate from %q to %q, no disabled seal in configuration",
|
||||
existBarrierSealConfig.Type, c.seal.BarrierSealConfigType())
|
||||
}
|
||||
} else {
|
||||
@ -3411,9 +3413,9 @@ func (c *Core) checkForSealMigration(ctx context.Context, unwrapSeal Seal) (seal
|
||||
// in the config and disabled.
|
||||
|
||||
if unwrapSeal.BarrierSealConfigType() == SealConfigTypeShamir {
|
||||
return sealMigrationCheckError, errors.New("Shamir seals cannot be set disabled (they should simply not be set)")
|
||||
return sealMigrationCheckError, "", errors.New("Shamir seals cannot be set disabled (they should simply not be set)")
|
||||
}
|
||||
return sealMigrationCheckDoNotAjust, nil
|
||||
return sealMigrationCheckDoNotAjust, "unchanged", nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -3439,7 +3441,7 @@ func (c *Core) checkForSealMigration(ctx context.Context, unwrapSeal Seal) (seal
|
||||
func (c *Core) adjustForSealMigration(unwrapSeal Seal) error {
|
||||
ctx := context.Background()
|
||||
|
||||
checkResult, err := c.checkForSealMigration(ctx, unwrapSeal)
|
||||
checkResult, _, err := c.checkForSealMigration(ctx, unwrapSeal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -3723,7 +3725,7 @@ func (c *Core) IsSealMigrated(lock bool) bool {
|
||||
c.stateLock.RLock()
|
||||
defer c.stateLock.RUnlock()
|
||||
}
|
||||
done, _ := c.sealMigrated(context.Background())
|
||||
done, _, _ := c.sealMigrated(context.Background())
|
||||
return done
|
||||
}
|
||||
|
||||
|
||||
@ -6026,25 +6026,26 @@ func (b *SystemBackend) pathInternalOpenAPI(ctx context.Context, req *logical.Re
|
||||
}
|
||||
|
||||
type SealStatusResponse struct {
|
||||
Type string `json:"type"`
|
||||
Initialized bool `json:"initialized"`
|
||||
Sealed bool `json:"sealed"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Nonce string `json:"nonce"`
|
||||
Version string `json:"version"`
|
||||
BuildDate string `json:"build_date"`
|
||||
Migration bool `json:"migration"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
RecoverySeal bool `json:"recovery_seal"`
|
||||
StorageType string `json:"storage_type,omitempty"`
|
||||
HCPLinkStatus string `json:"hcp_link_status,omitempty"`
|
||||
HCPLinkResourceID string `json:"hcp_link_resource_ID,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
RecoverySealType string `json:"recovery_seal_type,omitempty"`
|
||||
RemovedFromCluster *bool `json:"removed_from_cluster,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Initialized bool `json:"initialized"`
|
||||
Sealed bool `json:"sealed"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Nonce string `json:"nonce"`
|
||||
Version string `json:"version"`
|
||||
BuildDate string `json:"build_date"`
|
||||
Migration bool `json:"migration"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
RecoverySeal bool `json:"recovery_seal"`
|
||||
StorageType string `json:"storage_type,omitempty"`
|
||||
HCPLinkStatus string `json:"hcp_link_status,omitempty"`
|
||||
HCPLinkResourceID string `json:"hcp_link_resource_ID,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
RecoverySealType string `json:"recovery_seal_type,omitempty"`
|
||||
RemovedFromCluster *bool `json:"removed_from_cluster,omitempty"`
|
||||
MigrationDoneAtEpoch int64 `json:"migration_done_at_epoch,omitempty"`
|
||||
}
|
||||
|
||||
type SealBackendStatus struct {
|
||||
@ -6157,6 +6158,9 @@ func (core *Core) GetSealStatus(ctx context.Context, lock bool) (*SealStatusResp
|
||||
RecoverySealType: recoverySealType,
|
||||
StorageType: core.StorageType(),
|
||||
}
|
||||
if p := core.sealMigrationDone.Load(); p != nil {
|
||||
s.MigrationDoneAtEpoch = p.Unix()
|
||||
}
|
||||
|
||||
if resourceIDonHCP != "" {
|
||||
s.HCPLinkStatus = hcpLinkStatus
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user