How to use managed policy with iam role - amazon-web-services

I am using terragrunt to call my terraform module.I have one terragrunt.hcl for my dev and another for testing environment.I would like to be able to attach AWS Managed policy(AdministratorAccess) to my Dev account and (AmazonEC2FullAccess) to my testing account using input variable so that I can remove the policy line in my aws_iam_role_policy section
terragrunt.hcl
terraform {
source = "..//module/vpc"
}
include {
path = find_in_parent_folders()
}
inputs = {
}
main.tf
resource "aws_iam_role" "GitHubActions" {
name = var.GithubAction_role
assume_role_policy = <<EOF
{
"Version":"2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal":{
"Federated": "${aws_iam_openid_connect_provider.github_oidc_github_actions.arn}"
}
}
EOF
}
resource "aws_iam_role_policy" "GitHubActions"{
name = var.policy
role = aws_iam_role.GitHubActions.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement":[
{
"Sid": "",
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
EOF
}

I'm not sure to fully understand your question. You cannot attach an IAM Policy to an account. However, you can attach it to an IAM Role which seems to be your goal here? If yes, you can use a data source:
data "aws_iam_policy" "AmazonEC2FullAccess" {
arn = "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
}
resource "aws_iam_role_policy_attachment" "attachment" {
role = aws_iam_role.GitHubActions.name
policy_arn = data.aws_iam_policy.AmazonEC2FullAccess.arn
}
See iam_role_policy_attachment and iam policy data source.

Related

"Invalid operation: Not authorized to get credentials of role" trying to load json from S3 to Redshift

I always get the error
Invalid operation: Not authorized to get credentials of role arn:aws:iam::xxxxx:role/default_glue_role
I simply want to load from a json from S3 into a Redshift cluster. It is not clear to me what role I have to attach (to Redshift ?).
I have tried attaching the following IAM policy to Redshift
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::xxxxx:role/default_glue_role"
}
}
and also tried with "Resource": "*" but I always get same error.
Thanks for help!
I had a long chat with AWS support about this same issues. A few things to check:
Your s3 bucket region is the same as your redshift cluster region
You are not signed in as the root aws user, you need to create a user with the correct permissions and sign in as this user to run your queries
You should add the following permissions to your user and redshift policies:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*",
"redshift:*",
"sqlworkbench:*",
"sts:*",
"secretsmanager:*",
"s3-object-lambda:*",
"ec2:*",
"sns:*",
"cloudwatch:*",
"tag:*",
"redshift-data:*",
"sqlworkbench:*",
"redshift-serverless:*"
],
"Resource": "*"
}
]
}
You should have the following trust relationships in your redshift and user role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"s3.amazonaws.com",
"redshift.amazonaws.com",
"iam.amazonaws.com",
"redshift-serverless.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
The actual set of permissions you need might be less but this is what worked for me. Took me a long time to figure this out! I hope it helps.
It looks like you might also need to add permissions for glue.
The redshift-serverless permission might tell you it's causing an error but you should be able to save it anyway (AWS told me to do this)
For everyone using Terraform:
What fixed for me it was the (4) suggestion from #patrick-ward:
data "aws_iam_policy_document" "dms_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
identifiers = [
"s3.amazonaws.com",
"redshift.amazonaws.com",
"iam.amazonaws.com",
"redshift-serverless.amazonaws.com",
"dms.amazonaws.com"
]
type = "Service"
}
}
}
resource "aws_iam_role" "dms-access-for-endpoint" {
assume_role_policy = data.aws_iam_policy_document.dms_assume_role.json
name = "dms-access-for-endpoint"
}
resource "aws_iam_role_policy_attachment" "dms-access-for-endpoint-AmazonDMSRedshiftS3Role" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSRedshiftS3Role"
role = aws_iam_role.dms-access-for-endpoint.name
}
resource "aws_iam_role" "dms-cloudwatch-logs-role" {
assume_role_policy = data.aws_iam_policy_document.dms_assume_role.json
name = "dms-cloudwatch-logs-role"
}
resource "aws_iam_role_policy_attachment" "dms-cloudwatch-logs-role-AmazonDMSCloudWatchLogsRole" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSCloudWatchLogsRole"
role = aws_iam_role.dms-cloudwatch-logs-role.name
}
resource "aws_iam_role" "dms-vpc-role" {
assume_role_policy = data.aws_iam_policy_document.dms_assume_role.json
name = "dms-vpc-role"
}
resource "aws_iam_role_policy_attachment" "dms-vpc-role-AmazonDMSVPCManagementRole" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
role = aws_iam_role.dms-vpc-role.name
}

Terraform - How to create IAM role for AWS Lambda and deploy both?

I am learning Terraform. I am trying to create a new Lambda function. And I realized that I also need to create an IAM role. So I am trying to do both using Terraform. But it does not allow me to create the role.
This is my Terraform file
provider "aws" {
profile = "default"
region = "eu-west-1"
}
data "aws_iam_policy" "AWSLambdaBasicExecutionRole" {
arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_iam_role" "terraform_function_role" {
name = "terraform_function_role"
assume_role_policy = "${data.aws_iam_policy.AWSLambdaBasicExecutionRole.policy}"
}
resource "aws_lambda_function" "terraform_function" {
filename = "terraform_function.zip"
function_name = "terraform_function"
handler = "index.handler"
role = "${aws_iam_role.terraform_function_role.id}"
runtime = "nodejs8.10"
source_code_hash = "${filebase64sha256("terraform_function.zip")}"
}
This is the error that I am getting
Error creating IAM Role terraform_function_role: MalformedPolicyDocument: Has prohibited field Resource
status code: 400
How do I fix this?
IAM Role's trust relationship (or assume role policy) defines which resource / service can assume the role. In this, we don't define the Resource field. Hence we can't attach IAM policies or use that policy as is. The correct format for Trust Relationship is:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}
In this scenario, all Lambda functions in your account can assume this role.
You can refer this AWS link for more examples.
Edit: Based on #ydaetskcoR comment, here's a working example:
provider "aws" {
profile = "default"
region = "eu-west-1"
}
data "aws_iam_policy_document" "AWSLambdaTrustPolicy" {
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "terraform_function_role" {
name = "terraform_function_role"
assume_role_policy = "${data.aws_iam_policy_document.AWSLambdaTrustPolicy.json}"
}
resource "aws_iam_role_policy_attachment" "terraform_lambda_policy" {
role = "${aws_iam_role.terraform_function_role.name}"
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "terraform_function" {
filename = "terraform_function.zip"
function_name = "terraform_function"
handler = "index.handler"
role = "${aws_iam_role.terraform_function_role.arn}"
runtime = "nodejs8.10"
source_code_hash = "${filebase64sha256("terraform_function.zip")}"
}
The changes from your code include the following:
Updated aws_iam_policy_document resource for assume role permissions
Changed aws_iam_role resource to use the above mentioned policy document
Created aws_iam_role_policy_attachment to attach LambdaBasicExecution policy (which enables logging to CloudWatch)
Updated aws_lambda_function resource to use IAM Role's ARN instead of Id because Lambda function needs the ARN
Since you are still in the learning phase, I suggest you move to terraform 0.12 instead, so you can use things like templatefile. therefore you don't need to create data objects.
One other thing is to always use the Least Privilege Principle when creating policies, meaning your Resource (Lambda, on this case) will only have access to what it needs. For now, it's only CloudWatch, but in a real world scenario this is very likely not the case.
Back to your question, here's how you can create an IAM Role, an IAM Policy and finally an IAM Policy Attachment (this is the bridge between the policy and the role) as well as the AssumeRolePolicy (this is the trust relationship between the service it's going to use it and the role itself). I have extracted it all into templates for you so it's easier to maintain later on. The gist (for an easier read on the eyes) can be found here.
# iam_role
resource "aws_iam_role" "iam_role" {
name = "iam-role"
assume_role_policy = templatefile("${path.module}/templates/lambda-base-policy.tpl", {})
}
#content of lambda-base-policy.tpl
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
#iam_policy
resource "aws_iam_policy" "policy" {
name = "policy"
policy = templatefile("${path.module}/templates/cloudwatch-policy.tpl", {})
}
#content of cloudwatch-policy.tpl
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
#iam_policy_attachment
resource "aws_iam_policy_attachment" "policy_attachment" {
name = "attachment"
roles = ["${aws_iam_role.iam_role.name}"]
policy_arn = "${aws_iam_policy.policy.arn}"
}
As mentioned in the comment, you have to create assume role then attach the assume rule with your newly created policy, here is the complete working example.
#assume role
resource "aws_iam_role" "role" {
name = "test-alb-logs-to-elk"
path = "/"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
# Created Policy for IAM Role (s3 and log access)
resource "aws_iam_policy" "policy" {
name = "my-test-policy"
description = "A test policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
EOF
}
# Attached IAM Role and the new created Policy
resource "aws_iam_role_policy_attachment" "test-attach" {
role = "${aws_iam_role.role.name}"
policy_arn = "${aws_iam_policy.policy.arn}"
}
# Created AWS Lamdba Function: Memory Size, NodeJS version, handler, endpoint, doctype and environment settings
resource "aws_lambda_function" "elb_logs_to_elasticsearch" {
function_name = "mytest-alb-logs-to-elk"
description = "elb-logs-to-elasticsearch"
memory_size = 1024
filename = "terraform_function.zip"
runtime = "nodejs8.10"
role = "${aws_iam_role.role.arn}"
handler = "index.handler"
}

InvalidClientTokenId when creating IAM Roles

I am trying to create the following IAM Role with a Policy. The Role is attached to a Lambda.
resource "aws_lambda_function" "lambda" {
function_name = "test"
s3_bucket = "${aws_s3_bucket.deployment_bucket.id}"
s3_key = "${var.deployment_key}"
handler = "${var.function_handler}"
runtime = "${var.lambda_runtimes[var.desired_runtime]}"
role = "${aws_iam_role.lambda_role.arn}"
}
resource "aws_iam_role" "lambda_role" {
name = "test-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "lambda_policy" {
name = test-policy"
role = "${aws_iam_role.lambda_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"xray:PutTelemetryRecords",
"xray:PutTraceSegments",
"logs:CreateLogGroup",
"logs:PutLogEvents"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
}
I run terraform apply from an EC2 instance that has an IAM Role attached to it. The IAM Role has the AdministratorAccess and can deploy VPCs and EC2s with Terraform without any issue. When I try to create the IAM Role and Policy above though it fails with InvalidClientTokenId error.
aws_iam_role.lambda_role: Error creating IAM Role test-role: InvalidClientTokenId: The security token included in the request is invalid
I then generated a set of access key credentials and hard-coded them and it still failed. Is there something special I need to do when creating an IAM Role? Any other terraform apply commands I run from this machine work fine until I need to create an IAM Role.

Enabling Cross Account Access to publish AWS ClouchWatch logs(Multiple Accounts) to Kinesis

I have two aws accounts prod and prod-support. In prod-support account I created a cross account role and attached a policy to grant access to prod account as below. I have already created the kinesis stream in prod-support account and was in active state.
Now I am trying to create a cloudwatch subscription in prod account to redirect logs from cloudwatch logs(prod) -> kinesis (prod-support) account.
provider "aws" {
region = "${var.aws_region}"
assume_role {
role_arn = "arn:aws:iam::111111111:role/deployment_role"
}
}
resource "aws_iam_role_policy" "tf_CWL_to_kinesis_policy" {
name = "tf_CWL_to_kinesis_policy"
role = "${aws_iam_role.tf_CWL_to_kinesis_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::22222222:role/CrossAccountRole"
},
{
"Effect": "Allow",
"Action": [
"kinesis:DescribeStream",
"kinesis:PutRecord",
"kinesis:PutRecords",
"kinesis:GetShardIterator",
"kinesis:GetRecords"
],
"Resource": "arn:aws:kinesis:${var.aws_region}:22222222:stream/tf_CWL_to_kinesis_stream"
}
]
}EOF
}
resource "aws_iam_role" "tf_CWL_to_kinesis_role" {
name = "tf_CWL_to_kinesis_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"AWS":"111111111"
},
"Effect": "Allow"
}
]
}EOF
}
resource "aws_cloudwatch_log_subscription_filter" "tf_CWL_to_kinesis_subscrp_filter" {
name = "tf_CWL_to_kinesis_subscrp_filter",
role_arn = "${aws_iam_role.tf_CWL_to_kinesis_role.arn}"
log_group_name = "/aws/lambda/egad-diagnostics-result-sender-lambda"
filter_pattern = ""
destination_arn = "arn:aws:kinesis:${var.aws_region}:2222222222:stream/tf_CWL_to_kinesis_stream"
depends_on = ["aws_iam_role.tf_CWL_to_kinesis_role"]
}
Couple of things to notice here.
Above terraform script uses assume role to execute. which means using prod-support credentials above terraform script assumes prod deployment-role to create the resources in prod account.
while creating cloudwatch subscription it tries to post message to kinesis steam. But i was not sure which role it is using to to post messages.
Above script is trying to access kinesis stream in prod-support account, but it was not able access it.
Any thoughts

Terraform: associate an aws_iam_role with an aws_iam_policy

Reading through the docs and having a hard time seeing how to associate an aws_iam_role with an aws_iam_policy. Obviously there's aws_iam_role_policy, but that only allows making "inline policies" for a particular role.
Any suggestions?
The aws_iam_policy_attachment resource allows connections to be created between IAM policies and the various other IAM objects.
For example:
resource "aws_iam_role" "foo" {
name = "example-role"
}
resource "aws_iam_policy" "foo" {
name = "example-policy"
description = "An example policy"
policy = "..."
}
resource "aws_iam_policy_attachment" "foo" {
name = "example-attachment"
policy_arn = "${aws_iam_policy.foo.arn}"
roles = ["${aws_iam_role.foo.name}"]
}
Policies can also be attached to users and groups, as illustrated on the Terraform documentation page.
What I've had to do is create a role and a policy and then attach them as shown in an answer by Martin Atkins.
resource "aws_iam_role" "context-builder-role" {
name = "context-builder-role-${terraform.workspace}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_policy" "arm_cfs_sqs_queue_policy" {
name = "starmine-inline-policy-${terraform.workspace}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Action": [
"sqs:SendMessage",
"sqs:GetQueueUrl",
"sqs:DeleteMessage"
],
"Effect": "Allow",
"Resource": "arn:aws:sqs:*"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "inline-policy-attach" {
role = aws_iam_role.context-builder-role.name
policy_arn = aws_iam_policy.arm_cfs_sqs_queue_policy.arn
}
You can also attach an AWS policy to a role by using the policies ARN:
resource "aws_iam_role_policy_attachment" "s3-read-only-attach" {
role = aws_iam_role.context-builder-role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
Follow the below steps:
Step 1) Create the policy which you want to associate with the aws role.
Step 2) Create aws role as follow:
i. Set role name.
ii. Set role type according to your preference.
iii. Attach the policy which you have created in step1.
iv. Review and create the role.
Hope it helps.......