Update 2
I've tried changing our custom policy to allow access to the particular bucket that's giving the AccessDenied
error, without any luck. Imagine that bucket1
is a bucket that the lambda normally accesses, and bucket2
is the bucket that's throwing AccessDenied
when the lambda accesses it. I've changed the Resource
block from
{
...
{
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::us-east-1-bucket1/*",
"Effect": "Allow"
}
...
to
{
...
{
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::us-east-1-bucket1/*",
"arn:aws:s3:::us-east-1-bucket2/*"
],
"Effect": "Allow"
}
...
I'm still getting the AccessDenied
error.
Update
Per @Caldazar's comment about IAM users vs roles, the lambda's execution role has 3 policies:
- the AWS managed
arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
, specifically:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets",
"xray:GetSamplingStatisticSummaries"
],
"Resource": [
"*"
]
}
]
}
- the AWS managed
arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
, specifically:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
- our custom policy, specifically:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:us-east-1:*:log-group:/aws/lambda/*:*:*",
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::us-east-1-bucket1/*",
"Effect": "Allow"
}
]
}
In lambda@edge I have an origin-response
response lambda that is trying to pull an object out of s3 to be used as the response. However I'm getting this AccessDenied
error when I try to list the contents of the bucket using a particular prefix. This is my code:
const getVidS3 = (s3, bucketName, fileName) =>
new Promise((res, rej) => {
const start = Date.now();
s3.listObjects(
{
Bucket: bucketName,
Delimiter: '/',
Prefix: `${fileName}/`,
MaxKeys: 1,
},
function (err, data) {
console.log(
'================ milliseconds to list objects:',
Date.now() - start
);
if (err) return rej(err);
if (!Array.isArray(data.Contents) || data.Contents.length < 1) {
return rej('original raw video not found');
}
console.log('============= s3 objects:', data);
const rawVidFileKey = data.Contents[0].Key;
s3.getObject(
{
Bucket: bucketName,
Key: rawVidFileKey,
},
(err, data) => {
console.log(
'================ milliseconds to get video object:',
Date.now() - start
);
if (err) {
return rej(err);
}
const contentType = data.ContentType;
const video = data.Body;
console.log('=============== S3 video data', data);
return res({ video, contentType });
}
);
}
);
});
The error is from listObjects
. I've gone over this set of suggestions but I'm not sure I took the right steps because I used the IAM user that I use to access the dashboard, which may have higher permissions than the one the lambda uses. More so, I recreated this getVidS3
function locally using my admin credentials and it works, so I think I need help determining how to give the lambda the appropriate permissions. I didn't create the system and I'm not very proficient with aws, so bear with me if this feels incomplete. What/where else can I check to see why this is happening? Thanks in advance.
CodePudding user response:
The problem is in your policy. The policy allows GET
of the objects, but not List
. You're missing the ListBucket
action on the bucket itself.
You need to change this:
{
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::us-east-1-bucket1/*",
"Effect": "Allow"
}
To this:
{
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::us-east-1-bucket1/*",
"arn:aws:s3:::us-east-1-bucket1"
]
"Effect": "Allow"
}