hashicorp/vault
Expiration and leases
Every dynamic secret, token, and renewable auth in Vault has a lease, and the expiration manager is what tracks them. Source: vault/expiration.go (3,116 lines), with shared helpers in vault/expiration_util_ce.go and vault/expiration_testing_util_common.go.
Purpose
- Persist a record for every issued lease so it survives restarts.
- Schedule per-lease timers that fire at the lease's expiry (or earlier on demand) and trigger revocation.
- Handle renewals against the issuing backend.
- Implement bulk operations: revoke-by-prefix, revoke-by-token, force-revoke, leader-only re-claim.
Directory layout
vault/
├── expiration.go # Manager + lease entries + revoker pool
├── expiration_testing_util_common.go
├── expiration_util_ce.go # CE stub
helper/fairshare/ # The fair-share work queue used by the revokerKey abstractions
| Symbol | File | Description |
|---|---|---|
ExpirationManager |
vault/expiration.go |
Holds the lease state; one per Core. |
leaseEntry |
vault/expiration.go |
The persisted record: ID, issue time, expiry time, namespace, mount, secret, auth, version. |
ExpirationManager.Register |
vault/expiration.go |
Called from Core.HandleRequest whenever a backend returns a Secret or Auth. |
ExpirationManager.Revoke |
vault/expiration.go |
Single-lease revoke. Calls into the issuing backend. |
ExpirationManager.RevokePrefix |
vault/expiration.go |
Bulk revoke by mount path; used at unmount. |
ExpirationManager.RevokeByToken |
vault/expiration.go |
Used when a token is revoked: clean up all leases issued through it. |
| Fair-share scheduler | helper/fairshare/ |
Per-namespace queue so noisy mounts don't starve quiet ones. |
How a lease is born
sequenceDiagram
participant H as Core.HandleRequest
participant B as Backend
participant E as ExpirationManager
participant Phys as Storage barrier
participant Tim as time.Timer
H->>B: HandleRequest(read|write|...)
B-->>H: *logical.Response{Secret: {LeaseID, TTL, Renewable}}
H->>E: Register(req, resp)
E->>Phys: persist leaseEntry
E->>Tim: set timer for expiry
H-->>Caller: response (LeaseID + TTL exposed)When the timer fires (or vault lease revoke <id> is called), the manager loads the lease, calls the originating backend's RevokeOperation, deletes the lease entry on success, and removes the parent/child edges.
Renewal
vault lease renew <id> calls into ExpirationManager.Renew, which:
- Loads the leaseEntry.
- Asks the backend to renew (
framework.Backend.HandleExistenceCheckplus the secret'sRenewcallback). - Extends the timer up to
MaxTTLorPeriod. - Persists the updated leaseEntry.
Tokens have their own renewal path (auth/token/renew) that ultimately funnels into ExpirationManager.RenewToken.
Restart behavior
On Core unseal the manager re-loads every lease entry and rebuilds its timer wheel. Lease entries that have expired during downtime are scheduled for immediate revocation. The "revocation backlog" metric in core_metrics.go reports how many of these are still outstanding.
Fair-share queue
Revocation is CPU- and IO-bound; pursuing thousands at once can knock storage over. helper/fairshare/ provides a multi-queue scheduler where each mount or namespace is a queue. Workers round-robin between queues so a single noisy mount can't starve revocation for everyone else.
Integration points
- Token store calls
RevokeByTokenwhen a token is revoked. - Mount / unmount calls
RevokePrefixto clean up leases at unmount time. - Replication uses
RegisterAuthand lease tombstones to keep secondary clusters in sync. - Quotas (
vault/quotas/) read lease counts to enforce lease-count limits. - The activity log subscribes to lease events to count clients.
Entry points for modification
- Add a new lease attribute: extend
leaseEntryinvault/expiration.goand bump the version. - Tweak revoker behavior: see
revokeWorkerand the fair-share configuration. - Add a per-mount default TTL: handled at the framework layer (
sdk/framework/lease.go) plus the mount tunables invault/mount.go.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.