To access resources stored in AWS S3 when using an IAM user, we need to define a policy containing required permissions for the user.

For example, if your bucket is named as zzz.buzz, then you would need something like:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::zzz.buzz",
                "arn:aws:s3:::zzz.buzz/*"
            ]
        }
    ]
}

Here, arn:aws:s3:::zzz.buzz/* allows a user to access everything inside the bucket, but won't allow the user to list the bucket or any folder (prefix) inside the bucket.

arn:aws:s3:::zzz.buzz on the other hand, allows the ListObjects operation.

Alternatively, you may use arn:aws:s3:::zzz.buzz* to include both cases.

Experiments and Errors

If you only give permissions on arn:aws:s3:::zzz.buzz/*, you will fail to execute commands like aws s3 ls s3://zzz.buzz with the error:

fatal error: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

If you only give permissions on arn:aws:s3:::zzz.buzz, you will be able to list the content in the bucket or any folder (prefix) in it, and have access to every single file in the bucket as well. Though no existing files can be deleted, and no new files can be uploaded. Effectively it's read-only access even if you have listed actions such as s3:PutObject, s3:DeleteObject or s3:* in the policy.

If you do try it, errors will be thrown:

upload failed: ./test to s3://zzz.buzz/test An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

delete failed: s3://zzz.buzz/test An error occurred (AccessDenied) when calling the DeleteObject operation: Access Denied

References