terraform-provider-aws: AWS profile does not work with role_arn and credential_source = Ec2InstanceMetadata
Terraform v0.11.7 AWS provider v1.25
I have a server that is set up to run in a production AWS account with an IAM role attached. I then use the aws ini configuration to set up a profile for the production account, and also a profile for the non-production account which has staging resources in it. There is a trust relationship between the role attached to the instance, and the role in the non-production account. On awscli this works as expected.
~/.aws/config
[profile production]
credential_source = Ec2InstanceMetadata
output = json
region = eu-west-1
[profile non-prod]
role_arn = arn:aws:iam::000000000000:role/Terraform
credential_source = Ec2InstanceMetadata
output = json
region = eu-west-1
In terraform I then point it to the non-prod profile, however I get access denied to resources.
provider "aws" {
version = "~> 1.25"
region = "eu-west-1"
profile = "non-prod"
}
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
aws_s3_bucket.staging: Refreshing state... (ID: ***)
Error: Error refreshing state: 1 error(s) occurred:
* aws_s3_bucket.staging: 1 error(s) occurred:
* aws_s3_bucket.staging: aws_s3_bucket.staging: error reading S3 bucket "***": Forbidden: Forbidden
Expected Behavior
I expect profile non-prod to authenticate by using assuming the non-production account role, using the role attached to the instance.
Actual Behavior
It appears to just authenticate as the role attached to the instance instead, which cannot access resources outside of it’s own account.
I have also tried the assume_role {...} provider config, however I get “No valid credential sources found for AWS Provider.”
Explicit profiles are much the preference in any case, as they can be configured independently; using restricted key/secret pairs on an employee’s machine, and the role attached to the instance in production.
Community Note
- Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
- Please do not leave “+1” or “me too” comments, they generate extra noise for issue followers and do not help prioritize the request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 32
- Comments: 27 (7 by maintainers)
Commits related to this issue
- provider: Authentication updates for Terraform AWS Provider v3.0.0 Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/5018 Reference: https://github.com/terraform-provide... — committed to hashicorp/terraform-provider-aws by bflad 4 years ago
- provider: Authentication updates for Terraform AWS Provider v3.0.0 (#14077) * Update module hashicorp/aws-sdk-go-base to v0.5.0 * provider: Authentication updates for Terraform AWS Provider v3.0.0... — committed to hashicorp/terraform-provider-aws by bflad 4 years ago
The root cause of this issue explained here https://github.com/hashicorp/aws-sdk-go-base/issues/7
I have a slightly different use case - running TF in EKS pod that uses IAM attached to Service Account as described here https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
The long story short, I get
~/.aws/configfile like this:Then I have
export AWS_PROFILE=profile2just before callingterraform. I have simple TF code to test this:Terraform picking up EKS node instance profile instead of everything defined in
~/.aws/config. I think I have slightly better workaround thanskip_metadata_api_check- trick AWS SDK into thinking it’s not running in AWS by definingAWS_METADATA_URLenvironment variable to some absurd endpoint:For my particular use case, AWS metadata IP should be anyway iptabled out so not accessible by EKS pods, I just haven’t got there yet. Still this is a bug in https://github.com/hashicorp/aws-sdk-go-base/ worth fixing - I can imagine there might be use cases these workarounds does not apply. Such as using
role_arnand instance profile for different provider instances or something if EKS node instance profile not intended to be hidden from it’s pods. Anyway diverging from official AWS SDK credentials chain logic (or official AWS SDK in general) sounds like a bad practice. It may come in all sorts of unintended behaviour/bugs, AWS systems are pretty complex and heavily rely on conventions and standards like this AWS credentials chaining order.Hi folks 👋 Version 3.0 of the Terraform AWS Provider will include a few authentication changes that should help in this case including:
~/.aws/config) by defaultAWS_METADATA_URL)This major version update will release in the next two weeks or so. Please follow the v3.0.0 milestone for tracking the progress of that release. If you are still having trouble after updating when its released, please file a new issue. Thanks!
@llibicpep I think your analysis nailed the problem, and was a huge help to me in putting together this proposed fix. It could still use some additional test cases if anyone else has time to pitch in. https://github.com/hashicorp/aws-sdk-go-base/pull/20
@bflad could you review?
Using AWS_SDK_LOAD_CONFIG=1 fixed a similar issue for me where I was using roles to switch from a master account. Obviously not related to this issue, but thought I’d leave a comment here for future seekers
@shanee-spring (and future readers of this) the thing that doesn’t work until TF v0.12 is using the ~/.aws/config to get the role arn (allowing you to not specify that in the Terraform backend directly).
@shanee-spring - The s3 backend does not use the
providerblock. It uses theterraform { backendblock. I was only able to get theproviderblock to work withskip_metadata_api_check = true, not thebackendblock. I tested with Terraform v0.12a and found that thebackendblock also works. I think the tracking issue for that is: https://github.com/hashicorp/terraform/issues/18213Easy test case for this with 2 accounts (this is
Terraform v0.12.5) …In account 1: Create an EC2 Instance, assign an IAM role to that instance In account 2: Create a role with a policy that allows account 1 to assume it (here it’s called
dev-account-role) In account 1: On the instance, plop the following into ~/.aws/config where12345678901is account 2 id:Run this .tf on this instance:
Expected: assumed_role_arn and instance_profile_role_arn are not the same.
Actual: they are the same.
As stated,
skip_metadata_api_check = truefixes it. Also worth mentioning that this fix doesn’t seem to work when this same tf file is applied by Atlantis. 😢Mine is when EC2 attached to a Role because needed for AWS Session Manager and i use shared credentials file for Terraform Backend when running
init(try access S3) got 403 denied turns out the caller identity is the Role from EC2 Instance Profile not from shared credentials, usingskip_metadata_api_check=truenot working but exportingAWS_METADATA_URLto non existent url works. Thanks @dee-kryvenkoThis should be supported in version 1.41.0 since the aws-sdk-go dependency was updated to v1.15.55 in #6164. See also: https://github.com/terraform-providers/terraform-provider-aws/blob/v1.41.0/vendor/vendor.json#L177-L184
https://github.com/aws/aws-sdk-go/pull/2201 just got merged which adds support for
credential_source