この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
いわさです。
以前、SAMテンプレートとOpenAPIで最小限のAPI Gatewayをデプロイしました。
本日は、このテンプレートを流用して、カスタムドメインとmTLS(Mutual TLS)を使うようにカスタマイズしてみます。
カスタムドメインとmTLSの手動設定は以下の記事を参考に
上記記事が最高です。
API Gatewayでは本機能でクライアント認証を行うことが出来ます。
そもそもカスタムドメインを使いたかったのもありますが、mTLSを使う上でカスタムドメインの利用が前提条件にもなっています。
SAMテンプレート
今回は、手動でクライアント証明書を事前に発行しておき、Route53パブリックホストゾーンを作成済みな環境を想定しています。
テンプレートをつかって、mTLSとカスタムドメインが構成されたAPI Gatewayと、パブリック証明書用のACMをデプロイします。
template-cfn.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ---
Parameters:
ApiName:
Description: API Gateway Name
Type: String
HostedZoneId:
Description: Hosted Zone Id
Type: String
CustomDomainName:
Description: Custom Domain Name
Type: String
TrustStoreS3Uri:
Description: TrustStore S3 URI
Type: String
Default: s3://xxx/xxx.pem
Resources:
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
Certificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Ref CustomDomainName
DomainValidationOptions:
- DomainName: !Ref CustomDomainName
HostedZoneId: !Ref HostedZoneId
ValidationMethod: DNS
ポイントとして、mTLSを使う場合はTLSバージョンは1.2のみサポートされているのでSecurityPolicy
で明示する必要があります。
また、今回はパブリックドメインを使うのでOwnershipVerificationCertificateArn
の指定は不要です。
参考記事に記載があるように、MutualTlsAuthentication
でバージョンも指定することが推奨されていますが、ここでも割愛しています。
OpenAPIドキュメントはAWSのIPアドレスチェック用のエンドポイントをバックエンドに指しており、CodeBuildフェーズでsam package
しています。
詳細は前回の記事をご確認ください。
openapi.json
{
"openapi" : "3.0.1",
"paths" : {
"/" : {
"get" : {
"responses" : {
"200" : {
"description" : "200 response",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/Empty"
}
}
}
}
},
"x-amazon-apigateway-integration" : {
"type" : "http_proxy",
"httpMethod" : "GET",
"uri" : "http://checkip.amazonaws.com",
"responses" : {
"default" : {
"statusCode" : "200"
}
},
"passthroughBehavior" : "when_no_match"
}
}
}
},
"components" : {
"schemas" : {
"Empty" : {
"title" : "Empty Schema",
"type" : "object"
}
}
}
}
リソース構成と接続の確認
デプロイは前回の記事のCodePipelineにまかせていますのでそちらをご確認ください。
ここではデプロイ後にまず接続を試してみます。
$ curl https://apihoge.tak1wa.com
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to apihoge.tak1wa.com:443
$ curl --key my_client.key --cert my_client.pem https://apihoge.tak1wa.com
203.0.113.1
クライアント証明書を使ってアクセスしたときだけアクセス出来ていますね。
次に、リソース構成も見てみましょう。
mTLSがONになっており、カスタムドメインが設定されています。
さいごに
お気づきかもしれませんが、デフォルトエンドポイントが有効になっていますね。
この状態だと、クライアント証明書なしでデフォルトエンドポイント経由でアクセスすることが出来てしまいます。
$ curl https://4pqf8o4iqj.execute-api.ap-northeast-1.amazonaws.com/iwasa-stage
203.0.113.1
デフォルトエンドポイント周りはSAMやCloudFormationの場合は有効化/無効化に少し癖があることがわかったので別途検証記事を紹介したいと思います。