module "database" { source = "../modules/database" for_each = module.config.databases name = each.key owner = each.value.owner pgvector = each.value.pgvector } module "database_access" { source = "../modules/database-access" for_each = module.config.service_databases role = each.value.role owner = module.database[each.value.database].owner } resource "vault_kv_secret_v2" "postgres" { for_each = module.config.service_databases mount = module.config.vault.mount name = "${each.value.service}/postgres/${each.value.database}" delete_all_versions = true data_json = jsonencode({ host = module.config.postgres.internal_host port = module.config.postgres.internal_port database = module.database[each.value.database].name username = module.database_access[each.key].username password = module.database_access[each.key].password sslmode = module.config.postgres.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 = module.database role = postgresql_role.vault.name grant_role = each.value.owner with_admin_option = true } 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=${module.config.postgres.sslmode}" username = postgresql_role.vault.name password = random_password.vault.result allowed_roles = keys(module.config.service_databases) } } resource "vault_database_secret_backend_role" "service" { for_each = module.config.service_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.owner}\";", "ALTER ROLE \"{{name}}\" SET role = \"${each.value.owner}\";", ] revocation_statements = [ "DROP ROLE IF EXISTS \"{{name}}\";", ] default_ttl = 3600 max_ttl = 86400 depends_on = [postgresql_grant_role.vault] }