AWS Lambda S3.getObject 抛出 "Access Denied",但仅当 运行 在本地
AWS Lambda S3.getObject throws "Access Denied", but only when running locally
我正在使用 AWS Lambda
和 serverless
框架构建一个使用 S3
存储文件的服务。
lambda 函数 ("hello
") 在部署到云时完美运行(它有一个 http 端点,我从浏览器调用它)。
相反,在本地调用时 (serverless invoke local --function hello
) 我收到“访问被拒绝”错误:
{
"errorMessage": "error getting object from S3: AccessDenied: Access Denied",
"errorType": "Error",
"stackTrace": [
"Error: error getting object from S3: AccessDenied: Access Denied",
" at module.exports.hello (/....js:24:9)",
" at processTicksAndRejections (internal/process/task_queues.js:93:5)"
]
}
这是我的简化函数:
'use strict';
const aws = require("aws-sdk");
const s3 = new aws.S3({ region: "eu-west-1" });
const bucket = "my-bucket-dev";
const key = "ads.json";
module.exports.hello = async (event) => {
let obj = null;
try {
return await s3.getObject({ Bucket: bucket, Key: key }).promise();
} catch(err) {
throw new Error(`error getting object from S3: ${err}`);
}
return {
statusCode: 200,
body: JSON.stringify({
message: `Hello function executed successfully!`,
obj,
input: event,
},
null,
2
),
};
}
这是我的serveless.yml(相关部分):
service: my-service
frameworkVersion: '2'
provider:
name: aws
runtime: nodejs12.x
profile: serverless
lambdaHashingVersion: 20201221
apiGateway:
shouldStartNameWithService: true
stage: ${opt:stage, "dev"}
region: eu-west-1
iam:
role:
statements:
- Effect: "Allow"
Action:
- "s3:ListBucket"
Resource: { "Fn::Join": [ "", [ "arn:aws:s3:::", "my-service-dev" ] ] }
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
Resource: { "Fn::Join": [ "", [ "arn:aws:s3:::", "my-service-dev", "/*" ] ] }
functions:
hello:
handler: index.hello
events:
- http:
method: get
path: hello
- s3: my-bucket-dev
我确实在某处读到 IAM 角色声明对于本地和云执行是不同的,但如果它是正确的,我有点困惑...
有人可以澄清一下吗?
我应该如何更正我的 serverless.yml
以避免本地调用错误?
引用 invoke-local 的文档:
When you use serverless invoke local, the situation is quite different: the role isn't available (the function is executed on your local machine), so unless you set a different user directly in the code (or via a key pair of environment variables), the AWS SDK will use the default profile specified inside your AWS credential configuration file.
因此,对于本地调用,要么在 ~/.aws/credentials
中适当配置本地 AWS 凭证,要么提供它们 via environment variables。
我正在使用 AWS Lambda
和 serverless
框架构建一个使用 S3
存储文件的服务。
lambda 函数 ("hello
") 在部署到云时完美运行(它有一个 http 端点,我从浏览器调用它)。
相反,在本地调用时 (serverless invoke local --function hello
) 我收到“访问被拒绝”错误:
{
"errorMessage": "error getting object from S3: AccessDenied: Access Denied",
"errorType": "Error",
"stackTrace": [
"Error: error getting object from S3: AccessDenied: Access Denied",
" at module.exports.hello (/....js:24:9)",
" at processTicksAndRejections (internal/process/task_queues.js:93:5)"
]
}
这是我的简化函数:
'use strict';
const aws = require("aws-sdk");
const s3 = new aws.S3({ region: "eu-west-1" });
const bucket = "my-bucket-dev";
const key = "ads.json";
module.exports.hello = async (event) => {
let obj = null;
try {
return await s3.getObject({ Bucket: bucket, Key: key }).promise();
} catch(err) {
throw new Error(`error getting object from S3: ${err}`);
}
return {
statusCode: 200,
body: JSON.stringify({
message: `Hello function executed successfully!`,
obj,
input: event,
},
null,
2
),
};
}
这是我的serveless.yml(相关部分):
service: my-service
frameworkVersion: '2'
provider:
name: aws
runtime: nodejs12.x
profile: serverless
lambdaHashingVersion: 20201221
apiGateway:
shouldStartNameWithService: true
stage: ${opt:stage, "dev"}
region: eu-west-1
iam:
role:
statements:
- Effect: "Allow"
Action:
- "s3:ListBucket"
Resource: { "Fn::Join": [ "", [ "arn:aws:s3:::", "my-service-dev" ] ] }
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
Resource: { "Fn::Join": [ "", [ "arn:aws:s3:::", "my-service-dev", "/*" ] ] }
functions:
hello:
handler: index.hello
events:
- http:
method: get
path: hello
- s3: my-bucket-dev
我确实在某处读到 IAM 角色声明对于本地和云执行是不同的,但如果它是正确的,我有点困惑...
有人可以澄清一下吗?
我应该如何更正我的 serverless.yml
以避免本地调用错误?
引用 invoke-local 的文档:
When you use serverless invoke local, the situation is quite different: the role isn't available (the function is executed on your local machine), so unless you set a different user directly in the code (or via a key pair of environment variables), the AWS SDK will use the default profile specified inside your AWS credential configuration file.
因此,对于本地调用,要么在 ~/.aws/credentials
中适当配置本地 AWS 凭证,要么提供它们 via environment variables。