Vault
Vault Agent and Vault Proxy quick start
Adopting a new tool can be challenging for an growing organization. Common challenges include resistance to change, lack of expertise, integration complexities, and ensuring proper training. Vault Agent and Vault Proxy simplify and streamline the integration of applications with HashiCorp Vault, making secrets management more efficient and user-friendly.
Vault Agent simplifies secrets management by acting as a client-side daemon. It handles authentication, secret retrieval, and caching for applications, reducing the need for application code changes and improving security. It allows applications to access secrets without needing direct integration with Vault, making it easier to adopt Vault in existing environments.
Vault Proxy simplifies integrating applications with HashiCorp Vault by acting as an API proxy, handling authentication, token renewal, and caching. It allows applications to access Vault secrets without needing direct integration with Vault, potentially easing the initial hurdle to adoption.
Both tools help streamline the adoption of HashiCorp Vault, making it easier to secure sensitive data without significant application refactoring.
What is Vault Agent?
Vault Agent behaves as a client-side daemon to make requests to Vault on behalf of the client application. This includes the authentication to Vault.
Vault clients (human users, applications, etc.) must authenticate with Vault and get a client token to make API requests. Because tokens have time-to-live (TTL), the clients must renew the token's TTL or re-authenticate to Vault based on its TTL. Vault Agent authenticates with Vault and manages the token's lifecycle so that the client application doesn't have to.
In addition, you can inject Consul Template markup into Vault Agent to render secrets into files where the client application loads data from.
 

This eliminates the need to change your application code to invoke the Vault API. Your existing applications can remain Vault-unaware.
Prerequisites
To complete this tutorial, you need to install the Vault binary.
Launch Terminal
This tutorial includes a free interactive command-line lab that lets you follow along on actual cloud infrastructure.
Lab setup
Note
If you do not have access to an HCP Vault Dedicated cluster, visit the Create a Vault Cluster on HCP tutorial.
- Launch the HCP Portal and login. 
- Click Vault in the left navigation pane. 
- In the Vault clusters pane, click vault-cluster. 
- Under Cluster URLs, click Public Cluster URL.  
- In a terminal, set the - VAULT_ADDRenvironment variable to the copied address.- $ export VAULT_ADDR=<Public_Cluster_URL>
- Return to the Overview page and click Generate token.  
- Copy the Admin Token. 
- Return to the terminal and set the - VAULT_TOKENenvironment variable.- $ export VAULT_TOKEN=<token>
- Set the - VAULT_NAMESPACEenvironment variable to- admin.- $ export VAULT_NAMESPACE=admin- The - adminnamespace is the top-level namespace automatically created by HCP Vault. All CLI operations default to use the namespace defined in this environment variable.
- Log in to HCP Vault Dedicated. - $ vault login $VAULT_TOKEN WARNING! The VAULT_TOKEN environment variable is set! The value of this variable will take precedence; if this is unwanted please unset VAULT_TOKEN or update its value accordingly. 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.CAESIGFwyvuxqc319bArV9jVMV_3gZH3OV434JYu8niYpDRRGigKImh2cy5oRjlaWVhtYWtBN1U1QUV4cnpZV1Bjb2kuWDhXaDIQyIAM token_accessor Ri7jMehrYjAWvnN7EufsRX9O.X8Wh2 token_duration 5h56m42s token_renewable false token_policies ["default" "hcp-root"] identity_policies [] policies ["default" "hcp-root"]- Tip - Vault server is ready and the token value saved in the - $HOME/.vault-tokenfile.
- Enable Key/Value v2 secrets engine at - secret/.- $ vault secrets enable -path=secret kv-v2 Success! Enabled the kv-v2 secrets engine at: secret/
Create a working directory
- Create a directory where you generate test files. - $ mkdir $HOME/vault-test && cd $HOME/vault-test- You will read the created secrets using Vault Agent. 
Create test data
- Create a mock data file. - $ tee 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 mock data in the KV v2 secrets engine. - $ vault kv put secret/customers/acme @data.json ======= Secret Path ======= secret/data/customers/acme ======= Metadata ======= Key Value --- ----- created_time 2023-02-23T16:25:46.030960819Z custom_metadata <nil> deletion_time n/a destroyed false version 1
Start a Vault Agent
Start a Vault Agent instance that connects to the Vault server running at
VAULT_ADDR.
- Create the Vault Agent configuration file. - $ tee agent-config.hcl -<<EOF pid_file = "./pidfile" vault { address = "$VAULT_ADDR" tls_skip_verify = true } auto_auth { method { type = "token_file" namespace = "$VAULT_NAMESPACE" config = { token_file_path = "$HOME/.vault-token" } } sink "file" { config = { path = "$HOME/vault-token-via-agent" } } } EOF
- Start a Vault Agent. - $ vault agent -config=agent-config.hcl- Example output: - ==> Vault Agent started! Log data will stream in below: ==> Vault Agent configuration: Cgo: disabled Log Level: Version: Vault v1.13.0, built 2023-02-14T14:25:23Z Version Sha: c2d6b060c0eec60393e866b761a5990716cb45de [INFO] vault-agent.sink.file: creating file sink [INFO] vault-agent.sink.file: file sink configured: path=$HOME/vault-token-via-agent mode=-rw-r----- [INFO] vault-agent.template.server: starting template server [INFO] vault-agent.template.server: no templates found [INFO] vault-agent.auth.handler: starting auth handler [INFO] vault-agent.auth.handler: authenticating [INFO] vault-agent.sink.server: starting sink server ...snip...
At this point, you still need to change your client application to make Vault
requests targeting VAULT_ADDR using the Vault token stored in the sink
location ($HOME/vault-token-via-agent).
Next, explore other Vault Agent features.
Define Vault Agent template
In the following scenario, the client application loads data read from customer.json.
- Press Ctrl + C to stop the running Vault Agent. 
- Create a - customer.json.tmplfile.- $ tee customer.json.tmpl -<<EOF { {{ with secret "secret/data/customers/acme" }} "Organization": "{{ .Data.data.organization }}", "ID": "{{ .Data.data.customer_id }}", "Contact": "{{ .Data.data.contact_email }}" {{ end }} } EOF
- Create a Vault Agent configuration file with a - templatestanza.- $ tee agent-template.hcl -<<EOF template { source = "$HOME/vault-test/customer.json.tmpl" destination = "$HOME/vault-test/customer.json" } EOF
- Start Vault Agent again with the additional configuration applied. - $ vault agent -config=agent-config.hcl \ -config=agent-template.hcl- Example output: - ==> Vault Agent started! Log data will stream in below: ==> Vault Agent configuration: Api Address 1: http://bufconn Cgo: disabled Log Level: Version: Vault v1.13.0-rc1+ent, built 2023-02-14T14:25:23Z Version Sha: c2d6b060c0eec60393e866b761a5990716cb45de [INFO] vault-agent.sink.file: creating file sink [INFO] vault-agent.sink.file: file sink configured: path=$HOME/vault-token-via-agent mode=-rw-r----- [INFO] vault-agent.auth.handler: starting auth handler [INFO] vault-agent.auth.handler: authenticating [INFO] vault-agent.template.server: starting template server ...snip... [INFO] (runner) starting [INFO] (runner) rendered "$HOME/vault-test/customer.json.tmpl" => "$HOME/vault-test/customer.json"
- Open a new browser or text editor and verify that the - customer.jsonfile has the secrets retrieved from Vault.- $ cat customer.json- Example output: - { "Organization": "ACME Inc.", "ID": "ABXX2398YZPIE7391", "Contact": "james@acme.com" }- This should match the data stored in - secret/.- $ vault kv get secret/customers/acme ======= Secret Path ======= secret/data/customers/acme ======= Metadata ======= Key Value --- ----- created_time 2023-02-23T16:25:46.030960819Z 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- If the template fails, make sure to set the - VAULT_NAMESPACEvariable.- $ echo $VAULT_NAMESPACE admin
The client application loads data from the customer.json file.
By leveraging the Vault Agent Template feature, you did not have to make any
code changes to the client application while you manage secrets with Vault.
Vault Agent logs
You can specify the behavior of Vault Agent logging using a command flag, environment variable, or configuration parameters.
- Start Vault Agent with the - -log-filecommand flag which defines the prefix for the log file.- $ vault agent -config=agent-config.hcl \ -log-file=$HOME/vault-test/vault-agent.log- The command generates a log file named - $HOME/vault-test/vault-agent.log.
- Verify the generated log file. - $ ls | grep .log vault-agent.log- You can open the file to verify its content. - $ cat vault-agent.log [INFO] vault-agent.sink.file: creating file sink [INFO] vault-agent.sink.file: file sink configured: path=/Users/yoko/vault-token-via-agent mode=-rw-r----- [INFO] vault-agent.template.server: starting template server [INFO] vault-agent.template.server: no templates found [INFO] vault-agent.auth.handler: starting auth handler [INFO] vault-agent.sink.server: starting sink server [INFO] vault-agent.auth.handler: authenticating [INFO] vault-agent.auth.handler: authentication successful, sending token to sinks ...snip...
Tip
To see the full list of available parameters, refer to the Vault Agent documentation.
Vault Proxy
Vault Proxy acts as a proxy between Vault and its client applications. See the Vault Agent and Vault Proxy documentation page for more details about feature parity between Vault Agent and Vault Proxy.
 

Vault Proxy provides auto-auth, caching, and API proxy functionality.
| Capability | Vault Agent | Vault Proxy | 
|---|---|---|
| Auto-auth to authenticate with Vault | ✅ | ✅ | 
| Run as a Windows Service | ✅ | ✅ | 
| Caching the newly created tokens and leases | ✅ | ✅ | 
| Templating to render user-supplied templates | ✅ | ❌ | 
| Process supervisor for injecting secrets as environment variables into a process | ✅ | ❌ | 
| API proxy to act as a proxy for Vault API | Deprecated | ✅ | 
| Static secret caching for KV secrets | ❌ | ✅ | 
The vault and auto_auth stanzas in the Vault Proxy and Vault Agent
configurations are identical; however, you must define listener and
api_proxy stanzas for Vault Proxy.
Example configuration for Vault Proxy:
vault-proxy-config.hcl
pid_file = "./pidfile"
vault {
   address = "http://127.0.0.1:8200"
   tls_skip_verify = true
}
auto_auth {
   method {
      type = "token_file"
      config = {
         token_file_path = "$HOME/.vault-token"
      }
   }
   sink "file" {
      config = {
            path = "$HOME/vault-proxy"
      }
   }
}
listener "tcp" {
   address     = "127.0.0.1:8100"
   tls_disable = true
}
api_proxy {
   use_auto_auth_token = true
   enforce_consistency = "always"
}
cache {
   cache_static_secrets = true
   static_secret_token_capability_refresh_interval = "5m"
}
Start a Vault Proxy
You can define an API endpoint for the client application to send requests to
rather than VAULT_ADDR.
- Press Ctrl + C to stop the running Vault Agent. 
- Create a file that defines the - listenerstanza and- api_proxystanza.- $ tee vault-proxy-config.hcl -<<EOF pid_file = "./pidfile" vault { address = "$VAULT_ADDR" tls_skip_verify = true } auto_auth { method { type = "token_file" namespace = "$VAULT_NAMESPACE" config = { token_file_path = "$HOME/.vault-token" } } sink "file" { config = { path = "$HOME/vault-token-via-agent" } } } listener "tcp" { address = "127.0.0.1:8100" tls_disable = true } api_proxy { use_auto_auth_token = true enforce_consistency = "always" } cache { cache_static_secrets = true static_secret_token_capability_refresh_interval = "5m" } EOF- This configuration creates a listener endpoint on the loop-back interface - 127.0.0.1:8100. You can add multiple- listenerstanzas. See the Vault Proxy documentation for more information.- The - api_proxystanza enables the- use_auto_auth_tokenparameter. When enabled, proxied requests do not need to set the- X-Vault-TokenHTTP header. Request will use the auto-auth token by default.- Set the - cache_static_secretsparameter in the- cachestanza to true to enable the static secrets caching feature. This enables Vault Proxy to cache static secrets read from the KV v1 and KV v2 secrets engines.- Note that the persistent caching feature available in Vault Community Edition is only supported in Kubernetes environments and does not cache static secrets. 
- Start the Vault Proxy. - $ vault proxy -config=vault-proxy-config.hcl- Vault Proxy is now listening to the proxy addresses - http://127.0.0.1:8100.- ==> Vault Proxy started! Log data will stream in below: ==> Vault Proxy configuration: Api Address 1: http://127.0.0.1:8100 Cgo: disabled Log Level: Version: Vault v1.16.0, built 2024-02-12T16:07:06Z Version Sha: 2ca8655bfeb501c0937240df2828ef0fb7c78de1
- Open another command terminal and send an API request to the Vault Proxy. - Read the secrets at - secret/customers/acmevia the proxy address.- This example uses jq to process the JSON output for readability. - $ curl -s http://127.0.0.1:8100/v1/secret/data/customers/acme \ | jq -r ".data.data"- Output: - { "contact_email": "james@acme.com", "customer_id": "ABXX2398YZPIE7391", "organization": "ACME Inc.", "region": "US-West", "status": "active", "type": "premium", "zip_code": "94105" }- A token was automatically attached to the request by the Vault Proxy because you set the - use_auto_auth_tokenparameter to- truein the configuration.
Static secret caching
Enterprise feature
The static secret caching feature is available with Vault Enterprise.- Exit the Vault Proxy and Vault community edition process by pressing Ctrl + C. 
- Update the - vault-proxy-config.hclto set- cache_static_secretsto- truein the- cachestanza.- vault-proxy-config.hcl - cache { cache_static_secrets = true static_secret_token_capability_refresh_interval = "5m" }
- Open a terminal and export an environment variable with a valid Vault Enterprise license. - $ export VAULT_LICENSE=0S3ASM3STC0OKI3....
- Reset the VULT_ADDR and VAULT_TOKEN environment variables. - $ export VAULT_ADDR=http://127.0.0.1:8200
- Login to Vault again. - $ vault login root
- In the same terminal start a Vault Enterprise dev server with - rootas the root token value.- $ vault server -dev -dev-root-token-id root
- Open a terminal and start the Vault Proxy with the static secret caching feature. - $ vault proxy -config=vault-proxy-config.hcl
- Resetting Vault Enterprise dev server cleaned out the preexisting secrets. Create a new secret. - $ vault kv put secret/customers/acme @data.json
- Read the secrets twice. Vault Proxy caches the secret when you first access it. The second time you access the secret, Vault proxy returns the cached secret. - $ curl --verbose -s http://127.0.0.1:8100/v1/secret/data/customers/acme \ | jq -r ".data.data"- Use the - --verboseor- -voption with the cURL command so that you can see more detail.- * Trying 127.0.0.1:8100... * Connected to 127.0.0.1 (127.0.0.1) port 8100 > GET /v1/secret/data/customers/acme HTTP/1.1 > Host: 127.0.0.1:8100 > User-Agent: curl/8.4.0 > Accept: */* > < HTTP/1.1 200 OK < Age: 65 < Cache-Control: no-store < Content-Length: 483 < Content-Type: application/json < Date: Tue, 20 Feb 2024 19:28:17 GMT < Strict-Transport-Security: max-age=31536000; includeSubDomains < X-Cache: HIT < { [483 bytes data] * Connection #0 to host 127.0.0.1 left intact { "contact_email": "james@acme.com", "customer_id": "ABXX2398YZPIE7391", "organization": "ACME Inc.", "region": "US-West", "status": "active", "type": "premium", "zip_code": "94105" }- Notice that the - X-Cacheis- HIT.
- Update the secrets to see what happens. - $ vault kv patch secret/customers/acme "customer_since"="2011"
- Read the secrets again via proxy. - $ curl --verbose http://127.0.0.1:8100/v1/secret/data/customers/acme \ | jq -r ".data.data"- The - Agevalue changed since the secrets were just updated.- * Trying 127.0.0.1:8100... * Connected to 127.0.0.1 (127.0.0.1) port 8100 > GET /v1/secret/data/customers/acme HTTP/1.1 > Host: 127.0.0.1:8100 > User-Agent: curl/8.4.0 > Accept: */* > < HTTP/1.1 200 OK < Age: 8 < Cache-Control: no-store < Content-Length: 506 < Content-Type: application/json < Date: Tue, 20 Feb 2024 19:29:21 GMT < Strict-Transport-Security: max-age=31536000; includeSubDomains < X-Cache: HIT < { [506 bytes data] * Connection #0 to host 127.0.0.1 left intact { "contact_email": "james@acme.com", "customer_id": "ABXX2398YZPIE7391", "customer_since": "2011", "organization": "ACME Inc.", "region": "US-West", "status": "active", "type": "premium", "zip_code": "94105" }
- Back in the terminal with the proxy running, press Ctrl + C to stop the running Vault Proxy. 
Self-healing tokens
Auto-auth is responsible for authenticating with Vault to obtain a client token, storing it, and managing its lifecycle. Vault Agent and Vault Proxy's auto-auth capabilities can recover from invalid token errors, such as those caused by unexpected events like a Vault administrator revoking the client token in use.
Test the self-healing capability
- Create a script to setup - approleauth method.- $ tee setup-approle.sh -<<EOF ## Create a policy named "read-only" vault policy write read-only -<<EOL path "secret/*" { capabilities = ["read", "list"] } EOL ## Enable and configure approle auth method vault auth enable approle vault write auth/approle/role/read-only policies=read-only token_num_uses=5 ## Retrive role ID and secret ID vault read -field=role_id auth/approle/role/read-only/role-id > $HOME/vault-test/roleID.txt vault write -f -field=secret_id auth/approle/role/read-only/secret-id > $HOME/vault-test/secretID.txt EOF- This script: - Creates a policy named read-onlywhich allows read and list operations against paths starts withsecret/.
- Enables approleauth method.
- Creates a role named read-onlywhich has the read-only policy attached. The token for this role has a use limit of 5.
- Retrieves the role ID for the read-onlyrole and store the value in theroleID.txtfile.
- Retrieves the secret ID and store the value in the secretID.txtfile.
 
- Creates a policy named 
- Make the script executable. - $ chmod +x setup-approle.sh
- Run the script to setup an - approleauth method.- $ ./setup-approle.sh Success! Uploaded policy: read-only Success! Enabled approle auth method at: approle/ Success! Data written to: auth/approle/role/read-only
- Create a new Vault Proxy configuration which uses - approleauth method.- $ tee vault-proxy-config-2.hcl -<<EOF pid_file = "./pidfile" vault { address = "$VAULT_ADDR" tls_skip_verify = true } auto_auth { method { type = "approle" config = { role_id_file_path = "$HOME/vault-test/roleID.txt" secret_id_file_path = "$HOME/vault-test/secretID.txt" } } sink "file" { config = { path = "$HOME/vault-token-via-agent" } } } listener "tcp" { address = "127.0.0.1:8100" tls_disable = true } api_proxy { use_auto_auth_token = true enforce_consistency = "always" } EOF
- Start a Vault Proxy. - $ vault proxy -config=vault-proxy-config-2.hcl
- From another command terminal, read the secrets through the proxy. - $ curl -s http://127.0.0.1:8100/v1/secret/data/customers/acme \ | jq -r ".data.data"- The command returns the secrets. - { "contact_email": "james@acme.com", "customer_id": "ABXX2398YZPIE7391", "organization": "ACME Inc.", "region": "US-West", "status": "active", "type": "premium", "zip_code": "94105" }
- Revoke the token stored in the - sinklocation.- $ vault token revoke $(cat $HOME/vault-token-via-agent) Success! Revoked token (if it existed)
- Try to read the secrets again. - $ curl -s http://127.0.0.1:8100/v1/secret/data/customers/acme \ | jq -r ".data.data"- The request fails and returns no data. 
- In the terminal where Vault Proxy is running, check the Vault Proxy 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- The log indicates - invalid token errorbecause you revoked the client token. The Vault Agent re-authenticate with Vault to get a new token, and stores it in the- sinklocation.
- Try to read the secret. This time, you should received the secrets. - $ curl -s http://127.0.0.1:8100/v1/secret/data/customers/acme \ | jq -r ".data.data"
Clean up
- Press Ctrl + C to stop the running Vault Agent. 
- Unset the - VAULT_TOKEN,- VAULT_NAMESPACEand- VAULT_ADDRenvironment variables.- $ unset VAULT_TOKEN VAULT_ADDR VAULT_NAMESPACE
- Delete the - $HOME/vault-testdirectory.- $ cd .. && rm -r $HOME/vault-test
Summary
This tutorial demonstrated the basics of Vault Agent. You learned how to configure and run Vault Agent and Vault Proxy.
The use of token_file in the auto-auth stanza is a convenient way to start the Vault Agent or Vault Proxy. For a production deployment, use one of the supported auth methods so that the Vault Agent or Vault Proxy can properly manage the token's lifecycle.
See the following tutorials for auto-auth examples:
The Vault Agent Template demonstrated that the client application can remain Vault-unaware while Vault manages the secrets.
See the following tutorials to see more template examples: