{
"Sid": "Allow bucket write",
"Effect": "Allow",
"Principal": {
"Service": [
"cloudtrail.amazonaws.com"
]
},
"Action": "s3:PutObject",
"Resource": "${aws_s3_bucket.log-dev-test-bucket-test.arn}/AWSLogs/${var.organization_id}/${aws:PrincipalAccount}/*",
"Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}
},
I am getting this message on my Resource section with regard to ${aws:PrincipalAccount}:
"Extra characters after interpolation expression: Template interpolation doesn't expect a colon at this location. Did you intend this to be a literal sequence to be processed as part of another language? If so, you can escape it by starting with "$${" instead of just "${".HCL"
The error message is suggesting to use $${aws:PrincipalAccount} to escape it.I don't know what that will do to it because i need to have this IAM policy variable in the policy statement resource section to achieve my goal.can any explain what escape will do if i use $$ instead of $ before {aws:PrincipalAccount}.Thank you
There is no such IAM variable as aws:PrincipalAccount. The avaiable IAM variables are listed in Request information that you can use for policy variables .
Related
I am trying to simulate an IAM policy I want to attach to a user so I can restrict their access to two buckets, one for file upload and one for file download.
The policy simulator tells me that the following policy does not work and I cannot figure out why, but it seems to be to do with the wildcards.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetObject",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mybucket-*-report-output/*.csv"
]
},
{
"Sid": "PutObjects",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::mybucket-*-report-input/*.csv"
]
}
]
}
The policy simulator says the following policy does work however:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetObject",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mybucket-*-report-output"
]
},
{
"Sid": "PutObjects",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::mybucket-*-report-input"
]
}
]
}
There must be something I am missing about how to structure the policy, but I want to restrict access to the buckets in the policy, for the operations mentioned, but I also want to ensure that the user can only add and retrieve files with .csv extension.
Below is a screenshot of the simulator:
Your policy is 100% correct - the IAM Policy Simulator is showing wrong results for some absurd reason.
I also can reproduce your problem using the above policy, and the results are all over the place - sometimes both allowed, both denied, only one allowed etc.
It seems to be having an issue with the double wildcard, and sometimes it is coming back with the wrong resource ARN being evaluated in the HTTP response being returned (I'm sometimes seeing both ARNs set to output instead of only 1 set to output in the network tab for the HTTP response - caching?).
It's not limited to PutObject either only and it's giving me loads of conflicting results with the double wildcard, even for other actions like s3:RestoreObject.
Regardless, I'm not sure what the issue is but your policy is correct - ignore IAM Policy Simulator in this case.
If you have access to AWS Support, I would create a support ticket there or post this same question as a potential bug on the AWS forums.
Evidence of a conflicting result, even though I have exactly recreated your scenario:
I have the following s3 IAM policy. It is intended to allow me to copy files from or put files into a bucket below from location temp/prod/tests within the bucket.
In the policy, I have added the StringLike condition, which I had hoped would allow the permissions in the policy to allow copying and puts when the object prefix contains temp/prod/tests.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:ReplicateObject",
"s3:PutObject",
"s3:ListBucket",
"s3:GetObjectAcl",
"s3:GetObject",
"s3:GetBucketLocation",
"s3:GetBucketAcl",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::MYBUCKET/temp/prod/tests/*",
"arn:aws:s3:::MYBUCKET"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"temp/prod/tests/*",
"temp/prod/tests/"
]
}
}
}
]
}
My problem is that the condition prevents me from copying anything under temp/prod/tests/, or putting any new object in this bucket beneath this location.
$ aws s3 cp --recursive s3://MYBUCKET/temp/prod/tests/ /tmp
download failed: s3://MYBUCKET/temp/prod/tests/testfiles/testfile to ../../../tmp/testfiles/testfile An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
And
$ aws s3 cp /tmp/test s3://MYBUCKET/temp/prod/tests/
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
If I remove the Condition, I am able to copy the files as expected.
I don't understand why the condition is not working, because as far as I can see, the requests I am making match the prefix of the condition.
Does anyone know why this is not working as I expect?
First of all, I think it is a good practice to split the rules according to resources. Some of the s3 actions require a bucket, some of them require an object. It's in the documentation to every service: https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazons3.html
Furthermore, the conditions instead of proper resources make the policy even more confusing.
In theory, for uploading an object you need just PutObject, you don't even need any List action. But for various cmdline tools I am curious about how far you would get with something like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "rule1",
"Effect": "Allow",
"Action": [
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload",
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::MYBUCKET/temp/prod/tests/*",
]
},
{
"Sid": "rule2",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketMultipartUploads"
],
"Resource": [
"arn:aws:s3:::MYBUCKET",
]
}
}
}
Most of the policy is derived from this blog post Writing IAM Policies: Grant Access to User-Specific Folders in an Amazon S3 Bucket
Following policy does as you mentioned in the question
It is intended to allow me to copy files from or put files into a bucket below from location temp/prod/tests within the bucket
PLUS all the actions within the folder temp/prod/tests/*. Those can be restricted further. Like you have few permissions asigned.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGroupToSeeBucketListInTheConsole",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": "*"
},
{
"Sid": "AllowListingOfUserFolder",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3::: MYBUCKET"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"temp/prod/tests/*"
]
}
}
},
{
"Sid": "AllowAllS3ActionsInUserFolder",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3::: MYBUCKET/temp/prod/tests/*"
}
]
}
I think part of the confusion here is your expectation that s3:prefix will be present and testable during a CopyObject operation. It's present during a ListBucket operation, and I think that may be the only operation in which it's present. Condition keys for S3 are documented, but the documentation does not appear to include a matrix of which keys are present during which API operations.
Specifically, I believe that s3:prefix will be absent during an actual CopyObject operation and that means that IAM will treat this as values do not match, hence the conditional test fails and the CopyObject operation is denied.
AWS policy evaluation logic is reasonably straighforward and well-defined but the context in which AWS global condition context keys are present is not well-defined, or at least not well-documented. It's also quite difficult to determine exactly why a given API operation was denied after the fact (i.e. which part of the aggregated policies caused the failure), which makes it difficult to write and test complex policies.
Ideally, you'd know which keys are present on which operations, but that doesn't seem to be documented. One way to deal with this is to test (see what works and what does not). Another way is to use the ...IfExists condition check, but this is really designed for use with policy keys that are optional rather than that are not even relevant. When you use StringLikeIfExists, for example:
If the policy key is present in the context of the request, process the key as specified in the policy [i.e. perform a StringLike test]. If the key is not present, evaluate the condition element as true.
In the case of your policy, I'd suggest:
use bucket resources with bucket actions and object resources with object actions (right now, you are mixing them together)
limit your prefix conditions to the ListBucket operation
no need to make GetObject or PutObject conditional, simply indicate the resource ARN for which these operations will be allowed (e.g. arn:aws:s3:::MYBUCKET/temp/prod/tests/*)
I found a solution that works with minimal change to the policy.
I added ForAllValues to the condition, and now I can copy any objects beneath temp/prod/tests/ or any of the subdirectories below temp/prod/tests/.
"Condition": {
"ForAllValues:StringLike": {
"s3:prefix": [
"temp/prod/tests/*",
"temp/prod/tests/"
]
}
}
From the AWS IAM ARN documentation at https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html, I can see wildcard use as shown below which is quite confusing.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ManageRichardAccessKeys",
"Effect": "Allow",
"Action": [
"iam:*AccessKey*",
"iam:GetUser"
],
"Resource": "arn:aws:iam::*:user/division_abc/subdivision_xyz/Richard"
},
{
"Sid": "ListForConsole",
"Effect": "Allow",
"Action": "iam:ListUsers",
"Resource": "*"
}
]
}
In the first statement "Resource": "arn:aws:iam::*:user/division_abc/subdivision_xyz/Richard", why are we not specifying the account number and just substituting with wildcard "*" - I understand that in the context of S3 this is left blank, but over here it is wildcard - what does the wild card here really mean? The wildcard appears to give it a meaning like "any account" but isnt this incorrect?
Also, for the second statement "Resource": "*", does this mean ListUsers for any resource? which does not make any sense - should this not be something like arn:aws:iam::123456789012: indicating list users for this AWS account (123456789012)?
Assuming that the queries actually work (I didn't test them):
Yes, leaving out the account number is a 'little' dangerous because it would also be permitting the user that has this policy to manage access keys for a same-named user in a different account, but the receiving account would not honor the request so it is safe.
The ListUsers command does not actually take many parameters (just a prefix), so it's really an "all or nothing" API call. Please note that it only applies to requesting a list of users, nothing else. (That is, there is no concept of calling "ListUsers for a resource".)
See: Actions, Resources, and Condition Keys for Identity And Access Management - AWS Identity and Access Management
I can't use a resource arn to restrict cloudwatch access.
But I can use conditions. Can I use a condition to only allow users to perform cloudwatch actions in a specific region? I haven't seen any examples of using conditions like this.
CloudWatch is very bad in terms of access control as it does not provide either resources to use in 'Resources' or condition Keys. At some point the DescribeAlarms action in particular was being performed on a US region and was causing unwanted errors when accessing through the console, but I don't see in my CloudTrail that it does now. Maybe it can be restricted to all actions now.
A policy statement to restrict cloudwatch access to the eu-central-region would be:
{
"Sid": "CloudWatchInFrankfurtOnly",
"Effect": "Deny",
"NotAction": ["cloudwatch:DescribeAlarms"],
"Resource": ["arn:aws:cloudwatch:*:*:alarm:*","arn:aws:cloudwatch::*:dashboard/*"],
"Condition": {"StringNotEquals": {"aws:RequestedRegion": "eu-central-1"}}
}
Yes you can use conditions in your policy, for example the below policy will only allow access to cloudwatch actions in eu-central-1.
{
"Statement": [
{ "Sid": "Stmt1338559372809",
"Action": [
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics",
"cloudwatch:DescribeAlarms"
],
"Effect": "Allow",
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:Region": "eu-central-1"
}
}
}
]
}
Hope it will Help!
I have an S3 bucket policy in AWS to control access via IP, as per their standard examples, & would like to be able to add a comment or description inline (in the interest of keeping documentation as close to the implementation as possible).
If I try to add a custom field, e.g. Description, I'll get a validation error on save — "Invalid policy element - Description".
I can find this reference to the grammar of required elements, but can't seem to find any info on whether there are any optional fields allowed at all by the schema, & if so what they are.
Is it possible to add any fields to give an overview of the policy inline?
{
"Version": "2012-10-17",
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"IpAddress": {"aws:SourceIp": "54.240.143.0/24"},
"NotIpAddress": {"aws:SourceIp": "54.240.143.188/32"}
}
}
]
}
From the page you cited, Sid is probably what you want to use for this. It's largely freeform, but you probably want to use underscores where you might otherwise use spaces.
sid_string
Provides a way to include information about an individual statement. Some services require this value to be unique within an AWS account. Some services allow spaces in the Sid value, and others do not.
"Sid": "ThisStatementProvidesPermissionsForConsoleAccess"