AWS S3 Digital Asset Management (DAM) plugin for Sanity.io
Allows uploading, referencing and deleting video and audio files to S3 directly from your Sanity studio. Is a flavor of sanity-plugin-external-dam.
Installing
Start by installing the plugin:
sanity install s3-dam
The rest of the work must be done inside AWS' console. The video below is a full walkthrough, be sure to watch from start to finish to avoid missing small details that are hard to debug.
Creating the S3 bucket
If you already have a bucket, make sure to follow the configuration below.
- Go into the console homepage for S3 and click on "Create bucket"
- Choose a name and region as you see fit
- "Object Ownership": ACL enabled & "Object writer"
- Untick "Block all public access"
- Disable "Bucket Versioning"
- Disable "Default encryption"
- Once created, click into the bucket's page and go into the "Permissions" tab to configure CORS
- Configure CORS for your bucket to accept the origins your studio will be hosted in (including localhost)
- Refer to S3's guide on CORS if this is new to you (it was for me too!)
- You can use the template at s3Cors.example.json
Creating the Lambda functions' role for accessing the bucket
- Go into the Identity and Access Management (IAM) console
- Start by going into the "Access management -> Policies" tab and "Create new Policy"
- In the "Create Policy" visual editor
- choose S3 as the "Service"
- Select the proper "Actions"
- getSignedUrl needs "Write->PutObject" and "Permissions Management->PutObjectAcl"
- deleteObject needs "Write->DeleteObject"
- In "Resources"
- "Specific"
- Click on "Add ARN to restrict access"
- Fill in the bucket name and "*" for the object's name (or click on "Any")
- Or use the ARN (Amazon Resource Name) of your bucket (find it under the bucket's properties tab) with an
/*
appended to it
- Or use the ARN (Amazon Resource Name) of your bucket (find it under the bucket's properties tab) with an
- Leave "Request conditions" empty
- Create the policy
- With the policy created, go into "Access management -> Roles" and "Create role"
- "Trusted entity type": AWS Service
- "Use case": Lambda
- In "Add permissions", select the policy you created above
- Name your role
- Leave "Step 1: Select trusted entities" as is
- Create the role
Creating the Lambda functions
We'll need to create 2 functions, one for getting signed URLs for posting objects and another for deleting objects. The steps below apply to both:
Configuring functions' HTTP access
- Go into the Lambda console
- "Create function"
- "Author from scratch"
- Runtime: Node.js 14.x or higher
- Architecture: your call - I'm using x86_64
- "Permissions" -> "Change default execution role" -> "Use an existing role"
- Select the role you created above
- "Advanced settings" -> "Enable function URL"
- "Auth type": NONE
- Question:: is there a better way to do this?
- Check "Configure cross-origin resource sharing (CORS)"
- "Allow headers": content-type
- "Allow methods": *
- "Auth type": NONE
- Create the function
- Open the function's page and, under the "Configuration" tab, select "Function URL" in the sidebar
- Set "content-type" as an "Allowed Headers" and set "Allowed Methods" to "*".
- Save the new configuration
Now we can change the code of each function
Editing functions' code
Use the templates at getSignedUrl.example.js and deleteObject.example.js.
With the functions' URLs in hand - which you can find in each functions' page -, open the plugin's configuration form in the Sanity tool.
There, you'll fill in the bucket key (ex: my-sanity-bucket
), the bucket region (ex: ap-south-1
), the URL for both Lambda functions and an optional secret for validating input in functions.
Using
Use the s3-dam.media
type in your fields. Examples:
{
name: "video",
title: "Video (S3)",
type: "s3-dam.media",
options: {
accept: "video/*",
storeOriginalFilename: true,
},
},
{
name: "anyFile",
title: "File (S3)",
type: "s3-dam.media",
options: {
// Accept ANY file
accept: "*",
storeOriginalFilename: true,
},
},
Contributing, roadmap & acknowledgments
Refer to sanity-plugin-external-dam for those :)