Protected S3 upload with files available via public get endpoint

Hi! Just followed the excellent chapters through to the end, and had a great time. Now, I am just playing around with different ways this setup could be manipulated.

Goal: make all created notes and attachments available to a public endpoint (read only), on an open route in the client.

I was able to achieve public notes via creating a global index and doing a query against a new common field I added to Dynamodb with a new getAll api gateway endpoint. However, making the images accessible seems to be a trickier task and I have been blocked on it for days.

Here is what I tried in s3-bucket.yml:

Resources:
  AttachmentsBucket:
    Type: AWS::S3::Bucket
    Properties:
      # Set the CORS policy
      CorsConfiguration:
        CorsRules:
          - AllowedOrigins:
              - '*'
            AllowedHeaders:
              - '*'
            AllowedMethods:
              - GET
              - PUT
              - POST
              - DELETE
              - HEAD
            MaxAge: 3000
      AccessControl: PublicRead
  AttachmentsBucketAllowPublicReadPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket:
        Ref: AttachmentsBucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - 's3:GetObject'
            Resource:
              Fn::Join: ['', ['arn:aws:s3:::', { 'Ref': 'AttachmentsBucket' }, '/*']]
            Principal: '*'
# Print out the name of the bucket that is created
Outputs:
  AttachmentsBucketName:
    Value:
      Ref: AttachmentsBucket

But on the front-end I get a message saying the credentials are required when the photo is attempted to be accessed with a signed out user.

I am assuming it is because I am attempting to get the photo via amplify with the wrong config settings. And while it seems like there should be a better approach to this scenario, it evades me.

What is the best approach to maintaining a private upload (for note owners that want to replace their image), but instead storing the image in a folder by noteId (vs private user folder) and making them available to a public get endpoint?

1 Like

oops, had this in the wrong category, switched it to general

Which call in your code is failing with the error? Also, how are you making API calls for users that are not logged in?

Any solution to this? This is exactly what I would like to do. This seems like a common use case.

These policies seem to help but still use the protected/private user folders.

I am looking for a solution similar to yours. Any help appreciated.

This does seem like a common use case. Let me get a better sense of it so we can add a chapter on it.

You want logged in users to create notes with attachments. And the notes are publicly viewable and you can download the attachments. But you can’t publicly edit them?

Is that right?

3 Likes

Yes, that is the use case. Authenticated users upload or replace attachments associated to their notes. Unauthenticated users can view the notes and download the attachments (read only).

That’s the correct use case.

For the get/public notes, you can use a bucket policy like the following:

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

For the authenticated users, it should be managed by the Amplify Storage API

2 Likes