Summary
As mentioned above, I want to create an IAM role that can ONLY read / write objects to a SPECIFIC sub-folder in the S3 bucket.
However, I’m unable to despite following the examples here and here
Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"StringEquals": {
"s3:prefix": "levelOne=A/levelTwo=B/levelThree=C"
}
},
"Action": [
"s3:Get*",
"s3:List*",
"S3:Put*"
],
"Resource": "arn:aws:s3:::insert_bucket_name",
"Effect": "Allow"
},
{
"Condition": {
"StringNotEquals": {
"s3:prefix": "levelOne=A/levelTwo=B/levelThree=C"
}
},
"Action": [
"s3:Get*",
"s3:List*",
"S3:Put*"
],
"Resource": "arn:aws:s3:::insert_bucket_name",
"Effect": "Deny"
}
]
}
Testing setup
AWS config file
[profile mybucketrole]
role_arn = arn:aws:iam::insert_account_id:role/insert_role_name
source_profile = default
Test command
aws s3api put-object
--bucket insert_bucket_name
--key levelOne=A/levelTwo=B/levelThree=C/123456789.jsonl
--profile mybucketrole
I would expect that the above command succeeds since I’m writing an object to the levelOne=A/levelTwo=B/levelThree=C
prefix, but I keep getting an
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
NOTE: I set up CloudTrail for my S3 bucket to verify that the intended role is being used by the test command (and indeed it is)
Other things I’ve tried
-
Replacing
StringEquals
+StringNotEquals
withStringLike
+StringNotLike
(respectively) per here -
Changing the resources to
"Resource": [ "arn:aws:s3:::insert_bucket_name", "arn:aws:s3:::insert_bucket_name/*" ]
What am I missing!?
3
Answers
I was able to get the behavior I wanted with the following permissions policies and CDK code.
NOTE:
WRITE policies
READ policies
CDK code
The resource needs to be
arn:aws:s3:::insert_bucket_name/*
to apply to objects within the bucket instead of the bucket itself. Depending on which operations you want to allow the resource needs to be["arn:aws:s3:::insert_bucket_name", "arn:aws:s3:::insert_bucket_name/*"]
At least the
Allow
part could also bearn:aws:s3:::insert_bucket_name/levelOne=A/levelTwo=B/levelThree=C/*
– but not sure if I would prefer that because now it is structurally different compared to theDeny
.Amazon S3 buckets are private by default. Therefore, there is no need to use
Deny
unless you are wanting to override permissions that were otherwise granted by another IAM policy (eg preventing an Admin who has access to all S3 buckets from accessing an HR confidential bucket).Therefore, you could use a policy like this: