Reputation: 15066
I have created a bucket with cloudformation:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
BucketName:
Type: String
Description: "Choose a name for the S3 Bucket"
Default: "myrandomnameforbucket"
S3Bucket:
Type: "AWS::S3::Bucket"
Properties:
AccessControl: "Private"
BucketName: !Ref BucketName
Now I'm writing a bucketPolicy but I'm facing some issues. What I want to achieve:
How can I achieve this? At the moment I denied a delete from userA and allowed an upload from userA.
- Effect: Deny
Principal:
AWS:
!GetAtt UserA.Arn
Action: "s3:DeleteObject"
Resource:
Fn::Join: ["", ["arn:aws:s3:::", Ref: "S3Bucket", "/*"]]
- Effect: Allow
Principal:
AWS:
!GetAtt UserA.Arn
Action: "s3:PutObject"
Resource:
Fn::Join: ["", ["arn:aws:s3:::", Ref: "S3Bucket", "/*"]]
- Effect: Allow
Principal: "?" # * is public?
Action: s3:GetObject
Resource:
Fn::Join: ["", ["arn:aws:s3:::", Ref: "S3Bucket", "/*"]]
Upvotes: 0
Views: 792
Reputation: 11573
I understand there are two questions:
The first question sounds easy at first, as the documentation states:
In resource-based policies, use the Principal element to specify the accounts or users who are allowed to access the resource
So this would mean you could do something like:
Principal:
AWS: !Ref "AWS::AccountId"
But when I tried it just didn't work. When setting the arn of a specific user it worked for me. This seems like a bug to me. Or an unclarity in the documentation. There is this other report I found.
Anyway, what you can do is to use Principal: AWS: "*"
and then use a Condition
to restrict to IAM users only.
The second question is much easier: policies are evaluated such that explicit deny
s have priority over general allow
s, see documentation.
The resulting policy can be e.g. written like this:
S3Policy:
Type: "AWS::S3::BucketPolicy"
Properties:
Bucket: !Ref S3Bucket
PolicyDocument:
Statement:
- Effect: Deny
Action: "s3:DeleteObject"
Resource: !Join ["", ["arn:aws:s3:::", Ref: "S3Bucket", "/*"]]
Principal:
AWS: !GetAtt UserA.Arn
- Effect: Allow
Action: "s3:PutObject"
Resource: !Join ["", ["arn:aws:s3:::", Ref: "S3Bucket", "/*"]]
Principal:
AWS: !GetAtt UserA.Arn
- Effect: Allow
Action: ["s3:GetObject", "s3:DeleteObject"]
Resource: !Join ["", ["arn:aws:s3:::", Ref: "S3Bucket", "/*"]]
Principal:
AWS: "*"
Condition:
StringEquals:
"aws:PrincipalType": ["User"]
Upvotes: 1
Reputation: 3791
{
"Version": "2012-10-17",
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "AllowGet",
"Effect": "Allow",
"Principal":{"AWS":"arn:aws:iam::account-number-without-hyphens:user/user1"},
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::s3_bucket_name",
"arn:aws:s3:::s3_bucket_name/*"
]
},
{
"Sid": "DenyDeleteObject",
"Effect": "Deny",
"Principal": {"AWS":"arn:aws:iam::account-number-without-hyphens:user/user1"},
"Action": "s3:Delete*",
"Resource": [
"arn:aws:s3:::s3_bucket_name",
"arn:aws:s3:::s3_bucket_name/*"
]
},
{
"Sid": "Allow anyone in your account to access bucket",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::account-number-without-hyphens:root"
},
"Action": [
"s3:Get*",
"s3:List*",
"s3:Put*",
"s3:Delete*"
],
"Resource": [
"arn:aws:s3:::s3_bucket_name",
"arn:aws:s3:::s3_bucket_name/*"
]
}
]
}
Here is a template in JSON format I quickly put together. My assumption here is that your group "ALL users (in my environment, nob public)" is everybody in the account. Hence, we define it in the third block. You can always manipulate the principal with whatever you want.
If you have any question please ask, I am happy to help.
Upvotes: 0