220

I am using a PHP library to upload a file to my bucket. I have set the ACL to public-read-write and it works fine but the file is still private.

I found that if I change the Grantee to Everyone it makes the file public. What I want to know is how do I make the default Grantee on all objects in my bucket to be set to "Everyone". Or is there another solution to make files public by default?

Code I am using is below:

public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
    if ($input === false) return false;
    $rest = new S3Request('PUT', $bucket, $uri);

    if (is_string($input)) $input = array(
        'data' => $input, 'size' => strlen($input),
        'md5sum' => base64_encode(md5($input, true))
    );

    // Data
    if (isset($input['fp']))
        $rest->fp =& $input['fp'];
    elseif (isset($input['file']))
        $rest->fp = @fopen($input['file'], 'rb');
    elseif (isset($input['data']))
        $rest->data = $input['data'];

    // Content-Length (required)
    if (isset($input['size']) && $input['size'] >= 0)
        $rest->size = $input['size'];
    else {
        if (isset($input['file']))
            $rest->size = filesize($input['file']);
        elseif (isset($input['data']))
            $rest->size = strlen($input['data']);
    }

    // Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
    if (is_array($requestHeaders))
        foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
    elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
        $input['type'] = $requestHeaders;

    // Content-Type
    if (!isset($input['type'])) {
        if (isset($requestHeaders['Content-Type']))
            $input['type'] =& $requestHeaders['Content-Type'];
        elseif (isset($input['file']))
            $input['type'] = self::__getMimeType($input['file']);
        else
            $input['type'] = 'application/octet-stream';
    }

    // We need to post with Content-Length and Content-Type, MD5 is optional
    if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false)) {
        $rest->setHeader('Content-Type', $input['type']);
        if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);

        $rest->setAmzHeader('x-amz-acl', $acl);
        foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
        $rest->getResponse();
    } else
        $rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');

    if ($rest->response->error === false && $rest->response->code !== 200)
        $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
    if ($rest->response->error !== false) {
        trigger_error(sprintf("S3::putObject(): [%s] %s", $rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
        return false;
    }
    return true;
}
timlyo
  • 2,086
  • 1
  • 23
  • 35
condo1234
  • 3,285
  • 6
  • 25
  • 34

7 Answers7

416

Go to http://awspolicygen.s3.amazonaws.com/policygen.html Fill in the details such as: enter image description here In Action select "GetObject" Select "Add Statement" Then select "Generate Policy"

Copy the text example:

{
  "Id": "Policy1397632521960",
  "Statement": [
    {
      "Sid": "Stmt1397633323327",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::bucketnm/*",
      "Principal": {
        "AWS": [
          "*"
        ]
      }
    }
  ]
}

Now go to your AWS S3 console, At the bucket level, click on Properties, Expand Permissions, then Select Add bucket policy. Paste the above generated code into the editor and hit save.

All your items in the bucket will be public by default.

jaxxbo
  • 7,314
  • 4
  • 35
  • 48
  • 15
    This is the correct response. Unlike the answer before, this post also taught me how to create policies and what they do. After reading this I can write a policy manually. – Jason Cheladyn Jan 29 '15 at 19:15
  • 1
    Same here. AWS tends to be opaque at times and probably for very good reason. This form of answer is helpful from ground zero. – Jerome Jun 02 '15 at 15:58
  • 2
    This works when you add new files to bucket but I need to change files already exists in bucket to be public. – Radenko Zec Sep 14 '17 at 13:01
  • 12
    Note: I needed to append a `/*` to the resources name to avoid the error "Bucket action doesn't apply to any resources": https://stackoverflow.com/questions/44228422/s3-bucket-action-doesnt-apply-to-any-resources – d13 Aug 13 '20 at 11:20
  • Handy YouTube vid here showing how to do this https://www.youtube.com/watch?v=_FeAyvqPW74 – JimmyTheCode Dec 07 '22 at 16:20
170

If you want to make all objects public by default, the simplest way is to do it trough a Bucket Policy instead of Access Control Lists (ACLs) defined on each individual object.

enter image description here

You can use the AWS Policy Generator to generate a bucket policy for your bucket.

For example, the following policy will allow anyone to read every object in your S3 bucket (just replace <bucket-name> with the name of your bucket):

{
  "Id": "Policy1380877762691",
  "Statement": [
    {
      "Sid": "Stmt1380877761162",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::<bucket-name>/*",
      "Principal": {
        "AWS": [
          "*"
        ]
      }
    }
  ]
}

The Bucket Policy contains a list of Statements and each statement has an Effect (either Allow or Deny) for a list of Actions that are performed by Principal (the user) on the specified Resource (identified by an Amazon Resource Name or ARN).

The Id is just an optional policy id and the Sid is an optional unique statement id.

For S3 Bucket Policies, the Resource ARNs take the form:

arn:aws:s3:::<bucket_name>/<key_name>

The above example allows (Effect: Allow) anyone (Principal: *) to access (Action: s3:GetObject) any object in the bucket (Resource: arn:aws:s3:::<bucket-name>/*).

dcro
  • 13,294
  • 4
  • 66
  • 75
36

My problem was slightly different, but since this question is on the top of google search I'll leave my solution, maybe it'll help somebody.

I already had had full access to S3 bucket before, but one day it just started to return Access Denied to all my files. The solution was straightforward simple.

  1. Go to Services - S3
  2. Click on your S3 bucket
  3. Switch to Permissions tab, then go to Bucket Policy tab
  4. And click the Save button.

It should reassign permission on all your files.

enter image description here

Anyway, here is full bucket policy that allows makes all object public

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::enter-here-your-media-bucket-name/*"
        }
    ]
}
Serhii Popov
  • 3,326
  • 2
  • 25
  • 36
  • This answer helped me but is it safe? What could someone with bad intent do after applying this policy? – rom Jan 20 '21 at 16:33
  • 4
    @rom If you really need public access to your files (aka media, js, css, pdf etc), then nothing bad will happen, as you only allow read access with `s3:GetObject` action. – Serhii Popov Jan 20 '21 at 17:23
  • fyi, If, for whatever reason, you want to hide the name of your bucket, it's visible in your screenshot. – Mohsen Kamrani Apr 28 '23 at 00:55
5

The JSON above did not work for me, but I found this to be working. I have tested it on multiple buckets. I can write to the buckets programmatically and read from them at the same time

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddCannedAcl",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<bucket_name>/*"
        }
    ]
}
3

Its simple...just add this to your bucket policy..this will make your bucket publicly accessible. I did this as my bucket was only holding images and logos, so making it public makes sense as there is no sensitive or user specific data/asset.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1380877761162",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket-assets/*"
        }
    ]
}
Milind
  • 4,535
  • 2
  • 26
  • 58
1

You can copy and paste the json in this section of the docs: https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html#bucket-policy-static-site

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

  1. Then go to your S3 console.
  2. Open your bucket.
  3. Click on the Permissions tab
  4. Scroll down to Bucket Policy. Click Edit: bucket policy
  5. Paste the json in the following input window (below the "Policy" heading, as shown below):

enter image description here

  1. Copy the ARN provided above the input window (see above image) to replace the "Resource": ["<paste value>/*"]

This video helped me: https://www.youtube.com/watch?v=_FeAyvqPW74

JimmyTheCode
  • 3,783
  • 7
  • 29
  • 71
0

  {
    "Version": "2012-10-17",
    "Id": "StagingBucketPolicy",
    "Statement": [
        {
            "Sid": "PublicReadOnly",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::mybucket/*"
        },
        {
            "Sid": "AllowAdminAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::1111111111:role/Administarator-Role"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::mybucket/*",
                "arn:aws:s3:::mybucket"
                ]
        }
     ]
  }
ADV-IT
  • 756
  • 1
  • 8
  • 10