Define custom HTTP headers
The Vault server and its clients communicate through HTTP requests. Vault responses contain headers that describe the content and include important security settings. Modifications to these headers may be necessary to meet an organization's requirements.
Challenge
Security requirements demand that the Vault server's response headers include customized fields for all requested paths.
Solution
Vault 1.9.0 introduced the ability to configure customizable headers at the
HTTP root path (/
) and on API endpoints (/v1/*
) through the Vault server
configuration file.
This tutorial demonstrates how to specify custom HTTP headers in the Vault
server configuration file by defining them in the custom_response_headers
stanza.
Prerequisites
To perform the tasks described in this tutorial, you need to have:
- A Vault environment of version 1.9 or later. Refer to the Getting Started tutorial to install Vault. Make sure that your Vault server has been initialized and unsealed.
Define Vault configuration
Create a Vault configuration file named vault-custom_headers.hcl
.
$ cat > vault-custom_headers.hcl <<EOFstorage "inmem" {} api_addr = "http://127.0.0.1:8200"cluster_addr = "https://127.0.0.1:8201"ui = true listener "tcp" { address = "127.0.0.1:8200" tls_disable = "true" custom_response_headers { "default" = { "Content-Security-Policy" = ["connect-src https://cluster.vault.external"], "X-Custom-Header" = ["Vault created header to meet security requirements"] }, "200" = { "X-Custom-Header" = ["200 customized header to meet security requirements"] }, "3xx" = { "X-Custom-Header" = ["3xx customized header to meet security requirements"] } }}EOF
The custom_response_headers
stanza is defined in the listener
stanza. This
stanza states that:
- every response, by
default
, includes a modifiedContent-Security-Policy
value and defines a new custom header,X-Custom-Header
. - 200 responses override the value of the custom header
X-Custom-Header
. - 3xx responses (e.g. 301, 302, 307) override the value of the custom header
X-Custom-Header
.
Learn more
Refer to the Vault tcp listener documentation for additional references and examples.
Start Vault
The Vault server loads its configuration when it starts.
Start the Vault server.
$ vault server -config=vault-custom_headers.hcl
The server listens at 127.0.0.1:8200
.
In another terminal, export an environment variable for the vault
CLI to
address the Vault server.
$ export VAULT_ADDR=http://127.0.0.1:8200
The server is uninitialized and sealed.
Initialize the Vault server and ouput the unseal key and root token to
vault-custom_headers-init-keys.json
.
$ vault operator init -key-shares 1 -key-threshold 1 -format json > vault-custom_headers-init-keys.json
Insecure operation
Vault should be initialized with more than a single key share and threshold in a production environment.
The server initializes and writes an unseal key and root token to
vault-custom_headers-init-keys.json
.
Create a variable named VAULT_UNSEAL_KEY
that is assigned the unseal key.
$ VAULT_UNSEAL_KEY=$(cat vault-custom_headers-init-keys.json | jq -r ".unseal_keys_b64[]")
Unseal the Vault server with the unseal key.
$ vault operator unseal $VAULT_UNSEAL_KEY
The command reports that Vault is initialized and unsealed.
Create an environment variable named VAULT_TOKEN
that is assigned the root token.
$ export VAULT_TOKEN=$(cat vault-custom_headers-init-keys.json | jq -r ".root_token")
The vault
CLI authenticates each command with the value stored in the
VAULT_TOKEN
environment variable.
Make a request
Request the root page of the Vault server.
$ curl --head --location \ --header "X-Vault-Request: true" \ --header "X-Vault-Token: $(vault print token)" \ http://127.0.0.1:8200/
The output displays two responses. The first response has status code 307
.
HTTP/1.1 307 Temporary RedirectCache-Control: no-storeContent-Security-Policy: connect-src https://cluster.vault.externalContent-Type: text/html; charset=utf-8Location: /ui/Strict-Transport-Security: max-age=31536000; includeSubDomainsX-Custom-Header: 3xx customized header to meet security requirements
It contains the Content-Security-Policy
and X-Custom-Header
fields. The
Content-Security-Policy
field is set to the value defined as default
for all
headers. The X-Custom-Header
field is set to the value defined for all 3xx
responses.
The second response has status code 200
.
HTTP/1.1 200 OKAccept-Ranges: bytesCache-Control: no-storeContent-Length: 5094Content-Security-Policy: connect-src https://cluster.vault.externalContent-Type: text/html; charset=utf-8Service-Worker-Allowed: /Strict-Transport-Security: max-age=31536000; includeSubDomainsVary: Accept-EncodingX-Content-Type-Options: nosniffX-Custom-Header: 200 customized header to meet security requirements
It contains the Content-Security-Policy
and X-Custom-Header
fields. The
Content-Security-Policy
field is set to the value defined as default
for all
headers. The X-Custom-Header
field is set to the value defined for the 200
response.
Request an invalid path of the Vault server.
$ curl --head --location \ --header "X-Vault-Request: true" \ --header "X-Vault-Token: $(vault print token)" \ http://127.0.0.1:8200/not_found
The response has the status code 404
.
HTTP/1.1 404 Not FoundCache-Control: no-storeContent-Security-Policy: connect-src https://cluster.vault.externalContent-Type: application/jsonStrict-Transport-Security: max-age=31536000; includeSubDomainsX-Custom-Header: Vault created header to meet security requirementsContent-Length: 14
It contains the Content-Security-Policy
and X-Custom-Header
fields that are
set to the value defined as default
for all headers.
Help and reference
In this tutorial, you configured a Vault server to return customized headers default to all requests or assigned to specific requests based on the return code. Learn more about customizing Vault HTTP Headers by referring to the tcp listener configuration documentation.