Remove the Seal HA beta feature flag (#23820)

This commit is contained in:
Victor Rodriguez
2023-10-27 09:13:06 -04:00
committed by GitHub
parent a76f71cc60
commit 40e9fcde49
7 changed files with 181 additions and 971 deletions

View File

@@ -436,7 +436,7 @@ func (c *OperatorDiagnoseCommand) offlineDiagnostics(ctx context.Context) error
var setSealResponse *SetSealResponse var setSealResponse *SetSealResponse
existingSealGenerationInfo, err := vault.PhysicalSealGenInfo(sealcontext, *backend) existingSealGenerationInfo, err := vault.PhysicalSealGenInfo(sealcontext, *backend)
if err != nil { if err != nil {
diagnose.Fail(sealcontext, fmt.Sprintf("Unable to get Seal genration information from storage: %s.", err.Error())) diagnose.Fail(sealcontext, fmt.Sprintf("Unable to get Seal generation information from storage: %s.", err.Error()))
goto SEALFAIL goto SEALFAIL
} }

View File

@@ -13,6 +13,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/hashicorp/vault/command/server"
"github.com/hashicorp/vault/vault/diagnose" "github.com/hashicorp/vault/vault/diagnose"
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
) )
@@ -172,6 +174,138 @@ func TestOperatorDiagnoseCommand_Run(t *testing.T) {
}, },
}, },
}, },
{
"diagnose_ok_multiseal",
[]string{
"-config", "./server/test-fixtures/config_diagnose_ok.hcl",
},
[]*diagnose.Result{
{
Name: "Parse Configuration",
Status: diagnose.OkStatus,
},
{
Name: "Start Listeners",
Status: diagnose.WarningStatus,
Children: []*diagnose.Result{
{
Name: "Create Listeners",
Status: diagnose.OkStatus,
},
{
Name: "Check Listener TLS",
Status: diagnose.WarningStatus,
Warnings: []string{
"TLS is disabled in a listener config stanza.",
},
},
},
},
{
Name: "Check Storage",
Status: diagnose.OkStatus,
Children: []*diagnose.Result{
{
Name: "Create Storage Backend",
Status: diagnose.OkStatus,
},
{
Name: "Check Consul TLS",
Status: diagnose.SkippedStatus,
},
{
Name: "Check Consul Direct Storage Access",
Status: diagnose.OkStatus,
},
},
},
{
Name: "Check Service Discovery",
Status: diagnose.OkStatus,
Children: []*diagnose.Result{
{
Name: "Check Consul Service Discovery TLS",
Status: diagnose.SkippedStatus,
},
{
Name: "Check Consul Direct Service Discovery",
Status: diagnose.OkStatus,
},
},
},
{
Name: "Create Vault Server Configuration Seals",
// We can't load from storage the existing seal generation info during the test, so we expect an error.
Status: diagnose.ErrorStatus,
},
{
Name: "Create Core Configuration",
Status: diagnose.OkStatus,
Children: []*diagnose.Result{
{
Name: "Initialize Randomness for Core",
Status: diagnose.OkStatus,
},
},
},
{
Name: "HA Storage",
Status: diagnose.OkStatus,
Children: []*diagnose.Result{
{
Name: "Create HA Storage Backend",
Status: diagnose.OkStatus,
},
{
Name: "Check HA Consul Direct Storage Access",
Status: diagnose.OkStatus,
},
{
Name: "Check Consul TLS",
Status: diagnose.SkippedStatus,
},
},
},
{
Name: "Determine Redirect Address",
Status: diagnose.OkStatus,
},
{
Name: "Check Cluster Address",
Status: diagnose.OkStatus,
},
{
Name: "Check Core Creation",
Status: diagnose.OkStatus,
},
{
Name: "Start Listeners",
Status: diagnose.WarningStatus,
Children: []*diagnose.Result{
{
Name: "Create Listeners",
Status: diagnose.OkStatus,
},
{
Name: "Check Listener TLS",
Status: diagnose.WarningStatus,
Warnings: []string{
"TLS is disabled in a listener config stanza.",
},
},
},
},
{
Name: "Check Autounseal Encryption",
Status: diagnose.ErrorStatus,
Message: "Diagnose could not create a barrier seal object.",
},
{
Name: "Check Server Before Runtime",
Status: diagnose.OkStatus,
},
},
},
{ {
"diagnose_raft_problems", "diagnose_raft_problems",
[]string{ []string{
@@ -478,17 +612,23 @@ func TestOperatorDiagnoseCommand_Run(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
tc := tc tc := tc
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() if tc.name == "diagnose_ok" && server.IsMultisealSupported() {
client, closer := testVaultServer(t) t.Skip("Test not valid in ENT")
defer closer() } else if tc.name == "diagnose_ok_multiseal" && !server.IsMultisealSupported() {
cmd := testOperatorDiagnoseCommand(t) t.Skip("Test not valid in community edition")
cmd.client = client } else {
t.Parallel()
client, closer := testVaultServer(t)
defer closer()
cmd := testOperatorDiagnoseCommand(t)
cmd.client = client
cmd.Run(tc.args) cmd.Run(tc.args)
result := cmd.diagnose.Finalize(context.Background()) result := cmd.diagnose.Finalize(context.Background())
if err := compareResults(tc.expected, result.Children); err != nil { if err := compareResults(tc.expected, result.Children); err != nil {
t.Fatalf("Did not find expected test results: %v", err) t.Fatalf("Did not find expected test results: %v", err)
}
} }
}) })
} }

View File

@@ -2626,11 +2626,6 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
} }
sealWrapperInfoKeysMap := make(map[string]infoKeysAndMap) sealWrapperInfoKeysMap := make(map[string]infoKeysAndMap)
sealHaBetaEnabled, err := server.IsSealHABetaEnabled()
if err != nil {
return nil, err
}
configuredSeals := 0 configuredSeals := 0
for _, configSeal := range config.Seals { for _, configSeal := range config.Seals {
sealTypeEnvVarName := "VAULT_SEAL_TYPE" sealTypeEnvVarName := "VAULT_SEAL_TYPE"
@@ -2655,20 +2650,18 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
wrapper = aeadwrapper.NewShamirWrapper() wrapper = aeadwrapper.NewShamirWrapper()
} }
configuredSeals++ configuredSeals++
} else if server.IsMultisealSupported() {
recordSealConfigWarning(fmt.Errorf("error configuring seal: %v", wrapperConfigError))
} else { } else {
if sealHaBetaEnabled { // It seems that we are checking for this particular error here is to distinguish between a
recordSealConfigWarning(fmt.Errorf("error configuring seal: %v", wrapperConfigError)) // mis-configured seal vs one that fails for another reason. Apparently the only other reason is
// a key not found error. It seems the intention is for the key not found error to be returned
// as a seal specific error later
if !errwrap.ContainsType(wrapperConfigError, new(logical.KeyNotFoundError)) {
return nil, fmt.Errorf("error parsing Seal configuration: %s", wrapperConfigError)
} else { } else {
// It seems that we are checking for this particular error here is to distinguish between a sealLogger.Error("error configuring seal", "name", configSeal.Name, "err", wrapperConfigError)
// mis-configured seal vs one that fails for another reason. Apparently the only other reason is recordSealConfigError(wrapperConfigError)
// a key not found error. It seems the intention is for the key not found error to be returned
// as a seal specific error later
if !errwrap.ContainsType(wrapperConfigError, new(logical.KeyNotFoundError)) {
return nil, fmt.Errorf("error parsing Seal configuration: %s", wrapperConfigError)
} else {
sealLogger.Error("error configuring seal", "name", configSeal.Name, "err", wrapperConfigError)
recordSealConfigError(wrapperConfigError)
}
} }
} }
@@ -2725,7 +2718,7 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Compute seal generation // Compute seal generation
sealGenerationInfo, err := c.computeSealGenerationInfo(existingSealGenerationInfo, allSealKmsConfigs, hasPartiallyWrappedPaths, sealHaBetaEnabled) sealGenerationInfo, err := c.computeSealGenerationInfo(existingSealGenerationInfo, allSealKmsConfigs, hasPartiallyWrappedPaths)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -2767,8 +2760,8 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
barrierSeal = vault.NewAutoSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, enabledSealWrappers)) barrierSeal = vault.NewAutoSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, enabledSealWrappers))
unwrapSeal = vault.NewDefaultSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, disabledSealWrappers)) unwrapSeal = vault.NewDefaultSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, disabledSealWrappers))
case sealHaBetaEnabled: case server.IsMultisealSupported():
// We know we are not using Shamir seal, that we are not migrating away from one, and seal HA is enabled, // We know we are not using Shamir seal, that we are not migrating away from one, and multi seal is supported,
// so just put enabled and disabled wrappers on the same seal Access // so just put enabled and disabled wrappers on the same seal Access
allSealWrappers := append(enabledSealWrappers, disabledSealWrappers...) allSealWrappers := append(enabledSealWrappers, disabledSealWrappers...)
barrierSeal = vault.NewAutoSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, allSealWrappers)) barrierSeal = vault.NewAutoSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, allSealWrappers))
@@ -2783,7 +2776,7 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
} }
default: default:
// We know there are multiple enabled seals and that the seal HA beta is not enabled // We know there are multiple enabled seals but multi seal is not supported.
return nil, errors.Join(sealConfigWarning, errors.New("error: more than one enabled seal found")) return nil, errors.Join(sealConfigWarning, errors.New("error: more than one enabled seal found"))
} }
@@ -2795,7 +2788,7 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
}, nil }, nil
} }
func (c *ServerCommand) computeSealGenerationInfo(existingSealGenInfo *vaultseal.SealGenerationInfo, sealConfigs []*configutil.KMS, hasPartiallyWrappedPaths bool, sealHaBetaEnabled bool) (*vaultseal.SealGenerationInfo, error) { func (c *ServerCommand) computeSealGenerationInfo(existingSealGenInfo *vaultseal.SealGenerationInfo, sealConfigs []*configutil.KMS, hasPartiallyWrappedPaths bool) (*vaultseal.SealGenerationInfo, error) {
generation := uint64(1) generation := uint64(1)
if existingSealGenInfo != nil { if existingSealGenInfo != nil {
@@ -2817,7 +2810,7 @@ func (c *ServerCommand) computeSealGenerationInfo(existingSealGenInfo *vaultseal
Seals: sealConfigs, Seals: sealConfigs,
} }
if sealHaBetaEnabled { if server.IsMultisealSupported() {
err := newSealGenInfo.Validate(existingSealGenInfo, hasPartiallyWrappedPaths) err := newSealGenInfo.Validate(existingSealGenInfo, hasPartiallyWrappedPaths)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -7,6 +7,6 @@ package server
//go:generate go run github.com/hashicorp/vault/tools/stubmaker //go:generate go run github.com/hashicorp/vault/tools/stubmaker
func IsSealHABetaEnabled() (bool, error) { func IsMultisealSupported() bool {
return false, nil return false
} }

View File

@@ -1,909 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package command
import (
"os"
"testing"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/vault/seal"
"github.com/hashicorp/vault/internalshared/configutil"
"github.com/stretchr/testify/require"
)
func init() {
if signed := os.Getenv("VAULT_LICENSE_CI"); signed != "" {
os.Setenv(EnvVaultLicense, signed)
}
}
func TestMultiSealCases(t *testing.T) {
cases := []struct {
name string
existingSealGenInfo *seal.SealGenerationInfo
allSealKmsConfigs []*configutil.KMS
expectedSealGenInfo *seal.SealGenerationInfo
isRewrapped bool
hasPartiallyWrappedPaths bool
sealHaBetaEnabled bool
isErrorExpected bool
expectedErrorMsg string
}{
// none_to_shamir
{
name: "none_to_shamir",
existingSealGenInfo: nil,
allSealKmsConfigs: []*configutil.KMS{
{
Type: "shamir",
Name: "shamirSeal1",
Priority: 1,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "shamir",
Name: "shamirSeal1",
Priority: 1,
},
},
},
sealHaBetaEnabled: true,
},
// none_to_auto
{
name: "none_to_auto",
existingSealGenInfo: nil,
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
sealHaBetaEnabled: true,
},
// none_to_multi
{
name: "none_to_multi",
existingSealGenInfo: nil,
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
isErrorExpected: true,
expectedErrorMsg: "Initializing a cluster or enabling multi-seal on an existing cluster must occur with a single seal before adding additional seals",
sealHaBetaEnabled: true,
},
// none_to_multi_with_disabled_seals_with_beta
{
name: "none_to_multi_with_disabled_seals_with_beta",
existingSealGenInfo: nil,
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
Disabled: true,
},
},
isErrorExpected: true,
expectedErrorMsg: "Initializing a cluster or enabling multi-seal on an existing cluster must occur with a single seal before adding additional seals",
sealHaBetaEnabled: true,
},
// none_to_multi_with_disabled_seals_no_beta
{
name: "none_to_multi_with_disabled_seals_no_beta",
existingSealGenInfo: nil,
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
Disabled: true,
},
},
isErrorExpected: false,
sealHaBetaEnabled: false,
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
Disabled: true,
},
},
},
},
// shamir_to_auto
{
name: "shamir_to_auto",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "shamir",
Name: "shamirSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 3,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
isRewrapped: false,
sealHaBetaEnabled: true,
},
// shamir_to_multi
{
name: "shamir_to_multi",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "shamir",
Name: "shamirSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 2,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 3,
},
},
isRewrapped: false,
sealHaBetaEnabled: true,
isErrorExpected: true,
expectedErrorMsg: "cannot add more than one seal",
},
// auto_to_shamir_no_common_seal
{
name: "auto_to_shamir_no_common_seal",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "shamir",
Name: "shamirSeal1",
Priority: 1,
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
isErrorExpected: true,
expectedErrorMsg: "must have at least one seal in common with the old generation",
},
// auto_to_shamir_with_common_seal
{
name: "auto_to_shamir_with_common_seal",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "shamir",
Name: "shamirSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
Disabled: true,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "shamir",
Name: "shamirSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
Disabled: true,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
},
// auto_to_auto_no_common_seal
{
name: "auto_to_auto_no_common_seal",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 1,
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
isErrorExpected: true,
expectedErrorMsg: "must have at least one seal in common with the old generation",
},
// auto_to_auto_with_common_seal
{
name: "auto_to_auto_with_common_seal",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
Disabled: true,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
Disabled: true,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
},
// auto_to_multi_add_one
{
name: "auto_to_multi_add_one",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
},
// auto_to_multi_add_two
{
name: "auto_to_multi_add_two",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
{
Type: "pkcs11",
Name: "autoSeal3",
Priority: 3,
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
isErrorExpected: true,
expectedErrorMsg: "cannot add more than one seal",
},
// multi_to_auto_delete_one
{
name: "multi_to_auto_delete_one",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
},
// multi_to_auto_delete_two
{
name: "multi_to_auto_delete_two",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
{
Type: "pkcs11",
Name: "autoSeal3",
Priority: 3,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
isErrorExpected: true,
expectedErrorMsg: "cannot delete more than one seal",
},
// disable_two_auto
{
name: "disable_two_auto",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
{
Type: "pkcs11",
Name: "autoSeal3",
Priority: 3,
},
},
},
allSealKmsConfigs: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
Disabled: true,
},
{
Type: "pkcs11",
Name: "autoSeal3",
Priority: 3,
Disabled: true,
},
},
expectedSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
Disabled: true,
},
{
Type: "pkcs11",
Name: "autoSeal3",
Priority: 3,
Disabled: true,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
sealHaBetaEnabled: true,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
cmd := &ServerCommand{}
cmd.logger = corehelpers.NewTestLogger(t)
if tc.existingSealGenInfo != nil {
tc.existingSealGenInfo.SetRewrapped(tc.isRewrapped)
}
sealGenInfo, err := cmd.computeSealGenerationInfo(tc.existingSealGenInfo, tc.allSealKmsConfigs, tc.hasPartiallyWrappedPaths, tc.sealHaBetaEnabled)
switch {
case tc.isErrorExpected:
require.Error(t, err)
require.ErrorContains(t, err, tc.expectedErrorMsg)
require.Nil(t, sealGenInfo)
default:
require.NoError(t, err)
require.Equal(t, tc.expectedSealGenInfo, sealGenInfo)
}
})
}
cases2 := []struct {
name string
existingSealGenInfo *seal.SealGenerationInfo
newSealGenInfo *seal.SealGenerationInfo
isRewrapped bool
hasPartiallyWrappedPaths bool
isErrorExpected bool
expectedErrorMsg string
}{
// same_generation_different_seals
{
name: "same_generation_different_seals",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal3",
Priority: 2,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
isErrorExpected: true,
expectedErrorMsg: "existing seal generation is the same, but the configured seals are different",
},
// same_generation_same_seals
{
name: "same_generation_same_seals",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
isErrorExpected: false,
},
// existing seal gen info rewrapped is set to false
{
name: "existing_sgi_rewrapped_false",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
isRewrapped: false,
hasPartiallyWrappedPaths: false,
isErrorExpected: true,
expectedErrorMsg: "cannot make seal config changes while seal re-wrap is in progress, please revert any seal configuration changes",
},
// single seal migration use-case
{
name: "single_seal_migration",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "transit",
Name: "transit",
Priority: 1,
},
},
},
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "transit",
Name: "transit-disabled",
Priority: 1,
Disabled: true,
},
{
Type: "shamir",
Name: "shamir",
Priority: 1,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
isErrorExpected: false,
},
// migrate from non-beta single seal to single seal
{
name: "none_to_single_seal",
existingSealGenInfo: nil,
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "shamir",
Name: "shamir",
Priority: 1,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
isErrorExpected: false,
},
// migrate from non-beta single seal to multi seal, with one disabled, so perform an old style migration
// we do not support this use-case at this time so trap the error
{
name: "none_to_multiple_seals_one_disabled",
existingSealGenInfo: nil,
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal",
},
{
Type: "pkcs11",
Name: "autoSeal",
Disabled: true,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
isErrorExpected: true,
expectedErrorMsg: "Initializing a cluster or enabling multi-seal on an existing cluster must occur with a single seal before adding additional seals",
},
// migrate from non-beta single seal to multi seal
{
name: "none_to_multiple_seals",
existingSealGenInfo: nil,
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
isErrorExpected: true,
expectedErrorMsg: "Initializing a cluster or enabling multi-seal on an existing cluster must occur with a single seal before adding additional seals",
},
// have partially wrapped paths
{
name: "have_partially_wrapped_paths",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: true,
isErrorExpected: true,
expectedErrorMsg: "cannot make seal config changes while seal re-wrap is in progress, please revert any seal configuration changes",
},
// no partially wrapped paths
{
name: "no_partially_wrapped_paths",
existingSealGenInfo: &seal.SealGenerationInfo{
Generation: 2,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
{
Type: "pkcs11",
Name: "autoSeal2",
Priority: 2,
},
},
},
newSealGenInfo: &seal.SealGenerationInfo{
Generation: 1,
Seals: []*configutil.KMS{
{
Type: "pkcs11",
Name: "autoSeal1",
Priority: 1,
},
},
},
isRewrapped: true,
hasPartiallyWrappedPaths: false,
isErrorExpected: false,
},
}
for _, tc := range cases2 {
t.Run(tc.name, func(t *testing.T) {
if tc.existingSealGenInfo != nil {
tc.existingSealGenInfo.SetRewrapped(tc.isRewrapped)
}
err := tc.newSealGenInfo.Validate(tc.existingSealGenInfo, tc.hasPartiallyWrappedPaths)
switch {
case tc.isErrorExpected:
require.Error(t, err)
require.ErrorContains(t, err, tc.expectedErrorMsg)
default:
require.NoError(t, err)
}
})
}
}

View File

@@ -2454,13 +2454,9 @@ func (s standardUnsealStrategy) unseal(ctx context.Context, logger log.Logger, c
return err return err
} }
sealHaEnabled, err := server.IsSealHABetaEnabled() if server.IsMultisealSupported() && !sealGenerationInfo.IsRewrapped() {
if err != nil { // Set the migration done flag so that a seal-rewrap gets triggered later.
return err // Note that in the case where multi seal is not supported, Core.migrateSeal() takes care of
}
if sealHaEnabled && !sealGenerationInfo.IsRewrapped() {
// Flag migration performed for seal-rewrap later
// Note that in the case where seal HA is not enabled, Core.migrateSeal() takes care of
// triggering the rewrap when necessary. // triggering the rewrap when necessary.
c.logger.Trace("seal generation information indicates that a seal-rewrap is needed", "generation", sealGenerationInfo.Generation, "rewrapped", sealGenerationInfo.IsRewrapped()) c.logger.Trace("seal generation information indicates that a seal-rewrap is needed", "generation", sealGenerationInfo.Generation, "rewrapped", sealGenerationInfo.IsRewrapped())
atomic.StoreUint32(c.sealMigrationDone, 1) atomic.StoreUint32(c.sealMigrationDone, 1)
@@ -2880,23 +2876,17 @@ func (c *Core) adjustForSealMigration(unwrapSeal Seal) error {
return err return err
} }
unwrapSeal = NewDefaultSeal(sealAccess) unwrapSeal = NewDefaultSeal(sealAccess)
case configuredType == SealConfigTypeMultiseal && server.IsMultisealSupported():
// 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 nil
case configuredType == SealConfigTypeMultiseal: case configuredType == SealConfigTypeMultiseal:
// The configured seal is multiseal and we know the stored type is not shamir, thus // The configured seal is multiseal and we know the stored type is not shamir, thus
// we are going from auto seal to multiseal. // we are going from auto seal to multiseal.
betaEnabled, err := server.IsSealHABetaEnabled() return fmt.Errorf("cannot seal migrate from %q to %q, multiple seals are not supported",
switch { existBarrierSealConfig.Type, c.seal.BarrierSealConfigType())
case err != nil:
return err
case !betaEnabled:
return fmt.Errorf("cannot seal migrate from %q to %q, Seal High Availability beta is not enabled",
existBarrierSealConfig.Type, c.seal.BarrierSealConfigType())
default:
// We are going from a single non-shamir seal to multiseal, and the seal HA beta is enabled.
// 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 nil
}
case storedType == SealConfigTypeMultiseal: case storedType == SealConfigTypeMultiseal:
// The stored type is multiseal and we know the type the configured type is not shamir, // The stored type is multiseal and we know the type the configured type is not shamir,
// thus we are going from multiseal to autoseal. // thus we are going from multiseal to autoseal.

View File

@@ -342,9 +342,7 @@ func readStoredKeys(ctx context.Context, storage physical.Backend, encryptor sea
} }
func (c *Core) SetPhysicalSealGenInfo(ctx context.Context, sealGenInfo *seal.SealGenerationInfo) error { func (c *Core) SetPhysicalSealGenInfo(ctx context.Context, sealGenInfo *seal.SealGenerationInfo) error {
if enabled, err := server.IsSealHABetaEnabled(); err != nil { if !server.IsMultisealSupported() {
return err
} else if !enabled {
return nil return nil
} }
@@ -372,9 +370,7 @@ func (c *Core) SetPhysicalSealGenInfo(ctx context.Context, sealGenInfo *seal.Sea
} }
func PhysicalSealGenInfo(ctx context.Context, storage physical.Backend) (*seal.SealGenerationInfo, error) { func PhysicalSealGenInfo(ctx context.Context, storage physical.Backend) (*seal.SealGenerationInfo, error) {
if enabled, err := server.IsSealHABetaEnabled(); err != nil { if !server.IsMultisealSupported() {
return nil, err
} else if !enabled {
return nil, nil return nil, nil
} }