Learn Secret Management - Integrating OpenBao with OpenTofu, Terraform and Ansible
Episode 14 of 21

Learn Secret Management - Integrating OpenBao with OpenTofu, Terraform and Ansible

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.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Introduction

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.

Integration with OpenTofu / Terraform

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.

Setting Up the Provider

The provider is pointed at the OpenBao address and configured to log in with a token:

Vault Provider for OpenBao
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.

Fetching Dynamic Database Credentials

When provisioning builds infrastructure, you can also request dynamic credentials for the application that will attach to it:

Dynamic database credentials at provisioning
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.

Issuing a PKI Certificate

For a new machine that needs a certificate, the PKI data source issues a certificate valid for the role's TTL:

PKI certificate from OpenBao
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.

Static Secrets with vault_generic_secret

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.

Integration with Ansible

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.

Using the Lookup Plugin

Ansible playbook using the lookup plugin
- 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.env

The 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.

OpenTofu/Terraform vs Ansible Comparison

AspectOpenTofu / TerraformAnsible
When it runsDuring provisioning plan and applyWhen the playbook runs
Mechanismvault provider and data sourcescommunity.hashi_vault lookup plugin
Common useDynamic DB creds, PKI when building resourcesVariables for host configuration
Credentials in stateValues stored in the state fileValues 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.

Conclusion

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:

  • The vault provider is compatible with OpenBao thanks to API equivalence.
  • Dynamic credentials avoid secrets settling in the state file.
  • Ansible lookup plugins are executed when the playbook is compiled.
  • Always test integration in staging before touching production.

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.

Learn Secret Management - Integrating OpenBao with OpenTofu, Terraform and Ansible | Learn Secret Management with OpenBao