When I use assume role without MFA enforced with Terragrunt, it works fine with the following command:
terragrunt plan --terragrunt-iam-role "arn:aws:iam::123456789012:role/devop"
However, if I enforce MFA in Trust Relationship Policy as following:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:user/jonsmith" },
"Action": "sts:AssumeRole",
"Condition": { "Bool": { "aws:MultiFactorAuthPresent": true } }
}
]
}
the Terragrunt iam role command returns the following error:
AccessDenied: User: arn:aws:iam::123456789012:user/jonsmith is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::123456789012:role/devop
without giving the opportunity to enter MFA token.
Is there a way to make Terragrunt read options like --serial-number and --token-code as well as the AWS CLI? Or read from a config file similar to the following:
[profile devop]
role_arn = arn:aws:iam::123456789012:role/devop
source_profile = default
mfa_serial = arn:aws:iam::123456789012:mfa/jonsmith
An interactive MFA prompt or param is not currently supported with --role-arn. The more common use case for us is to:
terragrunt apply --role-arn xxx, and since the MFA token is present, it will work.I'd be open to a PR that adds support for specifying the token dynamically, but it would need to be used in several places (once for S3/DynamoDB remote state, once before actually calling Terraform).
Hi @brikis98 , thanks for the reply. Not sure if I understand it correctly but I've tried the following:
aws sts assume-role \
--role-arn arn:aws:iam:: 123456789012:role/devop \
--role-session-name jonsmith \
--serial-number arn:aws:iam:: 123456789012:mfa/jonsmith \
--token-code 123456
terragrunt plan --terragrunt-iam-role arn:aws:iam:: 123456789012:role/devop
Successfully authenticated with the first command, but still getting AccessDenied error from the second one.
I used --terragrunt-iam-role because --role-arn is not the right argument for Terragrunt according to the documentation here.
UPDATE
If I set the temporary credentials returned from AWS CLI in environment variables then it's working.
so set
export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxx
export AWS_SESSION_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
then run
terragrunt plan --terragrunt-iam-role arn:aws:iam:: 123456789012:role/devop
If I set the temporary credentials returned from AWS CLI in environment variables then it's working.
Yes, that's exactly right. It's a slightly tedious process to assume an IAM role from the AWS CLI, so you may want to build a script to make it easier!
Yes, already found a Ruby gem here, and a Python implementation here, hopefully this can also help others as a temporary solution, but it would be better to have it supported directly in Terragrunt someday.
I haven't been working with Go for a while but I'll see if I can find the time to submit a PR for this, or if someone else can do it sooner.
@fredxinfan - Can you clarify if --terragrunt-iam-role is required? In my case I don't seem to need it, I can just set the environment variables and then run terragrunt plan. I will need to provide documentation to others and would like to make sure I'm not missing something.
Hi @jkinred , --terragrunt-iam-role is required if you need to assume a role and make changes on behalf of another AWS account.
For example, if you have a bastion AWS account which has a User created called john, then you have an organization AWS account which has a Role created called DevOp with permissions to manage resource. If User john wants to create a S3 bucket in organization AWS account, he needs to assume the DevOp Role first by using --terragrunt-iam-role option, then Terragrunt will print out something like:
Assuming IAM role arn:aws:iam::1234567890:role/DevOp
then john will be able to create the S3 bucket in the organization AWS account as DevOp Role.
However, if john omits --terragrunt-iam-role option, Terraform will try to create the bucket in bastion AWS account, where User john belongs to.
Of course, Amazon allows you to create and assume a Role as a User from the same AWS account, but it's considered as the best practice to maintain resource and users in separate AWS accounts.
Let me know if that makes sense.
Thanks for the detailed response, I was probably a bit too brief in my previous question.
We also configure our AWS accounts as you've described.
I am able to do the following:
aws sts assume-role \
--role-arn arn:aws:iam:: 123456789012:role/devop \
--role-session-name jonsmith \
--serial-number arn:aws:iam:: 123456789012:mfa/jonsmith \
--token-code 123456
<output>
export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxx
export AWS_SESSION_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
terragrunt plan
The important bit being that I don't need to specify --terragrunt-iam-role or --role-arn. I believe this makes sense as the role is already "assumed" in the values returned by aws sts assume-role and subsequently exported in the environment variables. Does this behaviour also work for you?
Hi @jkinred , ah, sorry, yes, what you have described above works fine. I have tried it myself, but personally I would still prefer to use the --terragrunt-iam-role option, because it's more clear on which role I'm currently acting as, and I could switch roles. It will also warn me when my credentials are expired, but if I just run terragrunt plan without --terragrunt-iam-role option when credentials are expired, it will try to operate on bastion account resource without warning, unless the account has no permissions to do so, which is probably fine in most scenarios assuming the policies are always defined correctly. I just personally prefer the less confusing solution.
Also, maybe Terragrunt should consider to change the option name from --terragrunt-iam-role to --role-arn, because it's inline with the AWS CLI option name. It's currently not supporting --role-arn.
Thanks for the responses @brikis98 and @jkinred - these examples do work for a single aws account, but how would you configure cross-account setup though, for example cross-account vpc peering? It would require multiple aws providers with different sets of credentials..
Deploying to multiple AWS accounts via a single call to apply is relatively rare and not very well supported by AWS CLI tools. Terragrunt's --terragrunt-iam-role parameter only supports one account, so you won't be able to use it. Instead, you will most likely need to use the assume_iam_role setting in each of the provider blocks.
Closing due to inactivity
Most helpful comment
Yes, already found a Ruby gem here, and a Python implementation here, hopefully this can also help others as a temporary solution, but it would be better to have it supported directly in Terragrunt someday.
I haven't been working with Go for a while but I'll see if I can find the time to submit a PR for this, or if someone else can do it sooner.