Search code examples
terraformmongodb-atlashashicorp-vaultvault

When using terraform to build a mongodb atlas cluster how do i use dynamic secrets through vault


I'm trying to get my terraform (which manages our mongo atlas infrastructure) to use dynamic secrets (through vault, running on localhost for now) when terraform is connecting to atlas, but I cant seem to get it to work.

I can't find any examples of how to do this so I have put together a sample github repo showing the few things I've tried to do so far.

All the magic is contained in the 3 provider files. I have the standard method of connecting to atlas using static keys (even with said keys generated as temporary API keys through vault) see provider1.tf

The problem comes when I try and use the atlas vault secret engine for terraform along with the mongo atlas provider. There are just no examples!

My question is how do I use the atlas vault secret engine to generate and use temporary keys when provisioning infrastructure with terraform?

I've tried two different ways of wiring up the providers, see files provider2.tf and provider3.tf, code is copied here:

provider2.tf

provider "mongodbatlas" {
  public_key = vault_database_secrets_mount.db.mongodbatlas[0].public_key
  private_key  = vault_database_secrets_mount.db.mongodbatlas[0].private_key
}

provider "vault" {
  address = "http://127.0.0.1:8200"
}

resource "vault_database_secrets_mount" "db" {
  path = "db"

  mongodbatlas {
    name = "foo"
    public_key = var.mongodbatlas_org_public_key
    private_key = var.mongodbatlas_org_private_key
    project_id = var.mongodbatlas_project_id
  }
}

provider3.tf

provider "mongodbatlas" {
  public_key = vault_database_secret_backend_connection.db2.mongodbatlas[0].public_key
  private_key  = vault_database_secret_backend_connection.db2.mongodbatlas[0].private_key
}

resource "vault_mount" "db1" {
  path = "mongodbatlas01"
  type = "database"
}

resource "vault_database_secret_backend_connection" "db2" {
  backend       = vault_mount.db1.path
  name          = "mongodbatlas02"
  allowed_roles = ["dev", "prod"]

  mongodbatlas {
    public_key = var.mongodbatlas_org_public_key
    private_key = var.mongodbatlas_org_private_key
    project_id = var.mongodbatlas_project_id
  }
}

Both methods give the same sort of error:

mongodbatlas_cluster.cluster-terraform01: Creating...
╷
│ Error: error creating MongoDB Cluster: POST https://cloud.mongodb.com/api/atlas/v1.0/groups/10000000000000000000001/clusters: 401 (request "") You are not authorized for this resource.
│
│   with mongodbatlas_cluster.cluster-terraform01,
│   on main.tf line 1, in resource "mongodbatlas_cluster" "cluster-terraform01":
│    1: resource "mongodbatlas_cluster" "cluster-terraform01" {

Any pointers or examples would be greatly appreciated

many thanks


Solution

  • Once you have setup and started vault, enabled mongodbatlas, added config and roles to vault, its actually rather easy to connect terraform to atlas using dynamic ephemeral keys created by vault.

    Run these commands first to start and configure vault locally:

    vault server -dev
    export VAULT_ADDR='http://127.0.0.1:8200'
    vault secrets enable mongodbatlas
    # Write your master API keys into vault
    vault write mongodbatlas/config public_key=org-api-public-key private_key=org-api-private-key
    vault write mongodbatlas/roles/test project_id=100000000000000000000001 roles=GROUP_OWNER ttl=2h max_ttl=5h cidr_blocks=123.45.67.1/24
    

    Now add the vault provider and data source to your terraform config:

    provider "vault" {
      address = "http://127.0.0.1:8200"
    }
    
    data "vault_generic_secret" "mongodbatlas" {
      path = "mongodbatlas/creds/test"
    }
    

    Finally, add the mongodbatlas provider with the keys as provided by the vault data source:

    provider "mongodbatlas" {
      public_key  = data.vault_generic_secret.mongodbatlas.data["public_key"]
      private_key = data.vault_generic_secret.mongodbatlas.data["private_key"]
    }
    

    This is shown in a full example in this example github repo