この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
いわさです。
以下の記事でmTLS + カスタムドメインのAPI GatewayをSAMでデプロイしました。
しかし、デフォルトエンドポイントが無効化出来ていませんでした。
この記事ではデフォルトエンドポイントの無効化方法をためします。
DisableExecuteApiEndpointはうまくいかない?
SAMではこのための設定値が用意されています。
AWS::Serverless::Api - AWS Serverless Application Model
DisableExecuteApiEndpoint
クライアントがデフォルトの execute-api エンドポイント (https://{api_id}.execute-api.{region}.amazonaws.com) を使用して API を呼び出すことができるかどうかを指定します。デフォルトで、クライアントはデフォルトのエンドポイントを使用して API を呼び出すことができます。クライアントが API の呼び出しにカスタムドメイン名以外を使用しないようにするには、デフォルトのエンドポイントを無効にします。タイプ: ブール
必須: いいえ
AWS CloudFormation との互換性: このプロパティは、AWS::ApiGateway::RestApi リソースの DisableExecuteApiEndpoint プロパティに直接渡されます。
このプロパティ早速ためしてみましょう。
Api:
Type: AWS::Serverless::Api
Properties:
Name: !Ref ApiName
EndpointConfiguration: REGIONAL
OpenApiVersion: 3.0.1
StageName: iwasa-stage
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: ./openapi.json
Domain:
DomainName: !Ref CustomDomainName
CertificateArn: !Ref Certificate
EndpointConfiguration: REGIONAL
MutualTlsAuthentication:
TruststoreUri: !Ref TrustStoreS3Uri
Route53:
DistributionDomainName: !Ref CustomDomainName
HostedZoneId: !Ref HostedZoneId
SecurityPolicy: TLS_1_2
DisableExecuteApiEndpoint: true
Certificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Ref CustomDomainName
DomainValidationOptions:
- DomainName: !Ref CustomDomainName
HostedZoneId: !Ref HostedZoneId
ValidationMethod: DNS
しかし、デフォルトエンドポイントが無効化されていません。
こ、これは...
AWS::ApiGateway::RestApi リソースの DisableExecuteApiEndpoint プロパティに渡されない
ドキュメントでは、RestApiリソースのDisableExecuteApiEndpointプロパティに渡されるとされていますが、SAMのスタックから展開されたCloudFormationを確認してみましょう。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "---",
"Parameters": {
:
},
"Resources": {
"Api": {
"Type": "AWS::ApiGateway::RestApi",
"Metadata": {
"SamResourceId": "Api"
},
"Properties": {
"Body": {
"paths": {
"/": {
"get": {
"x-amazon-apigateway-integration": {
"httpMethod": "GET",
"passthroughBehavior": "when_no_match",
"type": "http_proxy",
"uri": "http://checkip.amazonaws.com",
"responses": {
"default": {
"statusCode": "200"
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Empty"
}
}
},
"description": "200 response"
}
}
}
}
},
"openapi": "3.0.1",
"components": {
"schemas": {
"Empty": {
"type": "object",
"title": "Empty Schema"
}
}
},
"x-amazon-apigateway-endpoint-configuration": {
"disableExecuteApiEndpoint": true
}
},
"Name": {
"Ref": "ApiName"
},
"Parameters": {
"endpointConfigurationTypes": "REGIONAL"
},
"EndpointConfiguration": {
"Types": [
"REGIONAL"
]
}
}
},
:
}
}
AWS::ApiGateway::RestApi
のDisableExecuteApiEndpoint
プロパティには値は渡されていないですね。
ただし、(代わりに?)OpenAPIドキュメントのx-amazon-apigateway-endpoint-configuration.disableExecuteApiEndpoint
が設定されています。
一見すると動作しそうにも見えるのですが、実はこの設定値、Swagger2.0は最上位ベンダー拡張に存在する必要があるので上記のとおりで良いのですが、OpenAPI3.0ではサーバーオブジェクトのベンダー拡張の下に存在する必要があるそうです。
OpenAPIを使っている場合は直接指定する
よって、ここではSAMのDisableExecuteApiEndpointプロパティは使わずに、OpenAPIドキュメントへ以下のように直接反映させることが現時点の解決策になります。
openapi.json
{
"openapi" : "3.0.1",
"servers": [
{
"x-amazon-apigateway-endpoint-configuration": {
"disableExecuteApiEndpoint": true
}
}
],
"paths" : {
:
},
"components" : {
:
}
}
デプロイしてみましょう。
お、デフォルトエンドポイントが無効化されている!
cURLでも確認してみます。
$ curl https://apihoge.tak1wa.com
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to apihoge.tak1wa.com:443
$ curl --key ./keys/my_client.key --cert ./keys/my_client.pem https://apihoge.tak1wa.com
120.51.74.235
$ curl https://4pqf8o4iqj.execute-api.ap-northeast-1.amazonaws.com/iwasa-stage
curl: (6) Could not resolve host: 4pqf8o4iqj.execute-api.ap-northeast-1.amazonaws.com
良さそうです。
さいごに
本日はSAMでデフォルトエンドポイントを無効化する方法を確認してみました。
試してないのですが、Swagger2.0であればDisableExecuteApiEndpointが使えるのだと思います。
ドキュメントと挙動は異なりますが。
OpenAPIかSwaggerかなどでこのあたりの挙動が変わってくるとは盲点でした。