API Gatewayを利用すればAPIを簡単に作成できます。 そして、APIキーの設定も簡単にできます。 このとき、CORS用のOPTIONSメソッドでAPIキー設定を次のようにしたかったので、試してみました。
- OPTIONSメソッド: APIキーは不要でよい
- 他のメソッド: APIキーが必須である
おすすめの方
- API Gateway と Lambda の組み合わせでCORSに対応したい方
- API GatewayのOPTIONSメソッド(CORS)でAPIキーを不要にしたい方
まずは、普通にAPIキーが必要なメソッドを作成する
sam init
sam init \
--runtime python3.11 \
--name api-gateway-no-required-api-key-in-options-method-sample \
--app-template hello-world \
--no-tracing \
--no-application-insights \
--structured-logging \
--package-type Zip
SAMテンプレート
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: api-gateway-no-required-api-key-in-options-method-sample
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: v1
OpenApiVersion: 3.0.1
ApiKeySourceType: HEADER
Auth:
ApiKeyRequired: true
UsagePlan:
CreateUsagePlan: PER_API
UsagePlanName: no-required-api-key-in-options-method-usage-plan
Quota:
Limit: 500
Period: MONTH
Throttle:
BurstLimit: 100
RateLimit: 50
Cors:
AllowMethods: "'DELETE,POST,GET,OPTIONS,PUT,PATCH'"
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowOrigin: "'https://www.example.com'" # 実験のため、適当に設定しています。適切な値を設定してください。
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.11
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId: !Ref MyApi
HelloWorldFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
Lambdaコード
今回の実験ではブラウザからアクセスしないので不要ですが、「headers」も返しておきます。
app.py
import json
def lambda_handler(event, context):
<pre><code>return {
"statusCode": 200,
"headers": {
"Access-Control-Allow-Methods": "DELETE,POST,GET,OPTIONS,PUT,PATCH",
"Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
"Access-Control-Allow-Origin": "https://www.example.com",
},
"body": json.dumps(
{
"message": "hello world",
}
),
}
</code></pre>
デプロイ
sam deploy \
--guided \
--region ap-northeast-1 \
--stack-name api-gateway-no-required-api-key-in-options-method-sample-stack
OPTIONSメソッドでAPIキーが必須になっていることを確認する
上記の内容をデプロイしたとき、API Gatewayの動作は、APIキーが無いと403が返ってきます。
OPTIONSメソッド(APIキーなし)は、403が返ってくる
$ curl -X OPTIONS -I \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 403
OPTIONSメソッド(APIキーあり)は、200が返ってくる
$ curl -X OPTIONS -I \
-H "x-api-key: valid-api-key" \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 200
GETメソッド(APIキーなし)は、403が返ってくる
$ curl -X GET -I \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 403
GETメソッド(APIキーあり)は、200が返ってくる
$ curl -X GET -I \
-H "x-api-key: valid-api-key" \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 200
OPTIONSメソッドは、APIキーを不要に設定する
SAMテンプレート
「AddApiKeyRequiredToCorsPreflight」を追加しました。未指定の場合は、デフォルトでtrueが設定されるのです。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: api-gateway-no-required-api-key-in-options-method-sample
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: v1
OpenApiVersion: 3.0.1
ApiKeySourceType: HEADER
Auth:
ApiKeyRequired: true
AddApiKeyRequiredToCorsPreflight: false
UsagePlan:
CreateUsagePlan: PER_API
UsagePlanName: no-required-api-key-in-options-method-usage-plan
Quota:
Limit: 500
Period: MONTH
Throttle:
BurstLimit: 100
RateLimit: 50
Cors:
AllowMethods: "'DELETE,POST,GET,OPTIONS,PUT,PATCH'"
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowOrigin: "'https://www.example.com'" # 実験のため、適当に設定しています。適切な値を設定してください。
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.11
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId: !Ref MyApi
HelloWorldFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
デプロイ
sam deploy
OPTIONSメソッド(APIキーなし)は、200が返ってくる
目論見通り、403ではなく、200が返ってきました。
$ curl -X OPTIONS -I \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 200
OPTIONSメソッド(APIキーあり)は、200が返ってくる
$ curl -X OPTIONS -I \
-H "x-api-key: valid-api-key" \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 200
GETメソッド(APIキーなし)は、403が返ってくる
$ curl -X GET -I \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 403
GETメソッド(APIキーあり)は、200が返ってくる
$ curl -X GET -I \
-H "x-api-key: valid-api-key" \
https://xxx.execute-api.ap-northeast-1.amazonaws.com/v1/hello
HTTP/2 200