diff --git a/builtin/logical/database/path_roles.go b/builtin/logical/database/path_roles.go index f68611af4261..b135eaf3d6aa 100644 --- a/builtin/logical/database/path_roles.go +++ b/builtin/logical/database/path_roles.go @@ -837,7 +837,7 @@ func (s *staticAccount) NextRotationTime() time.Time { if s.UsesRotationPeriod() { return s.LastVaultRotation.Add(s.RotationPeriod) } - return s.Schedule.Next(s.LastVaultRotation) + return s.Schedule.Next(time.Now()) } // NextRotationTimeFromInput calculates the next rotation time for period and @@ -879,10 +879,9 @@ func (s *staticAccount) IsInsideRotationWindow(t time.Time) bool { // // This will return true when the priority <= the current Unix time. If this // static account is schedule-based with a rotation window, this method will -// return false if now is outside the rotation window. -func (s *staticAccount) ShouldRotate(priority int64) bool { - now := time.Now() - return priority <= now.Unix() && s.IsInsideRotationWindow(now) +// return false if t is outside the rotation window. +func (s *staticAccount) ShouldRotate(priority int64, t time.Time) bool { + return priority <= t.Unix() && s.IsInsideRotationWindow(t) } // SetNextVaultRotation diff --git a/builtin/logical/database/rotation.go b/builtin/logical/database/rotation.go index 98778da91c42..d1bd3b81ebc5 100644 --- a/builtin/logical/database/rotation.go +++ b/builtin/logical/database/rotation.go @@ -217,7 +217,33 @@ func (b *databaseBackend) rotateCredential(ctx context.Context, s logical.Storag logger = logger.With("database", role.DBName) - if !role.StaticAccount.ShouldRotate(item.Priority) { + input := &setStaticAccountInput{ + RoleName: roleName, + Role: role, + } + + now := time.Now() + if !role.StaticAccount.ShouldRotate(item.Priority, now) { + if !role.StaticAccount.IsInsideRotationWindow(now) { + // We are a schedule-based rotation and we are outside a rotation + // window so we update priority and NextVaultRotation + item.Priority = role.StaticAccount.NextRotationTimeFromInput(now).Unix() + role.StaticAccount.SetNextVaultRotation(now) + b.logger.Trace("outside schedule-based rotation window, update priority", "next", role.StaticAccount.NextRotationTime()) + + // write to storage after updating NextVaultRotation so the next + // time this item is checked for rotation our role that we retrieve + // from storage reflects that change + entry, err := logical.StorageEntryJSON(databaseStaticRolePath+input.RoleName, input.Role) + if err != nil { + logger.Error("unable to encode entry for storage", "error", err) + return false + } + if err := s.Put(ctx, entry); err != nil { + logger.Error("unable to write to storage", "error", err) + return false + } + } // do not rotate now, push item back onto queue to be rotated later if err := b.pushItem(item); err != nil { logger.Error("unable to push item on to queue", "error", err) @@ -226,11 +252,6 @@ func (b *databaseBackend) rotateCredential(ctx context.Context, s logical.Storag return false } - input := &setStaticAccountInput{ - RoleName: roleName, - Role: role, - } - // If there is a WAL entry related to this Role, the corresponding WAL ID // should be stored in the Item's Value field. if walID, ok := item.Value.(string); ok {