I need to issue pre-signed URLs for allowing users to GET and PUT files into a specific S3 bucket. I created an IAM user and use its keys to create the pre-signed URLs, and
I was also working on a feature that used presigned GET and put URLs, specifically by a role associated with an AWS Lambda function. I found a bit of a twist though in that I also needed to also allow permission to use the KMS key that was encrypting the bucket.
I ran across this off-the-beaten-path article the pointed me in the right direction. It's not necessary to allow bucket-level permissions for URL presigning, only a handful of object-level permissions.
In short, my lambda role policy to support presigned URLs looked like the following. Note that the cloudwatch log permission is irrelevant for signing, but generally important for lambda functions:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*",
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "/*",
"Effect": "Allow"
},
{
"Sid": "KMSAccess",
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:Encrypt",
"kms:GenerateDataKey*",
"kms:ReEncrypt*"
],
"Effect": "Allow",
"Resource": ""
}
]
}
If you are using the built-in AES encryption (or no encryption), your policy can be simplified to this:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*",
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "/*",
"Effect": "Allow"
}
]
}