为什么AWS Lambda CFN S3响应在删除事件时返回403?

kon*_*ten 8 amazon-s3 amazon-web-services aws-cloudformation aws-lambda serverless-framework

我正在使用无服务器来部署我使用自定义资源迁移RDS数据库的应用程序.

我部署时一切正常,但是当我删除堆栈后一小时后自定义资源超时,并显示消息"自定义资源无法在预期时间内稳定".对预先签名的AWS S3 URL的请求将返回403错误代码AccessDenied.

我的第一个发送的,成功的响应主体到预先签名的URL(在创建时):

{
    "Status": "SUCCESS",
    "RequestId": "bd487606-8017-49f2-99af-b29b2bbad40b",
    "LogicalResourceId": "SheltersDBMigrationTrigger",
    "StackId": "arn:aws:cloudformation:us-east-1:848139458219:stack/update-shelters-dev/c08a80e0-2e4e-11e9-87a6-124d1eab42ba",
    "PhysicalResourceId": "DB_MIGRATION"
}
Run Code Online (Sandbox Code Playgroud)

我的第二个发送,失败的响应正文到预先签名的URL(删除时):

{
    "Status": "SUCCESS",
    "RequestId": "2d166d36-7c0c-4848-9eb5-aedaf5e9172c",
    "LogicalResourceId": "SheltersDBMigrationTrigger",
    "StackId": "arn:aws:cloudformation:us-east-1:848139458219:stack/update-shelters-dev/c08a80e0-2e4e-11e9-87a6-124d1eab42ba",
    "PhysicalResourceId": "DB_MIGRATION"
}
Run Code Online (Sandbox Code Playgroud)

lambda.go:

func handler(ctx context.Context, event cfn.Event) (rid string, data map[string]interface{}, err error) {
  rid = "DB_MIGRATION"

  if event.RequestType != cfn.RequestCreate {
    return
  }

  db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@(%s)/", os.Getenv("DB_MASTER_USER"), os.Getenv("DB_MASTER_PASSWORD"), os.Getenv("DB_ADDRESS")))
  if err != nil {
    panic(err)
  }
  defer db.Close()

  defer func() {
    if r := recover(); r != nil {
      err = fmt.Errorf("handler: Failed to migrate DB: %v", r)
    }
  }()

  MigrateDb(db)

  return
}

func main() {
  lambda.Start(cfn.LambdaWrap(handler))
}
Run Code Online (Sandbox Code Playgroud)

Lambda CFN的无服务器配置:

functions:
  dbMigration:
    handler: lambda-bin/migrate-db
    environment:
      DB_MASTER_USER: ${env:DB_MASTER_USER}
      DB_MASTER_PASSWORD: ${env:DB_MASTER_PASSWORD}
      DB_ADDRESS:
        "Fn::GetAtt": [ SheltersDB, Endpoint.Address ]
    vpc:
      securityGroupIds:
        - Ref: SheltersVPCSecurityGroup
      subnetIds:
        - Ref: SheltersSubnet1
        - Ref: SheltersSubnet2

...

Resources:
    SheltersDBMigrationTrigger:
      Type: Custom::DBMigration
      DependsOn:
        - SheltersDB
      Properties:
        ServiceToken: !GetAtt
          - DbMigrationLambdaFunction
          - Arn
    SheltersSubnet1:
      Type: AWS::EC2::Subnet
      Properties:
        AvailabilityZone: !Select [ 0, {Fn::GetAZs: ""} ]
        CidrBlock: 10.0.1.0/24
        VpcId: !Ref SheltersVPC
    SheltersSubnet2:
      Type: AWS::EC2::Subnet
      Properties:
        AvailabilityZone: !Select [ 1, {Fn::GetAZs: ""} ]
        CidrBlock: 10.0.2.0/24
        VpcId: !Ref SheltersVPC
    SheltersVPCSecurityGroup:
      Type: AWS::EC2::SecurityGroup
      Properties:
        GroupDescription: "Security group for DB connections"
        VpcId: !Ref SheltersVPC
    SheltersVPCSecurityGroupIngress:
      Type: AWS::EC2::SecurityGroupIngress
      Properties:
        GroupId: !Ref SheltersVPCSecurityGroup
        IpProtocol: tcp
        FromPort: "3306"
        ToPort: "3306"
        SourceSecurityGroupId: !Ref SheltersVPCSecurityGroup
    SheltersVPC:
      Type: AWS::EC2::VPC
      Properties:
        CidrBlock: 10.0.0.0/16
    SheltersRouteTable:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId: !Ref SheltersVPC
    SheltersSubnet1Association:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId: !Ref SheltersSubnet1
        RouteTableId: !Ref SheltersRouteTable
    SheltersSubnet2Association:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId: !Ref SheltersSubnet2
        RouteTableId: !Ref SheltersRouteTable
    SheltersVPCS3Endpoint:
      Type: AWS::EC2::VPCEndpoint
      Properties:
        VpcId: !Ref SheltersVPC
        PolicyDocument: "{\"Version\":\"2008-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"*\",\"Resource\":\"*\"}]}"
        RouteTableIds:
          - !Ref SheltersRouteTable
        ServiceName: !Join ['', ['com.amazonaws.', !Ref 'AWS::Region', '.s3']]
Run Code Online (Sandbox Code Playgroud)

这是我的完整源文件和日志的要点.

更新已识别的问题

似乎我的VPCEndpoint到S3 SheltersVPCS3Endpoint之前被删除了dBMigration,这就是我收到403的原因.

随着纯Cloudformation我想这可能已经解决了把一个简单的DependsOndbMigration,但无服务器似乎是不可能的.

kon*_*ten 1

经过与 AWS 支持人员一起进行长时间调查后,我们发现该文件在被删除SheltersVPCS3Endpoint之前已被dbMigration删除,因此 Lambda fn 无法与 S3 存储桶取得任何联系,从而触发了超时。

由于无法DependsOn在 Serverless 中添加任何功能,因此我不得不从 Serverless 迁移到 Cloudformation。当我添加以下内容时,似乎已经解决了。

  DbMigrationLambdaFunction:
     DependsOn:
       - SheltersVPCS3Endpoint
Run Code Online (Sandbox Code Playgroud)