Architecture
Vault is a complex system that has many different pieces. To help both users and developers of Vault build a mental model of how it works, this page documents the system architecture.
Advanced Topic! This page covers technical details of Vault. You don't need to understand these details to effectively use Vault. The details are documented here for those who wish to learn about them without having to go spelunking through the source code. However, if you're an operator of Vault, we recommend learning about the architecture due to the importance of Vault in an environment.
High-Level Overview
A very high level overview of Vault looks like this:
Let's begin to break down this picture. There is a clear separation of components that are inside or outside of the security barrier. Only the storage backend and the HTTP API are outside, all other components are inside the barrier.
The storage backend is untrusted and is used to durably store encrypted data. When the Vault server is started, it must be provided with a storage backend so that data is available across restarts. The HTTP API similarly must be started by the Vault server on start so that clients can interact with it.
When a Vault server is started, it starts in a sealed state. Before any operation can be performed on the Vault, it must be unsealed. This is done by providing the unseal keys. When the Vault is initialized, it generates an encryption key which is used to protect all Vault data. This key is protected by a root key. By default, Vault uses Shamir's Secret Sharing to split the root key into a configured number of shards (referred as key shares or unseal keys). A certain threshold of shards is required to reconstruct the root key, which is then used to decrypt the Vault's encryption key.
Refer to the Seal/Unseal documentation for further details.
The number of shares and the minimum threshold required can both be specified. Shamir's technique can be disabled, and the root key can be used directly for unsealing. Once Vault retrieves the encryption key, it is able to decrypt the data in the storage backend, and enters the unsealed state. Once unsealed, Vault loads all of the configured audit devices, auth methods, and secrets engines.
The default Vault configuration uses a Shamir seal; however, Vault can be auto unseal by a trusted cloud key management system (KMS) or hardware security module (HSM) to increase security.
The configuration of those audit devices, auth methods, and secrets engines must be stored in Vault since they are security sensitive. Only users with the correct permissions should be able to modify them, meaning they cannot be specified outside of the barrier. By storing them in Vault, any changes to them are protected by the ACL system and tracked by audit logs.
After the Vault is unsealed, requests can be processed from the HTTP API to the Core. The core is used to manage the flow of requests through the system, enforce ACLs, and ensure audit logging is done.
When a client first connects to Vault, it needs to authenticate. Vault provides configurable auth methods providing flexibility in the authentication mechanism used. Human friendly mechanisms such as username/password or GitHub might be used for operators, while applications may use public/private keys or tokens to authenticate. An authentication request flows through core and into an auth method, which determines if the request is valid and returns a list of associated policies.
Policies are just a named ACL rule. For example, the "root" policy is built-in
and permits access to all resources. You can create any number of named policies
with fine-grained control over paths. Vault operates exclusively in a allowed-access
mode, meaning that unless access is explicitly granted via a policy, the action
is not allowed. Since a user may have multiple policies associated, an action is
allowed if any policy permits it. Policies are stored and managed by an internal
policy store. This internal store is manipulated through the system backend,
which is always mounted at sys/
.
Once authentication takes place and an auth method provides a set of applicable policies, a new client token is generated and managed by the token store. This client token is sent back to the client, and is used to make future requests. This is similar to a cookie sent by a website after a user logs in. The client token may have a lease associated with it depending on the auth method configuration. This means the client token may need to be periodically renewed to avoid invalidation.
Once authenticated, requests are made providing the client token. The token is used to verify the client is authorized and to load the relevant policies. The policies are used to authorize the client request. The request is then routed to the secrets engine, which is processed depending on its type. If the secrets engine returns a secret, the core registers it with the expiration manager and attaches a lease ID. The lease ID is used by clients to renew or revoke their secret. If a client allows the lease to expire, the expiration manager automatically revokes the secret.
The core handles logging of requests and responses to the audit broker, which fans the request out to all the configured audit devices. Outside of the request flow, the core performs certain background activity. Lease management is critical, as it allows expired client tokens or secrets to be revoked automatically. Additionally, Vault handles certain partial failure cases by using write ahead logging with a rollback manager. This is managed transparently within the core and is not user visible.
Getting in Depth
This has been a brief high-level overview of the architecture of Vault. There are more details available for each of the sub-systems.
For other details, either consult the code, ask in IRC or reach out to the mailing list.