Terraform IAM Policy creation - MalformedPolicyDocument: The policy failed legacy parsing - amazon-web-services

I have the Terraform code (below) that is suppose to create an IAM policy. However, on terraform apply, I get the error:
Error: creating IAM Policy autoscale-policy: MalformedPolicyDocument: The policy failed legacy parsing
Terraform code:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.52.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
resource "aws_iam_policy" "autoscale_policy" {
name = "autoscale-policy"
description = "EBS Autoscaling Policy"
policy = <<EOT
{
"Version": "2012-10-17",
"Statement": {
"Action": [
"ec2:AttachVolume",
"ec2:DescribeVolumeStatus",
"ec2:DescribeVolumes",
"ec2:ModifyInstanceAttribute",
"ec2:DescribeVolumeAttribute",
"ec2:CreateVolume",
"ec2:DeleteVolume",
"ec2:CreateTags",
"kms:Decrypt",
"kms:CreateGrant",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Effect": "Allow"
}
}
EOT
}
However, when I use the AWS cli with the exact same policy, the policy is created in AWS with no issue:
--policy-name TestPolicy \
--policy-document \
'{
"Version": "2012-10-17",
"Statement": {
"Action": [
"ec2:AttachVolume",
"ec2:DescribeVolumeStatus",
"ec2:DescribeVolumes",
"ec2:ModifyInstanceAttribute",
"ec2:DescribeVolumeAttribute",
"ec2:CreateVolume",
"ec2:DeleteVolume",
"ec2:CreateTags",
"kms:Decrypt",
"kms:CreateGrant",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Effect": "Allow"
}
}'
Does anyone see where there might be a difference between the TF code and the CLI command? How come my TF code returns a MalformedPolicyDocument error when the policy works fine from the cli?

Statement should be an array.
resource "aws_iam_policy" "autoscale_policy" {
name = "autoscale-policy"
description = "EBS Autoscaling Policy"
policy = <<EOT
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"ec2:AttachVolume",
"ec2:DescribeVolumeStatus",
"ec2:DescribeVolumes",
"ec2:ModifyInstanceAttribute",
"ec2:DescribeVolumeAttribute",
"ec2:CreateVolume",
"ec2:DeleteVolume",
"ec2:CreateTags",
"kms:Decrypt",
"kms:CreateGrant",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Effect": "Allow"
}]
}
EOT
}
tested it works
OR you can you data resource to define your policies.
resource "aws_iam_policy" "autoscale_policy" {
name = "autoscale-policy"
description = "EBS Autoscaling Policy"
policy = data.aws_iam_policy_document.example.json
}
data "aws_iam_policy_document" "example" {
statement {
actions = [
"ec2:AttachVolume",
"ec2:DescribeVolumeStatus",
"ec2:DescribeVolumes",
"ec2:ModifyInstanceAttribute",
"ec2:DescribeVolumeAttribute",
"ec2:CreateVolume",
"ec2:DeleteVolume",
"ec2:CreateTags",
"kms:Decrypt",
"kms:CreateGrant",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
resources = ["*"]
effect = "Allow"
}
}

Related

Terraform AWS CMK script throws a Not Authorized Error

I am trying to create a CMK for my SQS queue to allow encrypted SNS messages to be sent to my encrypted queue. After I create the cmk, I will set it to the "kms_master_key_id" in my queue.
resource "aws_kms_key" "mycmk" {
description = "KMS Key"
deletion_window_in_days = 10
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "*"
}]
}
POLICY
}
This is throwing an error:
my_role_arn is not authorized to perform: kms:CreateKey on resource: *
I've double checked to make sure that action is allowed and it is.
Do I need to update the 'resource' in the policy? If so to what?
The role I am using to run this has these permissions:
Effect = "Allow"
Action = [
"kms:CreateAlias",
"kms:CreateGrant",
"kms:CreateKey",
"kms:DeleteAlias",
"kms:DisableKey",
"kms:EnableKey",
"kms:PutKeyPolicy",
"kms:RevokeGrant",
"kms:ScheduleKeyDeletion",
"kms:TagResource",
"kms:UntagResource",
"kms:UpdateAlias",
"kms:UpdateKeyDescription"
]
Resource = [
"arn:aws:kms:${local.aws_region}:${var.aws_account_id}:key/*",
"arn:aws:kms:${local.aws_region}:${var.aws_account_id}:alias/*"
]
As someone else suggested, it looks like the credentials you use to run Terraform don't have the right permissions.
CreateKey explicitly only works with the "*" resource, so change the policy to this:
data "aws_iam_policy_document" "key_Access" {
statement {
actions = [
"kms:CreateAlias",
"kms:CreateGrant",
"kms:DeleteAlias",
"kms:DisableKey",
"kms:EnableKey",
"kms:PutKeyPolicy",
"kms:RevokeGrant",
"kms:ScheduleKeyDeletion",
"kms:TagResource",
"kms:UntagResource",
"kms:UpdateAlias",
"kms:UpdateKeyDescription"
]
resources = [
"arn:aws:kms:${local.aws_region}:${var.aws_account_id}:key/*",
"arn:aws:kms:${local.aws_region}:${var.aws_account_id}:alias/*"
]
}
statement {
actions = ["kms:CreateKey"]
resources = ["*"]
}
}
With that being said, maybe don't make your own policy. Just assign the existing policy arn:aws:iam::aws:policy/AWSKeyManagementServicePowerUser to the role. That gives the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:CreateAlias",
"kms:CreateKey",
"kms:DeleteAlias",
"kms:Describe*",
"kms:GenerateRandom",
"kms:Get*",
"kms:List*",
"kms:TagResource",
"kms:UntagResource",
"iam:ListGroups",
"iam:ListRoles",
"iam:ListUsers"
],
"Resource": "*"
}
]
}

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": "*"
}
]
}

Terraform aws error creating IAM Role ecs_task_execution_role: MalformedPolicyDocument: Has prohibited field Resource

I using terraform to deploy containers with fargate.
I got an error:
error: Error creating IAM Role ecs_task_execution_role: MalformedPolicyDocument: Has prohibited field Resource
status code: 400, request id: 351d657b-32ef-4ffa-a1e8-bee912e5c788
on ecs.tf line 74, in resource "aws_iam_role" "ecs_execution_role":
74: resource "aws_iam_role" "ecs_execution_role" {
My terraform settings:
resource "aws_ecs_task_definition" "nginx" {
family = "nginx-${var.app}"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
execution_role_arn = "${aws_iam_role.ecs_execution_role.arn}"
task_role_arn = "${aws_iam_role.ecs_execution_role.arn}"
container_definitions = <<DEFINITION
[
...
}
resource "aws_iam_role" "ecs_execution_role" {
name = "ecs_task_execution_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": [
"sts:AssumeRole",
"ecs:CreateCluster",
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:StartTelemetrySession",
"ecs:Submit*",
"ecs:StartTask",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
What policy do I need? what is wrong with current policy?
When I change the action property in the policy to "Action": "sts:AssumeRole" I get this error in the task log:
Status reason CannotPullECRContainerError: AccessDeniedException: User: arn:aws:sts::993934193145:assumed-role/ecs_task_execution_role/0d2f817c-d7b5-4221-afb8-56baaee68b0e is not authorized to perform: ecr:GetAuthorizationToken on resource: * status code: 400, request
assume_role_policy in aws_iam_role is only for trust relationship, i.e. which IAM entity can assume the role.
The actually permissions you want to added to the role, could be placed in aws_iam_policy and attached to the role using aws_iam_role_policy_attachment.
For example, your code could be refactored into the following:
resource "aws_iam_role" "ecs_execution_role" {
name = "ecs_task_execution_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_policy" "ecs_permissions" {
name = "my_ecs_permissions"
description = "Permissions to enable CT"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"ecs:CreateCluster",
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:StartTelemetrySession",
"ecs:Submit*",
"ecs:StartTask",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "ecs_attachment" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = aws_iam_policy.ecs_permissions.arn
}
This is actually down to the assume_role_policy containing both the trust policy and the permissions
Instead you should move all not trust policy permissions into a standard policy
This assume_role_policy is very similar but slightly different than just a standard IAM policy and cannot use an aws_iam_policy resource. It can however, use an aws_iam_policy_document data source, see example below for how this could work.

IAM policy to restrict Instance creation not having proper tags allows some ami and restricts some ami both having correct tags

I've been trying to make a IAM policy that restricts creation of an Instance if certain tags are not applied at the time of Instance Creation. The policy is as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowToDescribeAll",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "*"
},
{
"Sid": "AllowRunInstances",
"Effect": "Allow",
"Action": "ec2:RunInstances",
"Resource": [
"arn:aws:ec2:*::image/*",
"arn:aws:ec2:*::snapshot/*",
"arn:aws:ec2:*:*:subnet/*",
"arn:aws:ec2:*:*:network-interface/*",
"arn:aws:ec2:*:*:security-group/*",
"arn:aws:ec2:*:*:key-pair/*"
]
},
{
"Sid": "AllowLaunchOnlyWithRequiredTags1",
"Effect": "Deny",
"Action": [
"ec2:RunInstances"
],
"Resource": [
"arn:aws:ec2:*:012345678901:instance/*"
],
"Condition": {
"StringNotLike": {
"aws:RequestTag/Purpose": "?*",
"aws:RequestTag/CostCategory": "?*",
"aws:RequestTag/Env": "?*",
"aws:RequestTag/CreatedBy": "?*",
"aws:RequestTag/Owner": "?*",
"aws:RequestTag/CreationDate": "?*",
"aws:RequestTag/Expiry": "?*",
"aws:RequestTag/Name": "?*",
"aws:RequestTag/Project": "?*"
}
}
}
]}
This policy works well if I select "Amazon Linux 2 AMI (HVM), SSD Volume Type" this type of AMI but gives permission denied error if I select "CentOS 7 (x86_64) - with Updates HVM" this type of AMI. Can someone explain why this is so? Thanks!

DynamoDB - Create Table - IAM Policy - Not Authorised Error

Objective : IAM user should be allowed to create a DynamoDB table in N.Virginia region only.
My IAM Policy attached to the IAM User:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CreateMyTable",
"Effect": "Allow",
"Action": [
"dynamodb:CreateTable",
"dynamodb:ListTables",
"dynamodb:DescribeTable",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:PutItem",
"cloudwatch:*",
"sns:CreateTopic"
],
"Resource": "*"
},
{
"Sid": "DenyOtherRegions",
"Effect": "Deny",
"Action": "dynamodb:*",
"Resource": "*",
"Condition": {
"ForAllValues:StringNotEqualsIfExists": {
"aws:RequestedRegion": "us-east-1"
}
}
}
]
}
I am getting following error:
Not Authorised
Am i missing out on any policy here? Please suggest.