AWS Bucket Policy - limit access to a bucket with bucket policy - amazon-web-services

Be default our users have full S3 access via IAM, I have one bucket however that I need to limit access to one specific user, and block all other users.
I followed this guide here https://aws.amazon.com/premiumsupport/knowledge-center/explicit-deny-principal-elements-s3/
and made this bucket policy -
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::XXXXXXXXXXXX:user/USERWHONEEDSACCESS"
]
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::NAMEOFBUCKET/*"
},
{
"Sid": "",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::NAMEOFBUCKET/*",
"Condition": {
"StringNotLike": {
"aws:userid": "USERWHONEEDSACCESS:*"
}
}
}
]
}
However it no worky. Any suggestions?

You can try the following:
{
"Version": "2012-10-17",
"Statement": [
{
"Principal": {
"AWS": [
"arn:aws:iam::XXXXXXXXXXXX:user/USERWHONEEDSACCESS"
]
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::nameofbucket/*",
"arn:aws:s3:::nameofbucket"
],
"Effect": "Allow"
},
{
"NotPrincipal": {
"AWS": [
"arn:aws:iam::XXXXXXXXXXXX:user/USERWHONEEDSACCESS"
]
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::nameofbucket/*",
"arn:aws:s3:::nameofbucket"
],
"Effect": "Deny"
}
]
}
In the How to Restrict Amazon S3 Bucket Access to a Specific IAM Role blog post you can read more about using NotPrincipal and restricting access to a single IAM User, specifically:
You can use the NotPrincipal element of an IAM or S3 bucket policy to limit resource access to a specific set of users. This element allows you to block all users who are not defined in its value array, even if they have an Allow in their own IAM user policies.
To generate this policy code snippet, I used this: https://asecure.cloud/a/s3_restrict_iam_user/ and I pre-filled the iamPrincipal and bucketName parameters with your example values.

While #Rigerta 's answer will work, I think it's worthy to explain why and how you can make your policy work
If you notice, in your policy you're specifying that only that user will be able to access all objects in your bucket
"Resource": "arn:aws:s3:::NAMEOFBUCKET/*"
However, the way IAM permissions work for S3 buckets is a bit tricky. Yes, that user has access to all objects and if he/she tries to push/pull an object via cli the operation will probably succeed, although via AWS console the bucket is unreachable. It's because the user has only access to the objects in the bucket, not the bucket itself
Therefore, you need to add the bucket to your resources. Changing
"Resource": "arn:aws:s3:::NAMEOFBUCKET/*"
by
"Resource": ["arn:aws:s3:::NAMEOFBUCKET/*", "arn:aws:s3:::NAMEOFBUCKET"]
should make it work.
You can check this blogpost for an example of an IAM policy for accessing a bucket. Notice how different actions are granted to different resources

Make sure that you are using an IAM unique identifier in your condition (it should start with the letters AIDA for IAM users).
"StringNotLike": {
"aws:userid": "AIDAXXXXXXXXXXXXX:*"
}
I suspect that you have written the username in your condition because you use the same placeholder as in the Principal. The IAM User Id is distinct from the username and the arn and cannot be found through the Console, but you can for example retrieve it with the aws cli get-user command.

Related

My AWS lifecycle policy doesn't implement due to a bucket policy

I have an s3 bucket where I have a policy in place to prevent anyone from getting access to the objects if they are not from my VPC, However, now when I put a lifecycle policy on the bucket it doesn't apply
Here is the current policy I have on the bucket:
{
"Version": "2012-10-17",
"Id": "Policy1636125293921",
"Statement": [
{
"Sid": "Stmt1636125292369",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketname/*",
"Condition": {
"StringNotEquals": {
"aws:SourceVPC": [
"vpc-0987654321",
"vpc-1234567890"
]
}
}
}
]
}
I have tried to add a second statement that gives full access to my user with this statement:
{
"Sid": "Stmt1636125292368",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/username"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::bucketname/*"
}
I've tried a few different combinations of this second statement, but it is still not running the lifecycle policy, the policy exists and is there, but it doesn't run. Under "Object management overview" for one of the objects the Expiration date and Expiration rule remain blank, however if I remove the DENY policy, then I am able to see the Expiration date. I need that DENY policy to keep doing what it does so I cant remove that. I will also add that the user I am using has full admin permissions.
Instead of having the Principal as "*" for the DENY statement, I replaced it with
"NotPrincipal": {
"AWS": [
"arn:aws:iam::123456789012:user/username",
"arn:aws:iam::123456789012:root"
The policy now denies anyone who isn't from my account, but it also allows anonymous users who are accessing the objects via the VPC to still have access. This has now allowed me to successfully run the lifecycle policy on the bucket.

S3 deny access to administrators

For one AWS S3 bucket, I would like to deny access to everyone except for one specific IAM role. I created a role-based policy to allow access and that works. But other IAM users are also able to access objects and I want to prevent this. I tried adding a bucket policy like this, which denies everyone except this principal and then allows this principal. But this policy blocks access to everyone including that role.
The other IAM users I am trying to block are attached to the built-in AdminstratorAccess policy.
{
"Version": "2012-10-17",
"Id": "PolicySecretBucket",
"Statement": [
{
"Sid": "StmtDenyAll",
"Effect": "Deny",
"NotPrincipal": {
"AWS": "arn:aws:iam::********:role/service-role/my-role"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "StmtAllowLambdaBot",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::********:role/service-role/my-role"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
this is how I would do it:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::MyExampleBucket",
"arn:aws:s3:::MyExampleBucket/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"AROAEXAMPLEID:*",
"ACCOUNT NUMBER"
]
}
}
}
]
}
this is how it works.
the user's will have an IAM policy which allows s3.* actions
we will deny all the s3 actions for the bucket MyExampleBucket for any user id but the user id of the role (and the user id of the root account in case if the role is deleted) using the bucket policy
to get the user id of the role:
aws iam get-role --role-name ROLE-NAME
And finally, why yours does not work: https://serverfault.com/a/988136
reference:
https://aws.amazon.com/blogs/security/how-to-restrict-amazon-s3-bucket-access-to-a-specific-iam-role/
Denying access to a specific bucket is actually quite difficult.
For example, an Administrator might have permissions to assume the Role, so they can still access the bucket.
You would also need to review all policies to ensure that only authorized people can use iam:PassRole to assume the role via an Amazon EC2 instance.
An safer approach would be to put the bucket in a separate AWS Account. Then, only give cross-account access to specific users (not a Role). This way, the default is that Admins have zero access and you then grant access to the desired people. There are less ways to "get around" this type of access.

Connecting Amazon S3 bucket to Other Server - IAM

I am trying to connect Amazon S3 to other services through Bucket policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"arn:aws:iam::ACCOUNT-ID:user/augmen",
}
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:GetObject"
],
"Resource": ["arn:aws:s3:::rajatv.input",
"arn:aws:s3:::rajatv.input/*"]
}
]
}
Still getting errors like:
This policy contains invalid Json
Invalid Bucket syntax
No Resources
It appears that you are wanting to give bucket access to a specific IAM User. If so, the best way is to put a policy on the IAM User themselves, so that the permissions apply only to them.
This policy would grant bucket access to whichever user has it as an IAM policy. To add it, go to the user, Add Inline Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PermitBucketAccess",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::rajatv.input",
"arn:aws:s3:::rajatv.input/*"
]
}
]
}
Bucket Policies, which are applied to the bucket itself, are best used to grant access to everyone, whereas an IAM policy is best for granting permissions to specific IAM Users, Groups and Roles.
Principal needs to have this format:
"Principal": {"AWS": ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:root"]},

AWS S3 Bucket Policy with NotPrincipal denying access

I have configured my S3 bucket with Bucket Policy that looks like this
{
"Version": "2012-10-17",
"Id": "Policy100000000000",
"Statement": [
{
"Sid": "Stmt1463490591045",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketname/*"
},
{
"Sid": "Stmt1463490591012",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::012345678900:user/user1",
"arn:aws:iam::012345678900:user/user2"
]
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::bucketname"
},
{
"Sid": "Stmt1463490660089",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::012345678900:user/user1",
"arn:aws:iam::012345678900:user/user2"
]
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketname/*.xml"
}
]
}
The goal is to allow access to xml files in the bucket root to the selected users only. The rule doesn't seem to be working, since I get access denied
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>DE3DB1FF18B53997</RequestId><HostId>Iy+RnfkFKygJWkSTI0dXjssFsGFP2MydZZi/R5KBw5M8mZnfClt6HMOKJvAwy7sJgSx9BJQ3DbN=</HostId></Error>
I've tried fetching the xml files with AWS Node.js and Python SDKs and with aws-cli. I keep getting the same access denied message.
The AWS documentation regarding Bucket Policies is quite scattered around and has not provided me with a solution to the problem. There's very little documentation at all about using notPrincipal in the policy.
The ListBucket permission works all right, which means that the problem is specific to the rule, not the aim users.
The goal is to allow access to xml files in the bucket root to the selected users only
As per current documentation, s3 do not support file listing resource per postfix/filetype. It only support with prefix, so you would need to put a star without .xml at the end (which allow to access all objects at the folder layer), then you could implement logic to your app if you would allow to access the file or not.
For the bucket policy, by default, s3 policy would give access to user from the account (where the bucket created), as long as the IAM policy have the permission to do so. This is defined from ACL (Access Control List), go to S3 > Permission > Access Control List to check it out.[ AWS S3 ACL docs ]. So the first 2 statement might not be necessary in the statements. For the last statement, this might work but need an additional assumed-role ARN which will vary depending on what is defined for the role session name.
It is recommended to not use the NotPrincipal, and instead use the Condition key at the statement. Put the roleId as the userId at the StringNotLike statement to ignore the deny statement for the particular roleId. Also include the account number at the userId. Example as follows.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::MyExampleBucket",
"arn:aws:s3:::MyExampleBucket/*"
],
"Condition": {
"StringNotLike": {
"aws:userId": [
"ROLE_ID_HERE:*",
"ACCOUNT_NUMBER_HERE"
]
}
}
}
]
}
Check out on this AWS blog for more info:
https://aws.amazon.com/blogs/security/how-to-restrict-amazon-s3-bucket-access-to-a-specific-iam-role/
Your last deny policy simply doesn't talk about what should happen (allow or deny) to the requests with principal user1 or user2. When you send an s3 request as user1 or user2, the bucket policy won't have any effect (since it doesn't have any rule matching the principal user1 or user2 w.r.t the given action and the given resource).
The goal is to allow access to xml files in the bucket root to the selected users only
In this situation, you can mention a rule for explicitly allowing those users the access to your xml files.
{
"Sid": "Stmt1463490660089",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::012345678900:user/user1",
"arn:aws:iam::012345678900:user/user2"
]
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucketname/*.xml"
}

S3 bucket policy, how to ALLOW a IAM group from another account?

I have one S3 bucket in one AWS account (say arn:aws:s3:::my-test-bucket), that needs to be accessed by a IAM group that is defined in another AWS account (say arn:aws:iam::1111222333444:group/mygroup). The following access policy refuses to save, and tells that arn:aws:s3:::my-test-bucket is an invalid principal.
{
"Statement": [
{
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:List*",
"s3:Get*"
],
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::1111222333444:group/mygroup"
},
"Resource": [
"arn:aws:s3:::my-test-bucket",
"arn:aws:s3:::my-test-bucket/*"
],
"Sid": "allow-put-for-dedicated-group"
}
],
}
I have tested by replacing the group with one of the users of the other account and this works:
{
"Statement": [
{
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:List*",
"s3:Get*"
],
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::1111222333444:user/me"
},
"Resource": [
"arn:aws:s3:::my-test-bucket",
"arn:aws:s3:::my-test-bucket/*"
],
"Sid": "allow-put-for-dedicated-user"
}
],
}
The group is existing, I do not understand why it says it is an invalid principal. In fact it does not accept any group of my other account.
Does anyone have an explanation (and possibly a solution) to this behaviour?
Thanks in advance,
Cheers
IAM groups are not valid principals in S3 bucket policies. See this AWS forum post and this SO post for more discussion.
Here's one idea: create an IAM role (for example cross-account-s3) in account #1 (the account with the S3 bucket). That role should have a policy that allows the appropriate S3 bucket access and it should have a trust relationship that says account #2 is trusted for sts:AssumeRole. Then in account #2, delegate permission to assume the cross-account-s3 role to the relevant IAM group. This requires you to trust the IAM admins in the 2nd account to not allow the wrong users to assume the cross-account-s3 role.
As jarmod said, IAM groups are not valid principles. Also jarmod's solution will work. However it is possible to reference the role that is assumed in the S3 bucket policy. This allows you to deny actions unless they are performed by that role, which then provides the visibility of who has access that you wanted or could be used to further limit the access provided. The role reference is via the Role ID, which can be obtained by the following AWS CLI command: aws iam get-role --role-name ROLE_NAME --profile PROFILE_NAME, where ROLE_NAME is the name of the role created with sts:AssumeRole and PROFILE_NAME is the AWS profile setup to access the role.
Something like the following could then be used for the S3 bucket policy:
{
"Statement": [
{
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:List*",
"s3:Get*"
],
"Effect": "Deny",
"Principal": "*"
"Resource": [
"arn:aws:s3:::my-test-bucket",
"arn:aws:s3:::my-test-bucket/*"
],
"Sid": "deny-put-for-anyone-but-dedicated-role",
"Condition": {
"StringNotLike": {
"aws:userId": [
"ROLE_ID:*"
]
}
}
}
],
}
More details about this can be found in this blog post, which includes using userId to limit access to a user.