vault: support keyring reload
This commit is contained in:
parent
2e86fa62d5
commit
796ae59a89
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue