为什么 AWS Lambda CFN S3-response returns 403 删除事件?
Why does AWS Lambda CFN S3-response returns 403 upon Delete event?
我正在使用 serverless to deploy an application where I use a Custom Resource 迁移 RDS 数据库。
我部署时一切正常,但是当我删除堆栈时,自定义资源在一小时后超时并显示消息 "Custom Resource failed to stabilize in expected time."。对预签名 AWS S3 URL returns 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"
}
我第二次向预签名 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"
}
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))
}
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']]
Here's a gist with my full source files and log.
更新发现问题
我的 S3 VPCEndpoint SheltersVPCS3Endpoint
似乎在 dBMigration
之前被删除,这就是我收到 403 的原因。
使用纯 Cloudformation,我想这可以通过将 DependsOn
放在 dbMigration
上来轻松解决,但是对于无服务器,这似乎是不可能的。
您需要为您的 lambda 函数提供正确的权限。
如果你添加
provider:
name: aws
iamRoleStatements:
$ref: ./iamRoleStatements.json
到您的无服务器配置
然后构建您的 iamRoleStatements.json 以授予您对放置在与无服务器配置相同目录中的 S3 存储桶的功能权限
[
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "*"
}
]
这确实让您的所有资源都有权对您的 s3 存储桶做任何他们想做的事情
如果您想了解有关使用 IAM i 无服务器函数的更多信息,请查看
https://serverless.com/blog/abcs-of-iam-permissions/
经过与 AWS 支持人员的长期调查,我们发现 SheltersVPCS3Endpoint
在 dbMigration
被删除之前被删除,因此 Lambda fn 无法与触发的 S3 存储桶取得任何联系超时。
由于无法向无服务器中的函数添加任何 DependsOn
,我不得不从无服务器迁移到 Cloudformation。当我添加以下内容时,似乎解决了。
DbMigrationLambdaFunction:
DependsOn:
- SheltersVPCS3Endpoint
我正在使用 serverless to deploy an application where I use a Custom Resource 迁移 RDS 数据库。
我部署时一切正常,但是当我删除堆栈时,自定义资源在一小时后超时并显示消息 "Custom Resource failed to stabilize in expected time."。对预签名 AWS S3 URL returns 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"
}
我第二次向预签名 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"
}
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))
}
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']]
Here's a gist with my full source files and log.
更新发现问题
我的 S3 VPCEndpoint SheltersVPCS3Endpoint
似乎在 dBMigration
之前被删除,这就是我收到 403 的原因。
使用纯 Cloudformation,我想这可以通过将 DependsOn
放在 dbMigration
上来轻松解决,但是对于无服务器,这似乎是不可能的。
您需要为您的 lambda 函数提供正确的权限。 如果你添加
provider:
name: aws
iamRoleStatements:
$ref: ./iamRoleStatements.json
到您的无服务器配置
然后构建您的 iamRoleStatements.json 以授予您对放置在与无服务器配置相同目录中的 S3 存储桶的功能权限
[
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "*"
}
]
这确实让您的所有资源都有权对您的 s3 存储桶做任何他们想做的事情
如果您想了解有关使用 IAM i 无服务器函数的更多信息,请查看 https://serverless.com/blog/abcs-of-iam-permissions/
经过与 AWS 支持人员的长期调查,我们发现 SheltersVPCS3Endpoint
在 dbMigration
被删除之前被删除,因此 Lambda fn 无法与触发的 S3 存储桶取得任何联系超时。
由于无法向无服务器中的函数添加任何 DependsOn
,我不得不从无服务器迁移到 Cloudformation。当我添加以下内容时,似乎解决了。
DbMigrationLambdaFunction:
DependsOn:
- SheltersVPCS3Endpoint