Terraform: Issue with assume_role - amazon-web-services

I'm trying to solve this mystery for few days now, but no joy. Basically, Terraform cannot assume role and failing with:
Initializing the backend...
2019/10/28 09:13:09 [DEBUG] New state was assigned lineage "136dca1a-b46b-1e64-0ef2-efd6799b4ebc"
2019/10/28 09:13:09 [INFO] Setting AWS metadata API timeout to 100ms
2019/10/28 09:13:09 [INFO] Ignoring AWS metadata API endpoint at default location as it doesn't return any instance-id
2019/10/28 09:13:09 [INFO] AWS Auth provider used: "SharedCredentialsProvider"
2019/10/28 09:13:09 [INFO] Attempting to AssumeRole arn:aws:iam::72xxxxxxxxxx:role/terraform-admin-np (SessionName: "terra_cnp", ExternalId: "", Policy: "")
Error: The role "arn:aws:iam::72xxxxxxxxxx:role/terraform-admin-np" 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
In AWS:
I have role: terraform-admin-np with 2 AWS managed policy: AmazonS3FullAccess & AdministratorAccess and a trust relationship with this:
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::72xxxxxxxxxx:root"
},
"Action": "sts:AssumeRole"
}
]
}
Then I have an user with policy document attached:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TfFullAccessSts",
"Effect": "Allow",
"Action": [
"sts:AssumeRole",
"sts:DecodeAuthorizationMessage",
"sts:AssumeRoleWithSAML",
"sts:AssumeRoleWithWebIdentity"
],
"Resource": "*"
},
{
"Sid": "TfFullAccessAll",
"Effect": "Allow",
"Action": "*",
"Resource": [
"*",
"arn:aws:ec2:region:account:network-interface/*"
]
}
]
}
and a S3 bucket: txxxxxxxxxxxxxxte with this policy document attached:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TFStateListBucket",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::72xxxxxxxxxx:root"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::txxxxxxxxxxxxxxte"
},
{
"Sid": "TFStateGetPutObject",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::72xxxxxxxxxx:root"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::txxxxxxxxxxxxxxte/*"
}
]
}
In Terraform:
The snippet from the provider.tf:
###---- Default Backend and Provider config values -----------###
terraform {
required_version = ">= 0.12"
backend "s3" {
encrypt = true
}
}
provider "aws" {
region = var.region
version = "~> 2.20"
profile = var.profile
assume_role {
role_arn = var.role_arn
session_name = var.session_name
}
}
Snippet from tgw_cnp.tfvars backend config:
## S3 backend config
key = "backend/tgw_cnp_state"
bucket = "txxxxxxxxxxxxxxte"
region = "us-east-2"
profile = "local-tgw"
role_arn = "arn:aws:iam::72xxxxxxxxxx:role/terraform-admin-np"
session_name = "terra_cnp"
and then running this way:
TF_LOG=debug terraform init -backend-config=tgw_cnp.tfvars
With this, I can assume role using AWS CLI without any issue:
# aws --profile local-tgw sts assume-role --role-arn "arn:aws:iam::72xxxxxxxxxx:role/terraform-admin-np" --role-session-name AWSCLI
{
"Credentials": {
"AccessKeyId": "AXXXXXXXXXXXXXXXXXXA",
"SecretAccessKey": "UixxxxxxxxxxxxxxxxxxxxxxxxxxxxMt",
"SessionToken": "FQoGZXIvYXdzEJb//////////wEaD......./5LFwNWf6riiNw9vtBQ==",
"Expiration": "2019-10-28T13:39:41Z"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROA2P7ZON5TSWMOBQEBC:AWSCLI",
"Arn": "arn:aws:sts::72xxxxxxxxxx:assumed-role/terraform-admin-np/AWSCLI"
}
}
but terraform fails with the above error. Any idea what's I'm doing wrong?

Okay, answering to my own question........
It worked now. I have had a silly mistake - the region in tgw_cnp.tfvars was wrong, which I was keep missing out. In AWS CLI as I didn't have to specify the region (it was getting it from the profile), so it worked without any issue but in TF I specified the region and the value was wrong, hence the failure. The suggestions in the error reporting was a bit misleading.
I can confirm the above config works fine. It's all good now.

Related

Cross account IAM roles for Kubernetes service account - s3 bucket

Hey im trying to cross account access for a role. i have 2 accounts: prod and non-prod.
and bucket in prod account, which im trying to write files to there from a non-prod role which is used as a service account in k8s cluster.
in prod account i configured:
a role with the following policy(read write access to the bucket):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListObjectsInBucket",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::test2"
]
},
{
"Sid": "AllObjectActions",
"Effect": "Allow",
"Action": "s3:*Object",
"Resource": [
"arn:aws:s3:::test2/*"
]
}
]
}
and the following trust:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::non-prod-AccountID:role/name-of-the-non-prod-role"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
in non prod i configured:
a role with the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::prod-Account-ID:role/prod-role-name"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
and trust as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::non-prod-accountID:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/1111111111111111111"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.us-east-1.amazonaws.com/id/1111111111111111111:sub":
"system:serviceaccount:name-space:name-of-the-service-account"
}
}
}
]
}
serviceAccount annotation is:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::non-prod-AccountID:role/non-prod-role-name
when running the command from inside the pod with the service account of the role in non-prod:
aws s3 cp hello.txt s3://test2/hello.txt
im having:
upload failed: ./hello.txt to s3://test2/hello.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
by the way the cluster is in another account (devops account) if its related, surely added OIDC provider identity to both non-prod and prod accounts as identity provider.
If you're getting the error An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: No OpenIDConnect provider found in your account for $oidc_url when trying to cross-account assume roles, but you can assume roles in your cluster account normally, here's some points:
EKS ACCOUNT
Create a ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: $sa_name
namespace: $eks_ns
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::$resource_account_id:role/$role_name
Annotate your deployment
spec.template.spec:
serviceAccountName: $sa_name
Get info about your cluster OIDC Provider
aws iam get-open-id-connect-provider --open-id-connect-provider-arn arn:aws:iam::$eks_cluster_account_id:oidc-provider/$oidc_provider
3.1. The output will be like:
{
"Url": "...",
"ClientIDList": ["..."],
"ThumbprintList": ["..."],
"CreateDate": "...",
"Tags": [...]
}
3.2. Take note of the outputs (Url and ThumbprintList specially)
RESOURCE ACCOUNT
Add the provider (if you don`t have it already), using the output from your cluster account
aws iam create-open-id-connect-provider --url $oidc_url --client-id-list sts.amazonaws.com --thumbprint-list $oidc_thumbprint
This should be enought to the mentioned error stop. If you now get An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity, you're problably using the $eks_cluster_account_id on Principal.Federated, instead of $resource_account_id created on the previous step. So, make sure you're using the ARN from the IP that is assigned to the resource account, not the cluster account.
Create a role and a policy to access your resources with following trusted entities policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::$resource_account_id:oidc-provider/$oidc_provider"
},
"Action": "sts:AssumeRoleWithWebIdentity"
}
]
}
Also, there's no need to have two roles. One is enough.

InsufficientS3BucketPolicyFault when enabling AWS Redshift audit logging through Terraform

Problem
I'm trying to enable audit logging on an AWS redshift cluster. I've been following the instructions provided by AWS here: https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html#db-auditing-enable-logging
Current Configuration
I've defined the relevant IAM role as follows
resource "aws_iam_role" "example-role" {
name = "example-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "redshift.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
And have granted the following IAM permissions to the example-role role:
{
"Sid": "AllowAccessForAuditLogging",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetBucketAcl"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket/*"
]
},
The relevant portion of the redshift cluster configuration is as follows:
resource "aws_redshift_cluster" "example-cluster-name" {
cluster_identifier = "example-cluster-name"
...
# redshift audit logging to S3
logging {
enable = true
bucket_name = "example-bucket-name"
}
master_username = var.master_username
iam_roles = [aws_iam_role.example-role.arn]
...
Error
terraform plan runs correctly, and produces the expected plan based on the above configuration. However, when running terraform apply the following error occurs:
Error: error enabling Redshift Cluster (example-cluster-name) logging: InsufficientS3BucketPolicyFault: Cannot read ACLs of bucket example-bucket-name. Please ensure that your IAM permissions are set up correctly.
note: i've replaced all resource identifiers with example-* resource names and identifiers.
#shimo's answer is correct. I just detail for someone like me
Redshift has full access to S3. But you need add bucket policy too. ( S3's permission)
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::361669875840:user/logs"
},
"Action": [
"s3:GetBucketAcl",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::<your-bucket>",
"arn:aws:s3:::<your-bucket>/*"
]
}
- `361669875840` is match with your region check [here][1]
[1]: https://github.com/finos/compliant-financial-infrastructure/blob/main/aws/redshift/redshift_template_public.yml

IAM CodeBuild policy condition - principal tag equals resource tag

Goal:
Create an IAM role policy that allows the role to perform defined actions on aws resources only if the role tag equals the resource tag.
For example:
IAM tag:
foo=bar
CodeBuild project tag:
foo=bar
IAM role policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codebuild:List*",
"codebuild:DescribeTestCases",
"codebuild:DescribeCodeCoverages",
"codebuild:BatchGet*"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/foo": "${aws:PrincipalTag/foo}"
}
}
}
]
}
When the user assumes the role, the user is denied access to codebuild:ListProjects on projects that have the same foo=bar key pair as the role within the AWS console and AWS CLI.
AWS console error:
User: arn:aws:sts::123456789:assumed-role/example-role/example-user is not authorized to perform: codebuild:ListProjects
AWS CLI error using the command: aws codebuild list-projects --profile test
An error occurred (AccessDeniedException) when calling the ListProjects operation: User: arn:aws:sts::123456789:assumed-role/example-role/botocore-session-59458209 is not authorized to perform: codebuild:ListProjects
Attempts:
#1
Use actual key pair value in policy condition:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codebuild:List*",
"codebuild:DescribeTestCases",
"codebuild:DescribeCodeCoverages",
"codebuild:BatchGet*"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/foo": "bar"
}
}
}
]
}
Result to codebuild:ListProjects access denied error on aws console
#2
Remove aws key brackets from aws:PrincipalTag/foo(shooting from the hip here)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codebuild:List*",
"codebuild:DescribeTestCases",
"codebuild:DescribeCodeCoverages",
"codebuild:BatchGet*"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/foo": "aws:PrincipalTag/foo"
}
}
}
]
}
#3
Used the resource type within the resource tag condition codebuild:ResourceTag/foo
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codebuild:List*",
"codebuild:DescribeTestCases",
"codebuild:DescribeCodeCoverages",
"codebuild:BatchGet*"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"codebuild:ResourceTag/foo": "${aws:PrincipalTag/foo}"
}
}
}
]
}
Same codebuild:ListProjects access denied error on aws console
From docs:
CodeBuild supports authorization based on tags for project-based actions
I think ListProjects action is not project-based. It is for entire codebuild, rather then for a specific project.

aws assume role on shell script does not assume the role

I'm following a tutorial where I assume roles on EC2 instances so it has access to services. I'm following this tutorial (https://medium.com/swlh/aws-iam-assuming-an-iam-role-from-an-ec2-instance-882081386c49), but I'm stuck on the cli part when I start running a "aws s3 ls". Just so I know it works, I gave the AssumedRole all access to s3.
This is my setup:
ImplicitRole // will be attached to EC2
policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::xxx:role/*"
}
]
}
AssumedRole // will be the role assumed once logged in to EC2
policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
What happens is I would run the following on cli
aws sts assume-role --role-arn arn:aws:iam::****:role/AssumedRole --role-session-name test-session
Then I will get the Credentials
{
"Credentials": {
"AccessKeyId": "key",
"SecretAccessKey": "secret",
"SessionToken": "longtoken",
"Expiration": "2020-07-08T07:29:51+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AKDIEEOOKDLKSDJFDJ:test-session",
"Arn": "arn:aws:sts::xxxx:assumed-role/AssumedRole/test-session"
}
}
and then will update the variables eg: set AWS_ACCESS_KEY_ID=XXXX , etc
Once done I run the following but it would give me ListObject AccessDenied
aws s3 ls s3://bucket
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

Terraform : AWS Redshift IAM role

Im trying to setup a redshift cluster and an IAM role that will have access to the cluster. I am using terraform for this. According the documentation I need to create a Service role and attach the AmazonS3ReadOnlyAccess policy to it. I have the following config in my terraform script:
resource "aws_iam_role" "my_admin_role" {
name = "my-role"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*",
"redshift:*"
],
"Resource": "*"
}
]
}
EOF
}
However this gives me an error:
Errors:
* aws_iam_role.my_admin_role: "assume_role_policy": required field is not set
* aws_iam_role.my_admin_role: : invalid or unknown key: policy
How do I setup a service role for redshift ?
You mix the resources aws_iam_role and aws_iam_role_policy
Sample usage of resource aws_iam_role
resource "aws_iam_role" "test_role" {
name = "test_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
Sample usage of resource aws_iam_role_policy
resource "aws_iam_role_policy" "test_policy" {
name = "test_policy"
role = "${aws_iam_role.test_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
}