To recap, you were needing a bucket policy that restricted access to your S3 bucket and contents, but allow access to your Cloudfront Origin Access Identity as well as your IAM Role(s) you wanted to specify. I have a few ways you can do this, one with the NotPrincipal element and the other with the Principal element. It depends on how many people are using your IAM Role, or if you plan on scaling the amount of access to the Role. You can prevent Amazon Identify and Access Management (IAM) entities from accessing your Amazon S3 buckets by designating permissions in a bucket policy using the NotPrincipal element and explicit Deny. However, NotPrincipal does not support wildcards.
In this policy example, you must list the role session name of every user and every instance ID that will be assuming the role:
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/cross-account-audit-app",
"arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/instanceID",
"arn:aws:iam::444455556666:role/cross-account-read-only-role",
"arn:aws:iam::444455556666:root"
]
}
To cover all of those users and instances, you would need a wildcard in the statement to represent the assumed role:
"arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/*"
However, wildcards are not supported with the NotPrincipal element. This will work if you only have yourself using the Role, or one Instance for example, but as you scale, you need to add the ARN for user/instance assuming the role.
In this example, instead of NotPrincipal
, use "Principal": "*"
as the target entity in each statement block, which includes the Condition for each Allow block. Wildcards are used in "aws:userid": ["ROLE-ID:*"]
to include all names that are passed by the calling process (such as application, service, or instance ID) when it makes a call to get temporary credentials. For more information, see Information Available in All Requests. The root account is included to prevent lockout:
"Condition": {
"StringLike": {
"aws:userid": [
"AROAID2GEXAMPLEROLEID:*",
"444455556666"
]
}
}
StringNotLike in the Deny block:
"Condition": {
"StringNotLike": {
"aws:userid": [
"AROAID2GEXAMPLEROLEID:*",
"444455556666"
]
}
}
Here is the complete policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::myExampleBucket",
"Condition": {
"StringLike": {
"aws:userid": [
"AROAID2GEXAMPLEROLEID:*",
"444455556666"
]
}
}
},
{
"Sid": "",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::myExampleBucket/*",
"Condition": {
"StringLike": {
"aws:userid": [
"AROAID2GEXAMPLEROLEID:*",
"444455556666"
]
}
}
},
{
"Sid": "",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::myExampleBucket/*",
"arn:aws:s3:::myExampleBucket"
],
"Condition": {
"StringNotLike": {
"aws:userid": [
"AROAID2GEXAMPLEROLEID:*",
"444455556666"
]
}
}
}
]
}
Note:
To get information about an IAM role
The following get-role command gets information about the role named Test-Role:
aws iam get-role --role-name Test-Role
Output:
{
"Role": {
"AssumeRolePolicyDocument": "<URL-encoded-JSON>",
"RoleId": "AIDIODR4TAW7CSEXAMPLE",
"CreateDate": "2013-04-18T05:01:58Z",
"RoleName": "Test-Role",
"Path": "/",
"Arn": "arn:aws:iam::123456789012:role/Test-Role"
}
}
Important Note
Basically when you create the Origin Access Identity using the CloundFront API, you get the UserID and S3 canonical ID and you will have to note it down to use this in the condition string.
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html#private-content-creating-oai-api
If you currently don't have the ID for the Origin Access Identity of your CloudFront, please create a new one and you can save the ID element and S3 Canonical ID as suggested.