vault: make keyring immutable
This commit is contained in:
parent
28560a612f
commit
490bece0a0
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -20,7 +19,6 @@ type Keyring struct {
|
|||
masterKey []byte
|
||||
keys map[uint32]*Key
|
||||
activeTerm uint32
|
||||
l sync.RWMutex
|
||||
}
|
||||
|
||||
// EncodedKeyring is used for serialization of the keyring
|
||||
|
@ -46,17 +44,27 @@ func NewKeyring() *Keyring {
|
|||
return k
|
||||
}
|
||||
|
||||
// AddKey adds a new key to the keyring
|
||||
func (k *Keyring) AddKey(key *Key) error {
|
||||
k.l.Lock()
|
||||
defer k.l.Unlock()
|
||||
// Clone returns a new copy of the keyring
|
||||
func (k *Keyring) Clone() *Keyring {
|
||||
clone := &Keyring{
|
||||
masterKey: k.masterKey,
|
||||
keys: make(map[uint32]*Key, len(k.keys)),
|
||||
activeTerm: k.activeTerm,
|
||||
}
|
||||
for idx, key := range k.keys {
|
||||
clone.keys[idx] = key
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
// AddKey adds a new key to the keyring
|
||||
func (k *Keyring) AddKey(key *Key) (*Keyring, error) {
|
||||
// Ensure there is no confict
|
||||
if exist, ok := k.keys[key.Term]; ok {
|
||||
if !bytes.Equal(key.Value, exist.Value) {
|
||||
return fmt.Errorf("Conflicting key for term %d already installed", key.Term)
|
||||
return nil, fmt.Errorf("Conflicting key for term %d already installed", key.Term)
|
||||
}
|
||||
return nil
|
||||
return k, nil
|
||||
}
|
||||
|
||||
// Add a time if none
|
||||
|
@ -64,71 +72,66 @@ func (k *Keyring) AddKey(key *Key) error {
|
|||
key.InstallTime = time.Now()
|
||||
}
|
||||
|
||||
// Make a new keyring
|
||||
clone := k.Clone()
|
||||
|
||||
// Install the new key
|
||||
k.keys[key.Term] = key
|
||||
clone.keys[key.Term] = key
|
||||
|
||||
// Update the active term if newer
|
||||
if key.Term > k.activeTerm {
|
||||
k.activeTerm = key.Term
|
||||
if key.Term > clone.activeTerm {
|
||||
clone.activeTerm = key.Term
|
||||
}
|
||||
return nil
|
||||
return clone, nil
|
||||
}
|
||||
|
||||
// RemoveKey removes a new key to the keyring
|
||||
func (k *Keyring) RemoveKey(term uint32) error {
|
||||
k.l.Lock()
|
||||
defer k.l.Unlock()
|
||||
|
||||
func (k *Keyring) RemoveKey(term uint32) (*Keyring, error) {
|
||||
// Ensure this is not the active key
|
||||
if term == k.activeTerm {
|
||||
return fmt.Errorf("Cannot remove active key")
|
||||
return nil, fmt.Errorf("Cannot remove active key")
|
||||
}
|
||||
|
||||
// Check if this term does not exist
|
||||
if _, ok := k.keys[term]; !ok {
|
||||
return k, nil
|
||||
}
|
||||
|
||||
// Delete the key
|
||||
delete(k.keys, term)
|
||||
return nil
|
||||
clone := k.Clone()
|
||||
delete(clone.keys, term)
|
||||
return clone, nil
|
||||
}
|
||||
|
||||
// ActiveTerm returns the currently active term
|
||||
func (k *Keyring) ActiveTerm() uint32 {
|
||||
k.l.RLock()
|
||||
defer k.l.RUnlock()
|
||||
return k.activeTerm
|
||||
}
|
||||
|
||||
// ActiveKey returns the active encryption key, or nil
|
||||
func (k *Keyring) ActiveKey() *Key {
|
||||
k.l.RLock()
|
||||
defer k.l.RUnlock()
|
||||
return k.keys[k.activeTerm]
|
||||
}
|
||||
|
||||
// TermKey returns the key for the given term, or nil
|
||||
func (k *Keyring) TermKey(term uint32) *Key {
|
||||
k.l.RLock()
|
||||
defer k.l.RUnlock()
|
||||
return k.keys[term]
|
||||
}
|
||||
|
||||
// SetMasterKey is used to update the master key
|
||||
func (k *Keyring) SetMasterKey(val []byte) {
|
||||
k.l.Lock()
|
||||
defer k.l.Unlock()
|
||||
k.masterKey = val
|
||||
func (k *Keyring) SetMasterKey(val []byte) *Keyring {
|
||||
clone := k.Clone()
|
||||
clone.masterKey = val
|
||||
return clone
|
||||
}
|
||||
|
||||
// MasterKey returns the master key
|
||||
func (k *Keyring) MasterKey() []byte {
|
||||
k.l.RLock()
|
||||
defer k.l.RUnlock()
|
||||
return k.masterKey
|
||||
}
|
||||
|
||||
// Serialize is used to create a byte encoded keyring
|
||||
func (k *Keyring) Serialize() ([]byte, error) {
|
||||
k.l.RLock()
|
||||
defer k.l.RUnlock()
|
||||
|
||||
// Create the encoded entry
|
||||
enc := EncodedKeyring{
|
||||
MasterKey: k.masterKey,
|
||||
|
@ -142,18 +145,6 @@ func (k *Keyring) Serialize() ([]byte, error) {
|
|||
return buf, err
|
||||
}
|
||||
|
||||
// Wipe is used to prepare for sealing my removing everything from memory
|
||||
func (k *Keyring) Wipe() {
|
||||
if k.masterKey != nil {
|
||||
memzero(k.masterKey)
|
||||
k.masterKey = nil
|
||||
}
|
||||
for idx, key := range k.keys {
|
||||
memzero(key.Value)
|
||||
k.keys[idx] = nil
|
||||
}
|
||||
}
|
||||
|
||||
// DeserializeKeyring is used to deserialize and return a new keyring
|
||||
func DeserializeKeyring(buf []byte) (*Keyring, error) {
|
||||
// Deserialize the keyring
|
||||
|
@ -164,10 +155,11 @@ func DeserializeKeyring(buf []byte) (*Keyring, error) {
|
|||
|
||||
// Create a new keyring
|
||||
k := NewKeyring()
|
||||
k.SetMasterKey(enc.MasterKey)
|
||||
k.masterKey = enc.MasterKey
|
||||
for _, key := range enc.Keys {
|
||||
if err := k.AddKey(key); err != nil {
|
||||
return nil, fmt.Errorf("failed to add key for term %d: %v", key.Term, err)
|
||||
k.keys[key.Term] = key
|
||||
if key.Term > k.activeTerm {
|
||||
k.activeTerm = key.Term
|
||||
}
|
||||
}
|
||||
return k, nil
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestKeyring(t *testing.T) {
|
|||
// Add a key
|
||||
testKey := []byte("testing")
|
||||
key1 := &Key{Term: 1, Version: 1, Value: testKey, InstallTime: time.Now()}
|
||||
err := k.AddKey(key1)
|
||||
k, err := k.AddKey(key1)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ func TestKeyring(t *testing.T) {
|
|||
}
|
||||
|
||||
// Should handle idempotent set
|
||||
err = k.AddKey(key1)
|
||||
k, err = k.AddKey(key1)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ func TestKeyring(t *testing.T) {
|
|||
// Should not allow conficting set
|
||||
testConflict := []byte("nope")
|
||||
key1Conf := &Key{Term: 1, Version: 1, Value: testConflict, InstallTime: time.Now()}
|
||||
err = k.AddKey(key1Conf)
|
||||
_, err = k.AddKey(key1Conf)
|
||||
if err == nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func TestKeyring(t *testing.T) {
|
|||
// Add a new key
|
||||
testSecond := []byte("second")
|
||||
key2 := &Key{Term: 2, Version: 1, Value: testSecond, InstallTime: time.Now()}
|
||||
err = k.AddKey(key2)
|
||||
k, err = k.AddKey(key2)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ func TestKeyring(t *testing.T) {
|
|||
}
|
||||
|
||||
// Remove the old key
|
||||
err = k.RemoveKey(1)
|
||||
k, err = k.RemoveKey(1)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ func TestKeyring(t *testing.T) {
|
|||
}
|
||||
|
||||
// Remove the active key should fail
|
||||
err = k.RemoveKey(2)
|
||||
k, err = k.RemoveKey(2)
|
||||
if err == nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -119,14 +119,14 @@ func TestKeyring_MasterKey(t *testing.T) {
|
|||
}
|
||||
|
||||
// Set master
|
||||
k.SetMasterKey(master)
|
||||
k = k.SetMasterKey(master)
|
||||
out = k.MasterKey()
|
||||
if !bytes.Equal(out, master) {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
|
||||
// Update master
|
||||
k.SetMasterKey(master2)
|
||||
k = k.SetMasterKey(master2)
|
||||
out = k.MasterKey()
|
||||
if !bytes.Equal(out, master2) {
|
||||
t.Fatalf("bad: %v", out)
|
||||
|
@ -136,12 +136,12 @@ func TestKeyring_MasterKey(t *testing.T) {
|
|||
func TestKeyring_Serialize(t *testing.T) {
|
||||
k := NewKeyring()
|
||||
master := []byte("test")
|
||||
k.SetMasterKey(master)
|
||||
k = k.SetMasterKey(master)
|
||||
|
||||
testKey := []byte("testing")
|
||||
testSecond := []byte("second")
|
||||
k.AddKey(&Key{Term: 1, Version: 1, Value: testKey, InstallTime: time.Now()})
|
||||
k.AddKey(&Key{Term: 2, Version: 1, Value: testSecond, InstallTime: time.Now()})
|
||||
k, _ = k.AddKey(&Key{Term: 1, Version: 1, Value: testKey, InstallTime: time.Now()})
|
||||
k, _ = k.AddKey(&Key{Term: 2, Version: 1, Value: testSecond, InstallTime: time.Now()})
|
||||
|
||||
buf, err := k.Serialize()
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue