Amplify-js: Storage.put should set ACL public-read for public files

Created on 1 Jun 2018  路  18Comments  路  Source: aws-amplify/amplify-js

public files should be put with ACL of public-read

Inside the Storage.put

    const params: any = {
      Bucket: bucket,
      Key: final_key,
      Body: file,
      ContentType: type
    };

if (opt.level === "public") {
       params["Acl"] = "public-read";
}
Storage feature-request

Most helpful comment

"Bucket" : {"Ref" : "bucketName"},

Slightly modified to include the env, etc, but this works perfect for me. Thank you @XC3S

"S3BucketPolicy": {
  "Type": "AWS::S3::BucketPolicy",
  "Properties": {
    "Bucket": {
      "Fn::Join": [
        "",
        [
          { "Ref": "bucketName" },
          {
            "Fn::Select": [
              3,
              {
                "Fn::Split": [
                  "-",
                  {
                    "Ref": "AWS::StackName"
                  }
                ]
              }
            ]
          },
          "-",
          {
            "Ref": "env"
          }
        ]
      ]
    },
    "PolicyDocument": {
      "Statement": [
        {
          "Sid": "PublidReadGetObject",
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Principal": "*",
          "Resource": {
            "Fn::Join": [
              "",
              [
                "arn:aws:s3:::",
                { "Ref": "bucketName" },
                {
                  "Fn::Select": [
                    3,
                    {
                      "Fn::Split": [
                        "-",
                        {
                          "Ref": "AWS::StackName"
                        }
                      ]
                    }
                  ]
                },
                "-",
                {
                  "Ref": "env"
                },
                "/*"
              ]
            ]
          }
        }
      ]
    }
  }
},

All 18 comments

I'm running into this same issue

i've gotten around this for now just by adding a bucket policy that makes all items public read.

+1

I have some files I'd like to set to public readable and some remain private... would be useful to have the option to set ACL here rather than have to call the low level S3 API.

Below is possible solution.

Update: https://github.com/mbahar/aws-amplify/blob/986a9ec4/packages/aws-amplify/src/Storage/Storage.ts#L153

const { contentType, contentDisposition, cacheControl, expires, metadata, ACL } = opt;

Under: https://github.com/mbahar/aws-amplify/blob/986a9ec4/packages/aws-amplify/src/Storage/Storage.ts#L170 add:

if (ACL) { params.ACL = ACL; }

Called like this:

var options = {
  ACL: 'public-read'
}
Storage.put('some-everyone-read-file.txt', 'hello', options)

References:

I found an alternative way to achieve this.

When you create a Cognito federated identity, two roles, Auth and UnAuth are created. I edited the policy attached to the UnAuth role (name is something like oneClick_Cognito_...Unauth_Role_...) and added S3 List Bucket and S3 Read Object permissions for the object I wanted to be public read.

@nidsharm When solve this ? Hurry

We are having the same problem.

@nidsharm @arocki7 Hi Guys, I've put a workaround on this thread that requires no code changes, or you could implement @JohnJohnXia PR referenced above. Or you have the option to use the low level AWS S3 API... there are plenty of options here for you to get this working.

Thanks @hutch120 for the tip!

I solved it by adding a bucket policy:

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

I recommend to generate the bucket policy by adding the following to the Resources of your s3-cloudformation-template.json

"S3BucketPolicy": {
    "Type" : "AWS::S3::BucketPolicy",
    "Properties" : {
        "Bucket" : {"Ref" : "bucketName"},
        "PolicyDocument": {
            "Statement":[{
                "Sid": "PublidReadGetObject",
                "Effect": "Allow",
                "Action": "s3:GetObject",
                "Principal": "*",
                "Resource": { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "bucketName" } , "/*" ]]}
            }]
        }
    }
},

then publish again

Was it merged?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@philiiiiiipp i am facing same issue am uploading to the S3 storage and it does that successfully but i need to make certain images public
i have tried
{ acl: "public-read", contentType: fileType, customPrefix, level: "public" }
but no luck can you please let me know how to achieve this 馃
any help is appreciated

"Bucket" : {"Ref" : "bucketName"},

Slightly modified to include the env, etc, but this works perfect for me. Thank you @XC3S

"S3BucketPolicy": {
  "Type": "AWS::S3::BucketPolicy",
  "Properties": {
    "Bucket": {
      "Fn::Join": [
        "",
        [
          { "Ref": "bucketName" },
          {
            "Fn::Select": [
              3,
              {
                "Fn::Split": [
                  "-",
                  {
                    "Ref": "AWS::StackName"
                  }
                ]
              }
            ]
          },
          "-",
          {
            "Ref": "env"
          }
        ]
      ]
    },
    "PolicyDocument": {
      "Statement": [
        {
          "Sid": "PublidReadGetObject",
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Principal": "*",
          "Resource": {
            "Fn::Join": [
              "",
              [
                "arn:aws:s3:::",
                { "Ref": "bucketName" },
                {
                  "Fn::Select": [
                    3,
                    {
                      "Fn::Split": [
                        "-",
                        {
                          "Ref": "AWS::StackName"
                        }
                      ]
                    }
                  ]
                },
                "-",
                {
                  "Ref": "env"
                },
                "/*"
              ]
            ]
          }
        }
      ]
    }
  }
},

I believe you will still need to add s3:PutObjectAcl permissions through the parameters.json and s3-cloudformation-template.json...would be nice if this was done automatically, or was configurable from amplify storage add/update

@asmajlovicmars @GeorgeBellTMH

I tried adding the S3BucketPolicy to s3-cloudformation-template.json under Resource: { } and deploying with amplify push
However when uploading with Storage.put(a, b, { acl: 'public-read' }) i'm getting 403 access denied on the upload request and not sure why

@GeorgeBellTMH
I agree with @GeorgeBellTMH

Following the recommendations above I added one more statement to the "S3AuthPublicPolicy.Properties.PolicyDocument" :
{ "Effect": "Allow", "Action": [ "s3:PutObjectAcl" ], "Resource": [ { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3Bucket" }, "/public/*" ] ] } ] }

It seems to work, and I hope this helps others.

Was this page helpful?
0 / 5 - 0 ratings