Make sure we sanitize the rotation config on each clone (#11050)

* Make sure we sanitize the rotation config on each clone

* Add regression test for missing rotation config

* use Equals

* simplify

Co-authored-by: Scott G. Miller <smiller@hashicorp.com>
This commit is contained in:
Brian Kassouf 2021-03-08 08:59:21 -08:00 committed by GitHub
parent e5b6ec4d05
commit aa00b53ba1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 4 deletions

View File

@ -92,7 +92,7 @@ func (b *AESGCMBarrier) RotationConfig() (kc KeyRotationConfig, err error) {
if b.keyring == nil {
return kc, errors.New("keyring not yet present")
}
return b.keyring.rotationConfig, nil
return b.keyring.rotationConfig.Clone(), nil
}
func (b *AESGCMBarrier) SetRotationConfig(ctx context.Context, rotConfig KeyRotationConfig) error {
@ -1146,7 +1146,6 @@ func (b *AESGCMBarrier) CheckBarrierAutoRotate(ctx context.Context) (string, err
rc, err := b.RotationConfig()
if err != nil {
b.l.RUnlock()
return "", err
}
@ -1156,9 +1155,9 @@ func (b *AESGCMBarrier) CheckBarrierAutoRotate(ctx context.Context) (string, err
switch {
case activeKey.Encryptions == 0 && !activeKey.InstallTime.IsZero() && time.Since(activeKey.InstallTime) > oneYear:
reason = legacyRotateReason
case ops > b.keyring.rotationConfig.MaxOperations:
case ops > rc.MaxOperations:
reason = "reached max operations"
case b.keyring.rotationConfig.Interval > 0 && time.Since(activeKey.InstallTime) > b.keyring.rotationConfig.Interval:
case rc.Interval > 0 && time.Since(activeKey.InstallTime) > rc.Interval:
reason = "rotation interval reached"
}
}

View File

@ -61,6 +61,34 @@ func TestAESGCMBarrier_Rotate(t *testing.T) {
testBarrier_Rotate(t, b)
}
func TestAESGCMBarrier_MissingRotateConfig(t *testing.T) {
inm, err := inmem.NewInmem(nil, logger)
if err != nil {
t.Fatalf("err: %v", err)
}
b, err := NewAESGCMBarrier(inm)
if err != nil {
t.Fatalf("err: %v", err)
}
// Initialize and unseal
key, _ := b.GenerateKey(rand.Reader)
b.Initialize(context.Background(), key, nil, rand.Reader)
b.Unseal(context.Background(), key)
// Write a keyring which lacks rotation config settings
oldKeyring := b.keyring.Clone()
oldKeyring.rotationConfig = KeyRotationConfig{}
b.persistKeyring(context.Background(), oldKeyring)
b.ReloadKeyring(context.Background())
// At this point, the rotation config should match the default
if !defaultRotationConfig.Equals(b.keyring.rotationConfig) {
t.Fatalf("expected empty rotation config to recover as default config")
}
}
func TestAESGCMBarrier_Upgrade(t *testing.T) {
inm, err := inmem.NewInmem(nil, logger)
if err != nil {

View File

@ -213,6 +213,7 @@ func DeserializeKeyring(buf []byte) (*Keyring, error) {
k := NewKeyring()
k.masterKey = enc.MasterKey
k.rotationConfig = enc.RotationConfig
k.rotationConfig.Sanitize()
for _, key := range enc.Keys {
k.keys[key.Term] = key
if key.Term > k.activeTerm {
@ -240,6 +241,17 @@ func (k *Keyring) Zeroize(keysToo bool) {
}
}
func (c KeyRotationConfig) Clone() KeyRotationConfig {
clone := KeyRotationConfig{
MaxOperations: c.MaxOperations,
Interval: c.Interval,
Disabled: c.Disabled,
}
clone.Sanitize()
return clone
}
func (c *KeyRotationConfig) Sanitize() {
if c.MaxOperations == 0 || c.MaxOperations > absoluteOperationMaximum || c.MaxOperations < absoluteOperationMinimum {
c.MaxOperations = absoluteOperationMaximum