Bringing OpenBao into the Infrastructure as Code world: fetching dynamic database credentials and PKI certificates through the Vault Provider in OpenTofu or Terraform, as well as the community.hashi_vault lookup plugin in Ansible playbooks.

In episode 13 you fetched temporary credentials inside CI/CD pipelines. Episode 14 extends the same principle to infrastructure provisioning: OpenTofu or Terraform fetch dynamic credentials and PKI certificates while building resources, while Ansible fetches secrets directly inside the playbook. The result: no secrets are manually copied into code or inventory.
HashiCorp provides the vault provider for Terraform. Because OpenBao is built to be API-compatible with Vault, the same provider can be used for OpenBao. This means all the capabilities — including dynamic credentials and PKI — work without needing a special provider.
The provider is pointed at the OpenBao address and configured to log in with a token:
terraform {
required_providers {
vault = {
source = "hashicorp/vault"
}
}
}
provider "vault" {
address = "https://bao.internal.example.com"
token = var.bao_token
}address points to the OpenBao address; the token can come from CI/CD or a bootstrap process. For production, avoid static tokens — use a dynamic secret or AppRole response-wrapping.
When provisioning builds infrastructure, you can also request dynamic credentials for the application that will attach to it:
data "vault_database_creds" "app" {
backend = "database"
role = "app-role"
}
output "app_db_user" {
value = data.vault_database_creds.app.username
}
output "app_db_password" {
value = data.vault_database_creds.app.password
sensitive = true
}Each apply triggers the creation of a new database user with a TTL matching the role. Sensitive values are marked with sensitive = true so they are not printed in the output or the pipeline logs.
For a new machine that needs a certificate, the PKI data source issues a certificate valid for the role's TTL:
data "vault_pki_secret_backend_sign" "app" {
backend = "pki"
role = "server"
common_name = "app.internal.example.com"
ttl = "24h"
}
resource "local_file" "cert" {
filename = "/etc/ssl/app.pem"
content = "${data.vault_pki_secret_backend_sign.app.certificate}\n"
}The certificate is written directly to the machine during provisioning, so there is no need to copy-paste certificates manually or store them in the repository.
For secrets that are indeed static, such as application configuration, use the vault_generic_secret data source. This data source reads values from any path in OpenBao and suits values that do not change.
Tip
Store the provider token carefully. Use vault_generic_secret for static secrets, or better yet a dynamic secret via vault_database_creds — so credentials never settle in the state file.
For configuration work that is imperative in nature, Ansible provides the community.hashi_vault lookup plugin. This lookup is executed when the playbook is compiled, so its value is available for use as variables, templates, or module arguments.
- hosts: webservers
vars:
db_password: "{{ lookup('community.hashi_vault.vault_kv2_get',
'secret/data/app',
url='https://bao.internal.example.com',
token=api_token) }}"
tasks:
- name: Tulis konfigurasi aplikasi
ansible.builtin.template:
src: app.env.j2
dest: /etc/app/app.envThe vault_kv2_get lookup reads a secret from the KV v2 engine. Its value is returned as an object; to get a specific field, access it with result.data.data.db_password when needed.
| Aspect | OpenTofu / Terraform | Ansible |
|---|---|---|
| When it runs | During provisioning plan and apply | When the playbook runs |
| Mechanism | vault provider and data sources | community.hashi_vault lookup plugin |
| Common use | Dynamic DB creds, PKI when building resources | Variables for host configuration |
| Credentials in state | Values stored in the state file | Values exist only at runtime |
In short: OpenTofu or Terraform fits when secrets are born together with the provisioned resources; Ansible fits when secrets are used for configuration after the machine is up.
In this episode 14, you understood using the vault provider in OpenTofu and Terraform to fetch dynamic database credentials and PKI certificates during provisioning, learned about vault_generic_secret for static secrets, and the community.hashi_vault.vault_kv2_get lookup plugin in Ansible playbooks.
Key takeaways:
vault provider is compatible with OpenBao thanks to API equivalence.In the next episode, episode 15, we step up to the architecture level: building an OpenBao High Availability cluster with Raft integrated storage and understanding the role of active and standby nodes.