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:
parent
976881954a
commit
2656c020ae
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -18,33 +18,32 @@ 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
|
||||
error error
|
||||
l sync.RWMutex
|
||||
wrapperType *wrapping.WrapperType
|
||||
error error
|
||||
l sync.RWMutex
|
||||
}
|
||||
|
||||
func (t *ToggleableWrapper) Encrypt(ctx context.Context, bytes []byte, opts ...wrapping.Option) (*wrapping.BlobInfo, error) {
|
||||
|
@ -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{}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue