How to create roles in terraform - amazon-web-services

I would like to create a aws_iam_role with terraform but after running terraform applyI get the following error message:
aws_iam_role.role: Error Updating IAM Role (edb_eb_role) Assume Role Policy: MalformedPolicyDocument: Has prohibited field Resource
That is my policy:
resource "aws_iam_role" "role" {
name = "edb_eb_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
},
{
"Action": [
"logs:*"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"*"
]
}
]
}
EOF
}
What did I wrong? I also tried to do it only with Principals but then I get the message that "Principals" is also not prohibited?

Assume_role_policy don't accept the aws policy json files. So the above code is not working. For detailed explanation of assume_role_policy in aws_iam_role, see this thread.
Update the code as shown below and execute.
variable policy_arn{
default = "arn:aws:iam::aws:policy/service-role/AWSLambdaRole"
}
resource "aws_iam_role" "edb_role" {
name = "edb_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": ["ec2.amazonaws.com" ]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "test-attach" {
role = "${aws_iam_role.edb_role.name}"
policy_arn = "${var.policy_arn}"
}
output "role" {
value = "${aws_iam_role.edb_role.name}"
}
Here, we are using the AWSLambdaRole Policy present in Policies section of IAM.
Add multiple policies to a role using aws_iam_role_policy_attach
Use the default policies provided by aws as show above. Else to create a new policy, see the docs here

Related

IAM policy for EBS volume with EC2 instance

I am trying to create an IAM role/policy to enable my EC2 instance to be able to list and attach EBS volumes (via scripts that call the aws cli). I want this policy to allow only listing/attaching of EBS volumes that have a specific tag.
I've noticed that the script is able to list/attach volumes when I set Resources: "*" and no Conditions in my policy below.
But as soon as I introduce the policy I have below, the AWS cli throws the following error:
./aws ec2 describe-volumes
An error occurred (UnauthorizedOperation) when calling the DescribeVolumes operation: You are not authorized to perform this operation.
Here is the IAM policy I have so far defined in terraform:
resource "aws_iam_role" "web_role" {
name = "web_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_instance_profile" "web_profile" {
name = "web_profile"
role = aws_iam_role.web_role.name
}
resource "aws_iam_role_policy" "web_disk_policy" {
name = "web_disk_policy"
role = aws_iam_role.web_role.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AttachVolume",
"ec2:DetachVolume",
"ec2:DescribeVolumes"
],
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"StringEquals": {
"ec2:ResourceTag/app": "web"
}
}
}
]
}
EOF
}
And my EC2 instances is created with the following:
resource "aws_instance" "web_vm" {
...
iam_instance_profile = aws_iam_instance_profile.web_profile.name
...
tags = {
app = "web"
}
}
And disk created with:
resource "aws_ebs_volume" "ebs-volume-1" {
availability_zone = "us-west-2a"
size = 10
tags = {
app = "web"
}
}
DescribeVolumes does not support aws:ResourceTag/${TagKey} condition, nor any other.
Most Describe/List type operations that target many resources aren't compatible with the conditional logic. DescribeVolumes does not work with conditions so split that off into a different statement.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AttachVolume",
"ec2:DetachVolume"
],
"Resource": [
"arn:aws:ec2:*:*:instance/*",
"arn:aws:ec2:*:*:volume/*"
],
"Condition": {
"StringEquals": {
"ec2:ResourceTag/app": "web"
}
}
},
{
"Effect": "Allow",
"Action": "ec2:DescribeVolumes",
"Resource": "*"
}
]
}

how to get sid in AWS S3 bucket policy in terraform

i want attaches a policy to an S3 bucket resource.
my terraform infra,
resource "aws_s3_bucket" "storage" {
bucket = "${var.service}-${local.stage}-storage"
acl = "public-read"
tags = {
Service = var.service
Stage = local.stage
}
cors_rule {
allowed_headers = [
"*"
]
allowed_methods = [
"GET",
"HEAD"
]
allowed_origins = [
"*"
]
max_age_seconds = 3000
}
}
this bucket for web static file hosting.i need bucket policy to public.
my policy in terraform,
resource "aws_s3_bucket_policy" "storage-policy" {
bucket = aws_s3_bucket.storage.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "????????",
"Statement": [
{
"Sid": "????????",
"Effect": "Allow",
"Principal": "*",
"Action": "*",
"Resource": "arn:aws:s3:::BUCKET-NAME/*"
}
]
}
POLICY
}
in this code, i need get Id, Sid field value.
how can i get this?
thanks.
The Id and Sid are whatever you want. For example:
resource "aws_s3_bucket_policy" "storage-policy" {
bucket = aws_s3_bucket.storage.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "my-bucket-polict",
"Statement": [
{
"Sid": "allow-all-access",
"Effect": "Allow",
"Principal": "*",
"Action": "*",
"Resource": "arn:aws:s3:::BUCKET-NAME/*"
}
]
}
POLICY
}

How do I create an IAM role in Terraform for Amazon ECR?

Following on the back of this answer, I'm trying to create an aws_iam_role that allows for access to ECR. However, when I define the following:
resource "aws_iam_role" "jenkins_ecr_role" {
name = "JenkinsECRRole"
assume_role_policy = <<END_OF_POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecr.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
END_OF_POLICY
}
I get the error:
Error: Error creating IAM Role JenkinsECRRole:
MalformedPolicyDocument: Invalid principal in policy: "SERVICE":"*"
It looks like ecr.amazonaws.com is a valid principal according to the AWS documentation. What am I doing wrong?
It seems that this question has not been fully answered so I'll try to give an example on how I added ecr for my gitlab-runner ec2 instance. First off the ec2 instance needs a iam_instance_profile which it seems that you already have. Second: You need the assume-role so that the instance can assume the role of the service.
Notice am given access to all the resources not just an specific one(you can adjusted as needed)
The role
resource "aws_iam_role" "role" {
name = "${local.env}-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": ["ec2.amazonaws.com"]
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
The policy to allow access to ECR
resource "aws_iam_policy" "policy" {
name = "${local.env}-ecr-access-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"ecr:*",
]
Effect = "Allow"
Resource = "*"
},
]
})
}
The attachment of the policy to the role
resource "aws_iam_policy_attachment" "attach" {
name = "${local.env}-attach"
roles = ["${aws_iam_role.role.name}"]
policy_arn = "${aws_iam_policy.policy.arn}"
}
And finally the profile the EC2 will need
resource "aws_iam_instance_profile" "profile" {
name = "${local.env}-gitlab-runner-instance-profile"
role = aws_iam_role.role.name
}
The EC2 instance
resource "aws_instance" "ec2" {
ami = "ami-06c94f9acb4ba21b2"
instance_type = "t2.small"
associate_public_ip_address = true
key_name = "<key_name>"
subnet_id = <subnet>
iam_instance_profile = aws_iam_instance_profile.profile.name
vpc_security_group_ids = ["<security_group>"]
tags = {
Environment = "dev"
}
}
I think you are trying to give EC2 permission to access the ECR. For this, you need to create IAM policy for ECR and create IAM role for EC2 and attach the role with the policy.
Please refer to this code:
resource "aws_iam_role" "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
}
resource "aws_iam_policy" "policy" {
name = "test-policy"
description = "A test policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ecr:*",
"cloudtrail:LookupEvents"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "test-attach" {
role = "${aws_iam_role.role.name}"
policy_arn = "${aws_iam_policy.policy.arn}"
}
Hope, it helps.
You need to attach a below mentioned manual policy to your IAM role.
resource "aws_iam_role_policy" "role_policy" {
name = "${aws_iam_role.role.name}"
role = "${aws_iam_role.role.id}"
policy = <<EOF
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "new statement",
"Effect": "Allow",
"Principal": {
"AWS": "<IAM-ROLE-ARN>"
},
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:CompleteLayerUpload",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
]
}
]
}
EOF
}
Your role is created for a Service that will need the policy to use other resources, I'm not sure if this helps.
You need to create a role that something will be able to assume, ec2, sagemaker, s3, something. ECR does not assume a role as it's just a registry.
For example, I have a Sagemaker instance:
resource "aws_iam_role" "sagemaker_model" {
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "sagemaker.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
Then that instance needs permission to use other Resource (ECR):
resource "aws_iam_policy" "ecr" {
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ecr:*"
],
"Resource": [
"*"
]
}
]
}
EOF
}
Then I attach that policy to the previous role:
resource "aws_iam_role_policy_attachment" "model_attach_ecr" {
role = aws_iam_role.sagemaker_model.name
policy_arn = aws_iam_policy.ecr.arn
}
Although ECR has a specific property that it has its own access policy, you will need to allow that the previously created role can access the specific container registry by creating one aws_ecr_repository_policy:
resource "aws_ecr_repository_policy" "policy" {
repository = <aws_ecr_repository.repo.name>
policy = <<EOF
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "new statement",
"Effect": "Allow",
"Principal": {
"AWS": "${aws_iam_role.sagemaker_model.arn}"
},
"Action": [
"ecr:*"
]
}
]
}
EOF
}
In this one, you will need to replace <aws_ecr_repository.repo.name> by the actual repository name.
I hope this helps.

Terraform ARN ID of Subnet in IAM

I'm trying to create a custom IAM role with Terraform:
resource "aws_iam_role" "prod_role" {
name = "test_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:GetConsole*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:${var.aws_region}:*:subnet/${aws_subnet.prod1.id}",
"arn:aws:ec2:${var.aws_region}:*:subnet/${aws_subnet.prod2.id}",
"arn:aws:ec2:${var.aws_region}:*:network-interface/*",
"arn:aws:ec2:${var.aws_region}:*:instance/*",
"arn:aws:ec2:${var.aws_region}:*:volume/*",
"arn:aws:ec2:${var.aws_region}::image/ami-*",
"arn:aws:ec2:${var.aws_region}:*:key-pair/*",
"arn:aws:ec2:${var.aws_region}:*:security-group/*"
]
}
]
}
EOF
}
My issue is that subnet ID's pulled into the policy are wrong. My ARN looke like this:
arn:aws:ec2:us-east-1:*:subnet/subnet-0bbg694edda209ab9
and it should look like this:
arn:aws:ec2:us-east-1:*:subnet/0bbg694edda209ab9
How do I get just the ID of the subnet (without the subnet-) for use with IAM?
This may not be the optimal solution however you could utilise the replace interpolation syntax for Terraform. Replacing "subnet-" with "". The result would look like so
arn:aws:ec2:${var.aws_region}:*:subnet/${replace(aws_subnet.prod1.id, "subnet-", "")}

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
}