vault: support keyring reload

This commit is contained in:
Armon Dadgar 2015-05-28 16:09:15 -07:00
parent 2e86fa62d5
commit 796ae59a89
3 changed files with 59 additions and 1 deletions

View File

@ -77,6 +77,11 @@ type SecurityBarrier interface {
// VerifyMaster is used to check if the given key matches the master key
VerifyMaster(key []byte) error
// ReloadKeyring is used to re-read the underlying keyring.
// This is used for HA deployments to ensure the latest keyring
// is present in the leader.
ReloadKeyring() error
// Seal is used to re-seal the barrier. This requires the barrier to
// be unsealed again to perform any further operations.
Seal() error
@ -85,7 +90,8 @@ type SecurityBarrier interface {
// should use the new key, while old values should still be decryptable.
Rotate() error
// AddKey is used to add a new key to the keyring
// AddKey is used to add a new key to the keyring. This assumes the keyring
// has already been updated and does not persist a new keyring.
AddKey(k *Key) error
// ActiveKeyInfo is used to inform details about the active key

View File

@ -187,6 +187,46 @@ func (b *AESGCMBarrier) VerifyMaster(key []byte) error {
return nil
}
// ReloadKeyring is used to re-read the underlying keyring.
// This is used for HA deployments to ensure the latest keyring
// is present in the leader.
func (b *AESGCMBarrier) ReloadKeyring() error {
b.l.Lock()
defer b.l.Unlock()
// Create the AES-GCM
gcm, err := b.aeadFromKey(b.keyring.MasterKey())
if err != nil {
return err
}
// Read in the keyring
out, err := b.backend.Get(keyringPath)
if err != nil {
return fmt.Errorf("failed to check for keyring: %v", err)
}
// Decrypt the barrier init key
plain, err := b.decrypt(gcm, out.Value)
if err != nil {
if strings.Contains(err.Error(), "message authentication failed") {
return ErrBarrierInvalidKey
}
return err
}
defer memzero(plain)
// Recover the keyring
keyring, err := DeserializeKeyring(plain)
if err != nil {
return fmt.Errorf("keyring deserialization failed: %v", err)
}
// Setup the keyring and finish
b.keyring = keyring
return nil
}
// Unseal is used to provide the master key which permits the barrier
// to be unsealed. If the key is not correct, the barrier remains sealed.
func (b *AESGCMBarrier) Unseal(key []byte) error {

View File

@ -357,6 +357,12 @@ func testBarrier_Rotate(t *testing.T, b SecurityBarrier) {
if info.Term != 3 {
t.Fatalf("Bad term: %d", info.Term)
}
// Should be fine to reload keyring
err = b.ReloadKeyring()
if err != nil {
t.Fatalf("err: %v", err)
}
}
func testBarrier_Rekey(t *testing.T, b SecurityBarrier) {
@ -431,4 +437,10 @@ func testBarrier_Rekey(t *testing.T, b SecurityBarrier) {
if out == nil {
t.Fatalf("bad: %v", out)
}
// Should be fine to reload keyring
err = b.ReloadKeyring()
if err != nil {
t.Fatalf("err: %v", err)
}
}