Open-Source Wikis

/

Vault

/

Systems

/

Core

hashicorp/vault

Core

vault.Core is the central object instantiated by every Vault server process. It owns the storage barrier, mount tables, token store, identity store, policy store, expiration manager, audit broker, plugin catalog, and the lifecycle that turns a sealed binary into an active cluster member. Source: vault/core.go (5,042 lines) plus dozens of core_*.go siblings.

Purpose

Hold every long-lived subsystem and orchestrate their lifecycle: init → seal → unseal → standby/active → seal → shutdown. Every HTTP request lands in Core.HandleRequest (vault/request_handling.go).

Directory layout

vault/
├── core.go                       # the Core struct and most lifecycle methods
├── core_metrics.go               # periodic metric emission
├── core_metrics_oss.go           # CE stub
├── core_stubs_oss.go             # CE stubs for Enterprise hooks
├── core_util.go, core_util_common.go
├── request_handling.go           # HandleRequest, the per-request pipeline
├── request_handling_ce.go        # CE stub
├── ha.go                         # active/standby state machine, leader election
├── seal.go, seal_*.go            # seal/unseal, autoseal, key rotation
├── init.go                       # first-time initialization (master key, root token)
├── rekey.go                      # rekey of barrier and recovery keys
├── generate_root.go              # operator generate-root flow
├── rollback.go                   # periodic per-mount rollback ticker
├── policy.go, policy_store.go    # policy storage
├── acl.go, acl_util.go           # capability checks
├── mount.go                      # mount tables
├── router.go, router_access.go   # URL routing
├── token_store.go                # token CRUD
├── identity_store.go (+16 more)  # entities, aliases, groups, OIDC
├── expiration.go                 # leases and renewal
├── login_mfa.go                  # login-time MFA
├── audit.go                      # mount/unmount of audit devices
├── quotas/                       # rate-limit and lease-count quotas
├── plugincatalog/                # external plugin metadata
├── seal/                         # the seal package (separate from seal.go)
├── eventbus/                     # in-process pub/sub
├── replication/                  # CE replication hooks (mostly stubs)
└── ...

Key abstractions

Symbol File Description
Core vault/core.go The god object. ~150 fields.
CoreConfig vault/core.go Configuration passed by command/server.go when constructing a Core.
NewCore vault/core.go Constructor; wires up mounts, audit broker, expiration manager, and plugin catalog.
Core.HandleRequest vault/request_handling.go Per-request pipeline: identity, policy, audit, route, response.
Core.Initialize / Core.Init vault/init.go First-time setup: generate master key, write barrier keyring, mint root token.
Core.Unseal vault/seal.go Provide an unseal share or a KMS key to unwrap the keyring.
Core.Seal / Core.SealAccess vault/seal.go, vault/seal_access.go Seal the core (shut down handlers and zero the keyring in memory).
Core.runStandby vault/ha.go Standby loop that participates in leader election.
Core.PostUnseal vault/core.go Hook run after unseal; mounts backends, starts expiration.
Core.PreSeal vault/core.go Hook run before seal; flushes audit, stops timers, unmounts backends.
Core.checkToken vault/request_handling.go Token + ACL check for an incoming request.

Lifecycle states

stateDiagram-v2
    [*] --> Sealed: NewCore
    Sealed --> Initialized: Initialize (first time only)
    Sealed --> Unsealing: Unseal (key share or KMS)
    Initialized --> Sealed: Seal
    Unsealing --> Standby: keyring assembled, not active
    Standby --> Active: leader lock acquired
    Active --> Standby: leader lock lost
    Active --> Sealed: explicit Seal or fatal error
    Standby --> Sealed: explicit Seal
    Sealed --> [*]: shutdown

The states are exposed through vault read sys/seal-status. The active/standby split lets a cluster member receive requests but forward writes to the active node via vault/request_forwarding.go.

Per-request pipeline

Core.HandleRequest (vault/request_handling.go, 3,140 lines) is the canonical pipeline:

  1. Resolve namespace and parse path.
  2. Look up the token in the token store.
  3. Apply login MFA if the request is a login.
  4. Check ACL capabilities (vault/acl.go).
  5. Apply quotas (vault/quotas/).
  6. Audit-log the request (audit/).
  7. Route to the backend (vault/router.go).
  8. If the backend returned a Secret/Auth, register a lease (vault/expiration.go) or mint a token (vault/token_store.go).
  9. Audit-log the response.
  10. Return.

Every step has its own helper file (request_handling_util.go, request_handling_ce.go, request_handling_filtered.go, …).

Integration points

  • Storage: Core holds the physical backend, the barrier, and the keyring; backends only see the storage view supplied by the router.
  • Listeners: opened by command/server.go; the HTTP handler calls into Core.
  • Plugins: vault/plugincatalog/ is owned by Core and passed to backends through their system view.
  • Replication: hooks at vault/replication/ and vault/forwarded_writer_oss.go are present in OSS but mostly empty.
  • Metrics: vault/core_metrics.go (36k lines) emits per-second snapshots of mounts, tokens, leases, audit health.

Entry points for modification

  • New lifecycle hook: extend Core.PostUnseal / Core.PreSeal and call your subsystem's Setup / Teardown.
  • New per-request step: add to Core.HandleRequest in vault/request_handling.go. Be careful — every step here must be O(1) in the request size and avoid blocking I/O when possible.
  • New storage path on core/: paths under core/ are reserved for Core's own metadata (mount table, keyring, leader lock, …). Don't reuse them.

For step-by-step request behavior see Architecture / request lifecycle.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Core – Vault wiki | Factory