Updates to recovery keys (#6152)

This commit is contained in:
Brian Kassouf 2019-02-01 11:29:55 -08:00 committed by GitHub
parent a9392f9840
commit aaca35be94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 32 deletions

View File

@ -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{

View File

@ -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)

View File

@ -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

View File

@ -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))
for i := 0; i < len(in); i++ {
out[i] = in[len(in)-1-i]
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
}

View File

@ -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 {

View File

@ -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() {