From 083fa51bfb83bb90f087b723eaaf2eebc4bf32c7 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Wed, 27 May 2015 17:25:36 -0700 Subject: [PATCH] vault: expose information about keys --- vault/barrier.go | 10 ++++++++++ vault/barrier_aes_gcm.go | 20 ++++++++++++++++++++ vault/barrier_test.go | 26 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/vault/barrier.go b/vault/barrier.go index 296e75b3da..ae5585919a 100644 --- a/vault/barrier.go +++ b/vault/barrier.go @@ -2,6 +2,7 @@ package vault import ( "errors" + "time" "github.com/hashicorp/vault/logical" ) @@ -69,6 +70,9 @@ type SecurityBarrier interface { // should use the new key, while old values should still be decryptable. Rotate() error + // ActiveKeyInfo is used to inform details about the active key + ActiveKeyInfo() (*KeyInfo, error) + // Rekey is used to change the master key used to protect the keyring Rekey([]byte) error @@ -105,3 +109,9 @@ func (e *Entry) Logical() *logical.StorageEntry { Value: e.Value, } } + +// KeyInfo is used to convey information about the encryption key +type KeyInfo struct { + Term int + InstallTime time.Time +} diff --git a/vault/barrier_aes_gcm.go b/vault/barrier_aes_gcm.go index 25a816f251..cb20d4742e 100644 --- a/vault/barrier_aes_gcm.go +++ b/vault/barrier_aes_gcm.go @@ -321,6 +321,26 @@ func (b *AESGCMBarrier) Rotate() error { return nil } +// ActiveKeyInfo is used to inform details about the active key +func (b *AESGCMBarrier) ActiveKeyInfo() (*KeyInfo, error) { + b.l.RLock() + defer b.l.RUnlock() + if b.sealed { + return nil, ErrBarrierSealed + } + + // Determine the key install time + term := b.keyring.ActiveTerm() + key := b.keyring.TermKey(term) + + // Return the key info + info := &KeyInfo{ + Term: int(term), + InstallTime: key.InstallTime, + } + return info, nil +} + // Rekey is used to change the master key used to protect the keyring func (b *AESGCMBarrier) Rekey(key []byte) error { b.l.Lock() diff --git a/vault/barrier_test.go b/vault/barrier_test.go index 5622f57600..546cd01064 100644 --- a/vault/barrier_test.go +++ b/vault/barrier_test.go @@ -3,6 +3,7 @@ package vault import ( "reflect" "testing" + "time" ) func testBarrier(t *testing.T, b SecurityBarrier) { @@ -243,6 +244,19 @@ func testBarrier_Rotate(t *testing.T, b SecurityBarrier) { t.Fatalf("err: %v", err) } + // Check the key info + info, err := b.ActiveKeyInfo() + if err != nil { + t.Fatalf("err: %v", err) + } + if info.Term != 1 { + t.Fatalf("Bad term: %d", info.Term) + } + if time.Since(info.InstallTime) > time.Second { + t.Fatalf("Bad install: %v", info.InstallTime) + } + first := info.InstallTime + // Write a key e1 := &Entry{Key: "test", Value: []byte("test")} if err := b.Put(e1); err != nil { @@ -255,6 +269,18 @@ func testBarrier_Rotate(t *testing.T, b SecurityBarrier) { t.Fatalf("err: %v", err) } + // Check the key info + info, err = b.ActiveKeyInfo() + if err != nil { + t.Fatalf("err: %v", err) + } + if info.Term != 2 { + t.Fatalf("Bad term: %d", info.Term) + } + if !info.InstallTime.After(first) { + t.Fatalf("Bad install: %v", info.InstallTime) + } + // Write another key e2 := &Entry{Key: "foo", Value: []byte("test")} if err := b.Put(e2); err != nil {