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:
parent
e5b6ec4d05
commit
aa00b53ba1
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue