vault: handle read of key upgrades

This commit is contained in:
Armon Dadgar 2015-05-28 16:11:31 -07:00
parent 796ae59a89
commit 82ef0b1ac7
1 changed files with 87 additions and 0 deletions

View File

@ -38,6 +38,14 @@ const (
// lockRetryInterval is the interval we re-attempt to acquire the
// HA lock if an error is encountered
lockRetryInterval = 10 * time.Second
// keyRotateCheckInterval is how often a standby checks for a key
// rotation taking place.
keyRotateCheckInterval = 30 * time.Second
// keyRotateGracePeriod is how long we allow an upgrade path
// for standby instances before we delete the upgrade keys
keyRotateGracePeriod = 2 * time.Minute
)
var (
@ -1163,6 +1171,15 @@ func (c *Core) postUnseal() error {
if cache, ok := c.physical.(*physical.Cache); ok {
cache.Purge()
}
// HA mode requires us to handle keyring rotation and rekeying
if c.ha != nil {
if err := c.checkKeyUpgrades(); err != nil {
return err
}
if err := c.barrier.ReloadKeyring(); err != nil {
return err
}
}
if err := c.loadMounts(); err != nil {
return err
}
@ -1241,6 +1258,16 @@ func (c *Core) preSeal() error {
func (c *Core) runStandby(doneCh, stopCh chan struct{}) {
defer close(doneCh)
c.logger.Printf("[INFO] core: entering standby mode")
// Monitor for key rotation
keyRotateDone := make(chan struct{})
keyRotateStop := make(chan struct{})
go c.periodicCheckKeyUpgrade(keyRotateDone, keyRotateStop)
defer func() {
close(keyRotateStop)
<-keyRotateDone
}()
for {
// Check for a shutdown
select {
@ -1318,6 +1345,66 @@ func (c *Core) runStandby(doneCh, stopCh chan struct{}) {
}
}
// periodicCheckKeyUpgrade is used to watch for key rotation events as a standby
func (c *Core) periodicCheckKeyUpgrade(doneCh, stopCh chan struct{}) {
defer close(doneCh)
for {
select {
case <-time.After(keyRotateCheckInterval):
// Only check if we are a standby
c.stateLock.RLock()
standby := c.standby
c.stateLock.RUnlock()
if !standby {
continue
}
if err := c.checkKeyUpgrades(); err != nil {
c.logger.Printf("[ERR] core: upgrade due to key rotation failed: %v", err)
}
case <-stopCh:
return
}
}
}
// checkKeyUpgrades is used to check if there have been any key rotations
// and if there is a chain of upgrades available
func (c *Core) checkKeyUpgrades() error {
for {
// Get the current term
info, err := c.barrier.ActiveKeyInfo()
if err != nil {
return err
}
// Check for an upgrade key
upgrade := fmt.Sprintf("%s%d", keyringUpgradePrefix, info.Term)
entry, err := c.barrier.Get(upgrade)
if err != nil {
return err
}
// Nothing to do if no upgrade
if entry == nil {
break
}
// Deserialize the key
key, err := DeserializeKey(entry.Value)
if err != nil {
return err
}
// Add the key
if err := c.barrier.AddKey(key); err != nil {
return err
}
c.logger.Printf("[INFO] core: upgraded to key term %d", key.Term)
}
return nil
}
// acquireLock blocks until the lock is acquired, returning the leaderCh
func (c *Core) acquireLock(lock physical.Lock, stopCh <-chan struct{}) <-chan struct{} {
for {