Terraform bad policy - amazon-web-services

Hello I have the following policy definition in my terraform, but it keeps returning as malformed
resource "aws_iam_role_policy" "task-policy" {
name = "docker-flowcell-restore-task-policy"
role = "${aws_iam_role.task-role.id}"
policy = "${file("${path.module}/policies/role-docker-flowcell-restore-${var.environment}-ecs-policy.json")}"
}
Been struggling with trying to find the error in this for awhile.
here is the error
aws_iam_role_policy.task-policy: Error putting IAM role policy docker-flowcell-restore-task-policy: MalformedPolicyDocument: Syntax errors in policy.
Here is the policy that is failing
{
"Version": "2012-10-17",
"Statement": [
{
"Sid":"AllowWritesS3",
"Action": [
"s3:GetObject",
"s3:RestoreObject"
],
"Effect": "Allow",
"Resource": [
"Temp_name_for_post",
"Temp_name_for_post"
]
},
{
"SID": "Allow for user for upload S3 bucket",
"Action": [
"s3:PutObject",
"s3:AbortMultipartUpload"
],
"Resource":[
"temp_name_for_post",
"temp_name_for_post"
]
}
]
}

Unfortunately AWS doesn't tell you exactly what the syntax errors are, so you have to find them yourself. Sometimes you can do this by eye; other times you may just want to use the AWS Console as Jeffrey suggested - and perhaps take out each statement one-by-one then re-validate, to see where the error lies (it's a lot quicker than waiting for Terraform to finish).
In your case, you need to:
change SID to Sid in your second statement
change the Sid value in that second statement so it has no spaces in it (eg. "AllowForUserForUploadS3Bucket")
use valid S3 ARNs instead of "temp_name_for_post", such as "arn:aws:s3:::my-bucket/*" to refer to all objects in a bucket named my-bucket
After changing these items, the policy now validates for me via the AWS Console.

It looks like your iam policy is malformed. Here are docs on iam syntax and grammar. Another option to see what is wrong with the policy would be to copy the contents of that file into the iam policy validator in the aws console. The Sid field is not required, but if present it must be unique in the policy, and it cannot contain spaces.

Related

AWS IAM Policy grant permissions for some EC2 instances

I want to restrict access for a specific user to see just few EC2 instances. I created a new user in IAM Roles and I attached a new Policy to it. The content of that Policy is attached below. I tried to look over documentation and to do it myself like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": [
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID1",
"arn:aws:ec2:eu-west-1:ACCOUNT_ID:instance/i-INSTANCE_ID2"
]
}
]
}
I placed my region,ACCOUNT_ID(the owner id, not of the new user created) and instance-id, but when I connect with that user and I go to list all Instances I got this An error occurred fetching instance data: You are not authorized to perform this operation..
After I placed the code in JSON editor, in Policy Review step I got this message:
This policy defines some actions, resources, or conditions that do not
provide permissions. To grant access, policies must have an action
that has an applicable resource or condition. For details, choose Show
remaining Learn more
The AWS documentation mention exactly the same configuration or these examples.
I assume you connect as that user in the console (but it would be the same with CLI) Here is what I think is happening:
To list all the instances, the console most probably calls the DescribeInstances API. As per the list of action/resources/tags that can be used in IAM policy, this API does not support the resource filter in IAM.
This means your user has no authorization to list instances and they will not be shown in the console. You can validate this theory by using the CLI to request the details of a specific instance id, if my hypothesis is correct, it will be authorized.
As DescribeInstances can not be restricted by resource or tags, I don't think it is possible to filter the instance list for a user.
To have the console working, you'll need to add the following statement in your IAM policy
"Statement": [
{ your existing statement },
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*"
}
]
Please report if I was right :-) The example you mentioned in your question shows exactly that : Resources = * on DescribeInstances and Resources specific InstanceId on other operations.
The previous answer is wrong, you can Conditionally allow access to ec2:DescribeInstances by tag names. It's an AWS best practice as well. Also explicitly deny access to the ec2:CreateTags and ec2:DeleteTags actions to prevent users from creating or deleting tags to take control of the instance.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:DescribeInstances",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/UserName": "${aws:username}"
}
}
},
{
"Effect": "Deny",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Resource": "*"
}
]
}
DescribeInstances action does not support condition.
https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html

AWS lambda-function-public-access-prohibited rule in Config

In AWS's Config, I set a rule called: "lambda-function-public-access-prohibited". This says it runs its own lambda to "check", but I can't seem to find much else on what it's doing or how it determines that it's publicly accessible.
Can anyone point me to documentation on this or know what it's doing exactly?
Thank you!
This is the AWS Reference
Under Function policy, if the policy allows actions for the principal element “” or {“AWS”: “”}, it is publicly accessible.
Consider adding the following IAM condition to scope access to your account only.
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "<account_id>"
}
}
}
source: https://hub.steampipe.io/mods/turbot/aws_compliance/controls/control.pci_v321_lambda_1?context=benchmark.pci_v321/benchmark.pci_v321_lambda
EDIT: This config rule was triggered by an S3 bucket resource attached to the lambda. In the console's resource-based policy form, you can specify an AWS account number. Once specified this will automatically create the above policy. After rescanning your config rules should appear as resolved.
Make sure you don't give * in resource or actions, so as to get all resources who have AWS account can access your lambda.
{
"Sid": "lambdaAccess",
"Effect": "Allow",
"Action": [
"lambda:*"
],
"Resource": "*"
},
Instead you can give ARN in resources and specific action like read, write, get access in action item.
Recommended :
{
"Sid": "lambdaAccess",
"Effect": "Allow",
"Action": [
"lambda:GetFunction"
],
"Resource": "arn:aws-us:lambda:us-west-1:123456789:function:lambda1234"
},

What is the ARN of an assumed role assumed by a Lambda function?

I am trying to use the NotPrincipal element in my bucket policy to explicitly deny access to my s3 bucket while whitelisting a particular lambda that accesses the bucket. I specified the role ARN and assumed role ARN for the lambda's role in the NotPrincipal element:
"arn:aws:iam::{Account ID}:role/service-role/{Lambda role name}",
"arn:aws:sts::{Account ID}:assumed-role/{Lambda role name}/{role session name}"
This doc explains the structure of the assumed role ARNs:
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids
I can't seem to get the assumed role ARN correct. The bucket policy is valid, but it seems I can provide anything for the role session name (the last part of the assumed-role ARN), and the ARN is considered valid. What does AWS set this role session name to when Lambda or other service assumes a service role? Is it possible to list active sessions for a role or list the assumed-role ARNs? I am currently using the Lambda function name for the role session name, but this is not working (the Lambda still cannot access the bucket).
Since I can't use wildcards in the NotPrincipal element, I need the full assumed-role ARN of the Lambda once it assumes the role.
UPDATE:
I tried using two conditions to deny all requests where the ARN does not match the ARN of the Lambda role or assumed role. The Lambda role is still denied from writing to S3 using the IAM policy simulator. Here is the policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "WhitelistRegistryAPILambdaRole",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:PutObject",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObjectVersion",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::{bucket name}",
"arn:aws:s3:::{bucket name}/*"
],
"Condition": {
"ArnNotLike": {
"AWS:SourceARN": "arn:aws:iam::{account ID}:role/{lambda role name}"
}
}
},
{
"Sid": "WhitelistRegistryAPILambdaAssumedRole",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:PutObject",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObjectVersion",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::{bucket name}",
"arn:aws:s3:::{bucket name}/*"
],
"Condition": {
"ArnNotLike": {
"AWS:SourceARN": "arn:aws:sts::{account ID}:assumed-role/{lambda role name}/{lambda function name}"
}
}
}
]
}
TL;DR:
The Assumed Role ARN of a Lambda Function is constructed as this:
arn:aws:sts::{AccountID}:assumed-role/{RoleName}/{FunctionName}
Details:
So the "role session name" is, in your case, the lambda function name.
You can easily verify this, by trying to call an API from your Lambda (DynamoDB ListTables for example) for which you do not have permissions. The error message in the callback will also contain the assumed role ARN (note that some service such as S3 do not provide detailed error messages when an operation is denied. DynamoDB, Lambda, and most of the recently launched services, will.)
I'm not sure to understand why you need a NotPrincipal, as probably there is a better way to handle the scenario you described :) More info would be useful to provide a more precise answer.
From the AWS IAM Documentation:
Important: Very few scenarios require the use of NotPrincipal, and we
recommend that you explore other authorization options before you
decide to use NotPrincipal.

S3 Principal Bucket Policy Permissions

I have a cloudformation template up in an S3 bucket (the url follows the pattern but is not exactly equal to: https://s3.amazonaws.com/bucket-name/cloudform.yaml). I need to be able to access it from CLI for a bash script. I'd prefer that everybody in an organization (all in this single account) has access to this template but other people outside of the organization don't have access to the template. A bucket policy I've tried looks like:
{
"Version": "2012-10-17",
"Id": "Policy11111111",
"Statement": [
{
"Sid": "Stmt111111111",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::7777777777:root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-name/*"
}
]
}
With this policy, I and a couple other people in my office are unable to access the url. Even when I'm logged in with the root account I'm getting Access Denied.
Also, this change (only setting Principal to *) makes the bucket accessible to anybody:
{
"Version": "2012-10-17",
"Id": "Policy11111111",
"Statement": [
{
"Sid": "Stmt111111111",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-name/*"
}
]
}
Obviously the signs point to my Principal field being misconfigured. 777777777 is the replacement for the Account ID I see under the My Account page.
So, do I need to worry about this on the IAM front? Considering that I am logged in as the root user, I'd guess I should have access to this as long as I put in a bucket policy. Any help would be much appreciated.
Short and sweet:
The bucket policy doesn't allow you to do what you want because of a wildcard limitation of the Principal element. Your best bet is to create an IAM group and put all IAM users into that group if they need access.
Long version:
Just to make it clear, any request to https://s3.amazonaws.com/bucket-name/cloudform.yaml MUST be signed and have the necessary authentication parameters or the request will be rejected with Access Denied. The only exception is if the bucket policy or the bucket ACL allows public access, but it doesn't sound like this is what you want.
When you say "everybody in an organization (all in this single account)" I assume you mean IAM users under the account who are accessing the file from the AWS console, or IAM users who are using some other code or tool (e.g. AWS CLI) to access the file.
So what it sounds like what you want is the ability to specify the Principal as
"Principal": {
"AWS": "arn:aws:iam::777777777777:user/*"
}
since that is what the pattern would be for any IAM user under the 777777777777 account id. Unfortunately this is not allowed because no wildcard is allowed in the Principal unless you use the catch-all wildcard "*". In other words "*" is allowed, but either "prefix*" or "*suffix" is not. (I wish AWS documented this better.)
You could specify every IAM user you have in the bucket policy like so:
"Principal": {
"AWS": [
"arn:aws:iam::777777777777:user/alice",
"arn:aws:iam::777777777777:user/bob",
"arn:aws:iam::777777777777:user/carl",
...
"arn:aws:iam::777777777777:user/zed",
}
But you probably don't want to update the policy for every new user.
It would be easiest to create an IAM group that grants access to that file. Then you would add all IAM users to that group. If you add new users then you'll have to manually add them to that group, so it is not as convenient as what you originally wanted.

AWS lambda function to use secret manager

created a secret manager key (non-rotational)with plain text option and encrypted. When i tried to get the value in lambda function , I am getting the error as permission denied.
Could you please help how to resolve the issue
You need to assign the role to lambda function to read from the secret manager.
AWS role
The following IAM policy allows read access to all resources that you create in AWS Secrets Manager. This policy applies to resources that you have created already and all resources that you create in the future.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetResourcePolicy",
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret",
"secretsmanager:ListSecretVersionIds"
],
"Resource": ["*"]
}
]
}
You can find more specific example below
iam-policy-examples-asm-secrets