Aws-vault: Query about using aws-vault with terraform to manage resources in multiple aws accounts

Created on 4 Oct 2018  路  8Comments  路  Source: 99designs/aws-vault

Hi

I want to use aws-vault to securely store and access AWS credentials but I didn't see a way of being able to use it with Terraform when Terraform is being used to manage resources in multiple accounts.

The issue is that, afaict, aws-vault only allows one profile to be active (i.e. have its variables set).

So if in terraform, I have multiple AWS providers which are needed to manage resources in different accounts, I couldn't see a way to use aws-vault to execute the terraform plan without resorting to using a shared credentials file or setting env variables outside of aws-vault.

I was wondering if there were any plans to support setting environment variables such that it allows for multiple profiles to be active.

Example:

aws-vault exec default work home -- env | grep AWS

`
AWS_VAULT=default
AWS_DEFAULT_REGION=us-east-1
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=%%%
AWS_SECRET_ACCESS_KEY=%%%
AWS_SESSION_TOKEN=%%%
AWS_SECURITY_TOKEN=%%%

AWS_VAULT1=work
AWS_DEFAULT_REGION1=us-east-2
AWS_REGION1=us-east-2
AWS_ACCESS_KEY_ID1=%%%
AWS_SECRET_ACCESS_KEY1=%%%
AWS_SESSION_TOKEN1=%%%
AWS_SECURITY_TOKEN1=%%%

AWS_VAULT2=play
AWS_DEFAULT_REGION2=us-east-3
AWS_REGION2=us-east-3
AWS_ACCESS_KEY_ID2=%%%
AWS_SECRET_ACCESS_KEY2=%%%
AWS_SESSION_TOKEN2=%%%
AWS_SECURITY_TOKEN2=%%%
`

regards,
Jinesh

Most helpful comment

Assume roles is quite useful. However, if don't want to use assume role, we can still use credential_process, since #300 has been merged.

terraform use two profile as usual

provider "aws" {
  alias = "work"
  profile = "work"
}

provider "aws" {
  alias = "play"
  profile = "play"
}

while use credential_process in ~/.aws/credentials

[work]
credential_process = aws-vault exec work --json

[play]
credential_process = aws-vault exec play --json

ps: if mfa_serial is set, please define an external prompt driver for aws-vault, e.g. osascript for macOS

credential_process = aws-vault exec play --json --prompt=osascript

All 8 comments

Just use assume roles, TF will be able to assume roles with the current profile credentials

Take a look at alias providers

Thank you both. I followed your advice and configured TF providers to use assume roles.

@jchoksi-whitbread I am trying to do exactly what you describe, use aws-vault to manage a Terraform project that connects to multiple AWS accounts. Can you share any more details about how you were able to configure aws-vault and Terraform to make that work?

@jacob you have to assume a role that allows you to sts:assume all other roles in the accounts you need access to.
Then you use provider alias for those resources

@jacobwgillespie

In Terraform, you will need to define AWS providers. e.g.

# This is the default provider configuration, where all resources will be setup by
# Terraform.
provider "aws" {
  region = "eu-west-1"

  assume_role {
    role_arn = "arn:aws:iam::123456789012:role/OrganizationAccountAccessRole"
  }
}

# The following provider configuration is where Route53 DNS records will be
# setup by Terraform.
provider "aws" {
  alias  = "account_to_setup_dns_resources_in"
  region = "eu-west-1"
}

In the resources you define, you need to specify when a resource should use a non default provider. e.g. below I need to create a Route53 record in a different account to where I create the other resources.

#
# Route53 Record
#
resource "aws_route53_record" "bastion-r53" {
  provider = "aws.account_to_setup_dns_resources_in"
  count    = "${var.ec2i_instance_count > 1 ? var.ec2i_instance_count : 1}"
  zone_id  = "${var.a53_zone_id}"
  name     = "${lower(format("%s", replace(lookup(module.bastion-ec2_instance.tags[count.index], "Name"), "/(${local.my_env_name})-(.+)/", "$2-$1")))}"
  type     = "A"
  ttl      = "300"
  records  = ["${element(aws_eip.bastion-eip.*.public_ip, count.index)}"]
}

To make the above work, you launch aws-vault using credentials which has the ability to assume a role in the required AWS account. Note, in my example above, the user credentials I use to launch aws-vault assumes role to create resources in a different account using the default provider and it creates the dns record in the aws account which it belongs too.

See https://www.terraform.io/docs/configuration/providers.html#multiple-provider-instances to understand what makes the first provider the default.

Thank you @FernandoMiguel and @jchoksi-whitbread, I appreciate it! This makes total sense, I've been using multiple providers and provider aliases for a while, but I was unaware that AWS assume roles could work cross-account.

For anyone else who finds this later, I also found this helpful in explaining the cross-account assume role functionality: https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html

Assume roles is quite useful. However, if don't want to use assume role, we can still use credential_process, since #300 has been merged.

terraform use two profile as usual

provider "aws" {
  alias = "work"
  profile = "work"
}

provider "aws" {
  alias = "play"
  profile = "play"
}

while use credential_process in ~/.aws/credentials

[work]
credential_process = aws-vault exec work --json

[play]
credential_process = aws-vault exec play --json

ps: if mfa_serial is set, please define an external prompt driver for aws-vault, e.g. osascript for macOS

credential_process = aws-vault exec play --json --prompt=osascript
Was this page helpful?
0 / 5 - 0 ratings

Related issues

afedulov picture afedulov  路  3Comments

jonscheiding picture jonscheiding  路  3Comments

ismailyenigul picture ismailyenigul  路  4Comments

raguay picture raguay  路  4Comments

kevinburke picture kevinburke  路  5Comments