Terraform assume role despite correct IAM setup - amazon-web-services

Ive been able to test this role by assuming it using the CLI with the given the profile. However, I still get this error on apply:
│ Error: error configuring Terraform AWS Provider: IAM Role (arn:aws:iam::<omitted>:role/<omitted>) cannot be assumed.
│
│ There are a number of possible causes of this - the most common are:
│ * The credentials used in order to assume the role are invalid
│ * The credentials do not have appropriate permission to assume the role
│ * The role ARN is not valid
│
│ Error: NoCredentialProviders: no valid providers in chain. Deprecated.
│ For verbose messaging see aws.Config.CredentialsChainVerboseErrors
│
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on providers.tf line 3, in provider "aws":
│ 3: provider "aws" {
│
The provider configuration looks like so:
provider "aws" {
region = var.aws_region
profile = var.aws_profile
assume_role {
role_arn = var.assume_role_arn
session_name = "assume-role-${timestamp()}"
}
}
Assuming all variables are correct - what am I doing wrong?
I was able to re-create this in a simple repositiory:
https://github.com/SparkPost/tf-recreate-assume-role-bug
You'll obviously have to create a correct assume role setup with permissions both in the assume-role policy of the role and the policy of the user/role doing the assuming.
Edit:
It's been requested, so here's the trust policy of the assumed role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<omitted>:user/<my username>"
]
},
"Action": "sts:AssumeRole"
}
]
}
Additionally, it should be noted that I am an admin user with permission to assume all roles.
Here's the command I used to test the assume role from the CLI:
aws sts --profile <profile used in module> assume-role --role-arn <role arn from error message> --role-session-name test
This returned successfully.

Your timestamp() will return illegal characters for session name. You have to format it to have only good characters, e.g.:
session_name = "assume-role-${formatdate("MMM-DD-YYYY", timestamp())}"

Related

Granting cloudtrails access to kms keys in terraform

My first attempt at doing this resulted in a circular reference:
resource "aws_kms_key" "cloudtrails-key" {
description = "KMS Master Key for trails logs"
key_usage = "ENCRYPT_DECRYPT"
customer_master_key_spec = "SYMMETRIC_DEFAULT"
deletion_window_in_days = 30
is_enabled = true
enable_key_rotation = false
policy = data.aws_iam_policy_document.cloudtrails-key-policy.json
multi_region = true
tags = {
ManagedBy = "terraform"
Name = "${var.project_name}-${var.environment}-${var.aws_account_id}-cloudtrails-key"
Environment = var.environment
Usage = "monitoring"
}
}
data "aws_iam_policy_document" "cloudtrails-key-policy" {
statement {
principals {
type = "Service"
identifiers = [ "cloudtrail.amazonaws.com" ]
}
actions = [
"kms:CallerAccount",
"kms:EncryptionAlgorithm",
"kms:EncryptionContext:*",
"kms:EncryptionContextKeys",
"kms:RequestAlias",
"kms:ViaService"
]
resources = [ aws_kms_key.cloudtrails-key.arn ]
condition {
test = "ForAnyValue:StringLike"
variable = "aws:SourceArn"
values = toset([for k, v in var.all_account_ids : "arn:aws:cloudtrail:*:${v}:trail/full-cloudtrails"])
}
}
}
As I couldn't determine how to remove the circular reference, I decided to try using grants instead:
resource "aws_kms_grant" "cloudtrails-key-grant" {
depends_on = [ aws_kms_key.cloudtrails-key ]
for_each = var.all_account_ids
name = "${each.key}-cloudtrails-key-grant"
key_id = aws_kms_key.cloudtrails-key.key_id
grantee_principal = "arn:aws:cloudtrail::${each.value}:trail/full-cloudtrails"
operations = [ "Encrypt" ]
}
var.all_account_ids refers to a map of account names and account IDs.
I then updated the aws_kms_key block to remove the policy argument. However, this resulted instead in the following output on apply:
Terraform v1.3.8
on linux_amd64
aws_kms_grant.cloudtrails-key-grant["users"]: Creating...
aws_kms_grant.cloudtrails-key-grant["root"]: Creating...
aws_kms_grant.cloudtrails-key-grant["dev"]: Creating...
aws_kms_grant.cloudtrails-key-grant["shared"]: Creating...
aws_kms_grant.cloudtrails-key-grant["monitoring"]: Creating...
aws_cloudtrail.full-cloudtrails: Modifying... [id=full-cloudtrails]
...
aws_kms_grant.cloudtrails-key-grant["users"]: Still creating... [2m50s elapsed]
aws_kms_grant.cloudtrails-key-grant["monitoring"]: Still creating... [2m50s elapsed]
╷
│ Error: updating CloudTrail Trail (full-cloudtrails): InsufficientEncryptionPolicyException: Insufficient permissions to access S3 bucket full-cloudtrails or KMS key arn:aws:kms:us-east-1:703617067304:key/mrk-c0a4616ba4f74ae9b5ac4ecd1f96e95b.
│
│ with aws_cloudtrail.full-cloudtrails,
│ on monitoring.tf line 1, in resource "aws_cloudtrail" "full-cloudtrails":
│ 1: resource "aws_cloudtrail" "full-cloudtrails" {
│
╵
╷
│ Error: creating KMS Grant for Key (mrk-c0a4616ba4f74ae9b5ac4ecd1f96e95b): InvalidArnException: ARN is not valid: arn:aws:cloudtrail:us-east-1:323924548037:trail/full-cloudtrails
│
│ with aws_kms_grant.cloudtrails-key-grant["root"],
│ on security.tf line 19, in resource "aws_kms_grant" "cloudtrails-key-grant":
│ 19: resource "aws_kms_grant" "cloudtrails-key-grant" {
│
╵
╷
│ Error: creating KMS Grant for Key (mrk-c0a4616ba4f74ae9b5ac4ecd1f96e95b): InvalidArnException: ARN is not valid: arn:aws:cloudtrail:us-east-1:739800733271:trail/full-cloudtrails
│
│ with aws_kms_grant.cloudtrails-key-grant["shared"],
│ on security.tf line 19, in resource "aws_kms_grant" "cloudtrails-key-grant":
│ 19: resource "aws_kms_grant" "cloudtrails-key-grant" {
│
╵
╷
│ Error: creating KMS Grant for Key (mrk-c0a4616ba4f74ae9b5ac4ecd1f96e95b): InvalidArnException: ARN is not valid: arn:aws:cloudtrail:us-east-1:703617067304:trail/full-cloudtrails
│
│ with aws_kms_grant.cloudtrails-key-grant["monitoring"],
│ on security.tf line 19, in resource "aws_kms_grant" "cloudtrails-key-grant":
│ 19: resource "aws_kms_grant" "cloudtrails-key-grant" {
│
╵
╷
│ Error: creating KMS Grant for Key (mrk-c0a4616ba4f74ae9b5ac4ecd1f96e95b): InvalidArnException: ARN is not valid: arn:aws:cloudtrail:us-east-1:457407591303:trail/full-cloudtrails
│
│ with aws_kms_grant.cloudtrails-key-grant["dev"],
│ on security.tf line 19, in resource "aws_kms_grant" "cloudtrails-key-grant":
│ 19: resource "aws_kms_grant" "cloudtrails-key-grant" {
│
╵
╷
│ Error: creating KMS Grant for Key (mrk-c0a4616ba4f74ae9b5ac4ecd1f96e95b): InvalidArnException: ARN is not valid: arn:aws:cloudtrail:us-east-1:158889104371:trail/full-cloudtrails
│
│ with aws_kms_grant.cloudtrails-key-grant["users"],
│ on security.tf line 19, in resource "aws_kms_grant" "cloudtrails-key-grant":
│ 19: resource "aws_kms_grant" "cloudtrails-key-grant" {
│
╵
I tried adding the region (though I would prefer multi-region), taking off the trail name after the slash, using wildcards for region, but everything resulted in the above invalid ARN exception.
I was curious to know if anyone has any working recipes for granting cloudtrails encryption access to a KMS key, as I'm unsure what I'm doing wrong with either method (policy or grant)
The solution for the cyclical reference was to broaden the resource scope to all keys, and not just the one key. This was done on all examples in AWS documentation. I also had to add the default key policy offered by AWS otherwise I got a warning that I would be locking myself out.
The Default Key Policy can be found documented here. The specific key policy required for CloudTrail is found here. Using these two resources, the final working configuration is below:
data "aws_iam_policy_document" "cloudtrail-key-policy" {
statement {
principals {
type = "Service"
identifiers = [ "cloudtrail.amazonaws.com" ]
}
actions = [
"kms:DescribeKey",
"kms:GenerateDataKey*"
]
resources = [ "*" ]
condition {
test = "ForAnyValue:StringLike"
variable = "kms:EncryptionContext:aws:cloudtrail:arn"
values = toset([for k, v in var.all_account_ids : "arn:aws:cloudtrail:*:${v}:trail/${k}-full-cloudtrail"])
}
condition {
test = "ForAnyValue:StringLike"
variable = "aws:SourceArn"
values = toset([for k, v in var.all_account_ids : "arn:aws:cloudtrail:*:${v}:trail/${k}-full-cloudtrail"])
}
}
statement {
principals {
type = "AWS"
identifiers = [ "arn:aws:iam::${var.aws_account_id}:role/terraform-${var.environment}" ]
}
actions = [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
]
resources = [ "*" ]
}
statement {
principals {
type = "AWS"
identifiers = [ "arn:aws:iam::${var.aws_account_id}:root" ]
}
actions = [ "kms:*" ]
resources = [ "*" ]
}
}
Additionally, no grants were needed as we're doing this for a service. According to the documentation, service ARNs are excluded:
The grantee principal can be any AWS principal, including an AWS
account (root), an IAM user, an IAM role, a federated role or user, or
an assumed role user. The grantee principal can be in the same account
as the KMS key or a different account. However, the grantee principal
cannot be a service principal, an IAM group, or an AWS organization
The above text can be found here
Hopefully this helps future readers with the same issue.
EDIT: Updated with final working config

Error in Cloud9 for terraform - InvalidClientTokenId: The security token included in the request is invalid

I am trying to create a role in Cloud9 with Terraform.
resource "aws_iam_role" "firehose_role" {
name = "firehose_test_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "firehose.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
Error:
failed creating IAM Role (firehose_test_role): InvalidClientTokenId: The security token included in the request is invalid │ status code: 403, request id: 6ea2ca59-70ac-47b8-b83c-6547ad98aec1
And when I disable the "AWS managed temporary credentials", this is what I get:
Error: Invalid provider configuration
│
│ Provider "registry.terraform.io/hashicorp/aws" requires explicit configuration. Add a provider block to the root module and configure the provider's required arguments as described
│ in the provider documentation.
│
╵
╷
│ Error: error configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
│
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
│
│ Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, http response error StatusCode: 404, request to EC2 IMDS failed
│
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on <empty> line 0:
│ (source code not available)
So, what can I do here to make it work on Cloud9?

How to perform terraform provisioning for other accounts using assumed role?

I want to provision terraform instance in Account A and from account A to account B.
1)Created a role in account A (arn - arn:aws:iam::XXXXXXX:role/stg-tf-devops-ec2_role to assume role in account B and also have fullEC2 access to provision instance in account A
2)Created a role in account B (arn - arn:aws:iam::YYYYYYY:role/TF_Automation_DevOps) and added ec2 privilege in that role and edited the trust policy and added the role arn created in account A
In account A - I have an instance which i'm using for terraform execution is attached to that stg-tf-devops-ec2_role
Now from my understanding this instance should take care of provisioning instances in both account A and account B without access and secret key.But unfortunately i'm getting below error
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
region = var.region
}
provider "aws" {
region = var.region
assume_role {
role_arn = "arn:aws:iam::YYYYYYYYY:role/TF_Automation_DevOps"
}
alias = "dim"
}
Error message when executing terraform plan is as below
terraform plan
╷
│ Error: error configuring Terraform AWS Provider: IAM Role (arn:aws:iam::YYYYYYYYYY:role/TF_Automation_DevOps) cannot be assumed.
│
│ There are a number of possible causes of this - the most common are:
│ * The credentials used in order to assume the role are invalid
│ * The credentials do not have appropriate permission to assume the role
│ * The role ARN is not valid
│
│ Error: NoCredentialProviders: no valid providers in chain. Deprecated.
│ For verbose messaging see aws.Config.CredentialsChainVerboseErrors
│
│
│ with provider["registry.terraform.io/hashicorp/aws"].dim,
│ on main.tf line 17, in provider "aws":
│ 17: provider "aws" {
Could you please advice how to proceed further or what went wrong and how to debug further?
As requested in comments,here i'm able to use aws cli without access key and secret key and fetch details from account A
aws ec2 describe-instances --region eu-west-2|head -10
{
"Reservations": [
{
"Groups": [],
"Instances": [
{
"AmiLaunchIndex": 0,
"ImageId": "ami-0aac9d7fa83beb6d2",
"InstanceId": "i-0d13491bfd0af559e",
"InstanceType": "t3.medium",
Got the below error when checking whether able to assume the role on account b
$ aws sts assume-role --role-arn "arn:aws:iam::YYYYYYYYYYY:role/TF_Automation_DevOp" --role-session-name "access_chk"
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:sts::YYYYYYYYYYY:assumed-role/stg-tf-devops-ec2_role/i-066506ec0993d0148 is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::YYYYYYYYYYY:role/TF_Automation_DevOp
Trusted policy in account B as below
{​​​​​​​
"Version": "2012-10-17",
"Statement": [
{​​​​​​​
"Effect": "Allow",
"Principal": {​​​​​​​
"AWS": "arn:aws:iam::XXXXXXXX:role/stg-tf-devops-ec2_role"
}​​​​​​​,
"Action": "sts:AssumeRole"
}​​​​​​​
]
}​​​​​​​
Role on account A is having below privileges

Execute Terraform Plan with AWS assume_role and non-default AWS credentials

I'm trying to run terraform plan locally with a non-default aws credentials profile, where my default profile will not work. I also need to use assume_role in terraform provider "aws". My code looks something like this:
provider "aws" {
version = "~> 2.45"
region = "us-east-1"
profile = <profile name>
allowed_account_ids = [<account_id>]
assume_role {
role_arn = "arn:aws:iam::<account id>:role/<role name>"
}
}
The error I'm getting is:
Error: The role "arn:aws:iam::<account_id>:role/<role_name>" cannot be assumed.
There are a number of possible causes of this - the most common are:
* The credentials used in order to assume the role are invalid
* The credentials do not have appropriate permission to assume the role
* The role ARN is not valid
Interestingly, when I put access_key and secret_key in the provider like this:
provider "aws" {
version = "~> 2.45"
region = "us-east-1"
access_key = <aws access key>
secret_key = <aws secret key>
assume_role {
role_arn = "arn:aws:iam::<account_id>:role/<role_name>"
}
}
terraform plan works fine. I've double checked my aws credentials file several time and it's setup correctly, but I'm not sure why terraform plan doesn't work.
I've also tried deleting the assume_role parameter in provider "aws" when i have access_key and secret_key in the file, and terraform plan works fine, which means i don't need the assume_role. however, if i use the profile from aws credentials without assume_role in terraform file, i'm getting:
Error: error using credentials to get account ID: error calling sts:GetCallerIdentity: SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
status code: 403, request id:
You need amend the Trust Policy on the IAM Role like below
How to use trust policies with IAM roles
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:user/<Your username>"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
Once you update the Trust Policy on the IAM Role you can verify this via assume-role command
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/xaccounts3access --role-session-name s3-access-example
You would receive something like:
{
"AssumedRoleUser": {
"AssumedRoleId": "AROA3XFRBF535PLBIFPI4:s3-access-example",
"Arn": "arn:aws:sts::123456789012:assumed-role/xaccounts3access/s3-access-example"
},
"Credentials": {
"SecretAccessKey": "9drTJvcXLB89EXAMPLELB8923FB892xMFI",
"SessionToken": "AQoXdzELDDY//////////wEaoAK1wvxJY12r2IrDFT2IvAzTCn3zHoZ7YNtpiQLF0MqZye/qwjzP2iEXAMPLEbw/m3hsj8VBTkPORGvr9jM5sgP+w9IZWZnU+LWhmg+a5fDi2oTGUYcdg9uexQ4mtCHIHfi4citgqZTgco40Yqr4lIlo4V2b2Dyauk0eYFNebHtYlFVgAUj+7Indz3LU0aTWk1WKIjHmmMCIoTkyYp/k7kUG7moeEYKSitwQIi6Gjn+nyzM+PtoA3685ixzv0R7i5rjQi0YE0lf1oeie3bDiNHncmzosRM6SFiPzSvp6h/32xQuZsjcypmwsPSDtTPYcs0+YN/8BRi2/IcrxSpnWEXAMPLEXSDFTAQAM6Dl9zR0tXoybnlrZIwMLlMi1Kcgo5OytwU=",
"Expiration": "2016-03-15T00:05:07Z",
"AccessKeyId": "ASIAJEXAMPLEXEG2JICEA"
}
}
You also have to specify the role arn on the backend.tf:
terraform {
backend "s3" {
bucket = "your_bucket"
key = "your_key"
region = "us-east-1" (or whataver is the one you're using)
role_arn = "arn:aws:iam::<account_id>:role/<role_name>"
}
}

Terraform aws assume role

I have a problem with AWS assume role using terraform.
In AWS I have three accounts: root, staging and production (let's focus only on root & staging account) in single organization. The root account has one IAM user terraform (with AdministratorAccess policy) which is used by terraform to provisioning all stuff.
The image of organization structure
Root account ID: 111111111111
Staging account ID: 333333333333
A terraform script looks like that:
############## backend.tf
terraform {
required_version = "0.12.19"
}
############## providers.tf
provider "aws" {
region = "eu-west-1"
profile = "default"
}
provider "aws" {
version = ">= 2.44"
region = "eu-west-1"
profile = "default"
assume_role {
role_arn = "arn:aws:iam::333333333333:role/staging-admin"
}
allowed_account_ids = ["333333333333"]
alias = "staging"
}
############## organization.tf
resource "aws_organizations_account" "staging" {
email = "staging#domain.com"
name = "Staging"
parent_id = "ZZZZZ"
}
############## data.tf
data "aws_iam_policy_document" "assume_staging_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
resources = [
aws_iam_role.staging.arn
]
}
}
data "aws_iam_policy" "administrator_access" {
arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
data "template_file" "cross_admin_trust_policy" {
template = file("templates/cross_admin_trust_policy.json")
vars = {
staging_account_number = aws_organizations_account.staging.id
}
}
############## iam.tf
resource "aws_iam_role" "staging" {
name = "staging-admin"
description = "Assumable role granting administrator permissions to the staging account"
assume_role_policy = data.template_file.cross_admin_trust_policy.rendered
max_session_duration = 20000
provider = aws.staging
}
resource "aws_iam_role_policy_attachment" "staging_admin_access" {
role = aws_iam_role.staging.name
policy_arn = data.aws_iam_policy.administrator_access.arn
provider = aws.staging_ireland
}
resource "aws_iam_role_policy_attachment" "staging_attach_assume_any_admin" {
role = aws_iam_role.staging.name
policy_arn = data.aws_iam_policy.administrator_access.arn
provider = aws.staging_ireland
}
and my policy.json file:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${staging_account_number}:role/staging-admin"
},
"Action": "sts:AssumeRole"
}
]
}
when I execute terraform plan I'm getting this error:
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.
data.aws_iam_policy.administrator_access: Refreshing state...
aws_organizations_account.staging: Refreshing state... [id=333333333333]
data.template_file.cross_admin_trust_policy: Refreshing state...
Error: The role "arn:aws:iam::333333333333:role/staging-admin" cannot be assumed.
There are a number of possible causes of this - the most common are:
* The credentials used in order to assume the role are invalid
* The credentials do not have appropriate permission to assume the role
* The role ARN is not valid
on providers.tf line 25, in provider "aws"
Someone has an idea how to fix?
According to https://aws.amazon.com/premiumsupport/knowledge-center/iam-assume-role-cli/
Run the aws sts get-caller-identity command to check your identity.
Run the aws sts assume-role --role-arn arn:aws:iam::333333333333:role/staging-admin command to see if this role can be assumed by your identity.
Check your IAM role's trust relationship. You should restrict it so that the IAM role should be only assumed by specific IAM users.
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam:: 333333333333:root" },
"Action": "sts:AssumeRole"
}
}
According to the data you provided you don't have a role, and you trying to add roles with first apply. Correct me if I'm wrong.
You need to manually create an "account aws role" in IAM with "AdministratorAccess" policy attached.