当我的 Lambda 有权访问 S3 存储桶时,为什么我的 GetObjectRequest return 出现 403 Access Denied 错误?
Why does my GetObjectRequest return a 403 Access Denied error when my Lambda has access to the S3 bucket?
我有一个向 S3 存储桶发出 GetObject
请求的 Lambda 函数。
但是,我收到以下错误:
AccessDenied: Access Denied
at deserializeAws_restXmlGetObjectCommandError (/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:6284:41)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at /node_modules/@aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:6:20
at /node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:11:20
at StandardRetryStrategy.retry (/node_modules/@aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46)
at /node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:22
at GetS3Data (/src/input.ts:21:26)
at Main (/src/main.ts:8:34)
at Runtime.run [as handler] (/handler.ts:6:9) {
Code: 'AccessDenied',
RequestId: '3K61PMQGW4825D3W',
HostId: '5PpmWpu2I4WZPx37Y0pRfDAcdCmjX8fchuE+HLpUzy7uqoJirtb9Os0g96kWfluM/ctkn/mEC5o=',
'$fault': 'client',
'$metadata': {
httpStatusCode: 403,
requestId: undefined,
extendedRequestId: '5PpmWpu2I4WZPx37Y0pRfDAcdCmjX8fchuE+HLpUzy7uqoJirtb9Os0g96kWfluM/ctkn/mEC5o=',
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
}
}
我已授予访问 Lambda 函数的权限以发出此请求。
有什么问题?
serverless.ts
import type { AWS } from "@serverless/typescript";
const serverlessConfiguration: AWS = {
service: "affiliations",
frameworkVersion: "2",
custom: {
esbuild: {
bundle: true,
minify: false,
sourcemap: true,
exclude: ["aws-sdk"],
target: "node14",
define: { "require.resolve": undefined },
platform: "node",
},
},
plugins: ["serverless-esbuild"],
provider: {
name: "aws",
region: "us-east-2",
runtime: "nodejs14.x",
apiGateway: {
minimumCompressionSize: 1024,
shouldStartNameWithService: true,
},
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1",
NODE_OPTIONS: "--enable-source-maps --stack-trace-limit=1000",
},
lambdaHashingVersion: "20201221",
vpc: {
securityGroupIds: ["<redacted>"],
subnetIds: ["redacted>"],
},
iam: {
role: {
statements: [
{
Effect: "Allow",
Action: ["s3:GetObject"],
Resource: "<redacted>",
},
],
},
},
},
useDotenv: true,
// import the function via paths
functions: {
run: {
handler: "handler.run",
timeout: 300,
events: [
{
sns: {
arn: "<redacted>",
},
},
],
},
},
};
module.exports = serverlessConfiguration;
s3.ts
export const GetS3Data = async (payload: GetObjectRequest) => {
try {
const response = await S3Service.getObject(payload);
const result = await new Promise((resolve, reject) => {
const data = [];
response.Body.on("data", (chunk) => data.push(chunk));
response.Body.on("err", reject);
response.Body.once("end", () => resolve(data.join("")));
});
return [result, null];
} catch (err) {
Logger.error({
method: "GetS3Data",
error: err.stack,
});
return [null, err];
}
};
package.json
"@aws-sdk/client-s3": "^3.36.0",
您的 403 Access Denied
错误掩盖了 404 Not Found
错误,因为您的代码和无服务器配置看起来非常好并且应该按预期工作,前提是您已正确指定资源。
如果您没有正确的 s3:ListBucket
权限,如果指定键的对象不存在,S3 端点将不会 return 404 Not Found
错误。
GetObject
的 API reference 强调了这种细微差别:
If you have the s3:ListBucket permission on the bucket, Amazon S3 will return an HTTP status code 404 ("no such key") error.
If you don’t have the s3:ListBucket permission, Amazon S3 will return an HTTP status code 403 ("access denied") error.
这是为了防止攻击者枚举 public 个存储桶并了解存储桶中实际存在的对象。
在这种情况下,缺少 404 不允许泄露有关对象是否存在的信息(就像登录页面上的 Invalid Credentials
消息而不是 Invalid Password
表示存在具有所提供用户名的用户)。
向 Lambda 提供执行 s3:ListBucket
操作的权限以揭露 404 错误 and/or 最后仔细检查您的 GetObjectRequest
以确保正确指定密钥 存在的对象:
iam: {
role: {
statements: [
{
Effect: "Allow",
Action: ["s3:GetObject", "s3:ListBucket"],
Resource: "<redacted>",
},
],
},
}
忘记在资源末尾添加/*
Resource: "<redacted>/*",
我有一个向 S3 存储桶发出 GetObject
请求的 Lambda 函数。
但是,我收到以下错误:
AccessDenied: Access Denied
at deserializeAws_restXmlGetObjectCommandError (/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:6284:41)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at /node_modules/@aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:6:20
at /node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:11:20
at StandardRetryStrategy.retry (/node_modules/@aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46)
at /node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:22
at GetS3Data (/src/input.ts:21:26)
at Main (/src/main.ts:8:34)
at Runtime.run [as handler] (/handler.ts:6:9) {
Code: 'AccessDenied',
RequestId: '3K61PMQGW4825D3W',
HostId: '5PpmWpu2I4WZPx37Y0pRfDAcdCmjX8fchuE+HLpUzy7uqoJirtb9Os0g96kWfluM/ctkn/mEC5o=',
'$fault': 'client',
'$metadata': {
httpStatusCode: 403,
requestId: undefined,
extendedRequestId: '5PpmWpu2I4WZPx37Y0pRfDAcdCmjX8fchuE+HLpUzy7uqoJirtb9Os0g96kWfluM/ctkn/mEC5o=',
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
}
}
我已授予访问 Lambda 函数的权限以发出此请求。
有什么问题?
serverless.ts
import type { AWS } from "@serverless/typescript";
const serverlessConfiguration: AWS = {
service: "affiliations",
frameworkVersion: "2",
custom: {
esbuild: {
bundle: true,
minify: false,
sourcemap: true,
exclude: ["aws-sdk"],
target: "node14",
define: { "require.resolve": undefined },
platform: "node",
},
},
plugins: ["serverless-esbuild"],
provider: {
name: "aws",
region: "us-east-2",
runtime: "nodejs14.x",
apiGateway: {
minimumCompressionSize: 1024,
shouldStartNameWithService: true,
},
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1",
NODE_OPTIONS: "--enable-source-maps --stack-trace-limit=1000",
},
lambdaHashingVersion: "20201221",
vpc: {
securityGroupIds: ["<redacted>"],
subnetIds: ["redacted>"],
},
iam: {
role: {
statements: [
{
Effect: "Allow",
Action: ["s3:GetObject"],
Resource: "<redacted>",
},
],
},
},
},
useDotenv: true,
// import the function via paths
functions: {
run: {
handler: "handler.run",
timeout: 300,
events: [
{
sns: {
arn: "<redacted>",
},
},
],
},
},
};
module.exports = serverlessConfiguration;
s3.ts
export const GetS3Data = async (payload: GetObjectRequest) => {
try {
const response = await S3Service.getObject(payload);
const result = await new Promise((resolve, reject) => {
const data = [];
response.Body.on("data", (chunk) => data.push(chunk));
response.Body.on("err", reject);
response.Body.once("end", () => resolve(data.join("")));
});
return [result, null];
} catch (err) {
Logger.error({
method: "GetS3Data",
error: err.stack,
});
return [null, err];
}
};
package.json
"@aws-sdk/client-s3": "^3.36.0",
您的 403 Access Denied
错误掩盖了 404 Not Found
错误,因为您的代码和无服务器配置看起来非常好并且应该按预期工作,前提是您已正确指定资源。
如果您没有正确的 s3:ListBucket
权限,如果指定键的对象不存在,S3 端点将不会 return 404 Not Found
错误。
GetObject
的 API reference 强调了这种细微差别:
If you have the s3:ListBucket permission on the bucket, Amazon S3 will return an HTTP status code 404 ("no such key") error.
If you don’t have the s3:ListBucket permission, Amazon S3 will return an HTTP status code 403 ("access denied") error.
这是为了防止攻击者枚举 public 个存储桶并了解存储桶中实际存在的对象。
在这种情况下,缺少 404 不允许泄露有关对象是否存在的信息(就像登录页面上的 Invalid Credentials
消息而不是 Invalid Password
表示存在具有所提供用户名的用户)。
向 Lambda 提供执行 s3:ListBucket
操作的权限以揭露 404 错误 and/or 最后仔细检查您的 GetObjectRequest
以确保正确指定密钥 存在的对象:
iam: {
role: {
statements: [
{
Effect: "Allow",
Action: ["s3:GetObject", "s3:ListBucket"],
Resource: "<redacted>",
},
],
},
}
忘记在资源末尾添加/*
Resource: "<redacted>/*",