19

I tried uploading to s3 and when I see the logs from the s3 bucket logs this is what it says:

mybucket-me [17/Oct/2013:08:18:57 +0000] 120.28.112.39 
arn:aws:sts::778671367984:federated-user/dean@player.com BB3AA9C408C0D26F 
REST.POST.BUCKET avatars/dean%2540player.com/4.png "POST / HTTP/1.1" 403 
AccessDenied 231 - 132 - "http://localhost:8080/ajaxupload/test.html" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17" -

I got an access denied. From where it's pointing I think the only thing that I'm missing out is adding of bucket policy. So here goes.

Using my email I could log in to my app and upload an avatar. The bucket name where I want to put my avatar is mybucket-me and in that it has a sub bucket named avatars.

-mybucket-me
 -avatars
  -dean@player.com //dynamic based on who are logged in
   -myavatar.png //image uploaded

How do I add a bucket policy so I could grant a federated such as I to upload in s3 or what is the correct statement that I will add on my bucket policy so it could grant me a permission to upload into our bucket?

starball
  • 20,030
  • 7
  • 43
  • 238
Wondering Coder
  • 1,652
  • 9
  • 31
  • 51

4 Answers4

25

2019+

You now either have to:

  • Set Block new public ACLs and uploading public objects to false if your items are public (top left policie in the picture)

enter image description here

  • Set acl: 'private' when uploading your image if your items are private

Example in Node.js:

const upload = multer({
    storage: multerS3({
        s3: s3,
        bucket: 'moodboard-img',
        acl: 'private',
        metadata: function (req, file, cb) {
            cb(null, {fieldName: file.fieldname});
        },
        key: function (req, file, cb) {
            cb(null, Date.now().toString())
        }
    })
})
Sebastien Horin
  • 10,803
  • 4
  • 52
  • 54
  • 1
    I was facing the same issue and changing acl to private worked for me. Thanks :D – Abhay Maniyar Nov 23 '19 at 14:04
  • Wasted three hours, it's 1 AM but finally. I was using S3 with CloudFront which is why everything is private and it was causing error in uploading a file with Public access. – Lalit Fauzdar Jun 07 '22 at 19:33
10

To upload to S3 bucket, you need to Add/Create IAM/Group Policy, for example:

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

Where arn:aws:s3:::test is your Amazon Resource Name (ARN).

Source: Writing IAM Policies: How to Grant Access to an Amazon S3 Bucket

Related:

kenorb
  • 155,785
  • 88
  • 678
  • 743
  • 1
    I don't think "DeleteObject" is specifically required for most uploads https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property but otherwise this is the most restrictive permissions to get this to work, I think – piisexactly3 Apr 18 '19 at 19:21
7

You can attach the following policy to the bucket:

{
    "Version": "2008-10-17",
    "Id": "Policy1358656005371",
    "Statement": [
        {
            "Sid": "Stmt1354655992561",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:sts::778671367984:federated-user/dean@player.com"                  
                ]
            },
            "Action": [
                "s3:List*",
                "s3:Get*"
            ],
            "Resource": [
                "arn:aws:s3:::my.bucket",
                "arn:aws:s3:::my.bucket/*"
            ]
        }
    ]
}

to grant the federated user dean@player.com read-only permissions to 'my.bucket'.

This policy is not very maintainable because it names this user in particular. To give access to only certain federated users in a more scalable way, it would be better to do this when you call GetFederationToken. If you post your STS code I can help you assigning the policy there, but it is very similar to the above.

prestomation
  • 7,225
  • 3
  • 39
  • 37
  • hi, sorry for the late response. Im using the s3 browser upload, we have an API that we call which give us the credentials. Here is a link where almost all of the relevant code are posted. [link](http://stackoverflow.com/questions/19401936/signaturedoesnotmatch-browser-based-upload-to-s3?noredirect=1#comment28781719_19401936) – Wondering Coder Oct 17 '13 at 22:51
  • Will this be okay actions are only "List & Get"? What im trying to do is an upload or post method. Also your correct what I need is the scalable way, different user will be uploading on the bucket. Please help. – Wondering Coder Oct 17 '13 at 23:00
  • You need to change the actions to whatever you need, just "s3:*" will give you access to all S3 actions. What language are you using? Post the code you have so far – prestomation Oct 18 '13 at 00:47
  • Hi prestomation, im using javascript+jquery Ajax. Here is a link to all my related source code. Please [click](http://stackoverflow.com/questions/19401936/signaturedoesnotmatch-browser-based-upload-to-s3?noredirect=1#comment28781719_19401936) – Wondering Coder Oct 19 '13 at 12:44
  • Please notice that s3:* access will also give you DeleteBucket permission. Limiting that action to specific key within a bucket should prevent actual bucket deletion, but that is still a bad practice. – Jukka Dahlbom Feb 13 '15 at 12:14
1

if you are using programmatic access using credential or aws-sdk with any server then try to comment ACL:public-read then everything works fine without any changes if IAM has already permission to (crud) itself

enjoy ! no more google

Nitish Kumar
  • 111
  • 3