DEV Community

loading...
Cover image for AWS Amplify: How to interact with an existing S3 bucket

AWS Amplify: How to interact with an existing S3 bucket

Brice Pellé
・5 min read

The AWS Amplify framework provides solutions that allows Frontend and Mobile web developers to easily implement solutions that interact with resources in the AWS cloud. For example, the Amplify CLI allows you to create a fully configured and secure S3 bucket to store items. Meanwhile, the Amplify Storage module lets you easily list the content of your bucket, upload items, and fetch items.

The Amplify libraries are not just great for interacting with resources created by the Amplify CLI. As highlighted here, you can manually configure your application to interact with an existing S3 bucket. In this article, I’m going to show you how you can set up an Amplify application to interact with an existing S3 bucket.

Let’s take a very common situation where you have an S3 bucket that was created outside an Amplify project, and that is used as an origin for a Amazon CloudFront distribution. The origin content is stored under a prefix in the bucket. Public access to the bucket is not allowed. Let’s set up an app that lets authenticated users manage files in the bucket.

Setting up your Amplify app

In your application folder, initialize Amplify and follow the prompt to configure.

$ amplify init

Initializing the app creates two IAM roles: AuthRole and UnauthRole. These roles are respectively used by authorized users and unauthorized users (if you configure guest access). You’ll use the AuthRole role in a bit.

Next set up auth to define a Cognito User Pool for your app. This will allow users to sign in.

$ amp add auth

Step through the configuration

 Do you want to use the default authentication and security configuration? 
❯ Default configuration

 How do you want users to be able to sign in? (Use arrow keys)
❯ Username

Select to configure additional settings. Set up greenlist filtering. This configures a Lambda function that checks the user’s email domain name when they try to register. Only emails with matching domains are permitted to register. You can edit the created Lambda function to implement custom checks and filtering.

 Do you want to configure advanced settings?
❯ Yes, I want to make some additional changes.

 Do you want to enable any of the following capabilities?
❯ Email Domain Filtering (whitelist)

 Do you want to enable any of the following capabilities? Email Domain Filtering (whitelist)
? Enter a comma-delimited list of allowed email domains (example: 'mydomain.com, myotherdomain.com'). your-own-domain.com

Create a policy resource

The next step is to create a policy granting access to the bucket that you will then associate with AuthRole. To do this, you will create a new policy category in your Amplify project. I like this approach because it allows to manage the policy independently of the auth category. Also your configuration is not lost if you update auth.

Open the file amplify/backend/backend-config.json, and define a new s3Auth resource in the policy category.

"policy": {
    "s3Auth": {
      "service": "iam",
      "providerPlugin": "awscloudformation"
    }
  }

Create the following file structure in the amplify/backend/ directory

policy
└── s3Auth
    ├── parameters.json
    └── template.json

Edit policy/s3Auth/parameters.json to make the AuthRoleName value available as a parameter to your template:

{
  "authRoleName": {
    "Ref": "AuthRoleName"
  }
}

Edit policy/s3Auth/template.json where you define the s3sappolicy inline policy for the AuthRole (see: "Roles": [{ "Ref": "authRoleName" }]). Note the “statement” and the “resource”. You should specify the actions allowed on the bucket and items. You can find some user policy examples here. The policy below is an example that limits access to files under <PREFIX>/.

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "inline policy for s3 access",
  "Parameters": {
    "authRoleName": { "Type": "String" },
    "env": { "Type": "String" }
  },
  "Conditions": {
    "ShouldNotCreateEnvResources": {
      "Fn::Equals": [{ "Ref": "env" }, "NONE"]
    }
  },
  "Resources": {
    "s3sappolicy": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "s3-policy-for-bucket-access",
        "Roles": [{ "Ref": "authRoleName" }],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "InteractWithObjects",
              "Effect": "Allow",
              "Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
              "Resource": "<BUCKET>/<PREFIX>/*"
            },
            {
              "Sid": "ListBucket",
              "Effect": "Allow",
              "Action": "s3:ListBucket",
              "Resource": "<BUCKET>",
              "Condition": {
                "StringLike": {
                  "s3:prefix": ["<PREFIX>", "<PREFIX>/*"]
                }
              }
            }
          ]
        }
      }
    }
  }
}

Run amplify env checkout <current-env-name> to populate the CLI runtime files and make it aware of the newly added custom resources; then run amplify push to deploy your changes.

$ amplify status

Current Environment: dev

| Category | Resource name              | Operation | Provider plugin   |
| -------- | -------------------------- | --------- | ----------------- |
| Policy   | s3Auth                     | No Change | awscloudformation |
| Function | s5b5b8cbf5b5b8cbfPreSignup | No Change | awscloudformation |
| Auth     | s5b5b8cbf5b5b8cbf          | No Change | awscloudformation |

Configuring your bucket

Your app will initiate cross-origin HTTP requests on your behalf to interact with your S3 bucket. You need to set up a CORS policy on your bucket to allow those requests.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <ExposeHeader>x-amz-server-side-encryption</ExposeHeader>
    <ExposeHeader>x-amz-request-id</ExposeHeader>
    <ExposeHeader>x-amz-id-2</ExposeHeader>
    <ExposeHeader>ETag</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

You can set this up in the S3 console by selecting your bucket and opening the Permissions tab.

Alt Text

Connecting your app

At this point, you have created the resources necessary to authenticate users to your app and to access your S3 bucket. Now’s let’s connect your app. Your Amplify project provides an aws-exports.js file that has the configuration information for your Cognito User Pool. You need to specify the S3 setting for the Storage module.

import Amplify, { Storage } from 'aws-amplify'
import config from './aws-exports'

Amplify.configure(config)
Amplify.configure({
  Storage: {
    AWSS3: {
      bucket: '<BUCKET>',
      region: '<REGION>',
    },
    customPrefix: {
      private: '<PREFIX>/'
    },
  },
})
Storage.configure({ level: 'private' })

Note that there is no concept of public or protected resources for this application. The configuration defines a custom prefix for private level access, and the default access level is also set to private. You can list all files under in the bucket under <PREFIX>/

async () => {
  const result = await Storage.list('')
  console.log(result)
}

All uploads and downloads will be done at the private level as well.

Conclusion

Whether you are getting started on a brand new project or looking to interact with existing resources on AWS, Amplify provides tools that can help with that. In this article I showed you how to connect to an existing S3 bucket using the Amplify libraries in an Amplify project. To learn more about how Amplify can help your app dev project, visit the Amplify Framework Documentation.

Discussion (1)

Collapse
ddotx profile image
Dome J

I cannot use amplify push to create new added policy.