求助:构建API Gateway调用StateMachine的CloudFormation模板及相关问题
解决API Gateway与Step Functions State Machine关联及生成CloudFormation模板的问题
我来帮你搞定这两个核心问题,先从API Gateway和State Machine的关联说起,再讲如何从现有AWS部署导出CloudFormation模板。
一、在CloudFormation中关联API Gateway与Step Functions State Machine
要实现API Gateway触发Step Functions State Machine,你需要补充几个关键资源:API Gateway的IAM执行角色、完善API Gateway的资源与方法、配置Integration指向State Machine的StartExecution动作。下面是完整的补充配置,我会整合到你已有的代码中:
1. 新增API Gateway调用Step Functions的IAM角色
这个角色需要允许API Gateway调用Step Functions的StartExecution动作,权限限定在你的目标State Machine上:
ApiGatewayStepFunctionsRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: apigateway.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AllowStartExecution PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: states:StartExecution Resource: !Ref UpdateShoppingPath
2. 完善API Gateway资源与方法
你之前定义的UserBaseUsers资源不完整,需要先创建RestApi根资源,再补充POST和OPTIONS(处理CORS)方法:
# 新增API Gateway根资源 UserBaseApi: Type: AWS::ApiGateway::RestApi Properties: Name: UserBaseApi # 完善子资源定义 UserBaseUsers: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt UserBaseApi.RootResourceId PathPart: UserBase/Users RestApiId: !Ref UserBaseApi # 新增POST方法,关联到Step Functions UserBaseUsersPostMethod: Type: AWS::ApiGateway::Method Properties: AuthorizationType: NONE # 根据你的需求修改,比如IAM、Cognito等 HttpMethod: POST ResourceId: !Ref UserBaseUsers RestApiId: !Ref UserBaseApi Integration: Type: AWS IntegrationHttpMethod: POST Uri: !Sub arn:aws:apigateway:${AWS::Region}:states:action/StartExecution Credentials: !GetAtt ApiGatewayStepFunctionsRole.Arn RequestTemplates: application/json: | { "input": "$util.escapeJavaScript($input.json('$'))", "stateMachineArn": "${UpdateShoppingPath}" } IntegrationResponses: - StatusCode: 200 ResponseTemplates: application/json: | { "executionArn": "$input.path('$.executionArn')", "startDate": "$input.path('$.startDate')" } MethodResponses: - StatusCode: 200 # 新增OPTIONS方法处理CORS UserBaseUsersOptionsMethod: Type: AWS::ApiGateway::Method Properties: AuthorizationType: NONE HttpMethod: OPTIONS ResourceId: !Ref UserBaseUsers RestApiId: !Ref UserBaseApi Integration: Type: MOCK IntegrationResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: "'*'" method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'" method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" ResponseTemplates: application/json: "" PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' MethodResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Headers: true
3. 添加API Gateway部署
最后需要添加Deployment资源,让你的API配置生效:
ApiDeployment: Type: AWS::ApiGateway::Deployment DependsOn: - UserBaseUsersPostMethod - UserBaseUsersOptionsMethod Properties: RestApiId: !Ref UserBaseApi StageName: prod
注意事项
- 我注释掉了你Lambda函数中
Events字段的API Gateway配置,因为手动创建API Gateway会和Serverless Transform自动生成的API Gateway冲突,你可以根据需求选择其中一种方式。 RequestTemplates中会把API的请求体作为State Machine的输入参数,同时指定目标State Machine的ARN。
二、从现有AWS部署生成CloudFormation模板
你可以通过以下几种方式生成模板:
- CloudFormation控制台导出:如果你的资源是通过CloudFormation部署的,直接在控制台选择对应的Stack,点击「Export template」即可导出YAML/JSON格式的模板,这是最可靠的方式,会保留原始配置。
- AWS CDK导入:如果你使用AWS CDK,可以用
cdk import命令将现有资源导入到CDK项目中,然后通过cdk synth生成CloudFormation模板,适合需要用CDK管理现有资源的场景。 - 第三方工具:比如Former2这类工具,它可以扫描你的AWS账户资源,自动生成对应的CloudFormation代码。使用时需要给工具分配必要的IAM权限,生成后建议手动清理冗余配置。
- AWS Config:通过AWS Config的资源配置快照,可以导出资源的配置信息,再转化为CloudFormation模板,适合批量导出资源的场景。
注意事项
- 自动生成的模板可能包含不必要的默认配置,需要手动调整。
- 部分资源(比如某些服务的动态配置)可能无法完全导出,需要手动补充。
完整整合后的CloudFormation模板
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: Post: Type: AWS::Serverless::Function Properties: FunctionName: UserBase-fnUsers Handler: UsersHandler.getUsers Runtime: nodejs6.10 Policies: [AmazonDynamoDBReadOnlyAccess, AmazonS3ReadOnlyAccess] Environment: Variables: S3_BUCKET: UserBase-Users-bucket UsersTable: UserBase-Users-tblUsers # 注释自动生成的API Gateway,改用手动配置 # Events: # GetUsers: # Type: Api # Properties: # Path: /UserBase/Users # Method: post Options: Type: AWS::Serverless::Function Properties: FunctionName: UserBase-fnUsers-Options Handler: UsersHandler.getOptions Runtime: nodejs6.10 # 注释自动生成的API Gateway,改用手动配置 # Events: # GetOptions: # Type: Api # Properties: # Path: /UserBase/Users # Method: options UsersTable: Type: AWS::DynamoDB::Table Properties: TableName: UserBase-Users-tblUsers AttributeDefinitions: - AttributeName: Id AttributeType: S KeySchema: - AttributeName: Id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 StreamSpecification: StreamViewType: KEYS_ONLY StatesExecutionRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - !Sub states.${AWS::Region}.amazonaws.com Action: "sts:AssumeRole" Path: "/" Policies: - PolicyName: StatesExecutionPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "lambda:InvokeFunction" Resource: "*" UpdateShoppingPath: Type: "AWS::StepFunctions::StateMachine" Properties: DefinitionString: !Sub - |- { "Comment": "State machine to update the shopping path", "StartAt": "UpdatePath", "States": { "UpdatePath": { "Type": "Task", "Resource": "${lambdaArn}", "End": true } } } - {lambdaArn: !GetAtt [ Post, Arn ]} RoleArn: !GetAtt [ StatesExecutionRole, Arn ] # 新增API Gateway资源 UserBaseApi: Type: AWS::ApiGateway::RestApi Properties: Name: UserBaseApi UserBaseUsers: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt UserBaseApi.RootResourceId PathPart: UserBase/Users RestApiId: !Ref UserBaseApi # 新增API Gateway调用Step Functions的IAM角色 ApiGatewayStepFunctionsRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: apigateway.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: AllowStartExecution PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: states:StartExecution Resource: !Ref UpdateShoppingPath # 新增POST方法 UserBaseUsersPostMethod: Type: AWS::ApiGateway::Method Properties: AuthorizationType: NONE HttpMethod: POST ResourceId: !Ref UserBaseUsers RestApiId: !Ref UserBaseApi Integration: Type: AWS IntegrationHttpMethod: POST Uri: !Sub arn:aws:apigateway:${AWS::Region}:states:action/StartExecution Credentials: !GetAtt ApiGatewayStepFunctionsRole.Arn RequestTemplates: application/json: | { "input": "$util.escapeJavaScript($input.json('$'))", "stateMachineArn": "${UpdateShoppingPath}" } IntegrationResponses: - StatusCode: 200 ResponseTemplates: application/json: | { "executionArn": "$input.path('$.executionArn')", "startDate": "$input.path('$.startDate')" } MethodResponses: - StatusCode: 200 # 新增OPTIONS方法处理CORS UserBaseUsersOptionsMethod: Type: AWS::ApiGateway::Method Properties: AuthorizationType: NONE HttpMethod: OPTIONS ResourceId: !Ref UserBaseUsers RestApiId: !Ref UserBaseApi Integration: Type: MOCK IntegrationResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: "'*'" method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'" method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" ResponseTemplates: application/json: "" PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' MethodResponses: - StatusCode: 200 ResponseParameters: method.response.header.Access-Control-Allow-Origin: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Headers: true # 新增API Gateway部署 ApiDeployment: Type: AWS::ApiGateway::Deployment DependsOn: - UserBaseUsersPostMethod - UserBaseUsersOptionsMethod Properties: RestApiId: !Ref UserBaseApi StageName: prod
内容的提问来源于stack exchange,提问作者tmp dev
相关产品推荐
相关产品推荐

