Sriram R
Sriram R

Reputation: 2229

S3 Public Access Alternatives

I've been learning AWS for a little while now and there's one thing that just confuses me.

Let's say I own a app like Instagram (Lol but still) and my users upload a lot of images on my app. Now I take them and store it on a s3 bucket through whatever means. Now the images are stored securely on S3 and the URL of the image is stored on my DB so that my users can easily access the image from the app.

Now, for the image to be accessible everywhere [ Mobile Apps, Desktop App and Web App ], I have to make the bucket public and all the images inside it public so that any application can access the image through the URL. But S3 recommends us not to make the bucket and it's contents public.

I tried not making the bucket public and just set a CORS configuration such like

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>https://www.trailer2you.herokuapp.com</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>https://www.t2ytest-private.herokuapp.com</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>https://www.t2ybeta.herokuapp.com</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <ExposeHeader>Access-Control-Allow-Origin</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

But this also doesn't work. The only way all the apps can access the image through the URL is to make the bucket and all it's contents public through a policy like

{
    "Id": "Policy1598785179613",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1598785170418",
            "Action": [
                "s3:GetObject"
            ],
            "Effect": "Allow",
            "Resource": "{my ARN}",
            "Principal": "*"
        }
    ]
}

But this is what S3 discourages us from doing. Is there any other alternative to achieve something like this. There must be something but I'm new to cloud and I'm not able to find the proper resource for this in the documentation. If someone could point me out to a documentation for something similar to this case, I'd be grateful.

Upvotes: 1

Views: 2444

Answers (2)

Marcin
Marcin

Reputation: 238199

To complement's @John's answer, you could also use server your images from the bucket using CloudFront (CF) through Origin Access Identity (OAI):

Using OAI with CF you can keep your bucket fully private, and force your users to access your images through CF only. The use of CF would also speed up the downloads as it is AWS's content delivery network, closer to the end users than S3.

Upvotes: 2

John Rotenstein
John Rotenstein

Reputation: 269340

Objects in Amazon S3 are private by default.

There are several ways to provide access to a bucket:

  • Permissions on an IAM User or IAM Role (good for staff members and software, but not for end-users)
  • A Bucket Policy that makes a bucket public (good for web sites, but not for private content)
  • A pre-signed URL that provides time-limited access to a private object

It sounds like a pre-signed URL is best for your situation. Imagine a photo-sharing website:

  • A user authenticates to the application
  • The user requests access to a photo
  • The application checks whether the user is entitled to view the photo
  • If so, the application generates a pre-signed URL that has a limited validity period (eg 5 minutes)
  • The user follows this link, or the link is embedded in a web page (eg as a <img> tag)
  • Amazon S3 processes the request by verifying that the pre-signed URL is correctly signed and that the time period has not expired. If everything is okay, it returns the object (file). If it is not okay, then it says "Access Denied"
  • User A then shares a photo with User B. The application updates this information in its database
  • User B can then request access to the photo via the same process

For more details, see: Amazon S3 pre-signed URLs

Upvotes: 7

Related Questions