From ead96e8c9941baec532290649be83002f9226bf7 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Wed, 27 May 2015 17:05:02 -0700 Subject: [PATCH] vault: first pass at key rotation --- vault/barrier.go | 4 ++++ vault/barrier_aes_gcm.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/vault/barrier.go b/vault/barrier.go index 966fa57b3..bf40e8604 100644 --- a/vault/barrier.go +++ b/vault/barrier.go @@ -65,6 +65,10 @@ type SecurityBarrier interface { // be unsealed again to perform any further operations. Seal() error + // Rotate is used to create a new encryption key. All future writes + // should use the new key, while old values should still be decryptable. + Rotate() error + // SecurityBarrier must provide the storage APIs BarrierStorage } diff --git a/vault/barrier_aes_gcm.go b/vault/barrier_aes_gcm.go index 540ec93e2..df018a423 100644 --- a/vault/barrier_aes_gcm.go +++ b/vault/barrier_aes_gcm.go @@ -283,6 +283,44 @@ func (b *AESGCMBarrier) Seal() error { return nil } +// Rotate is used to create a new encryption key. All future writes +// should use the new key, while old values should still be decryptable. +func (b *AESGCMBarrier) Rotate() error { + b.l.Lock() + defer b.l.Unlock() + if b.sealed { + return ErrBarrierSealed + } + + // Generate a new key + encrypt, err := b.GenerateKey() + if err != nil { + return fmt.Errorf("failed to generate encryption key: %v", err) + } + + // Get the next term + term := b.keyring.ActiveTerm() + + // Add a new encryption key + newKeyring, err := b.keyring.AddKey(&Key{ + Term: term + 1, + Version: 1, + Value: encrypt, + }) + if err != nil { + return fmt.Errorf("failed to add new encryption key: %v", err) + } + + // Persist the new keyring + if err := b.persistKeyring(newKeyring); err != nil { + return err + } + + // Swap the keyrings + b.keyring = newKeyring + return nil +} + // Put is used to insert or update an entry func (b *AESGCMBarrier) Put(entry *Entry) error { defer metrics.MeasureSince([]string{"barrier", "put"}, time.Now())