Convert seal.Access struct into a interface (OSS) (#20510)

* Move seal barrier type field from Access to autoSeal struct.

Remove method Access.SetType(), which was only being used by a single test, and
which can use the name option of NewTestSeal() to specify the type.

* Change method signatures of Access to match those of Wrapper.

* Turn seal.Access struct into an interface.

* Tweak Access implementation.

Change `access` struct to have a field of type wrapping.Wrapper, rather than
extending it.

* Add method Seal.GetShamirWrapper().

Add method Seal.GetShamirWrapper() for use by code that need to perform
Shamir-specific operations.
This commit is contained in:
Victor Rodriguez 2023-05-04 14:22:30 -04:00 committed by GitHub
parent 976881954a
commit 2656c020ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 166 additions and 115 deletions

View File

@ -96,7 +96,7 @@ func testVaultServerAllBackends(tb testing.TB) (*api.Client, func()) {
// testVaultServerAutoUnseal creates a test vault cluster and sets it up with auto unseal
// the function returns a client, the recovery keys, and a closer function
func testVaultServerAutoUnseal(tb testing.TB) (*api.Client, []string, func()) {
testSeal := seal.NewTestSeal(nil)
testSeal, _ := seal.NewTestSeal(nil)
autoSeal, err := vault.NewAutoSeal(testSeal)
if err != nil {
tb.Fatal("unable to create autoseal", err)

View File

@ -547,9 +547,7 @@ func (c *ServerCommand) runRecoveryMode() int {
info["Seal Type"] = sealType
var seal vault.Seal
defaultSeal := vault.NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(),
})
defaultSeal := vault.NewDefaultSeal(vaultseal.NewAccess(aeadwrapper.NewShamirWrapper()))
sealLogger := c.logger.ResetNamed(fmt.Sprintf("seal.%s", sealType))
wrapper, sealConfigError = configutil.ConfigureWrapper(configSeal, &infoKeys, &info, sealLogger)
if sealConfigError != nil {
@ -562,9 +560,7 @@ func (c *ServerCommand) runRecoveryMode() int {
if wrapper == nil {
seal = defaultSeal
} else {
seal, err = vault.NewAutoSeal(&vaultseal.Access{
Wrapper: wrapper,
})
seal, err = vault.NewAutoSeal(vaultseal.NewAccess(wrapper))
if err != nil {
c.UI.Error(fmt.Sprintf("error creating auto seal: %v", err))
}
@ -2442,7 +2438,8 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
var barrierWrapper wrapping.Wrapper
if c.flagDevAutoSeal {
var err error
barrierSeal, err = vault.NewAutoSeal(vaultseal.NewTestSeal(nil))
access, _ := vaultseal.NewTestSeal(nil)
barrierSeal, err = vault.NewAutoSeal(access)
if err != nil {
return nil, nil, nil, nil, nil, err
}
@ -2473,9 +2470,7 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
var seal vault.Seal
sealLogger := c.logger.ResetNamed(fmt.Sprintf("seal.%s", sealType))
c.allLoggers = append(c.allLoggers, sealLogger)
defaultSeal := vault.NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(),
})
defaultSeal := vault.NewDefaultSeal(vaultseal.NewAccess(aeadwrapper.NewShamirWrapper()))
var sealInfoKeys []string
sealInfoMap := map[string]string{}
wrapper, sealConfigError = configutil.ConfigureWrapper(configSeal, &sealInfoKeys, &sealInfoMap, sealLogger)
@ -2489,9 +2484,7 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
seal = defaultSeal
} else {
var err error
seal, err = vault.NewAutoSeal(&vaultseal.Access{
Wrapper: wrapper,
})
seal, err = vault.NewAutoSeal(vaultseal.NewAccess(wrapper))
if err != nil {
return nil, nil, nil, nil, nil, err
}

View File

@ -74,7 +74,5 @@ func (tss *TransitSealServer) MakeSeal(t testing.T, key string) (vault.Seal, err
t.Fatalf("error setting wrapper config: %v", err)
}
return vault.NewAutoSeal(&seal.Access{
Wrapper: transitSeal,
})
return vault.NewAutoSeal(seal.NewAccess(transitSeal))
}

View File

@ -153,12 +153,11 @@ func TestSysInit_Put_ValidateParams(t *testing.T) {
}
func TestSysInit_Put_ValidateParams_AutoUnseal(t *testing.T) {
testSeal := seal.NewTestSeal(nil)
testSeal, _ := seal.NewTestSeal(&seal.TestSealOpts{Name: "transit"})
autoSeal, err := vault.NewAutoSeal(testSeal)
if err != nil {
t.Fatal(err)
}
autoSeal.SetType("transit")
// Create the transit server.
conf := &vault.CoreConfig{

View File

@ -1367,7 +1367,7 @@ func (b *RaftBackend) Peers(ctx context.Context) ([]Peer, error) {
// SnapshotHTTP is a wrapper for Snapshot that sends the snapshot as an HTTP
// response.
func (b *RaftBackend) SnapshotHTTP(out *logical.HTTPResponseWriter, access *seal.Access) error {
func (b *RaftBackend) SnapshotHTTP(out *logical.HTTPResponseWriter, access seal.Access) error {
out.Header().Add("Content-Disposition", "attachment")
out.Header().Add("Content-Type", "application/gzip")
@ -1377,7 +1377,7 @@ func (b *RaftBackend) SnapshotHTTP(out *logical.HTTPResponseWriter, access *seal
// Snapshot takes a raft snapshot, packages it into a archive file and writes it
// to the provided writer. Seal access is used to encrypt the SHASUM file so we
// can validate the snapshot was taken using the same root keys or not.
func (b *RaftBackend) Snapshot(out io.Writer, access *seal.Access) error {
func (b *RaftBackend) Snapshot(out io.Writer, access seal.Access) error {
b.l.RLock()
defer b.l.RUnlock()
@ -1401,7 +1401,7 @@ func (b *RaftBackend) Snapshot(out io.Writer, access *seal.Access) error {
// access is used to decrypt the SHASUM file in the archive to ensure this
// snapshot has the same root key as the running instance. If the provided
// access is nil then it will skip that validation.
func (b *RaftBackend) WriteSnapshotToTemp(in io.ReadCloser, access *seal.Access) (*os.File, func(), raft.SnapshotMeta, error) {
func (b *RaftBackend) WriteSnapshotToTemp(in io.ReadCloser, access seal.Access) (*os.File, func(), raft.SnapshotMeta, error) {
b.l.RLock()
defer b.l.RUnlock()
@ -1894,7 +1894,7 @@ func (l *RaftLock) Value() (bool, string, error) {
// sealer implements the snapshot.Sealer interface and is used in the snapshot
// process for encrypting/decrypting the SHASUM file in snapshot archives.
type sealer struct {
access *seal.Access
access seal.Access
}
// Seal encrypts the data with using the seal access object.

View File

@ -1098,9 +1098,7 @@ func CreateCore(conf *CoreConfig) (*Core, error) {
wrapper := aeadwrapper.NewShamirWrapper()
wrapper.SetConfig(context.Background(), awskms.WithLogger(c.logger.Named("shamir")))
c.seal = NewDefaultSeal(&vaultseal.Access{
Wrapper: wrapper,
})
c.seal = NewDefaultSeal(vaultseal.NewAccess(wrapper))
}
c.seal.SetCore(c)
return c, nil
@ -1544,7 +1542,10 @@ func (c *Core) unsealWithRaft(combinedKey []byte) error {
if c.seal.BarrierType() == wrapping.WrapperTypeShamir {
// If this is a legacy shamir seal this serves no purpose but it
// doesn't hurt.
err := c.seal.GetAccess().Wrapper.(*aeadwrapper.ShamirWrapper).SetAesGcmKeyBytes(combinedKey)
shamirWrapper, err := c.seal.GetShamirWrapper()
if err == nil {
err = shamirWrapper.SetAesGcmKeyBytes(combinedKey)
}
if err != nil {
return err
}
@ -1795,7 +1796,11 @@ func (c *Core) migrateSeal(ctx context.Context) error {
}
// We have recovery keys; we're going to use them as the new shamir KeK.
err = c.seal.GetAccess().Wrapper.(*aeadwrapper.ShamirWrapper).SetAesGcmKeyBytes(recoveryKey)
shamirWrapper, err := c.seal.GetShamirWrapper()
if err != nil {
return err
}
err = shamirWrapper.SetAesGcmKeyBytes(recoveryKey)
if err != nil {
return fmt.Errorf("failed to set master key in seal: %w", err)
}
@ -2793,9 +2798,7 @@ func (c *Core) adjustForSealMigration(unwrapSeal Seal) error {
case existBarrierSealConfig.Type == wrapping.WrapperTypeShamir.String():
// The configured seal is not Shamir, the stored seal config is Shamir.
// This is a migration away from Shamir.
unwrapSeal = NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(),
})
unwrapSeal = NewDefaultSeal(vaultseal.NewAccess(aeadwrapper.NewShamirWrapper()))
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
@ -2958,9 +2961,7 @@ func (c *Core) unsealKeyToMasterKey(ctx context.Context, seal Seal, combinedKey
case vaultseal.StoredKeysSupportedShamirRoot:
if useTestSeal {
testseal := NewDefaultSeal(&vaultseal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(),
})
testseal := NewDefaultSeal(vaultseal.NewAccess(aeadwrapper.NewShamirWrapper()))
testseal.SetCore(c)
cfg, err := seal.BarrierConfig(ctx)
if err != nil {
@ -2970,7 +2971,11 @@ func (c *Core) unsealKeyToMasterKey(ctx context.Context, seal Seal, combinedKey
seal = testseal
}
err := seal.GetAccess().Wrapper.(*aeadwrapper.ShamirWrapper).SetAesGcmKeyBytes(combinedKey)
shamirWrapper, err := seal.GetShamirWrapper()
if err != nil {
return nil, err
}
err = shamirWrapper.SetAesGcmKeyBytes(combinedKey)
if err != nil {
return nil, &ErrInvalidKey{fmt.Sprintf("failed to setup unseal key: %v", err)}
}

View File

@ -18,7 +18,6 @@ import (
"github.com/armon/go-metrics"
"github.com/hashicorp/errwrap"
aeadwrapper "github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/namespace"
@ -966,7 +965,11 @@ func (c *Core) reloadShamirKey(ctx context.Context) error {
}
shamirKey = keyring.rootKey
}
return c.seal.GetAccess().Wrapper.(*aeadwrapper.ShamirWrapper).SetAesGcmKeyBytes(shamirKey)
shamirWrapper, err := c.seal.GetShamirWrapper()
if err != nil {
return err
}
return shamirWrapper.SetAesGcmKeyBytes(shamirKey)
}
func (c *Core) performKeyUpgrades(ctx context.Context) error {

View File

@ -16,7 +16,6 @@ import (
"github.com/hashicorp/vault/physical/raft"
"github.com/hashicorp/vault/vault/seal"
aeadwrapper "github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/pgpkeys"
"github.com/hashicorp/vault/shamir"
@ -328,7 +327,11 @@ func (c *Core) Initialize(ctx context.Context, initParams *InitParams) (*InitRes
switch c.seal.StoredKeysSupported() {
case seal.StoredKeysSupportedShamirRoot:
keysToStore := [][]byte{barrierKey}
if err := c.seal.GetAccess().Wrapper.(*aeadwrapper.ShamirWrapper).SetAesGcmKeyBytes(sealKey); err != nil {
shamirWrapper, err := c.seal.GetShamirWrapper()
if err != nil {
return nil, err
}
if err := shamirWrapper.SetAesGcmKeyBytes(sealKey); err != nil {
c.logger.Error("failed to set seal key", "error", err)
return nil, fmt.Errorf("failed to set seal key: %w", err)
}

View File

@ -1268,7 +1268,7 @@ func (c *Core) isRaftHAOnly() bool {
return isRaftHA && !isRaftStorage
}
func (c *Core) joinRaftSendAnswer(ctx context.Context, sealAccess *seal.Access, raftInfo *raftInformation) error {
func (c *Core) joinRaftSendAnswer(ctx context.Context, sealAccess seal.Access, raftInfo *raftInformation) error {
if raftInfo.challenge == nil {
return errors.New("raft challenge is nil")
}

View File

@ -401,11 +401,10 @@ func (c *Core) BarrierRekeyUpdate(ctx context.Context, key []byte, nonce string)
}
case c.seal.BarrierType() == wrapping.WrapperTypeShamir:
if c.seal.StoredKeysSupported() == seal.StoredKeysSupportedShamirRoot {
testseal := NewDefaultSeal(&seal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(),
})
shamirWrapper := aeadwrapper.NewShamirWrapper()
testseal := NewDefaultSeal(seal.NewAccess(shamirWrapper))
testseal.SetCore(c)
err = testseal.GetAccess().Wrapper.(*aeadwrapper.ShamirWrapper).SetAesGcmKeyBytes(recoveredKey)
err = shamirWrapper.SetAesGcmKeyBytes(recoveredKey)
if err != nil {
return nil, logical.CodedError(http.StatusInternalServerError, fmt.Errorf("failed to setup unseal key: %w", err).Error())
}
@ -533,7 +532,10 @@ func (c *Core) performBarrierRekey(ctx context.Context, newSealKey []byte) logic
}
if c.seal.StoredKeysSupported() != seal.StoredKeysSupportedGeneric {
err := c.seal.GetAccess().Wrapper.(*aeadwrapper.ShamirWrapper).SetAesGcmKeyBytes(newSealKey)
shamirWrapper, err := c.seal.GetShamirWrapper()
if err == nil {
err = shamirWrapper.SetAesGcmKeyBytes(newSealKey)
}
if err != nil {
return logical.CodedError(http.StatusInternalServerError, fmt.Errorf("failed to update barrier seal key: %w", err).Error())
}

View File

@ -13,6 +13,8 @@ import (
"strings"
"sync/atomic"
aeadwrapper "github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/physical"
@ -59,32 +61,35 @@ type Seal interface {
SetCore(*Core)
Init(context.Context) error
Finalize(context.Context) error
StoredKeysSupported() seal.StoredKeysSupport
StoredKeysSupported() seal.StoredKeysSupport // SealAccess
SealWrapable() bool
SetStoredKeys(context.Context, [][]byte) error
GetStoredKeys(context.Context) ([][]byte, error)
BarrierType() wrapping.WrapperType
BarrierConfig(context.Context) (*SealConfig, error)
BarrierType() wrapping.WrapperType // SealAccess
BarrierConfig(context.Context) (*SealConfig, error) // SealAccess
SetBarrierConfig(context.Context, *SealConfig) error
SetCachedBarrierConfig(*SealConfig)
RecoveryKeySupported() bool
RecoveryKeySupported() bool // SealAccess
RecoveryType() string
RecoveryConfig(context.Context) (*SealConfig, error)
RecoveryConfig(context.Context) (*SealConfig, error) // SealAccess
RecoveryKey(context.Context) ([]byte, error)
SetRecoveryConfig(context.Context, *SealConfig) error
SetCachedRecoveryConfig(*SealConfig)
SetRecoveryKey(context.Context, []byte) error
VerifyRecoveryKey(context.Context, []byte) error
GetAccess() *seal.Access
VerifyRecoveryKey(context.Context, []byte) error // SealAccess
GetAccess() seal.Access // SealAccess
GetShamirWrapper() (*aeadwrapper.ShamirWrapper, error)
}
type defaultSeal struct {
access *seal.Access
access seal.Access
config atomic.Value
core *Core
}
func NewDefaultSeal(lowLevel *seal.Access) Seal {
var _ Seal = (*defaultSeal)(nil)
func NewDefaultSeal(lowLevel seal.Access) Seal {
ret := &defaultSeal{
access: lowLevel,
}
@ -103,11 +108,11 @@ func (d *defaultSeal) checkCore() error {
return nil
}
func (d *defaultSeal) GetAccess() *seal.Access {
func (d *defaultSeal) GetAccess() seal.Access {
return d.access
}
func (d *defaultSeal) SetAccess(access *seal.Access) {
func (d *defaultSeal) SetAccess(access seal.Access) {
d.access = access
}
@ -288,6 +293,16 @@ func (d *defaultSeal) SetRecoveryKey(ctx context.Context, key []byte) error {
return fmt.Errorf("recovery not supported")
}
func (d *defaultSeal) GetShamirWrapper() (*aeadwrapper.ShamirWrapper, error) {
// defaultSeal is meant to be for Shamir seals, so it should always have a ShamirWrapper.
// Nonetheless, NewDefaultSeal does not check, so let's play it safe.
w, ok := d.GetAccess().GetWrapper().(*aeadwrapper.ShamirWrapper)
if !ok {
return nil, fmt.Errorf("expected defaultSeal to have a ShamirWrapper, but found a %T instead", d.GetAccess().GetWrapper())
}
return w, nil
}
// SealConfig is used to describe the seal configuration
type SealConfig struct {
// The type, for sanity checking
@ -432,7 +447,7 @@ func (e *ErrDecrypt) Is(target error) bool {
return ok || errors.Is(e.Err, target)
}
func writeStoredKeys(ctx context.Context, storage physical.Backend, encryptor *seal.Access, keys [][]byte) error {
func writeStoredKeys(ctx context.Context, storage physical.Backend, encryptor seal.Access, keys [][]byte) error {
if keys == nil {
return fmt.Errorf("keys were nil")
}
@ -458,7 +473,7 @@ func writeStoredKeys(ctx context.Context, storage physical.Backend, encryptor *s
// Store the seal configuration.
pe := &physical.Entry{
Key: StoredBarrierKeysPath,
Key: StoredBarrierKeysPath, // TODO(SEALHA): will we need to store more than one set of keys?
Value: value,
}
@ -469,7 +484,7 @@ func writeStoredKeys(ctx context.Context, storage physical.Backend, encryptor *s
return nil
}
func readStoredKeys(ctx context.Context, storage physical.Backend, encryptor *seal.Access) ([][]byte, error) {
func readStoredKeys(ctx context.Context, storage physical.Backend, encryptor seal.Access) ([][]byte, error) {
pe, err := storage.Get(ctx, StoredBarrierKeysPath)
if err != nil {
return nil, fmt.Errorf("failed to fetch stored keys: %w", err)

View File

@ -36,32 +36,51 @@ func (s StoredKeysSupport) String() string {
// Access is the embedded implementation of autoSeal that contains logic
// specific to encrypting and decrypting data, or in this case keys.
type Access struct {
type Access interface {
wrapping.Wrapper
WrapperType wrapping.WrapperType
wrapping.InitFinalizer
GetWrapper() wrapping.Wrapper
}
func (a *Access) Init(ctx context.Context) error {
if initWrapper, ok := a.Wrapper.(wrapping.InitFinalizer); ok {
return initWrapper.Init(ctx)
type access struct {
w wrapping.Wrapper
}
var _ Access = (*access)(nil)
func NewAccess(w wrapping.Wrapper) Access {
return &access{
w: w,
}
}
func (a *access) KeyId(ctx context.Context) (string, error) {
return a.w.KeyId(ctx)
}
func (a *access) SetConfig(ctx context.Context, options ...wrapping.Option) (*wrapping.WrapperConfig, error) {
return a.w.SetConfig(ctx, options...)
}
func (a *access) GetWrapper() wrapping.Wrapper {
return a.w
}
func (a *access) Init(ctx context.Context, options ...wrapping.Option) error {
if initWrapper, ok := a.w.(wrapping.InitFinalizer); ok {
return initWrapper.Init(ctx, options...)
}
return nil
}
func (a *Access) SetType(t wrapping.WrapperType) {
a.WrapperType = t
}
func (a *Access) Type(ctx context.Context) (wrapping.WrapperType, error) {
if a != nil && a.WrapperType != "" {
return a.WrapperType, nil
}
return a.Wrapper.Type(ctx)
func (a *access) Type(ctx context.Context) (wrapping.WrapperType, error) {
return a.w.Type(ctx)
}
// Encrypt uses the underlying seal to encrypt the plaintext and returns it.
func (a *Access) Encrypt(ctx context.Context, plaintext, aad []byte) (blob *wrapping.BlobInfo, err error) {
wTyp, err := a.Wrapper.Type(ctx)
func (a *access) Encrypt(ctx context.Context, plaintext []byte, options ...wrapping.Option) (blob *wrapping.BlobInfo, err error) {
wTyp, err := a.w.Type(ctx)
if err != nil {
return nil, err
}
@ -79,14 +98,14 @@ func (a *Access) Encrypt(ctx context.Context, plaintext, aad []byte) (blob *wrap
metrics.IncrCounter([]string{"seal", "encrypt"}, 1)
metrics.IncrCounter([]string{"seal", wTyp.String(), "encrypt"}, 1)
return a.Wrapper.Encrypt(ctx, plaintext, wrapping.WithAad(aad))
return a.w.Encrypt(ctx, plaintext, options...)
}
// Decrypt uses the underlying seal to decrypt the cryptotext and returns it.
// Note that it is possible depending on the wrapper used that both pt and err
// are populated.
func (a *Access) Decrypt(ctx context.Context, data *wrapping.BlobInfo, aad []byte) (pt []byte, err error) {
wTyp, err := a.Wrapper.Type(ctx)
func (a *access) Decrypt(ctx context.Context, data *wrapping.BlobInfo, options ...wrapping.Option) (pt []byte, err error) {
wTyp, err := a.w.Type(ctx)
defer func(now time.Time) {
metrics.MeasureSince([]string{"seal", "decrypt", "time"}, now)
metrics.MeasureSince([]string{"seal", wTyp.String(), "decrypt", "time"}, now)
@ -100,12 +119,12 @@ func (a *Access) Decrypt(ctx context.Context, data *wrapping.BlobInfo, aad []byt
metrics.IncrCounter([]string{"seal", "decrypt"}, 1)
metrics.IncrCounter([]string{"seal", wTyp.String(), "decrypt"}, 1)
return a.Wrapper.Decrypt(ctx, data, wrapping.WithAad(aad))
return a.w.Decrypt(ctx, data, options...)
}
func (a *Access) Finalize(ctx context.Context) error {
if finalizeWrapper, ok := a.Wrapper.(wrapping.InitFinalizer); ok {
return finalizeWrapper.Finalize(ctx)
func (a *access) Finalize(ctx context.Context, options ...wrapping.Option) error {
if finalizeWrapper, ok := a.w.(wrapping.InitFinalizer); ok {
return finalizeWrapper.Finalize(ctx, options...)
}
return nil
}

View File

@ -18,31 +18,30 @@ type TestSealOpts struct {
Name wrapping.WrapperType
}
func NewTestSeal(opts *TestSealOpts) *Access {
if opts == nil {
opts = new(TestSealOpts)
}
return &Access{
Wrapper: wrapping.NewTestWrapper(opts.Secret),
WrapperType: opts.Name,
}
}
func NewToggleableTestSeal(opts *TestSealOpts) (*Access, func(error)) {
func NewTestSeal(opts *TestSealOpts) (Access, *ToggleableWrapper) {
if opts == nil {
opts = new(TestSealOpts)
}
w := &ToggleableWrapper{Wrapper: wrapping.NewTestWrapper(opts.Secret)}
return &Access{
Wrapper: w,
WrapperType: opts.Name,
}, w.SetError
if opts.Name != "" {
w.wrapperType = &opts.Name
}
return NewAccess(w), w
}
func NewToggleableTestSeal(opts *TestSealOpts) (Access, func(error)) {
if opts == nil {
opts = new(TestSealOpts)
}
w := &ToggleableWrapper{Wrapper: wrapping.NewTestWrapper(opts.Secret)}
return NewAccess(w), w.SetError
}
type ToggleableWrapper struct {
wrapping.Wrapper
wrapperType *wrapping.WrapperType
error error
l sync.RWMutex
}
@ -71,4 +70,11 @@ func (t *ToggleableWrapper) SetError(err error) {
t.error = err
}
func (t *ToggleableWrapper) Type(ctx context.Context) (wrapping.WrapperType, error) {
if t.wrapperType != nil {
return *t.wrapperType, nil
}
return t.Wrapper.Type(ctx)
}
var _ wrapping.Wrapper = &ToggleableWrapper{}

View File

@ -46,6 +46,7 @@ func (s *SealAccess) VerifyRecoveryKey(ctx context.Context, key []byte) error {
return s.seal.VerifyRecoveryKey(ctx, key)
}
// TODO(SEALHA): This looks like it belongs in Seal instead, it only has two callers
func (s *SealAccess) ClearCaches(ctx context.Context) {
s.seal.SetBarrierConfig(ctx, nil)
if s.RecoveryKeySupported() {
@ -53,6 +54,6 @@ func (s *SealAccess) ClearCaches(ctx context.Context) {
}
}
func (s *SealAccess) GetAccess() *seal.Access {
func (s *SealAccess) GetAccess() seal.Access {
return s.seal.GetAccess()
}

View File

@ -14,6 +14,8 @@ import (
"sync/atomic"
"time"
aeadwrapper "github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2"
proto "github.com/golang/protobuf/proto"
log "github.com/hashicorp/go-hclog"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
@ -36,8 +38,9 @@ var (
// decrypting stored keys via an underlying AutoSealAccess implementation, as
// well as logic related to recovery keys and barrier config.
type autoSeal struct {
*seal.Access
seal.Access
barrierType wrapping.WrapperType
barrierConfig atomic.Value
recoveryConfig atomic.Value
core *Core
@ -50,18 +53,21 @@ type autoSeal struct {
// Ensure we are implementing the Seal interface
var _ Seal = (*autoSeal)(nil)
func NewAutoSeal(lowLevel *seal.Access) (*autoSeal, error) {
func NewAutoSeal(lowLevel seal.Access) (*autoSeal, error) {
ret := &autoSeal{
Access: lowLevel,
}
ret.barrierConfig.Store((*SealConfig)(nil))
ret.recoveryConfig.Store((*SealConfig)(nil))
// Having the wrapper type in a field is just a convenience since Seal.BarrierType()
// does not return an error.
var err error
ret.WrapperType, err = ret.Type(context.Background())
ret.barrierType, err = ret.Type(context.Background())
if err != nil {
return nil, err
}
return ret, nil
}
@ -69,7 +75,7 @@ func (d *autoSeal) SealWrapable() bool {
return true
}
func (d *autoSeal) GetAccess() *seal.Access {
func (d *autoSeal) GetAccess() seal.Access {
return d.Access
}
@ -97,7 +103,11 @@ func (d *autoSeal) Finalize(ctx context.Context) error {
}
func (d *autoSeal) BarrierType() wrapping.WrapperType {
return d.WrapperType
return d.barrierType
}
func (d *autoSeal) GetShamirWrapper() (*aeadwrapper.ShamirWrapper, error) {
return nil, fmt.Errorf("autoSeal does not use a ShamirWrapper")
}
func (d *autoSeal) StoredKeysSupported() seal.StoredKeysSupport {

View File

@ -69,12 +69,12 @@ func (p *phy) Len() int {
func TestAutoSeal_UpgradeKeys(t *testing.T) {
core, _, _ := TestCoreUnsealed(t)
testSeal := seal.NewTestSeal(nil)
testSeal, toggleableWrapper := seal.NewTestSeal(nil)
var encKeys []string
changeKey := func(key string) {
encKeys = append(encKeys, key)
testSeal.Wrapper.(*wrapping.TestWrapper).SetKeyId(key)
toggleableWrapper.Wrapper.(*wrapping.TestWrapper).SetKeyId(key)
}
// Set initial encryption key.

View File

@ -22,9 +22,7 @@ func NewTestSeal(t testing.T, opts *seal.TestSealOpts) Seal {
switch opts.StoredKeys {
case seal.StoredKeysSupportedShamirRoot:
newSeal := NewDefaultSeal(&seal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(),
})
newSeal := NewDefaultSeal(seal.NewAccess(aeadwrapper.NewShamirWrapper()))
// Need StoredShares set or this will look like a legacy shamir seal.
newSeal.SetCachedBarrierConfig(&SealConfig{
StoredShares: 1,
@ -33,9 +31,7 @@ func NewTestSeal(t testing.T, opts *seal.TestSealOpts) Seal {
})
return newSeal
case seal.StoredKeysNotSupported:
newSeal := NewDefaultSeal(&seal.Access{
Wrapper: aeadwrapper.NewShamirWrapper(),
})
newSeal := NewDefaultSeal(seal.NewAccess(aeadwrapper.NewShamirWrapper()))
newSeal.SetCachedBarrierConfig(&SealConfig{
StoredShares: 0,
SecretThreshold: 1,
@ -43,7 +39,8 @@ func NewTestSeal(t testing.T, opts *seal.TestSealOpts) Seal {
})
return newSeal
default:
seal, err := NewAutoSeal(seal.NewTestSeal(opts))
access, _ := seal.NewTestSeal(opts)
seal, err := NewAutoSeal(access)
if err != nil {
t.Fatal(err)
}