Vault Proxy Integration#
HashiCorp Vault proxy is a lightweight, client-side daemon designed to simplify interactions with HashiCorp Vault, automating critical tasks like authentication, token renewal, and static secret caching.
What Is HashiCorp Vault Proxy?#
Vault Proxy aims to remove the initial hurdle to adopt Vault by providing a more scalable and simpler way for applications to integrate with Vault. Vault Proxy acts as an API Proxy for Vault, and can optionally allow or force interacting clients to use its automatically authenticated token.
Key Features of Vault Proxy#
- Automated Authentication (Auto-Auth)
- Supports multiple authentication methods such as AppRole, Kubernetes, and AWS. This auto-auth feature automatically handles the process of authenticating to Vault, eliminating manual steps.
- Token and Lease Management and Renewal
- Once authenticated, Vault Agent continuously monitors token and lease expiration. It automatically renews tokens and leases as needed, ensuring applications maintain uninterrupted access to secrets.
- Caching
- Allows client-side caching of responses containing newly created tokens, responses containing leased secrets, and static KV secrets.
- API Proxy
- Acts as a proxy for communicating with Vault's API, optionally using (or forcing the use of) the Auto-Auth token.
Please view the Vault Proxy Documentation for more information on features.
Potential Use Cases#
High-Performance Environments#
In systems where high throughput is critical, local caching provided by the Vault Proxy reduces latency by serving secrets directly from cache. This is particularly beneficial in microservices architectures and real-time applications where speed is paramount.
Disaster Recovery and Business Continuity#
By caching secrets locally, the Vault Proxy ensures that in the event of a temporary Vault server outage, applications can still access critical secrets. This capability is vital for maintaining business continuity during maintenance or unexpected disruptions.
QuickStart with Proxy#
Pre-requisites#
- Ensure you have installed the Vault Enterprise Binary
Setup#
-
Export an environmental variable for the Vault CLI to access the Vault server.
Bashexport VAULT_ADDR=<VAULT_ADDRESS>
-
Export an environmental variable for the Vault CESI Namespace.
Bashexport VAULT_NAMESPACE=admin/<CESI_NAMESPACE>
-
Login to Vault. Make sure to set the
-namespace
flag to adminBashvault login -method=saml -namespace=admin Success! You are now authenticated. The token information displayed below is already stored in the token helper. You do NOT need to run "vault login" again. Future Vault requests will automatically use this token. Key Value --- ----- token hvs.token token_accessor accessor token_duration 1h token_renewable true token_policies ["default"] identity_policies ["default"] policies ["default"] token_meta_role saml_role
Create a Working Directory#
- Create a directory to store configuration and template files.
mkdir $HOME/vault-test && cd $HOME/vault-test
Create data#
-
Create a data file
Bashtee data.json -<<EOF { "organization": "ACME Inc.", "customer_id": "ABXX2398YZPIE7391", "region": "US-West", "zip_code": "94105", "type": "premium", "contact_email": "james@acme.com", "status": "active" } EOF
-
Create the data in a KV v2 Secrets Engine
Bashvault kv put secret/customers/acme @data.json
Create an AppRole#
Auto-auth authenticates with Vault to get a client token, store, and manage the token lifecycle. Vault Agent can heal from an invalid token error caused by unexpected incidence (for example, Vault admin revoked the client token used by the Vault Agent). We will be using an AppRole to configure the token and to enable this self-healing capability and enable the static secret caching feature.
For easier implementation, AppRoles can also be configured with terraform from our examples repo.
Note
If installing multiple proxies, please try to reduce the number of roles needed for the agent to preserve client count. Vault considers an AppRole to be only 1 client as long as the same Role ID is used.
Please contact the secrets management team for additional questions.
- Create a policy for the approle auth method with permission to subscribe to KV event updates with the Vault event notification system. For example, to create a policy that grants access to static secret (KVv1 and KVv2) events, you need permission to subscribe to the events endpoint, as well as the list and subscribe permissions on KV secrets you want to get secrets from.
- By subscribing to KV events, that means that Proxy will receive updates as soon as a secret changes, which reduces staleness in the cache. Vault Proxy will only check for a secret update if an event notification indicates that the related secret was updated
vault policy write proxy -<<EOL
path "sys/events/subscribe/kv*" {
capabilities = ["read"]
}
path "*" {
capabilities = ["list", "subscribe"]
subscribe_event_types = ["kv*"]
}
path "secret/*" {
capabilities = ["read", "list"]
}
path "sys/leases/*" {
capabilities = ["create", "update"]
}
path "auth/token/*" {
capabilities = ["create", "update"]
}
EOL
capabilities-self
access to allows tokens to request cached secrets.
1. Vault tokens receive update permissions by default. If you have modified or removed the default policy, you must explicitly create a policy with the appropriate permissions.
path "sys/capabilities-self" {
capabilities = ["update"]
}
vault write auth/approle/role/proxy policies=proxy token_num_uses=5
vault read -field=role_id auth/approle/role/proxy/role-id > $HOME/vault-test/roleID.txt
vault write -f -field=secret_id auth/approle/role/proxy/secret-id > $HOME/vault-test/secretID.txt
Start a Vault Proxy#
Note
If you are having issues with the Vault Proxy, please make sure the $VAULT_NAMESPACE environmental variable has been correctly set
You will be reading the secrets created above with the Vault Agent while using an AppRole for auto authentication
- Create a Vault Agent configuration file
tee proxy-config.hcl -<<EOF
pid_file = "./pidfile"
vault {
address = $VAULT_ADDR
tls_skip_verify = true
}
auto_auth {
method {
type = "approle"
config = {
role_id_file_path = "/home/$HOME/vault-test/roleID.txt"
secret_id_file_path = "/home/$HOME/vault-test/secretID.txt"
}
}
sink "file" {
config = {
path = "/home/$HOME/vault-token-via-agent"
}
}
}
// Address in which the proxy will listen on
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = true
}
api_proxy {
// if use_auto_auth_token is enabled, auto_auth stanza must be configured
use_auto_auth_token = true
enforce_consistency = "always"
}
cache {
// Requires Vault Enterprise 1.16 or later
cache_static_secrets = true
static_secret_token_capability_refresh_interval = "5m" //Determines how often Proxy needs to verify and update cached tokens and secrets
}
EOF
log-level
set to debug. Take note of the Api Address
from the proxy configuration
vault proxy -config=vault-proxy-config-2.hcl -log-level=debug
Example output:
==> Vault Proxy started! Log data will stream in below:
==> Vault Proxy configuration:
Api Address 1: http://127.0.0.1:8200
Cgo: disabled
Log Level: debug
Version: Vault v1.18.4+ent, built 2025-01-29T14:07:00Z
Version Sha: a7b6963bc01c138f0b8e24163597817234b8d517
2025-02-25T14:41:40.240-0600 [INFO] proxy.sink.file: creating file sink
2025-02-25T14:41:40.241-0600 [INFO] proxy.sink.file: file sink configured: path=/home/$HOME/vault-token-via-agent mode=-rw-r----- owner=1036104 group=1036104
2025-02-25T14:41:40.241-0600 [INFO] proxy.cache: cache configured: cache_static_secrets=true disable_caching_dynamic_secrets=false
2025-02-25T14:41:40.242-0600 [DEBUG] proxy.apiproxy: configuring inmem auto-auth sink
2025-02-25T14:41:40.243-0600 [DEBUG] proxy: would have sent systemd notification (systemd not present): notification=READY=1
2025-02-25T14:41:40.243-0600 [INFO] proxy.cache.staticsecretcacheupdater: starting static secret cache updater subsystem
2025-02-25T14:41:40.243-0600 [INFO] proxy.auth.handler: starting auth handler
2025-02-25T14:41:40.243-0600 [INFO] proxy.auth.handler: authenticating
2025-02-25T14:41:40.243-0600 [INFO] proxy.sink.server: starting sink server
2025-02-25T14:41:40.291-0600 [INFO] proxy.auth.handler: authentication successful, sending token to sinks
2025-02-25T14:41:40.292-0600 [INFO] proxy.sink.file: token written: path=/home/$HOME/vault-token-via-agent
2025-02-25T14:41:40.293-0600 [DEBUG] proxy.cache.leasecache: storing auto-auth token into the cache
2025-02-25T14:41:40.293-0600 [INFO] proxy.auth.handler: starting renewal process
2025-02-25T14:41:40.334-0600 [INFO] proxy.auth.handler: renewed auth token
2025-02-25T14:41:40.426-0600 [DEBUG] proxy.cache.staticsecretcacheupdater: starting pre-event stream update of static secrets
2025-02-25T14:41:40.427-0600 [DEBUG] proxy.cache.staticsecretcacheupdater: finished pre-event stream update of static secrets
...snip...
Self-Healing Tokens#
As we configured the AppRole above, it should now automatically refresh its token in an event that the TTL expires or the token is revoked. This can be viewed in the logs
...snip...
[INFO] proxy.apiproxy: proxy received an invalid token error
[INFO] proxy.auth.handler: invalid token found, re-authenticating
[INFO] proxy.auth.handler: authenticating
[INFO] proxy.auth.handler: authentication successful, sending token to sinks
[INFO] proxy.auth.handler: starting renewal process
[INFO] proxy.sink.file: token written: path=/user/vault-token-via-agent
[INFO] proxy.auth.handler: renewed auth token
Cache Static Secrets#
- In a separate terminal or window, export the environmental variables for
VAULT_ADDR
. Use the API Address that was configured for you for theVAULT_ADDR
Bashexport VAULT_ADDR=<API_ADDRESS>
- Run a command to fetch the sample data.
vault kv get secret/customers/acme
======= Secret Path =======
secret/data/customers/acme
======= Metadata =======
Key Value
--- -----
created_time 2025-02-14T17:46:02.756842519Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
======== Data ========
Key Value
--- -----
contact_email james@acme.com
customer_id ABXX2398YZPIE7391
organization ACME Inc.
region US-West
status active
type premium
zip_code 94105
Example output:
[INFO] proxy.apiproxy: received request: method=GET path=/v1/secret/data/customers/acme
[DEBUG] proxy.cache.leasecache: forwarding request from cache: method=GET path=/v1/secret/data/customers/acme
[INFO] proxy.apiproxy: forwarding request to Vault: method=GET path=/v1/secret/data/customers/acme
[DEBUG] proxy.apiproxy.client: performing request: method=GET url=https://VAULT_ADDRESS:8200/v1/secret/data/customers/acme
[DEBUG] proxy.cache.leasecache: storing static secret response into the cache: path=admin/CESI_UNIT/secret/data/customers/acme id=5b8b353a20d950abe9643fe141eb571ac83ecfb818940acd7271bac252d9a61b
vault kv get secret/customers/acme
again. The vault proxy should now fetch the cached secrets which can be seen in the logs.
[INFO] proxy.apiproxy: received request: method=GET path=/v1/secret/data/customers/acme
[DEBUG] proxy.cache.leasecache: returning cached static secret response: id=5b8b353a20d950abe9643fe141eb571ac83ecfb818940acd7271bac252d9a61b path=admin/CESI_UNIT/secret/data/customers/acme
static_secret_token_capability_refresh_interval
parameter within the cache stanza of the Proxy config, the cache will evict it's contents containing tokens and secrets. Secrets are not renewed and are newly cached during each call to read the secrets.
[DEBUG] proxy.cache.staticsecretcapabilitymanager: successfully evicted capabilities index from cache: index.ID=7b1ffbb375f7104b1ada51236306a7399c5dd0a9332bfbc3dd08c7fb81e4d2ac