Updates to recovery keys (#6152)
This commit is contained in:
parent
a9392f9840
commit
aaca35be94
|
@ -111,7 +111,7 @@ func TestSealMigration(t *testing.T) {
|
|||
|
||||
core := cluster.Cores[0].Core
|
||||
|
||||
newSeal := vault.NewAutoSeal(seal.NewTestSeal(logger))
|
||||
newSeal := vault.NewAutoSeal(seal.NewTestSeal(nil))
|
||||
newSeal.SetCore(core)
|
||||
autoSeal = newSeal
|
||||
if err := adjustCoreForSealMigration(ctx, core, coreConfig, newSeal, &server.Config{
|
||||
|
|
|
@ -507,8 +507,7 @@ func (c *ServerCommand) Run(args []string) int {
|
|||
var seal vault.Seal
|
||||
var sealConfigError error
|
||||
if c.flagDevAutoSeal {
|
||||
sealLogger := c.logger.Named(vaultseal.Test)
|
||||
seal = vault.NewAutoSeal(vaultseal.NewTestSeal(sealLogger))
|
||||
seal = vault.NewAutoSeal(vaultseal.NewTestSeal(nil))
|
||||
} else {
|
||||
sealLogger := c.logger.Named(sealType)
|
||||
allLoggers = append(allLoggers, sealLogger)
|
||||
|
|
|
@ -67,6 +67,7 @@ type Seal interface {
|
|||
RecoveryKeySupported() bool
|
||||
RecoveryType() string
|
||||
RecoveryConfig(context.Context) (*SealConfig, error)
|
||||
RecoveryKey(context.Context) ([]byte, error)
|
||||
SetRecoveryConfig(context.Context, *SealConfig) error
|
||||
SetCachedRecoveryConfig(*SealConfig)
|
||||
SetRecoveryKey(context.Context, []byte) error
|
||||
|
@ -233,6 +234,14 @@ func (d *defaultSeal) RecoveryConfig(ctx context.Context) (*SealConfig, error) {
|
|||
return nil, fmt.Errorf("recovery not supported")
|
||||
}
|
||||
|
||||
func (d *defaultSeal) RecoveryKey(ctx context.Context) ([]byte, error) {
|
||||
if d.PretendToAllowRecoveryKeys {
|
||||
return d.PretendRecoveryKey, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("recovery not supported")
|
||||
}
|
||||
|
||||
func (d *defaultSeal) SetRecoveryConfig(ctx context.Context, config *SealConfig) error {
|
||||
if d.PretendToAllowRecoveryKeys {
|
||||
return nil
|
||||
|
|
|
@ -3,19 +3,19 @@ package seal
|
|||
import (
|
||||
"context"
|
||||
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/helper/xor"
|
||||
"github.com/hashicorp/vault/physical"
|
||||
)
|
||||
|
||||
type TestSeal struct {
|
||||
logger log.Logger
|
||||
secret []byte
|
||||
}
|
||||
|
||||
var _ Access = (*TestSeal)(nil)
|
||||
|
||||
func NewTestSeal(logger log.Logger) *TestSeal {
|
||||
func NewTestSeal(secret []byte) *TestSeal {
|
||||
return &TestSeal{
|
||||
logger: logger,
|
||||
secret: secret,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,13 @@ func (t *TestSeal) KeyID() string {
|
|||
}
|
||||
|
||||
func (t *TestSeal) Encrypt(_ context.Context, plaintext []byte) (*physical.EncryptedBlobInfo, error) {
|
||||
ct, err := t.obscureBytes(plaintext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &physical.EncryptedBlobInfo{
|
||||
Ciphertext: ReverseBytes(plaintext),
|
||||
Ciphertext: ct,
|
||||
KeyInfo: &physical.SealKeyInfo{
|
||||
KeyID: t.KeyID(),
|
||||
},
|
||||
|
@ -45,15 +50,32 @@ func (t *TestSeal) Encrypt(_ context.Context, plaintext []byte) (*physical.Encry
|
|||
}
|
||||
|
||||
func (t *TestSeal) Decrypt(_ context.Context, dwi *physical.EncryptedBlobInfo) ([]byte, error) {
|
||||
return ReverseBytes(dwi.Ciphertext), nil
|
||||
return t.obscureBytes(dwi.Ciphertext)
|
||||
}
|
||||
|
||||
// reverseBytes is a helper to simulate "encryption/decryption"
|
||||
// obscureBytes is a helper to simulate "encryption/decryption"
|
||||
// on protected values.
|
||||
func ReverseBytes(in []byte) []byte {
|
||||
func (t *TestSeal) obscureBytes(in []byte) ([]byte, error) {
|
||||
out := make([]byte, len(in))
|
||||
|
||||
if len(t.secret) != 0 {
|
||||
// make sure they are the same length
|
||||
localSecret := make([]byte, len(in))
|
||||
copy(localSecret, t.secret)
|
||||
|
||||
var err error
|
||||
|
||||
out, err = xor.XORBytes(in, localSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
// if there is no secret, simply reverse the string
|
||||
for i := 0; i < len(in); i++ {
|
||||
out[i] = in[len(in)-1-i]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
|
|
@ -303,6 +303,30 @@ func (d *autoSeal) RecoveryConfig(ctx context.Context) (*SealConfig, error) {
|
|||
return conf.Clone(), nil
|
||||
}
|
||||
|
||||
func (d *autoSeal) RecoveryKey(ctx context.Context) ([]byte, error) {
|
||||
pe, err := d.core.physical.Get(ctx, recoveryKeyPath)
|
||||
if err != nil {
|
||||
d.core.logger.Error("autoseal: failed to read recovery key", "error", err)
|
||||
return nil, errwrap.Wrapf("failed to read recovery key: {{err}}", err)
|
||||
}
|
||||
if pe == nil {
|
||||
d.core.logger.Warn("autoseal: no recovery key found")
|
||||
return nil, fmt.Errorf("no recovery key found")
|
||||
}
|
||||
|
||||
blobInfo := &physical.EncryptedBlobInfo{}
|
||||
if err := proto.Unmarshal(pe.Value, blobInfo); err != nil {
|
||||
return nil, errwrap.Wrapf("failed to proto decode recovery keys: {{err}}", err)
|
||||
}
|
||||
|
||||
pt, err := d.Decrypt(ctx, blobInfo)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to decrypt encrypted recovery keys: {{err}}", err)
|
||||
}
|
||||
|
||||
return pt, nil
|
||||
}
|
||||
|
||||
// SetRecoveryConfig writes the recovery configuration to the physical storage
|
||||
// and sets it as the seal's recoveryConfig.
|
||||
func (d *autoSeal) SetRecoveryConfig(ctx context.Context, conf *SealConfig) error {
|
||||
|
@ -353,24 +377,9 @@ func (d *autoSeal) VerifyRecoveryKey(ctx context.Context, key []byte) error {
|
|||
return fmt.Errorf("recovery key to verify is nil")
|
||||
}
|
||||
|
||||
pe, err := d.core.physical.Get(ctx, recoveryKeyPath)
|
||||
pt, err := d.RecoveryKey(ctx)
|
||||
if err != nil {
|
||||
d.core.logger.Error("autoseal: failed to read recovery key", "error", err)
|
||||
return errwrap.Wrapf("failed to read recovery key: {{err}}", err)
|
||||
}
|
||||
if pe == nil {
|
||||
d.core.logger.Warn("autoseal: no recovery key found")
|
||||
return fmt.Errorf("no recovery key found")
|
||||
}
|
||||
|
||||
blobInfo := &physical.EncryptedBlobInfo{}
|
||||
if err := proto.Unmarshal(pe.Value, blobInfo); err != nil {
|
||||
return errwrap.Wrapf("failed to proto decode recovery keys: {{err}}", err)
|
||||
}
|
||||
|
||||
pt, err := d.Decrypt(ctx, blobInfo)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("failed to decrypt encrypted recovery keys: {{err}}", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if subtle.ConstantTimeCompare(key, pt) != 1 {
|
||||
|
|
|
@ -14,6 +14,7 @@ var (
|
|||
type TestSealOpts struct {
|
||||
StoredKeysDisabled bool
|
||||
RecoveryKeysDisabled bool
|
||||
Secret []byte
|
||||
}
|
||||
|
||||
func testCoreUnsealedWithConfigs(t testing.T, barrierConf, recoveryConf *SealConfig) (*Core, [][]byte, [][]byte, string) {
|
||||
|
@ -35,7 +36,7 @@ func testCoreUnsealedWithConfigs(t testing.T, barrierConf, recoveryConf *SealCon
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
err = core.UnsealWithStoredKeys(context.Background())
|
||||
if err != nil {
|
||||
if err != nil && IsFatalError(err) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if core.Sealed() {
|
||||
|
|
Loading…
Reference in New Issue