amazon-cloudformation - c# aws api gateway serverless.template 结构不通过 CloudFormation 处理
问题描述
我已经构建了一个 .NET 无服务器应用程序并具有以下 serverless.template
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Description": "API Gateway to access InSite data-store.",
"Resources": {
"Get": {
"Type": "AWS::Serverless::Function",
"Properties": {
"VpcConfig": {
"SecurityGroupIds": [
"sg-111a1476"
],
"SubnetIds": [
"subnet-3029a769",
"subnet-5ec0b928"
]
},
"Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::Get",
"Runtime": "dotnetcore2.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaBasicExecutionRole",
"AWSLambdaVPCAccessExecutionRole",
"AmazonSSMFullAccess"
],
"Environment": {
"Variables":{
"LOG_LEVEL":"2",
"CONNECTION_STRING":"insite-api-connectionstring"
}
},
"Events": {
"PutResource": {
"Type": "Api",
"Properties": {
"Path": "/",
"Method": "GET"
}
}
}
}
},
"GetTableBasic": {
"Type": "AWS::Serverless::Function",
"Properties": {
"VpcConfig": {
"SecurityGroupIds": [
"sg-111a1476"
],
"SubnetIds": [
"subnet-3029a769",
"subnet-5ec0b928"
]
},
"Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::GetTableBasic",
"Runtime": "dotnetcore2.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaBasicExecutionRole",
"AWSLambdaVPCAccessExecutionRole",
"AmazonSSMFullAccess"
],
"Environment": {
"Variables":{
"LOG_LEVEL":"2",
"CONNECTION_STRING":"insite-api-connectionstring"
}
},
"Events": {
"PutResource": {
"Type": "Api",
"Properties": {
"Path": "/tables/{tableid}/{columnid}",
"Method": "GET"
}
}
}
}
},
"PostClickCollectNotification": {
"Type": "AWS::Serverless::Function",
"Properties": {
"VpcConfig": {
"SecurityGroupIds": [
"sg-111a1476"
],
"SubnetIds": [
"subnet-3029a769",
"subnet-5ec0b928"
]
},
"Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::PostClickCollectNotification",
"Runtime": "dotnetcore2.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaBasicExecutionRole",
"AWSLambdaVPCAccessExecutionRole",
"AmazonSSMFullAccess"
],
"Environment": {
"Variables":{
"LOG_LEVEL":"2",
"CONNECTION_STRING":"insite-api-connectionstring"
}
},
"Events": {
"PutResource": {
"Type": "Api",
"Properties": {
"Path": "/order/notify",
"Method": "POST"
}
}
}
}
},
"PostClickCollectStockUpdate": {
"Type": "AWS::Serverless::Function",
"Properties": {
"VpcConfig": {
"SecurityGroupIds": [
"sg-111a1476"
],
"SubnetIds": [
"subnet-3029a769",
"subnet-5ec0b928"
]
},
"Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::PostClickCollectStockUpdate",
"Runtime": "dotnetcore2.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaBasicExecutionRole",
"AWSLambdaVPCAccessExecutionRole",
"AmazonSSMFullAccess"
],
"Environment": {
"Variables":{
"LOG_LEVEL":"2",
"TARGET_TABLE":"InSiteClickCollect",
"CONNECTION_STRING":"insite-api-connectionstring"
}
},
"Events": {
"PutResource": {
"Type": "Api",
"Properties": {
"Path": "/order/stock/update/",
"Method": "POST"
}
}
}
}
},
"GetTableResponse": {
"Type": "AWS::Serverless::Function",
"Properties": {
"VpcConfig": {
"SecurityGroupIds": [
"sg-111a1476"
],
"SubnetIds": [
"subnet-3029a769",
"subnet-5ec0b928"
]
},
"Handler": "AWSServerlessInSiteDataGw::AWSServerlessInSiteDataGw.Functions::GetTableResponse",
"Runtime": "dotnetcore2.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaBasicExecutionRole",
"AWSLambdaVPCAccessExecutionRole",
"AmazonSSMFullAccess"
],
"Environment": {
"Variables":{
"LOG_LEVEL":"2",
"CONNECTION_STRING":"insite-api-connectionstring"
}
},
"Events": {
"PutResource": {
"Type": "Api",
"Properties": {
"Path": "tables/query/{tableid}",
"Method": "GET"
}
}
}
}
},
"ServerlessRestApi": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Description":"InSite Web API Version 2.0.0.0",
"Body": {
"swagger": "2.0",
"info": {
"version": "1.0",
"title": {
"Ref": "AWS::StackName"
}
},
"x-amazon-apigateway-api-key-source" : "HEADER",
"schemes":["https"],
"paths": {
"tables/query/{tableid}": {
"get": {
"x-amazon-apigateway-integration": {
"httpMethod": "GET",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableResponse.Arn}/invocations"
}
},
"responses": {},
"security": [
{
"api_key": []
}
]
}
},
"/products/update/": {
"post": {
"x-amazon-apigateway-integration": {
"httpMethod": "POST",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PostClickCollectStockUpdate.Arn}/invocations"
}
},
"responses": {}
}
},
"/": {
"get": {
"x-amazon-apigateway-integration": {
"httpMethod": "GET",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Get.Arn}/invocations"
}
},
"responses": {}
}
},
"/tables/{tableid}/{columnid}": {
"get": {
"x-amazon-apigateway-integration": {
"httpMethod": "GET",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableBasic.Arn}/invocations"
}
},
"responses": {}
}
}
},
"securityDefinitions": {
"api_key": {
"type": "apiKey",
"name": "x-api-key",
"in": "header"
}
}
}
}
},
"InternalUsagePlan": {
"Type": "AWS::ApiGateway::UsagePlan",
"Properties": {
"ApiStages": [
{
"ApiId": {
"Ref": "ServerlessRestApi"
},
"Stage": {
"Ref": "ServerlessRestApiProdStage"
}
}
],
"Description": "Internal Apps Usage Plan",
"UsagePlanName": "Insite-datagw-InternalAppPlan-new"
}
},
"ExternalUsagePlan": {
"Type": "AWS::ApiGateway::UsagePlan",
"Properties": {
"ApiStages": [
{
"ApiId": {
"Ref": "ServerlessRestApi"
},
"Stage": {
"Ref": "ServerlessRestApiProdStage"
}
}
],
"Description": "External Apps Usage Plan",
"UsagePlanName": "InSite-datagw-ExternalAppPlan-new"
}
},
"KeyHeartInHand": {
"Type": "AWS::ApiGateway::ApiKey",
"DependsOn": [
"ServerlessRestApi",
"ServerlessRestApiProdStage"
],
"Properties": {
"Name": "apikeyHeartInHand-new",
"Description": "Api Key for Heart In Hand",
"Enabled": true,
"GenerateDistinctId": true,
"StageKeys": [
{
"RestApiId": {
"Ref": "ServerlessRestApi"
},
"StageName": {
"Ref": "ServerlessRestApiProdStage"
}
}
]
}
},
"LinkHeartInHandKey": {
"Type": "AWS::ApiGateway::UsagePlanKey",
"Properties": {
"KeyId": {
"Ref": "KeyHeartInHand"
},
"KeyType": "API_KEY",
"UsagePlanId": {
"Ref": "InternalUsagePlan"
}
}
},
"KeyUmbraco": {
"Type": "AWS::ApiGateway::ApiKey",
"DependsOn": [
"ServerlessRestApi",
"ServerlessRestApiProdStage"
],
"Properties": {
"Name": "KeyUmbraco-new",
"Description": "Api Key for Umbraco Website",
"Enabled": true,
"GenerateDistinctId": true,
"StageKeys": [
{
"RestApiId": {
"Ref": "ServerlessRestApi"
},
"StageName": {
"Ref": "ServerlessRestApiProdStage"
}
}
]
}
},
"LinkPricelineSiteKey": {
"Type": "AWS::ApiGateway::UsagePlanKey",
"Properties": {
"KeyId": {
"Ref": "KeyUmbraco"
},
"KeyType": "API_KEY",
"UsagePlanId": {
"Ref": "InternalUsagePlan"
}
}
},
"KeyPenTest": {
"Type": "AWS::ApiGateway::ApiKey",
"DependsOn": [
"ServerlessRestApi",
"ServerlessRestApiProdStage"
],
"Properties": {
"Name": "apiKeyPenTesting-new",
"Description": "Api Key for pen testing",
"Enabled": true,
"GenerateDistinctId": true,
"StageKeys": [
{
"RestApiId": {
"Ref": "ServerlessRestApi"
},
"StageName": {
"Ref": "ServerlessRestApiProdStage"
}
}
]
}
},
"LinkPenTestKey": {
"Type": "AWS::ApiGateway::UsagePlanKey",
"Properties": {
"KeyId": {
"Ref": "KeyPenTest"
},
"KeyType": "API_KEY",
"UsagePlanId": {
"Ref": "InternalUsagePlan"
}
}
}
},
"Outputs": {
"ApiURL": {
"Description": "API endpoint URL for Prod environment",
"Value": {
"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
}
}
}
}
该应用程序通过 AWS Toolkit for Visual Studio 部署正常,但处理后的 cloudformation 似乎缺少我对 AWS::ApiGateway::RestApi 部分所做的大部分更新(如果不是全部的话)。当我在 AWS 控制台中签入时,处理后的 CF 模板如下所示:
"ServerlessRestApi": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Body": {
"info": {
"version": "1.0",
"title": {
"Ref": "AWS::StackName"
}
},
"paths": {
"/order/stock/update/": {
"post": {
"x-amazon-apigateway-integration": {
"httpMethod": "POST",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PostClickCollectStockUpdate.Arn}/invocations"
}
},
"responses": {}
}
},
"/order/notify": {
"post": {
"x-amazon-apigateway-integration": {
"httpMethod": "POST",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PostClickCollectNotification.Arn}/invocations"
}
},
"responses": {}
}
},
"/tables/{tableid}/{columnid}": {
"get": {
"x-amazon-apigateway-integration": {
"httpMethod": "POST",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableBasic.Arn}/invocations"
}
},
"responses": {}
}
},
"tables/query/{tableid}": {
"get": {
"x-amazon-apigateway-integration": {
"httpMethod": "POST",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableResponse.Arn}/invocations"
}
},
"responses": {}
}
},
"/": {
"get": {
"x-amazon-apigateway-integration": {
"httpMethod": "POST",
"type": "aws_proxy",
"uri": {
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Get.Arn}/invocations"
}
},
"responses": {}
}
}
},
"swagger": "2.0"
}
}
},
由于上述问题,我的 API 网关中未设置 apiKey required = true。其他一切都创建得很好,创建了 api 密钥,创建了使用计划,创建了密钥和计划之间的链接,但是将 api 密钥设置为 required = true 不会发生。我在这里不知所措。我尝试使用新名称部署堆栈以创建一个新的 API,但同样的事情发生了。
解决方案
您的模板似乎存在一些问题。
首先,您使用AWS::ApiGateway::RestApi
资源而不是 AWS SAMAWS::Serverless::Api
资源来定义您的 API。我建议尽可能多地使用 AWS SAM 资源,除非有特定的理由不使用它们。
其次,您似乎没有使用Auth
无服务器功能上的可用属性。您应该能够通过添加"Auth": { "ApiKeyRequired": true }
到您的功能(文档)来获得您想要的功能。
最后,我看到了对ServerlessRestApiProdStage
资源的引用,但没有对其进行定义,这可能是由于您使用AWS::ApiGateway::RestApi
AWS SAM 并将其与 AWS SAM 混合使用所致。如果您更改为使用AWS::Serverless::Api
,则可以使用访问自动生成的阶段{ "Fn::GetAtt" : [ "ServerlessRestApi", "Stage" ] }
希望这可以帮助!
推荐阅读
- sql-server - T-SQL 查询将多列更改为按日期分组的单列
- wordpress - Wordpress 无法向 Office 365 电子邮件 ID 发送电子邮件
- android - 滚动ScrollView android上的显示和隐藏按钮
- javascript - 在 express.js 中处理 post 请求
- android - java.lang.IllegalStateException:找不到所需的视图 - 黄油刀有时不工作
- python - 像 Twitter 上的连锁店一样吸引追随者的追随者
- typescript - 将对象键作为通用传递
- angular - 将 cdkDrag 指令动态添加到生成的组件中
- vue.js - 第二个请求有 300 毫秒开销的 Vuejs 问题
- bigtable - BigTable:来自不同列族的两个列限定符可以具有相同的名称吗?