OpenBao agent templates
OpenBao Agent's Template functionality allows OpenBao secrets to be rendered to files or environment variables (via the Process Supervisor Mode) using Consul Template markup.
Functionality
The template_config
stanza configures overall default behavior for the
templating engine. Note that template_config
can only be defined once, and is
different from the template
stanza. Unlike template
which focuses on where
and how a specific secret is rendered, template_config
contains parameters
affecting how the templating engine as a whole behaves and its interaction with
the rest of Agent. This includes, but is not limited to, program exit behavior.
Other parameters that apply to the templating engine as a whole may be added
over time.
The template
stanza configures the OpenBao agent for rendering secrets to files
using Consul Template markup language. Multiple template
stanzas can be
defined to render multiple files.
When the agent is started with templating enabled, it will attempt to acquire a OpenBao token using the configured auto-auth Method. On failure, it will back off for a short while (including some randomness to help prevent thundering herd scenarios) and retry. On success, secrets defined in the templates will be retrieved from OpenBao and rendered locally.
Templating language
The template output content can be provided directly as part of the contents
option in a template
stanza or as a separate .ctmpl
file and specified in
the source
option of a template
stanza.
In order to fetch secrets from OpenBao, whether those are static secrets, dynamic
credentials, or certificates, OpenBao Agent templates require the use of the
secret
function
or pkiCert
function
from Consul Template.
The secret
function works for all types of secrets and depending on the type
of secret that's being rendered by this function, template will have different
renewal behavior as detailed in the Renewals
section. The pkiCert
function is intended to
work specifically for certificates issued by the PKI Secrets
Engine. Refer to the Certificates section
for differences in certificate renewal behavior between secret
and pkiCert
.
The following links contain additional resources for the templating language used by OpenBao Agent templating.
Template language example
The following is an example of a template that retrieves a generic secret from OpenBao's KV store:
{{ with secret "secret/my-secret" }}
{{ .Data.data.foo }}
{{ end }}
The following is an example of a template that issues a PKI certificate in OpenBao's PKI secrets engine. The fetching of the certificate or key from a PKI role through this function will be based on the certificate's expiration.
To generate a new certificate and create a bundle with the key, certificate, and CA, use:
{{ with pkiCert "pki/issue/my-domain-dot-com" "common_name=foo.example.com" }}
{{ .Data.Key }}
{{ .Data.Cert }}
{{ .Data.CA }}
{{ end }}
To fetch only the issuing CA for this mount, use:
{{- with secret "pki/cert/ca" -}}
{{ .Data.certificate }}
{{- end -}}
Alternatively, pki/cert/ca_chain
can be used to fetch the full CA chain.
Global configurations
The top level template_config
block has the following configuration entries that affect
all templates:
-
exit_on_retry_failure
(bool: false)
- This option configures OpenBao Agent to exit after it has exhausted its number of template retry attempts due to failures. -
static_secret_render_interval
(string or integer: 5m)
- If specified, configures how often OpenBao Agent Template should render non-leased secrets such as KV v2. This setting will not change how often OpenBao Agent Templating renders leased secrets. Uses duration format strings.
template_config
stanza example
template_config {
exit_on_retry_failure = true
static_secret_render_interval = "10m"
}
In another example template_config
with error_on_missing_key
parameter in the template stanza
as well as exit_on_retry_failure
result in the agent exiting in case of no key
/ value issues instead of the default retry behavior.
template_config {
exit_on_retry_failure = true
static_secret_render_interval = "10m"
}
template {
source = "/tmp/agent/template.ctmpl"
destination = "/tmp/agent/render.txt"
error_on_missing_key = true
}
Interaction between exit_on_retry_failure
and error_on_missing_key
The parameter
error_on_missing_key
can be
specified within the template
stanza which determines if a template should
error when a key is missing in the secret. When error_on_missing_key
is not
specified or set to false
and the key to render is not in the secret's
response, the templating engine will ignore it (or render "<no value>"
) and
continue on with its rendering.
If the desire is to have Agent fail and exit on a missing key, both
template.error_on_missing_key
and template_config.exit_on_retry_failure
must
be set to true. Otherwise, the templating engine will error and render to its
destination, but agent will not exit and will retry until the key exists or until
the process is terminated.
Note that a missing key from a secret's response is different from a missing or
non-existent secret. The templating engine will always error if a secret is
missing, but will only error for a missing key if error_on_missing_key
is set.
Whether OpenBao Agent will exit when the templating engine errors depends on the
value of exit_on_retry_failure
.
Template configurations
The top level template
block has multiple configuration entries. The
parameters found in the template configuration section in the consul-template
documentation
page
can be used here:
The parameters marked with Δ
below are only applicable to file templates and
cannot be used with env_template
entries in process supervisor mode.
source
(string: "")
- Path on disk to use as the input template. This option is required if not using thecontents
option.destination
Δ(string: required)
- Path on disk where the rendered secrets should be created. If the parent directories do not exist, OpenBao Agent will attempt to create them, unlesscreate_dest_dirs
is false.create_dest_dirs
Δ(bool: true)
- This option tells OpenBao Agent to create the parent directories of the destination path if they do not exist.contents
(string: "")
- This option allows embedding the contents of a template in the configuration file rather then supplying thesource
path to the template file. This is useful for short templates. This option is mutually exclusive with thesource
option.command
Δ(string: "")
- This is the optional command to run when the template is rendered. The command will only run if the resulting template changes. The command must return within 30s (configurable), and it must have a successful exit code. OpenBao Agent is not a replacement for a process monitor or init system. This is deprecated in favor of theexec
option.command_timeout
Δ(duration: 30s)
- This is the maximum amount of time to wait for the optional command to return. This is deprecated in favor of theexec
option.error_on_missing_key
(bool: false)
- Exit with an error when accessing a struct or map field/key that does notexist. The default behavior will print<no value>
when accessing a field that does not exist. It is highly recommended you set this to "true". Also seeexit_on_retry_failure
in global OpenBao Agent Template Config.exec
Δ(object: optional)
- The exec block executes a command when the template is rendered and the output has changed. The block parameters arecommand
(string or array: required)
andtimeout
(string: optional, defaults to 30s)
.command
can be given as a string or array of strings to execute, such as"touch myfile"
or["touch", "myfile"]
. To protect against command injection, we strongly recommend using an array of strings, and we attempt to parse that way first. Note also that using a comma with the string approach will cause it to be interpreted as an array, which may not be desirable.perms
Δ(string: "")
- This is the permission to render the file. If this option is left unspecified, OpenBao Agent will attempt to match the permissions of the file that already exists at the destination path. If no file exists at that path, the permissions are 0644.backup
Δ(bool: true)
- This option backs up the previously rendered template at the destination path before writing a new one. It keeps exactly one backup. This option is useful for preventing accidental changes to the data without having a rollback strategy.left_delimiter
(string: "\{\{")
- Delimiter to use in the template. The default is "{{" but for some templates, it may be easier to use a different delimiter that does not conflict with the output file itself.right_delimiter
(string: "}}")
- Delimiter to use in the template. The default is "}}" but for some templates, it may be easier to use a different delimiter that does not conflict with the output file itself.sandbox_path
Δ(string: "")
- If a sandbox path is provided, any path provided to thefile
function is checked that it falls within the sandbox path. Relative paths that try to traverse outside the sandbox path will exit with an error.wait
Δ(object: required)
- This is theminimum(:maximum)
to wait before rendering a new template to disk and triggering a command, separated by a colon (:
).
Example template
stanza
template {
source = "/tmp/agent/template.ctmpl"
destination = "/tmp/agent/render.txt"
error_on_missing_key = true
}
If you only want to use the OpenBao agent to render one or more templates and do
not need to sink the acquired credentials, you can omit the sink
stanza from
the auto_auth
stanza in the agent configuration.
Renewals and updating secrets
The OpenBao Agent templating automatically renews and fetches secrets/tokens. Unlike OpenBao Agent caching, the behavior of how OpenBao Agent templating does this depends on the type of secret or token. The following is a high level overview of different behaviors.
Renewable secrets
If a secret or token is renewable, OpenBao Agent will renew the secret after 2/3 of the secret's lease duration has elapsed.
Non-Renewable secrets
If a secret or token isn't renewable or leased, OpenBao Agent will fetch the secret every 5 minutes. This can be configured using Template config static_secret_render_interval. Non-renewable secrets include (but not limited to) KV Version 2.
Non-Renewable leased secrets
If a secret or token is non-renewable but leased, OpenBao Agent will fetch the secret when 85% of the secrets time-to-live (TTL) is reached. Leased, non-renewable secrets include (but not limited to) dynamic secrets such as database credentials and KV Version 1.
Static roles
If a secret has a rotation_period
, such as a database static role,
OpenBao Agent template will fetch the new secret as it changes in OpenBao. It does
this by inspecting the secret's time-to-live (TTL).
Certificates
Certificates can be rendered using either pkiCert
or
secret
template functions, although it is recommended to use pkiCert
to
avoid unnecessarily generating certificates whenever Agent restarts or
re-authenticates.
Rendering using the pkiCert
template function
If a certificate is rendered using the pkiCert
template
function, OpenBao Agent template will have the following fetching and re-rendering
behaviors on certificates:
- Fetches a new certificate on Agent startup if none has been previously rendered or the current rendered one has expired.
- On Agent's auto-auth re-authentication, due to a token expiry for example, skip fetching unless the current rendered one has expired.
Rendering using the secret
template function
If a certificate is rendered using the secret
template
function, OpenBao Agent template will have the following fetching and re-rendering
behaviors on certificates:
- Fetches a new certificate on Agent startup, even if previously rendered certificates are still valid.
- If
generate_lease
is unset or set tofalse
, it uses the certificate'svalidTo
field to determine re-fetch interval. - If
generate_lease
is set totrue
, apply the non-renewable, leased secret rules. - On Agent's auto-auth re-authentication, due to a token expiry for example, it fetches and re-renders a new certificate even if the existing certificate is valid.
Templating configuration example
The following demonstrates OpenBao Agent Templates configuration blocks.
# Other OpenBao agent configuration blocks
# ...
template_config {
static_secret_render_interval = "10m"
exit_on_retry_failure = true
}
template {
source = "/tmp/agent/template.ctmpl"
destination = "/tmp/agent/render.txt"
}
template {
contents = "{{ with secret \"secret/my-secret\" }}{{ .Data.data.foo }}{{ end }}"
destination = "/tmp/agent/render-content.txt"
}
And the following demonstrates how the templates look when using env_template
with
Process Supervisor Mode
# Other OpenBao agent configuration blocks
# ...
template_config {
static_secret_render_interval = "10m"
exit_on_retry_failure = true
}
env_template "MY_ENV_VAR" {
contents = "{{ with secret \"secret/my-secret\" }}{{ .Data.data.foo }}{{ end }}"
}
env_template "ENV_VAR_FROM_FILE" {
source = "/tmp/agent/template.ctmpl"
}