If you’ve found yourself marveling at how cryptic and impenetrable understanding AWS services, then you are definitely not alone. For much too long have I relied on doing a quick web search and blindly copying and pasting settings and policies, so when I found myself doing it again this week for one of my applications I decided it was time to slow down and actually understand what it was that I was doing.
The Problem
I’m creating a demo environment that needs to be completely separate from our production data, so part of that entails creating its own S3 bucket for use with ActiveStorage. Having not really done this since ActiveStorage was first released I begin DuckDuckGoing (is this even a thing?) for a how-to.
Some perfectly fine write-ups and tutorials popped up on the first page, but I noticed that all of them recommended setting up an IAM User with AmazonS3FullAccess
permissions. As soon as I looked at the description for this policy it threw up a big red flag:
AmazonS3FullAccess: Provides full access to all buckets via the AWS Management Console
Full access to all buckets? That’s gonna be a big nope from me.
The Solution
At an absolute minimum the permissions need to be locked down to a single bucket, but ideally we’d only give the app the ability to perform solely the actions that are required for the framework to function properly. Luckily there’s a callout right in the Rails guide that states:
The core features of Active Storage require the following permissions:
s3:ListBucket
,s3:PutObject
,s3:GetObject
, ands3:DeleteObject
. If you have additional upload options configured such as setting ACLs then additional permissions may be required.
Assuming you already have a bucket created, we just need to create an IAM User so we can generate the access_key_id
and secret_access_key
necessary to configure the config/storage.yml
Amazon service.
Once you have your IAM user created you can use the policy template I’ve built down below as a guide to either create and attach the policy to a group you add your IAM user to, or just attach the policy directly to the user, which is what I did.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::BUCKET_NAME_GOES_HERE/*"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::BUCKET_NAME_GOES_HERE"
}
]
}
Final Notes
To their credit, one or two articles said something to the extent of “you may want to do this differently in production”, but let’s be honest, most people don’t read the entire article and/or will not remember to do this, so I find it to be a much better idea to set things up right from the start.
Hopefully this helps you in your ActiveStorage-related endeavors, and if you have any suggestions or comments on how you handle S3 permissions, I’d love to hear them!
Oldest comments (4)
I believe
arn:aws:s3:::*/*
will allow access to objects on any bucket the IAM user has access to. You should probably usearn:aws:s3:::NAME_OF_YOUR_BUCKET_GOES_HERE/*
if you want to restrict access just to that bucket.I was leaning on the S3 policy builder for feedback and mid-interpreted its recommendation. Always learning 😁 thanks for the catch. I’ve updated the post to reflect this.
Note that the
s3:ListBucket
permission still needs to be on the bucket resource, i.e.arn:aws:s3:::NAME_OF_YOUR_BUCKET_GOES_HERE
. This permission allows you to list objects in the bucket, which is needed for ActiveStorage's#delete_prefixed
.Ahh - that must be what was causing my validation warning in the editor! How does this look?