AWS S3 deny all access except for 1 user - bucket policy

11,172

It's quite simple:

  • By default, buckets have no public access
  • Do NOT add a Bucket Policy, since you do not want to grant access public access
  • Instead, add a policy to the IAM User granting them access

The main thing to realise is that the IAM User cannot access content via unauthenticated URLS (eg s3.amazonaws.com/bucket/file.jpg) because S3 doesn't know who they are. When the IAM User accesses the content, they will need to use authenticated access so that S3 knows who they are, such as:

The policy on the IAM User would look something like:

{
  "Effect": "Allow",
  "Action": "s3:*",
  "Resource": [
    "arn:aws:s3:::my_bucket",
    "arn:aws:s3:::my_bucket/*"
  ]
}
Share:
11,172
jeffery_the_wind
Author by

jeffery_the_wind

Currently a Doctoral student in the Dept. of Math and Stats at Université de Montréal. In the past I have done a lot of full stack development and applied math. Now trying to focus more on the pure math side of things and theory. Always get a lot of help from the Stack Exchange Community! Math interests include optimization and Algebra although in practice I do a lot of machine learning.

Updated on August 21, 2022

Comments

  • jeffery_the_wind
    jeffery_the_wind over 1 year

    I have set up a bucket in AWS S3. I granted access to the bucket for my IAM user with an ALLOW policy (Using the Bucket Policy Editor). I was able to save files to the bucket with the user. I have been working with the bucket for media serving before, so it seems the default action is to give public permission to view the files (images), which is fine for most web sites.

    In my new project I want to be able to access the S3 bucket with an IAM user but want to deny all other access. No public read access, no access whatsoever besides the IAM user who should have full access save/delete whatever.

    What seems like I should do, I was reading about here. It says to create a Deny policy using the NotPrincipal attribute, and that way it will still allow that user, but deny everyone else. For good measure I also added an Allow policy just for the user I want:

    {
        "Version": "2012-10-17",
        "Id": "Policy**********",
        "Statement": [
            {
                "Sid": "Stmt**********",
                "Effect": "Deny",
                "NotPrincipal": {
                    "AWS": "arn:aws:iam::*********:user/my_user"
                },
                "Action": "s3:*",
                "Resource": "arn:aws:s3:::my_bucket/*"
            },
            {
                "Sid": "Stmt*************",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::**********:user/my_user"
                },
                "Action": "s3:*",
                "Resource": "arn:aws:s3:::my_bucket/*"
            }
        ]
    }
    

    But this is denying access to everyone even my_user. Again I can confirm that I had access when I just used the Allow portion of the policy above, but then the public also has read access, which I am trying to turn off.

    How can I set up my bucket policy to give full access to only the unique IAM user and deny all access to any other user?

    Thanks.

    • Michael - sqlbot
      Michael - sqlbot over 7 years
      How, specifically, is "my_user" accessing the bucket?
  • jeffery_the_wind
    jeffery_the_wind over 7 years
    That is golden, thanks. I will try that. I noticed that adding both lines in the Resource was important. I tried with that setup I have above and lost control of the bucket through the web interface... So that was def not the right way.
  • jeffery_the_wind
    jeffery_the_wind over 7 years
    I created a new bucket, gave no bucket policy and added the IAM policy like you have, and it works fine for that user. But when I take the url for a photo and put it in my browser, I can access it that way as well. That is what I was trying to turn off. So it seems by default the whole bucket has public access. Does that sound right to you?
  • John Rotenstein
    John Rotenstein over 7 years
    If an object is still publicly accessible via an anonymous URL, then check the object itself and make sure it does not have an "Everybody" permission defined. This is because permissions can be granted at the object, bucket OR user level. Also try it in another browser or an Incognito window in case something is cached. Oh, and don't use the "Actions->Open" command, because that generates a Pre-Signed URL that grants temporary access. Instead, click the blue link shown in the Properties pane, which is anonymous.
  • jeffery_the_wind
    jeffery_the_wind over 7 years
    Thanks so much. What is happening is what you suggested. Each individual file DOES have an "Everybody" permission, where the bucket does not. When I turn these off, those files then become private. So it seems this is the issue. Do you know how to set this behavior? It seems to be giving this permission be default.
  • John Rotenstein
    John Rotenstein over 7 years
    It is possible to grant PUBLIC-READ access (which means Everybody can view/download the object) at the time that the object is uploaded, so check how the files are getting into S3 and what options are being set.
  • jeffery_the_wind
    jeffery_the_wind over 7 years
    Perfect. That is what was happening. I fixed my application to set the access level on the file when saving and now we are looking good!