Serverless配置现有S3桶触发Lambda部署报错排查
问题描述
需要配置Lambda函数,实现S3桶内产生对象创建事件时自动触发执行。
初始配置与首次报错
初始serverless.yml相关配置如下:
handleNewRawObjectInS3: handler: lambdas/handleNewRawObjectInS3/handleNewRawObjectInS3.handleS3Event events: - s3: bucket: ${file(../evn.${opt:stage, 'dev'}.json):RAW_IMAGE_BUCKET} event: s3:ObjectCreated:*
执行部署时返回错误:
Error: CREATE_FAILED: S3Bucketxxxxxxxxxrawimages (AWS::S3::Bucket) xxxxxxxxx-raw-images already exists in stack arn:aws:cloudformation:us-east-1:xxxx:stack/s3-xxxxxxxxx-raw-images/310e7010-xxx-xxx-xxxx-12f066874c93
报错原因:配置中指定的S3桶已经通过单独的CloudFormation模板提前创建完成,企业AWS环境限制不允许Serverless框架自动创建S3资源。新版本Serverless Framework支持通过S3事件配置中的existing: true参数关联已存在的S3桶,无需框架自动创建桶资源。
调整配置后二次报错
根据环境要求调整配置,添加existing: true参数,同时手动指定预先创建的部署桶、自定义IAM角色,完整serverless.yml配置如下:
service: my-service-events provider: name: aws runtime: nodejs14.x region: ${file(../evn.${opt:stage, 'dev'}.json):REGION} stage: ${opt:stage, 'dev'} deploymentBucket: # 企业环境不允许自动创建桶,手动指定已创建的部署桶 name: ${file(../evn.${opt:stage, 'dev'}.json):DEPLOYMENT_BUCKET} iam: # 企业环境不允许自动创建角色,手动指定自定义角色 role: myServerlessRole deploymentRole: ${file(../evn.${opt:stage, 'dev'}.json):DEPLOYMENT_ROLE} resources: - ${file(../iam-roles.${opt:stage, 'dev'}.yml)} functions: handleNewRawObjectInS3: handler: lambdas/handleNewRawObjectInS3/handleNewRawObjectInS3.handleS3Event events: - s3: bucket: ${file(../evn.${opt:stage, 'dev'}.json):RAW_IMAGE_BUCKET} event: s3:ObjectCreated:* existing: true
配置引用的自定义IAM角色文件内容如下:
Resources: myServerlessRole: Type: AWS::IAM::Role Properties: PermissionsBoundary: arn:aws:iam::xxx:policy/csr-Developer-Permissions-Boundary Path: /my/default/path/ RoleName: myServerlessRole-${self:service} AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole Policies: - PolicyName: myPolicyName PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: - 'Fn::Join': - ':' - - 'arn:aws:logs' - Ref: 'AWS::Region' - Ref: 'AWS::AccountId' - 'log-group:/aws/lambda/*:*:*' - Effect: "Allow" Action: - "s3:*" Resource: "arn:aws:s3:::*" - Effect: "Allow" Action: - "lambda:*" Resource: "*" - Effect: "Allow" Action: - cloudfront:CreateDistribution - cloudfront:GetDistribution - cloudfront:UpdateDistribution - cloudfront:DeleteDistribution - cloudfront:TagResource Resource: "arn:aws:cloudfront:::*"
再次执行部署返回新错误:
Error: CREATE_FAILED: CustomDashresourceDashexistingDashs3LambdaFunction (AWS::Lambda::Function) Resource handler returned message: "The role defined for the function cannot be assumed by Lambda. (Service: Lambda, Status Code: 400, Request ID: 812c5384-1c26-42c9-bdef-1ce4a59f2be4)" (RequestToken: 9cdbb5af-3bc7-d6bf-384b-5126d1048ccd, HandlerErrorCode: InvalidRequest)
该错误指向Serverless框架自动生成的、用于管理现有S3资源触发器的自定义Lambda函数,无法承担配置中指定的IAM角色。
解决方案
报错根因是全局配置的IAM角色被默认分配给了所有Lambda(包括框架自动生成的自定义资源Lambda),但该角色要么存在信任策略限制、要么没有适配自定义资源Lambda的使用场景,按以下步骤调整即可完成部署:
- 移除
provider.iam.role的全局角色配置,改为在业务函数handleNewRawObjectInS3的配置块下单独添加role: myServerlessRole,仅给业务Lambda分配自定义业务角色,避免框架自动生成的自定义资源Lambda错误复用业务角色。 - 提前创建专门给Serverless自定义资源使用的IAM角色:
- 信任策略必须允许
lambda.amazonaws.com服务执行sts:AssumeRole动作 - 绑定企业要求的权限边界
- 配置最小必要权限:S3桶通知配置权限(
s3:GetBucketNotification、s3:PutBucketNotification)、Lambda触发器配置权限(lambda:AddPermission、lambda:RemovePermission)、CloudWatch日志基础写入权限
- 信任策略必须允许
- 在
serverless.yml的provider.iam配置块下添加customResourceRole字段,值为上一步提前创建的自定义资源角色的完整ARN,指定框架生成的自定义资源Lambda使用该专属角色。 - 若角色是刚创建完成,等待10秒左右待IAM角色全局传播完成后再执行部署,避免因角色传播延迟导致的无法承担错误。
- (可选优化)当前业务角色配置了
s3:*、lambda:*的全量权限,建议根据实际业务需求收缩为最小权限,避免权限过度开放。
内容的提问来源于stack exchange,提问作者lowcrawler
相关产品推荐
相关产品推荐

