mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 17:52:32 +00:00
* Unseal HA changes, CE side * Transit wrapper update
This commit is contained in:
@@ -1275,6 +1275,9 @@ func (c *ServerCommand) Run(args []string) int {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
if setSealResponse.sealConfigWarning != nil {
|
||||
c.UI.Warn(fmt.Sprintf("Warnings during seal configuration: %v", setSealResponse.sealConfigWarning))
|
||||
}
|
||||
|
||||
for _, seal := range setSealResponse.getCreatedSeals() {
|
||||
seal := seal // capture range variable
|
||||
@@ -2557,7 +2560,8 @@ type SetSealResponse struct {
|
||||
unwrapSeal vault.Seal
|
||||
|
||||
// sealConfigError is present if there was an error configuring wrappers, other than KeyNotFound.
|
||||
sealConfigError error
|
||||
sealConfigError error
|
||||
sealConfigWarning error
|
||||
}
|
||||
|
||||
func (r *SetSealResponse) getCreatedSeals() []*vault.Seal {
|
||||
@@ -2602,9 +2606,13 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
}
|
||||
|
||||
var sealConfigError error
|
||||
var sealConfigWarning error
|
||||
recordSealConfigError := func(err error) {
|
||||
sealConfigError = errors.Join(sealConfigError, err)
|
||||
}
|
||||
recordSealConfigWarning := func(err error) {
|
||||
sealConfigWarning = errors.Join(sealConfigWarning, err)
|
||||
}
|
||||
enabledSealWrappers := make([]*vaultseal.SealWrapper, 0)
|
||||
disabledSealWrappers := make([]*vaultseal.SealWrapper, 0)
|
||||
allSealKmsConfigs := make([]*configutil.KMS, 0)
|
||||
@@ -2615,6 +2623,7 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
}
|
||||
sealWrapperInfoKeysMap := make(map[string]infoKeysAndMap)
|
||||
|
||||
configuredSeals := 0
|
||||
for _, configSeal := range config.Seals {
|
||||
sealTypeEnvVarName := "VAULT_SEAL_TYPE"
|
||||
if configSeal.Priority > 1 {
|
||||
@@ -2628,24 +2637,18 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
|
||||
sealLogger := c.logger.ResetNamed(fmt.Sprintf("seal.%s", configSeal.Type))
|
||||
|
||||
allSealKmsConfigs = append(allSealKmsConfigs, configSeal)
|
||||
var wrapperInfoKeys []string
|
||||
wrapperInfoMap := map[string]string{}
|
||||
wrapper, wrapperConfigError := configutil.ConfigureWrapper(configSeal, &wrapperInfoKeys, &wrapperInfoMap, sealLogger)
|
||||
if wrapperConfigError != nil {
|
||||
// It seems that we are checking for this particular error here is to distinguish between a
|
||||
// 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 {
|
||||
sealLogger.Error("error configuring seal", "name", configSeal.Name, "err", wrapperConfigError)
|
||||
recordSealConfigError(wrapperConfigError)
|
||||
if wrapperConfigError == nil {
|
||||
// for some reason configureWrapper in kms.go returns nil wrapper and nil error for wrapping.WrapperTypeShamir
|
||||
if wrapper == nil {
|
||||
wrapper = aeadwrapper.NewShamirWrapper()
|
||||
}
|
||||
}
|
||||
// for some reason configureWrapper in kms.go returns nil wrapper and nil error for wrapping.WrapperTypeShamir
|
||||
if wrapper == nil && wrapperConfigError == nil {
|
||||
wrapper = aeadwrapper.NewShamirWrapper()
|
||||
configuredSeals++
|
||||
} else {
|
||||
recordSealConfigWarning(fmt.Errorf("error configuring seal: %v", wrapperConfigError))
|
||||
}
|
||||
|
||||
sealWrapper := vaultseal.NewSealWrapper(
|
||||
@@ -2654,6 +2657,7 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
configSeal.Name,
|
||||
configSeal.Type,
|
||||
configSeal.Disabled,
|
||||
wrapperConfigError == nil,
|
||||
)
|
||||
|
||||
if configSeal.Disabled {
|
||||
@@ -2661,7 +2665,6 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
} else {
|
||||
enabledSealWrappers = append(enabledSealWrappers, sealWrapper)
|
||||
}
|
||||
allSealKmsConfigs = append(allSealKmsConfigs, configSeal)
|
||||
|
||||
sealWrapperInfoKeysMap[sealWrapper.Name] = infoKeysAndMap{
|
||||
keys: wrapperInfoKeys,
|
||||
@@ -2669,6 +2672,12 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
}
|
||||
}
|
||||
|
||||
if len(enabledSealWrappers) == 0 && len(disabledSealWrappers) == 0 && sealConfigWarning != nil {
|
||||
// All of them errored out, so warnings are now errors
|
||||
recordSealConfigError(sealConfigWarning)
|
||||
sealConfigWarning = nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Set the info keys, this modifies the function arguments `info` and `infoKeys`
|
||||
// TODO(SEALHA): Why are we doing this? What is its use?
|
||||
@@ -2724,10 +2733,11 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
sealLogger := c.logger
|
||||
switch {
|
||||
case len(enabledSealWrappers) == 0:
|
||||
return nil, errors.New("no enabled Seals in configuration")
|
||||
|
||||
return nil, errors.Join(sealConfigWarning, errors.New("no enabled Seals in configuration"))
|
||||
case configuredSeals == 0:
|
||||
return nil, errors.Join(sealConfigWarning, errors.New("no seals were successfully initialized"))
|
||||
case containsShamir(enabledSealWrappers) && containsShamir(disabledSealWrappers):
|
||||
return nil, errors.New("shamir seals cannot be set disabled (they should simply not be set)")
|
||||
return nil, errors.Join(sealConfigWarning, errors.New("shamir seals cannot be set disabled (they should simply not be set)"))
|
||||
|
||||
case len(enabledSealWrappers) == 1 && containsShamir(enabledSealWrappers):
|
||||
// The barrier seal is Shamir. If there are any disabled seals, then we put them all in the same
|
||||
@@ -2747,7 +2757,9 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
// so just put enabled and disabled wrappers on the same seal Access
|
||||
allSealWrappers := append(enabledSealWrappers, disabledSealWrappers...)
|
||||
barrierSeal = vault.NewAutoSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, allSealWrappers))
|
||||
|
||||
if configuredSeals < len(enabledSealWrappers) {
|
||||
c.UI.Warn("WARNING: running with fewer than all configured seals during unseal. Will not be fully highly available until errors are corrected and Vault restarted.")
|
||||
}
|
||||
case len(enabledSealWrappers) == 1:
|
||||
// We may have multiple seals disabled, but we know Shamir is not one of them.
|
||||
barrierSeal = vault.NewAutoSeal(vaultseal.NewAccess(sealLogger, sealGenerationInfo, enabledSealWrappers))
|
||||
@@ -2757,13 +2769,14 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
|
||||
|
||||
default:
|
||||
// We know there are multiple enabled seals and that the seal HA beta is not enabled
|
||||
return nil, errors.New("error: more than one enabled seal found")
|
||||
return nil, errors.Join(sealConfigWarning, errors.New("error: more than one enabled seal found"))
|
||||
}
|
||||
|
||||
return &SetSealResponse{
|
||||
barrierSeal: barrierSeal,
|
||||
unwrapSeal: unwrapSeal,
|
||||
sealConfigError: sealConfigError,
|
||||
barrierSeal: barrierSeal,
|
||||
unwrapSeal: unwrapSeal,
|
||||
sealConfigError: sealConfigError,
|
||||
sealConfigWarning: sealConfigWarning,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
2
go.mod
2
go.mod
@@ -92,7 +92,7 @@ require (
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.8
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.8
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2 v2.0.7
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.7
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.8
|
||||
github.com/hashicorp/go-memdb v1.3.4
|
||||
github.com/hashicorp/go-msgpack v1.1.5
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1994,8 +1994,8 @@ github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.8 h1:16I8OqBEuxZIo
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/gcpckms/v2 v2.0.8/go.mod h1:6QUMo5BrXAtbzSuZilqmx0A4px2u6PeFK7vfp2WIzeM=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2 v2.0.7 h1:KeG3QGrbxbr2qAqCJdf3NR4ijAYwdcWLTmwSbR0yusM=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/ocikms/v2 v2.0.7/go.mod h1:rXxYzjjGw4HltEwxPp9zYSRIo6R+rBf1MSPk01bvodc=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.7 h1:G25tZFw/LrAzJWxvS0/BFI7V1xAP/UsAIsgBwiE0mwo=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.7/go.mod h1:hxNA5oTfAvwPacWVg1axtF/lvTafwlAa6a6K4uzWHhw=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.8 h1:uvdmC28xaqklqRQ3HWvq9HP4jX7Vy4M5JrJqAxfo5ig=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.8/go.mod h1:zHX8LhkrU/M8sJkIQ85Dsrg7aqNEonY1+l6MlUC+6O4=
|
||||
github.com/hashicorp/go-memdb v1.3.4 h1:XSL3NR682X/cVk2IeV0d70N4DZ9ljI885xAEU8IoK3c=
|
||||
github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg=
|
||||
github.com/hashicorp/go-metrics v0.5.1 h1:rfPwUqFU6uZXNvGl4hzjY8LEBsqFVU4si1H9/Hqck/U=
|
||||
|
||||
@@ -388,7 +388,17 @@ func GetOCIKMSKMSFunc(kms *KMS, opts ...wrapping.Option) (wrapping.Wrapper, map[
|
||||
|
||||
var GetTransitKMSFunc = func(kms *KMS, opts ...wrapping.Option) (wrapping.Wrapper, map[string]string, error) {
|
||||
wrapper := transit.NewWrapper()
|
||||
wrapperInfo, err := wrapper.SetConfig(context.Background(), append(opts, wrapping.WithDisallowEnvVars(true), wrapping.WithConfigMap(kms.Config))...)
|
||||
var prefix string
|
||||
if p, ok := kms.Config["key_id_prefix"]; ok {
|
||||
prefix = p
|
||||
} else {
|
||||
prefix = kms.Name
|
||||
}
|
||||
if !strings.HasSuffix(prefix, "/") {
|
||||
prefix = prefix + "/"
|
||||
}
|
||||
wrapperInfo, err := wrapper.SetConfig(context.Background(), append(opts, wrapping.WithDisallowEnvVars(true), wrapping.WithConfigMap(kms.Config),
|
||||
transit.WithKeyIdPrefix(prefix))...)
|
||||
if err != nil {
|
||||
// If the error is any other than logical.KeyNotFoundError, return the error
|
||||
if !errwrap.ContainsType(err, new(logical.KeyNotFoundError)) {
|
||||
|
||||
@@ -5027,7 +5027,7 @@ func (c *Core) GetSealBackendStatus(ctx context.Context) (*SealBackendStatusResp
|
||||
if a, ok := c.seal.(*autoSeal); ok {
|
||||
r.Healthy = c.seal.Healthy()
|
||||
var uhMin time.Time
|
||||
for _, sealWrapper := range a.GetAllSealWrappersByPriority() {
|
||||
for _, sealWrapper := range a.GetConfiguredSealWrappersByPriority() {
|
||||
b := SealBackendStatus{
|
||||
Name: sealWrapper.Name,
|
||||
Healthy: sealWrapper.IsHealthy(),
|
||||
|
||||
@@ -6272,6 +6272,7 @@ func TestGetSealBackendStatus(t *testing.T) {
|
||||
Wrapper: aeadwrapper.NewShamirWrapper(),
|
||||
SealConfigType: wrapping.WrapperTypeShamir.String(),
|
||||
Priority: 1,
|
||||
Configured: true,
|
||||
},
|
||||
},
|
||||
))
|
||||
|
||||
@@ -405,7 +405,7 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
|
||||
if err != nil {
|
||||
return nil, logical.CodedError(http.StatusInternalServerError, fmt.Errorf("failed to setup test seal: %w", err).Error())
|
||||
}
|
||||
access.GetAllSealWrappersByPriority()[0].Name = existingConfig.Name
|
||||
access.GetConfiguredSealWrappersByPriority()[0].Name = existingConfig.Name
|
||||
|
||||
testseal := NewDefaultSeal(access)
|
||||
testseal.SetCore(c)
|
||||
|
||||
@@ -34,6 +34,11 @@ const (
|
||||
StoredKeysSupportedShamirRoot
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnconfiguredWrapper = errors.New("unconfigured wrapper")
|
||||
ErrNoHealthySeals = errors.New("no healthy seals!")
|
||||
)
|
||||
|
||||
func (s StoredKeysSupport) String() string {
|
||||
switch s {
|
||||
case StoredKeysNotSupported:
|
||||
@@ -204,9 +209,12 @@ type Access interface {
|
||||
SetShamirSealKey([]byte) error
|
||||
GetShamirKeyBytes(ctx context.Context) ([]byte, error)
|
||||
|
||||
// GetAllSealWrappersByPriority returns all the SealWrapper for all the seal wrappers, including disabled ones.
|
||||
// GetConfiguredSealWrappersByPriority returns all the SealWrappers including disabled and unconfigured wrappers.
|
||||
GetAllSealWrappersByPriority() []*SealWrapper
|
||||
|
||||
// GetConfiguredSealWrappersByPriority returns all the configured SealWrappers for all the seal wrappers, including disabled ones.
|
||||
GetConfiguredSealWrappersByPriority() []*SealWrapper
|
||||
|
||||
// GetEnabledSealWrappersByPriority returns the SealWrapper for the enabled seal wrappers.
|
||||
GetEnabledSealWrappersByPriority() []*SealWrapper
|
||||
|
||||
@@ -274,46 +282,60 @@ func NewAccessFromSealWrappers(logger hclog.Logger, generation uint64, rewrapped
|
||||
// The SealWrapper created uses the seal config type as the name, has priority set to 1 and the
|
||||
// disabled flag set to false.
|
||||
func NewAccessFromWrapper(logger hclog.Logger, wrapper wrapping.Wrapper, sealConfigType string) (Access, error) {
|
||||
sealWrapper := NewSealWrapper(wrapper, 1, sealConfigType, sealConfigType, false)
|
||||
sealWrapper := NewSealWrapper(wrapper, 1, sealConfigType, sealConfigType, false, true)
|
||||
|
||||
return NewAccessFromSealWrappers(logger, 1, true, []*SealWrapper{sealWrapper})
|
||||
}
|
||||
|
||||
func (a *access) GetAllSealWrappersByPriority() []*SealWrapper {
|
||||
return a.filterSealWrappers(enabledAndDisabled, healthyAndUnhealthy)
|
||||
return a.filterSealWrappers(allWrappers)
|
||||
}
|
||||
|
||||
func (a *access) GetConfiguredSealWrappersByPriority() []*SealWrapper {
|
||||
return a.filterSealWrappers(configuredWrappers, allWrappers)
|
||||
}
|
||||
|
||||
func (a *access) GetEnabledSealWrappersByPriority() []*SealWrapper {
|
||||
return a.filterSealWrappers(enabledOnly, healthyAndUnhealthy)
|
||||
return a.filterSealWrappers(configuredWrappers, enabledWrappers)
|
||||
}
|
||||
|
||||
func (a *access) AllSealWrappersHealthy() bool {
|
||||
return len(a.wrappersByPriority) == len(a.filterSealWrappers(enabledAndDisabled, healthyOnly))
|
||||
return len(a.wrappersByPriority) == len(a.filterSealWrappers(configuredWrappers, healthyWrappers))
|
||||
}
|
||||
|
||||
type (
|
||||
enabledFilter bool
|
||||
healthyFilter bool
|
||||
)
|
||||
type sealWrapperFilter func(*SealWrapper) bool
|
||||
|
||||
const (
|
||||
enabledOnly = enabledFilter(true)
|
||||
enabledAndDisabled = !enabledOnly
|
||||
healthyOnly = healthyFilter(true)
|
||||
healthyAndUnhealthy = !healthyOnly
|
||||
)
|
||||
func allWrappers(wrapper *SealWrapper) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *access) filterSealWrappers(enabled enabledFilter, healthy healthyFilter) []*SealWrapper {
|
||||
ret := make([]*SealWrapper, 0, len(a.wrappersByPriority))
|
||||
for _, sw := range a.wrappersByPriority {
|
||||
switch {
|
||||
case enabled == enabledOnly && sw.Disabled:
|
||||
continue
|
||||
case healthy == healthyOnly && !sw.IsHealthy():
|
||||
continue
|
||||
default:
|
||||
ret = append(ret, sw)
|
||||
func healthyWrappers(wrapper *SealWrapper) bool {
|
||||
return wrapper.IsHealthy()
|
||||
}
|
||||
|
||||
func enabledWrappers(wrapper *SealWrapper) bool {
|
||||
return !wrapper.Disabled
|
||||
}
|
||||
|
||||
func configuredWrappers(wrapper *SealWrapper) bool {
|
||||
return wrapper.Configured
|
||||
}
|
||||
|
||||
// Returns a slice of wrappers who satisfy all filters
|
||||
func (a *access) filterSealWrappers(filters ...sealWrapperFilter) []*SealWrapper {
|
||||
return filterSealWrappers(a.wrappersByPriority, filters...)
|
||||
}
|
||||
|
||||
func filterSealWrappers(wrappers []*SealWrapper, filters ...sealWrapperFilter) []*SealWrapper {
|
||||
ret := make([]*SealWrapper, 0, len(wrappers))
|
||||
outer:
|
||||
for _, sw := range wrappers {
|
||||
for _, f := range filters {
|
||||
if !f(sw) {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
ret = append(ret, sw)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@@ -336,7 +358,7 @@ func (a *access) GetEnabledWrappers() []wrapping.Wrapper {
|
||||
|
||||
func (a *access) Init(ctx context.Context, options ...wrapping.Option) error {
|
||||
var keyIds []string
|
||||
for _, sealWrapper := range a.GetAllSealWrappersByPriority() {
|
||||
for _, sealWrapper := range a.GetConfiguredSealWrappersByPriority() {
|
||||
if initWrapper, ok := sealWrapper.Wrapper.(wrapping.InitFinalizer); ok {
|
||||
if err := initWrapper.Init(ctx, options...); err != nil {
|
||||
return err
|
||||
@@ -390,11 +412,12 @@ const (
|
||||
// Encrypt uses the underlying seal to encrypt the plaintext and returns it.
|
||||
func (a *access) Encrypt(ctx context.Context, plaintext []byte, options ...wrapping.Option) (*MultiWrapValue, map[string]error) {
|
||||
// Note that we do not encrypt with disabled wrappers. Disabled wrappers are only used to decrypt.
|
||||
enabledWrappersByPriority := a.filterSealWrappers(enabledOnly, healthyOnly)
|
||||
if len(enabledWrappersByPriority) == 0 {
|
||||
candidateWrappers := a.filterSealWrappers(enabledWrappers, healthyWrappers)
|
||||
if len(candidateWrappers) == 0 {
|
||||
// If all seals are unhealthy, try any way since a seal may have recovered
|
||||
enabledWrappersByPriority = a.filterSealWrappers(enabledOnly, healthyAndUnhealthy)
|
||||
candidateWrappers = a.filterSealWrappers(enabledWrappers)
|
||||
}
|
||||
enabledWrappersByPriority := filterSealWrappers(candidateWrappers, configuredWrappers)
|
||||
|
||||
type result struct {
|
||||
name string
|
||||
@@ -474,6 +497,13 @@ GATHER_RESULTS:
|
||||
a.keyIdSet.set(ret)
|
||||
}
|
||||
|
||||
// Add errors for unconfigured wrappers
|
||||
for _, sw := range candidateWrappers {
|
||||
if !sw.Configured {
|
||||
errs[sw.Name] = ErrUnconfiguredWrapper
|
||||
}
|
||||
}
|
||||
|
||||
return ret, errs
|
||||
}
|
||||
|
||||
@@ -520,10 +550,13 @@ func (a *access) Decrypt(ctx context.Context, ciphertext *MultiWrapValue, option
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
wrappersByPriority := a.filterSealWrappers(enabledAndDisabled, healthyOnly)
|
||||
wrappersByPriority := a.filterSealWrappers(configuredWrappers, healthyWrappers)
|
||||
if len(wrappersByPriority) == 0 {
|
||||
// If all seals are unhealthy, try any way since a seal may have recovered
|
||||
wrappersByPriority = a.filterSealWrappers(enabledAndDisabled, healthyAndUnhealthy)
|
||||
wrappersByPriority = a.filterSealWrappers(configuredWrappers)
|
||||
}
|
||||
if len(wrappersByPriority) == 0 {
|
||||
return nil, false, ErrNoHealthySeals
|
||||
}
|
||||
|
||||
type result struct {
|
||||
@@ -534,23 +567,45 @@ func (a *access) Decrypt(ctx context.Context, ciphertext *MultiWrapValue, option
|
||||
}
|
||||
resultCh := make(chan *result)
|
||||
|
||||
decrypt := func(sealWrapper *SealWrapper) {
|
||||
pt, oldKey, err := a.tryDecrypt(ctx, sealWrapper, blobInfoMap, options)
|
||||
reportResult := func(name string, plaintext []byte, oldKey bool, err error) {
|
||||
resultCh <- &result{
|
||||
name: sealWrapper.Name,
|
||||
pt: pt,
|
||||
name: name,
|
||||
pt: plaintext,
|
||||
oldKey: oldKey,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
decrypt := func(sealWrapper *SealWrapper) {
|
||||
pt, oldKey, err := a.tryDecrypt(ctx, sealWrapper, blobInfoMap, options)
|
||||
reportResult(sealWrapper.Name, pt, oldKey, err)
|
||||
}
|
||||
|
||||
// Start goroutines to decrypt the value
|
||||
for i, sealWrapper := range wrappersByPriority {
|
||||
|
||||
first := wrappersByPriority[0]
|
||||
// First, if we only have one slot, try matching by keyId
|
||||
if len(blobInfoMap) == 1 {
|
||||
outer:
|
||||
for k := range blobInfoMap {
|
||||
for _, sealWrapper := range wrappersByPriority {
|
||||
keyId, err := sealWrapper.Wrapper.KeyId(ctx)
|
||||
if err != nil {
|
||||
reportResult(sealWrapper.Name, nil, false, err)
|
||||
continue
|
||||
}
|
||||
if keyId == k {
|
||||
first = sealWrapper
|
||||
break outer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go decrypt(first)
|
||||
for _, sealWrapper := range wrappersByPriority {
|
||||
sealWrapper := sealWrapper
|
||||
if i == 0 {
|
||||
// start the highest priority wrapper right away
|
||||
go decrypt(sealWrapper)
|
||||
} else {
|
||||
if sealWrapper != first {
|
||||
timer := time.AfterFunc(wrapperDecryptHighPriorityHeadStart, func() {
|
||||
decrypt(sealWrapper)
|
||||
})
|
||||
@@ -667,7 +722,7 @@ func JoinSealWrapErrors(msg string, errorMap map[string]error) error {
|
||||
func (a *access) Finalize(ctx context.Context, options ...wrapping.Option) error {
|
||||
var errs []error
|
||||
|
||||
for _, w := range a.GetAllSealWrappersByPriority() {
|
||||
for _, w := range a.GetConfiguredSealWrappersByPriority() {
|
||||
if finalizeWrapper, ok := w.Wrapper.(wrapping.InitFinalizer); ok {
|
||||
if err := finalizeWrapper.Finalize(ctx, options...); err != nil {
|
||||
errs = append(errs, err)
|
||||
|
||||
@@ -57,6 +57,7 @@ func NewTestSeal(opts *TestSealOpts) (Access, []*ToggleableWrapper) {
|
||||
fmt.Sprintf("%s-%d", opts.Name, i+1),
|
||||
wrapperType.String(),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -88,6 +89,7 @@ func NewToggleableTestSeal(opts *TestSealOpts) (Access, []func(error)) {
|
||||
fmt.Sprintf("%s-%d", opts.Name, i+1),
|
||||
wrapperType.String(),
|
||||
false,
|
||||
true,
|
||||
)
|
||||
funcs[i] = w.SetError
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ type SealWrapper struct {
|
||||
// Disabled indicates, when true indicates that this wrapper should only be used for decryption.
|
||||
Disabled bool
|
||||
|
||||
// Configured indicates the wrapper was successfully configured at initialization
|
||||
Configured bool
|
||||
|
||||
// hcLock protects lastHealthy, lastSeenHealthy, and healthy.
|
||||
// Do not modify those fields directly, use setHealth instead.
|
||||
// Do not access these fields directly, use getHealth instead.
|
||||
@@ -35,16 +38,21 @@ type SealWrapper struct {
|
||||
healthy bool
|
||||
}
|
||||
|
||||
func NewSealWrapper(wrapper wrapping.Wrapper, priority int, name string, sealConfigType string, disabled bool) *SealWrapper {
|
||||
func NewSealWrapper(wrapper wrapping.Wrapper, priority int, name string, sealConfigType string, disabled bool, configured bool) *SealWrapper {
|
||||
ret := &SealWrapper{
|
||||
Wrapper: wrapper,
|
||||
Priority: priority,
|
||||
Name: name,
|
||||
SealConfigType: sealConfigType,
|
||||
Disabled: disabled,
|
||||
Configured: configured,
|
||||
}
|
||||
|
||||
setHealth(ret, true, time.Now(), ret.lastHealthCheck)
|
||||
if configured {
|
||||
setHealth(ret, true, time.Now(), ret.lastHealthCheck)
|
||||
} else {
|
||||
setHealth(ret, false, time.Now(), ret.lastHealthCheck)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -37,9 +37,10 @@ type autoSeal struct {
|
||||
core *Core
|
||||
logger log.Logger
|
||||
|
||||
allSealsHealthy bool
|
||||
hcLock sync.RWMutex
|
||||
healthCheckStop chan struct{}
|
||||
unsealedWithUnhealthySeal bool
|
||||
allSealsHealthy bool
|
||||
hcLock sync.RWMutex
|
||||
healthCheckStop chan struct{}
|
||||
}
|
||||
|
||||
// Ensure we are implementing the Seal interface
|
||||
@@ -193,7 +194,7 @@ func (d *autoSeal) BarrierConfig(ctx context.Context) (*SealConfig, error) {
|
||||
|
||||
barrierTypeUpgradeCheck(d.BarrierSealConfigType(), conf)
|
||||
|
||||
if conf.Type != d.BarrierSealConfigType().String() {
|
||||
if conf.Type != d.BarrierSealConfigType().String() && conf.Type != "multiseal" {
|
||||
d.logger.Error("barrier seal type does not match loaded type", "seal_type", conf.Type, "loaded_type", d.BarrierSealConfigType())
|
||||
return nil, fmt.Errorf("barrier seal type of %q does not match loaded type of %q", conf.Type, d.BarrierSealConfigType())
|
||||
}
|
||||
@@ -471,10 +472,16 @@ func (d *autoSeal) StartHealthCheck() {
|
||||
defer cancel()
|
||||
|
||||
d.logger.Trace("performing a seal health check")
|
||||
|
||||
for _, sw := range d.Access.GetAllSealWrappersByPriority() {
|
||||
if !sw.Configured {
|
||||
d.logger.Warn(`WARNING: running in degraded mode, one or more seals failed to configure at
|
||||
startup, and Vault is running with fewer than the number of configured seals for high availability. Please correct the
|
||||
error and restart Vault.`)
|
||||
}
|
||||
}
|
||||
allHealthy := true
|
||||
allUnhealthy := true
|
||||
for _, sealWrapper := range d.Access.GetAllSealWrappersByPriority() {
|
||||
for _, sealWrapper := range d.Access.GetConfiguredSealWrappersByPriority() {
|
||||
mLabels := []metrics.Label{{Name: "seal_wrapper_name", Value: sealWrapper.Name}}
|
||||
|
||||
wasHealthy := sealWrapper.IsHealthy()
|
||||
|
||||
@@ -18,7 +18,7 @@ func NewTestSeal(t testing.T, opts *seal.TestSealOpts) Seal {
|
||||
switch opts.StoredKeys {
|
||||
case seal.StoredKeysSupportedShamirRoot:
|
||||
sealAccess, err := seal.NewAccessFromSealWrappers(logger, opts.Generation, true, []*seal.SealWrapper{
|
||||
seal.NewSealWrapper(aead.NewShamirWrapper(), 1, "shamir", "shamir", false),
|
||||
seal.NewSealWrapper(aead.NewShamirWrapper(), 1, "shamir", "shamir", false, true),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("error creating test seal", err)
|
||||
@@ -33,7 +33,7 @@ func NewTestSeal(t testing.T, opts *seal.TestSealOpts) Seal {
|
||||
return newSeal
|
||||
case seal.StoredKeysNotSupported:
|
||||
sealAccess, err := seal.NewAccessFromSealWrappers(logger, opts.Generation, true, []*seal.SealWrapper{
|
||||
seal.NewSealWrapper(aead.NewShamirWrapper(), 1, "shamir", "shamir", false),
|
||||
seal.NewSealWrapper(aead.NewShamirWrapper(), 1, "shamir", "shamir", false, true),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("error creating test seal", err)
|
||||
|
||||
Reference in New Issue
Block a user