# Give minimal IAM permissions for S3 actions

## Why a separate guide on this?

AWS offers the option to generate permissions based on Cloudtrail logs.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1686296905978/fb55b817-ed3a-4f48-be20-3eda4c0da36c.png align="center")

That's great for management events, however it doesn't work well for data events. But why?

AWS' policy generation gives you nothing:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1686297212146/5e3927de-7ece-40bd-804d-86f9a6b8c14e.png align="center")

And Cloudtrail doesn't record data events in the Event History tab (only Management events).

So when would you even need this?  
Here's the specific use case:

> *"I want to find out what S3 buckets a user accesses and what kind of actions it requires, so I can generate the minimum amount of IAM permissions for the user/users"*

## How-to

1. You need to have Cloudtrail log already set up. I'll not cover it in this guide (maybe later), but once you have it, let it run for a few days/weeks to allow some actions to be generated. These logs will be saved in an S3 bucket. Keep a note of it.
    
2. Go to *Cloudtrail* =&gt; *Event history* and click on *Create Athena table*
    
3. This will generate you a create table SQL command, which for me was wrong. Make sure you select a *Storage location* is set to the bucket that holds your data events and make sure on the bottom the LOCATION is correct. (it wasn't for me)
    
4. if it's correct, go ahead and create a table, then go to Athena
    
5. if not, then copy the create table SQL, go to Athena and try to create a table there pasting in your SQL query with the modified LOCATION property (unfortunately you can't edit the query from Cloudtrail 🤷‍♂️
    
6. once there, you can use this SQL to give you the buckets and the actions that are executed on it:
    
    ```sql
    SELECT 
        DISTINCT 
        split_part(resource.arn, '/', 1) AS bucket, 
        eventname AS action
    FROM 
        "default"."bucketxzy_cloudtrail_logs_s3_events" 
    CROSS JOIN 
        UNNEST(resources) AS t(resource)
    WHERE 
        useridentity.arn = 'arn:aws:iam::123456789012:user/john' 
    ORDER BY 
        bucket, action;
    ```
    
7. which will result in something like this:
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1686298585190/48d207cd-87b0-4c59-91a6-bb5b26af4f89.png align="center")
    
8. Once you have this, you can generate an IAM policy from them, which will look something like this (you'd need to find the appropriate permission for each action above):
    
    ```json
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "s3:DeleteObject",
                    "s3:GetObject",
                    "s3:ListBucket",
                    "s3:PutObject"
                ],
                "Resource": [
                    "arn:aws:s3:::your_bucket/*"
                ]
            }
        ]
    }
    ```
    

## Further considerations

Now the above gives you an overview of what buckets a user is accessing, but you can take this further. As an example:

* you can modify the SQL to bring back all users rather than just one
    
* you can request the full path to the object that's accessed, creating an even more granular permission set.
    

Additionally, please note, none of these services are free. Athena, S3 and Cloudtrail all cost money.
