module "app_database" { source = "../modules/app-database" for_each = local.databases service = { name = each.key, database = each.value } } resource "vault_kv_secret_v2" "postgres" { for_each = local.databases mount = module.config.vault.mount name = "${each.key}/postgres" delete_all_versions = true data_json = jsonencode(merge(module.app_database[each.key].credentials, { host = module.config.postgres.internal_host port = module.config.postgres.internal_port sslmode = each.value.sslmode })) } resource "random_password" "vault" { length = 32 special = false } resource "postgresql_role" "vault" { name = "vault" login = true create_role = true password = random_password.vault.result lifecycle { ignore_changes = [roles] } } resource "postgresql_grant_role" "vault" { for_each = local.databases role = postgresql_role.vault.name grant_role = each.value.username with_admin_option = true depends_on = [module.app_database] } resource "vault_database_secrets_mount" "postgres" { path = module.config.vault.database_mount postgresql { name = "postgres" connection_url = "postgresql://{{username}}:{{password}}@${module.config.postgres.internal_host}:${module.config.postgres.internal_port}/postgres?sslmode=disable" username = postgresql_role.vault.name password = random_password.vault.result allowed_roles = keys(local.databases) } } resource "vault_database_secret_backend_role" "service" { for_each = local.databases backend = vault_database_secrets_mount.postgres.path name = each.key db_name = vault_database_secrets_mount.postgres.postgresql[0].name creation_statements = [ "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' IN ROLE \"${each.value.username}\";", "ALTER ROLE \"{{name}}\" SET role = \"${each.value.username}\";", ] revocation_statements = [ "DROP ROLE IF EXISTS \"{{name}}\";", ] default_ttl = 3600 max_ttl = 86400 depends_on = [postgresql_grant_role.vault] }