Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Amazon s3: "Block public access" settings to allow for public read private write with signed url

enter image description hereI want to upload images through signed urls. The images should have public read access only. I'm confused on what settings I need to enable or disable.

If I disable all "Block public access" settings, it works as intended. What I worry is that AWS recommends these permissions to be turned on. Picture shows the settings I mentioned.

  const s3 = new aws.S3();
  const s3Params = {
    Bucket: process.env.S3_BUCKET,
    Key: fileName,
    Expires: 60,
    ContentType: fileType,
    ACL: 'private'
  };

When I set "ACL" to "private", I'm able to upload the image on client side with the signed url, but if I use "public-read", I get Access Denied. I also tried adding

{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"AddPerm",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::myapp/*"]
    }
  ]
}

to the "Bucket Policy" setting to get public read access, but I get Access Denied again because of the public access settings.

What would be the most secure way to have public read, private write access? Am I using S3 is an unintended way? Am I suppose to use the CloudFront service to serve these images publicly?

like image 807
John Wong Avatar asked Jul 08 '19 17:07

John Wong


People also ask

What is S3 block public access?

S3 Block Public Access provides controls across an entire AWS Account or at the individual S3 bucket level to ensure that objects never have public access, now and in the future. Public access is granted to buckets and objects through access control lists (ACLs), bucket policies, or both.

Which S3 access method allows you to deny access to individual items?

Restrict access to your S3 resources. By default, all S3 buckets are private and can be accessed only by users who are explicitly granted access. Restrict access to your S3 buckets or objects by doing the following: Writing IAM user policies that specify the users that can access specific buckets and objects.

Which features can be used to restrict access to Amazon S3 data?

You can configure any access point to accept requests only from a virtual private cloud (VPC) to restrict Amazon S3 data access to a private network. You can also configure custom block public access settings for each access point.


1 Answers

S3 block public access is just another layer of protection with main purpose to prevent you from accidentally granting public access to bucket/objects.

The access-denied messages that you are experiencing are due to the mentioned S3 block public access feature that prevents you from setting public access to your bucket/objects (exactly what you are trying to do).

If your use case requires public access to S3 objects and you know what you are doing then you can/need to disable this this feature (or at least some of the sub-options based on how you are going to grant the access). Example would be public website hosted on S3 which clearly requires you to allow public read.

What is the best way set up access to your objects depends on whether you want every object inside of the bucket to be publicly readable.

If every object is supposed to be publicly readable, then the easiest way to accomplish this is via bucket policy - the one that you have included in your post.

{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"AddPerm",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::myapp/*"]
    }
  ]
}

If only some of the objects are supposed to be publicly readable then you have several options.

First options is probably the easiest to implement - create separate buckets for private and non-private objects. This is usually the preferred way if possible because you can treat your confidential data separately from the public one and is the least error prone.

Second option is to create separate folders in a single bucket where one folder can hold confidential data and another folder can hold public data. Then you can use bucket policy again and add read access only to a specific folder.

"Resource":["arn:aws:s3:::myapp/public/*"]

Third option is to use object ACLs instead of Bucket Policies. You need to go for this option when there is no clear distinction between objects that are being uploaded and you want to let the one who is uploading the object to decide whether the object should be public or not. If you don't need to choose between public and private on per object case then you should avoid this option as it is the hardest one to manage and the easiest one to lose track of what is going on with your objects.

Just one last note. If you are using Bucket Policies to grant public read access to your objects then you don't need to specify ACL in s3params.

And to answer your questions:

Am I using S3 is an unintended way?

No, it is perfectly fine to grant public read access to your bucket/objects as long as you intent to do so. Those additional layers of protection are there because S3 buckets are used to store highly confidential data as well and from time to time, someone unintentionally changes the setting which can cause huge damage, depending on the nature of data stored inside. Therefore, public cloud providers are trying to make it harder to set public access for their data stores so that changing this setting is not made by mistake, but rather it should be well informed decision.

Am I suppose to use the CloudFront service to serve these images publicly?

CloudFront provides you with some nice features such as additional protection and caching at the AWS network's edges but it is definitely not mandatory to use it and since it is not a free service, I would advise to look closer into it before choosing to use it so that you don't waste your resources (money) meaninglessly.

like image 186
Matus Dubrava Avatar answered Sep 25 '22 05:09

Matus Dubrava