Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing an IAM policy and CORS configuration for Amazon S3

I am very new to all this but have been able to get an avatar/image uploader to work in my Rails application. A user can upload a new avatar to my S3 bucket and the avatar shows within the web application.

To this end, I've had to grant "AmazonS3FullAccess" policy to the user. That seems like a bit too much, since the user from the application only needs write (upload his avatar) and read (show the avatar on the web page) permission.

Would you agree that it is therefore better to write a custom policy rather than use AmazonS3FullAccess? If so, I've tried the policy code (adopted from here) below but this didn't work (403 Forbidden error when trying to upload an avatar image). Any suggestions how to correct this code?

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::mybucket"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": ["arn:aws:s3:::mybucket/*"]
    }
  ]
}
like image 721
Nick Avatar asked Jan 09 '23 08:01

Nick


1 Answers

I've grown white hair trying to figure out the proper configuration. Here's one that's working for me:

{
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:DeleteObject"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::mybucket/*",
                "arn:aws:s3:::mybucket"
            ]
        }
    ]
}

This policy should be attached to the proper entity ("Attached entity tab"), which can be a dedicated User. If you need API/Access keys, head to the "Security Credentials" tab for that user and generate some. This allows you more control over who's using that policy.

You can also edit this policy to allow anonymous access by specifying "Principal":"*" as suggested by @therealprashant in the comments, see the docs for more infos.

But you also need to set your CORS configuration. Open the S3 console, click on your bucket, show its Properties (right panel) and click on Permissions, you'll be able to edit the configuration.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://*.example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>http://example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Add as many CORSRule as you need, especially if you need https as well.

Hope that will help.

Edit

Here's the modified version I'm actually using nowadays.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:DeleteObject",
                "s3:GetObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::mybucket/*",
                "arn:aws:s3:::mybucket"
            ]
        }
    ]
}

Note: "principal" can be omitted (like I did here) in IAM policies that are attached to an IAM user, group, or role. During authorization, "principal" is evaluated to be the entity that the policy is attached to.

like image 134
Arnaud Avatar answered Jan 16 '23 22:01

Arnaud