【问题标题】:AWS APIGateway CloudFormation specify Api Key required for method?AWS APIGateway CloudFormation 指定方法所需的 API 密钥?
【发布时间】:2019-06-02 16:54:20
【问题描述】:

我有以下 CloudFormation 模板,它创建了我的 API 网关(由 Lambda 支持)。我想启用 API 密钥作为其中一种或多种方法的要求。我已成功创建 API 密钥、使用计划和两者之间的关联,但无法弄清楚如何为某些方法实际启用“需要 API 密钥”属性。 AWS 的文档将“ApiKeyRequired”属性指定为 AWS::ApiGateway::Method 组件的一部分,但我的 CF 模板没有或没有使用此组件?考虑到我以前从未需要它,我不确定如何使用它?

我的模板如下:

   "ServerlessRestApi": {
        "Type": "AWS::ApiGateway::RestApi",
        "Properties": {
            "Description":"This is a placeholder for the description of this web api",
            "ApiKeySourceType":"HEADER",
            "Body": {
                "info": {
                    "version": "1.0",
                    "title": {
                        "Ref": "AWS::StackName"
                    }
                },
                "paths": {
                    "/list/tables": {
                        "get": {
                            "x-amazon-apigateway-integration": {
                                "httpMethod": "POST",
                                "type": "aws_proxy",
                                "uri": {
                                    "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTableList.Arn}/invocations"
                                }
                            },
                            "security": [
                                {
                                   "api_key": []
                                }
                             ],
                            "responses": {}
                        }
                    },
                    "/list/columns/{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/${GetColumnList.Arn}/invocations"
                                }
                            },
                            "responses": {}
                        }
                    },
                    "datagw/general/table/get/{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": {}
                        }
                    },
                    "/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": {}
                        }
                    },
                    "securityDefinitions": {
                        "type": "api_key",
                        "name": "x-api-key",
                        "in": "header"
                      }
                },
                "swagger": "2.0"
            }
        }
    },

【问题讨论】:

    标签: amazon-web-services amazon-cloudformation aws-api-gateway


    【解决方案1】:

    我认为在每个路径下添加security,然后在paths 下添加securityDefinitions 会起作用。

    "paths": {
      "/list/tables": {
         "get": {
            "x-amazon-apigateway-integration": {
               "httpMethod": "POST",
               "type": "aws_proxy",
               "uri": {
                  "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015- 
                   03-31/functions/${GetTableList.Arn}/invocations"
               }
            },
            "security": [
               {
                  "api_key": []
               }
            ]
         }
      }
    },
    "securityDefinitions": {
      "type": "api_key",
      "name": "x-api-key",
      "in": "header"
    }
    

    【讨论】:

    • 谢谢 Athar - 我是否需要在 security > api_key 值中指定一个密钥 ID? (您在示例中将其显示为空括号)
    • 这是在 Swagger 中定义安全范围的语法。所以它应该只是一个空数组。请参阅步骤 #2 在swagger.io/docs/specification/authentication 中应用安全性
    • 谢谢,我今天会检查一下,如果成功,我会将问题标记为已回答。谢谢 Athar,非常感谢您花时间在这方面。
    • 不幸的是,这似乎不起作用。该方法与使用计划相关联,但它表示该方法不需要 API 密钥。我会用我的新模板更新我的帖子。
    • 我已经尝试过该解决方案,发现它不会强制该方法需要 API 密钥。虽然 Swagger 文档表示已设置所需的安全性,但在通过 Cloud Formation 部署时不会影响设置。
    【解决方案2】:

    我遇到了同样的问题,并通过放弃在 AWS::ApiGateway::RestApi 中使用 Body 属性来解决它:

     "ServerlessRestApi": {
            "Type": "AWS::ApiGateway::RestApi",
            "DependsOn": "AspNetCoreFunction",
            "Properties": {
               "Description":"My Api Gateway",
                "ApiKeySourceType" : "HEADER",      
                "EndpointConfiguration" : {  "Types" : [ "REGIONAL" ]}
            }
        },
    

    然后,我创建了一个代理资源。在您的情况下,您将为每个路径创建一个资源。在我拥有“{proxy+}”的地方,您将拥有“/list/tables”。

    "ProxyResource": {
        "Type": "AWS::ApiGateway::Resource",
        "Properties": {
            "RestApiId": {
                "Ref": "ServerlessRestApi"
            },
            "ParentId": {
                "Fn::GetAtt": [
                    "ServerlessRestApi",
                    "RootResourceId"
                ]
            },
            "PathPart": "{proxy+}"
        }
    },
    

    最后,我能够定义一个 AWS::ApiGateway::Method 然后强制使用 API 密钥:

    "CoreApiPostMethod":
      {
        "Type": "AWS::ApiGateway::Method",
         "DependsOn" : ["AspNetCoreFunction", "ServerlessRestApi"],
        "Properties":
        {
         "AuthorizationType" :"NONE",
          "OperationName" : "My API Post Request",
    
         "ApiKeyRequired" : true,
                "ResourceId": { "Ref": "ProxyResource"  },
        "RestApiId": {
          "Ref": "ServerlessRestApi"
        },
         "HttpMethod" : "POST",
          "Integration" : {  
           "ConnectionType" :  "INTERNET",
              "IntegrationHttpMethod" : "POST",
           "Type" : "AWS_PROXY",
            "Uri" : {
                              "Fn::Sub":"arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AspNetCoreFunction.Arn}/invocations"
                    }
          }        
        }
    
      },
    

    然后对其他 HTTP 方法遵循相同的模式。它比原始配置更冗长,但它确实让您可以更好地控制方法配置。

    【讨论】:

    • 我会试一试,它看起来最适合我的解决方案(尽管对于我拥有的所有路径来说它会非常冗长:P)
    【解决方案3】:

    聚会迟到了。

    "x-amazon-apigateway-api-key-source" : "HEADER",
    

    "securityDefinitions": {
        "<SOME_NAME>": {
            "type": "apiKey",
            "name": "x-api-key",
            "in": "header"
        }
     }
    

    "security" : [{
        "<SOME_NAME>" : []
    }]
    

    所以一个可行的解决方案可能是

                  "Body": {
                        "swagger": "2.0",
                        "info": {
                            "version": "2017-01-27T21:44:58Z",
                            "title": {"Ref": "AWS::StackName"}
                        },
                        "basePath": "/bbd",
                        "x-amazon-apigateway-api-key-source" : "HEADER",
                        "schemes": [
                            "https"
                        ],
                        "paths": {
                            "/{proxy+}": {
                                "x-amazon-apigateway-any-method": {
                                    "produces": [
                                        "application/json"
                                    ],
                                    "parameters": [
                                        {
                                            "name": "proxy",
                                            "in": "path",
                                            "required": true,
                                            "type": "string"
                                        }
                                    ],
                                    "security" : [{
                                        "bbd" : []
                                    }],
                                    "responses": {},
                                    "x-amazon-apigateway-integration": {
                                        "responses": {
                                            "default": {
                                                "statusCode": "200"
                                            }
                                        },
                                        "uri": "<URL>",
                                        "passthroughBehavior": "when_no_match",
                                        "httpMethod": "POST",
                                        "cacheNamespace": "xh7gp9",
                                        "cacheKeyParameters": [
                                            "method.request.path.proxy"
                                        ],
                                        "contentHandling": "CONVERT_TO_TEXT",
                                        "type": "aws_proxy"
                                    }
                                }
                            }
                        },
                        "securityDefinitions": {
                            "bbd": {
                                "type": "apiKey",
                                "name": "x-api-key",
                                "in": "header"
                            }
                        }
                    }
    

    【讨论】:

      【解决方案4】:
      "security" : [{
                      "myKey" : []
                  }],
      
      "myKey": {
                  "type": "apiKey",
                  "name": "x-api-key",
                  "in": "header"
              },
      

      在 body 中添加安全元素和在 securityDefinitions 中添加 myKey 元素对我有用。

      【讨论】:

        【解决方案5】:

        完整指南here。本指南提供了为任何 API Gateway 方法启用 API 密钥的基本设置。

        使用 AWS::Serverless::Api 定义您的 API。它支持Auth 属性,该属性具有名为 ApiKeyRequired 的属性。将此设置为 true。

        按照上述指南中的代码 sn-p 应该可以。

        AuthApiGateway:
            Type: AWS::Serverless::Api
            Properties:
               StageName: Prod
               Auth:
                   ApiKeyRequired: 'true' # This makes passing ApiKey mandatory
               DefinitionBody:
                   swagger: '2.0'
                   info: ...
        

        【讨论】:

          猜你喜欢
          • 2017-07-22
          • 2017-04-27
          • 2018-11-24
          • 2019-06-22
          • 2019-01-15
          • 2023-02-10
          • 2022-11-09
          • 2018-11-16
          • 2018-10-21
          相关资源
          最近更新 更多