<p>Let's start at the end: <em>it looks like DenyAllOthers parts are causing the user to not have S3 access.</em></p>
<p>Indeed:</p>
<blockquote>
<p><strong>By default, all requests are denied</strong>. (In general, requests made using the AWS account root user credentials for resources in the account are always allowed.)</p>
</blockquote>
<blockquote>
<p>An explicit allow in any permissions policy (<strong>identity-based or resource-based</strong>) overrides this default.</p>
</blockquote>
<blockquote>
<p>The existence of an Organizations SCP, IAM permissions boundary, or a session policy overrides the allow. If one or more of these policy types exists, they must all allow the request. Otherwise, it is implicitly denied.</p>
</blockquote>
<blockquote>
<p><strong>An explicit deny in any policy overrides any allows.</strong></p>
</blockquote>
<p><a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html" rel="nofollow noreferrer">https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html</a></p>
<p>That means that it is OK to not have any <code>Deny</code> rule. That would work for the customers.</p>
<p>I would suggest <code>Deny</code> <code>s3:PutObjectAcl</code> with anything else then bucket-owner-full-control - see an example here <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html" rel="nofollow noreferrer">https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html</a></p>
<p>An alternative - just disable public access on the whole bucket with <code>PublicAccessBlockConfiguration</code> <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html" rel="nofollow noreferrer">https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html</a></p>
<p>Speaking of that - creating accounts for the users via CloudFormation template allows you to pass the bucket name as a parameter. That way you can manage many users even with just PowerShell / unix sh or similar. You would have one template in a repo and you can change the permissions on a list of users with a simple loop. Terraform (suggested by one of the comments) or any other automation tool is also an option, usually the tools do use CloudFormation under the hood, so it may be still a good idea to understand CloudFormation just in case somethings does not work and you have to investigate. Or to made sure that some configuration option of your automation tool did not allow much broader permissions that you assume.</p>
<p>I also suggest to name the buckets in a clever way. If you name the upload buckets for example upload- you can allow read access to all the upload buckets by one rule with <code>arn:aws:s3:::upload-*/*</code>.</p>
<p>For your your analysts - create a group for them, add the permissions to the group.</p>
<p>It is good to know that you can put the IAM policy either on a bucket or on an identity (role/user/group...). Sometimes it does not matter, sometimes it does. If you ever need to allow access to a customer based on their AWS account, you will need to use a resource policy on the bucket. On the other side - maintaining a complex resource policy with many updates may be challenging. As an alternative you can also allow to assume roles.</p>

CC BY-SA 4.0
2022-01-25T21:12:05.357Z
2022-01-25T21:12:05.357Z
petrchpetr
<p>I am working on a buildout where I am doing the following. Eventually I will need to make this scalable so I am not doing this manually each time.</p>
<p>I have several clients dumping data into S3 buckets. Each client needs R/W access to just that bucket. For that, I can use this policy</p>
<pre><code>{
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [
        {
            &quot;Sid&quot;: &quot;BucketOperations&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: &quot;s3:ListBucket*&quot;,
            &quot;Resource&quot;: &quot;arn:aws:s3:::&lt;bucketname&gt;&quot;
        },
        {
            &quot;Sid&quot;: &quot;ObjectOperations&quot;,
            &quot;Effect&quot;: &quot;Allow&quot;,
            &quot;Action&quot;: [
               &quot;s3:AbortMultipartUpload&quot;,
               &quot;s3:DeleteObject*&quot;,
               &quot;s3:GetObject*&quot;,
               &quot;s3:PutObject*&quot;
            ],
            &quot;Resource&quot;: &quot;arn:aws:s3:::&lt;bucketname&gt;/*&quot;
        },
        {
            &quot;Sid&quot;: &quot;DenyAllOthers&quot;,
            &quot;Effect&quot;: &quot;Deny&quot;,
            &quot;Action&quot;: &quot;s3:*&quot;,
            &quot;NotResource&quot;: [
               &quot;arn:aws:s3:::&lt;bucketname&gt;&quot;,
               &quot;arn:aws:s3:::&lt;bucketname&gt;/*&quot;
            ]
        }
    ] 
}
</code></pre>
<p>On my end, I have several analysts that are using Athena to query the data via Tableau and other tools. I have a Glue job to index the source bucket, and each client dataset will need a Athena results bucket so I can maintain appropriate access.</p>
<p>My problem is that I don't know how to write the S3 policy so that I can have one-per-bucket, and then attach them to the IAM users. When I use the above policy to create</p>
<ul>
<li>bucket1-policy</li>
<li>bucket2-policy</li>
</ul>
<p>And then add them to an IAM user, eg</p>
<ul>
<li>bucket1-policy</li>
<li>bucket2-policy</li>
<li>my-athena-policy</li>
<li>...</li>
</ul>
<p>it looks like <code>DenyAllOthers</code> parts are causing the user to not have S3 access.</p>
<p>Is there a better way to write the S3 access policy, so I can have one per bucket, or do I need to have a separate policy for my Athena users to grant access to the two buckets and then deny the rest?</p>

CC BY-SA 4.0
2022-01-25T18:22:38.310Z
I'd probably brute force it: use terraform for managing this; it will become one line change afterwards. Not sure if worth your time if you are not familiar with TF.
Kyslik
CC BY-SA 4.0
2022-01-25T19:02:27.747Z
@Kyslik I'm not quite at the scale for a playbook yet. The immediate problem is how to handle the policies.
mpdonadio
<amazon-web-services><amazon-s3><aws-iam>
What is the proper AWS IAM policy for access to a single bucket that allows stacking?
mpdonadio
# What is the proper AWS IAM policy for access to a single bucket that allows stacking?

(Asked by: username_0 on 2022-01-25)

I am working on a buildout where I am doing the following. Eventually I will need to make this scalable so I am not doing this manually each time.
I have several clients dumping data into S3 buckets. Each client needs R/W access to just that bucket. For that, I can use this policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "BucketOperations",
            "Effect": "Allow",
            "Action": "s3:ListBucket*",
            "Resource": "arn:aws:s3:::"
        },
        {
            "Sid": "ObjectOperations",
            "Effect": "Allow",
            "Action": [
               "s3:AbortMultipartUpload",
               "s3:DeleteObject*",
               "s3:GetObject*",
               "s3:PutObject*"
            ],
            "Resource": "arn:aws:s3:::/*"
        },
        {
            "Sid": "DenyAllOthers",
            "Effect": "Deny",
            "Action": "s3:*",
            "NotResource": [
               "arn:aws:s3:::",
               "arn:aws:s3:::/*"
            ]
        }
    ] 
}

On my end, I have several analysts that are using Athena to query the data via Tableau and other tools. I have a Glue job to index the source bucket, and each client dataset will need a Athena results bucket so I can maintain appropriate access.
My problem is that I don't know how to write the S3 policy so that I can have one-per-bucket, and then attach them to the IAM users. When I use the above policy to create

bucket1-policy
bucket2-policy

And then add them to an IAM user, eg

bucket1-policy
bucket2-policy
my-athena-policy
...

it looks like DenyAllOthers parts are causing the user to not have S3 access.
Is there a better way to write the S3 access policy, so I can have one per bucket, or do I need to have a separate policy for my Athena users to grant access to the two buckets and then deny the rest?

**Tags:** amazon-web-services, amazon-s3, aws-iam

> **Comments:**
> **username_1**: I'd probably brute force it: use terraform for managing this; it will become one line change afterwards. Not sure if worth your time if you are not familiar with TF.  
> **username_0**: @username_1 I'm not quite at the scale for a playbook yet. The immediate problem is how to handle the policies.  

---

## 1 answers

### Answer by username_2 on 2022-01-25. Score: 1

Let's start at the end: *it looks like DenyAllOthers parts are causing the user to not have S3 access.*

Indeed:

> **By default, all requests are denied**. (In general, requests made using the AWS account root user credentials for resources in the account are always allowed.)

> An explicit allow in any permissions policy (**identity-based or resource-based**) overrides this default.

> The existence of an Organizations SCP, IAM permissions boundary, or a session policy overrides the allow. If one or more of these policy types exists, they must all allow the request. Otherwise, it is implicitly denied.

> **An explicit deny in any policy overrides any allows.**

<https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html>

That means that it is OK to not have any `Deny` rule. That would work for the customers.

I would suggest `Deny` `s3:PutObjectAcl` with anything else then bucket-owner-full-control - see an example here <https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html>

An alternative - just disable public access on the whole bucket with `PublicAccessBlockConfiguration` <https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html>

Speaking of that - creating accounts for the users via CloudFormation template allows you to pass the bucket name as a parameter. That way you can manage many users even with just PowerShell / unix sh or similar. You would have one template in a repo and you can change the permissions on a list of users with a simple loop. Terraform (suggested by one of the comments) or any other automation tool is also an option, usually the tools do use CloudFormation under the hood, so it may be still a good idea to understand CloudFormation just in case somethings does not work and you have to investigate. Or to made sure that some configuration option of your automation tool did not allow much broader permissions that you assume.

I also suggest to name the buckets in a clever way. If you name the upload buckets for example upload- you can allow read access to all the upload buckets by one rule with `arn:aws:s3:::upload-*/*`.

For your your analysts - create a group for them, add the permissions to the group.

It is good to know that you can put the IAM policy either on a bucket or on an identity (role/user/group...). Sometimes it does not matter, sometimes it does. If you ever need to allow access to a customer based on their AWS account, you will need to use a resource policy on the bucket. On the other side - maintaining a complex resource policy with many updates may be challenging. As an alternative you can also allow to assume roles.


---

