API Gateway のリソースポリシーで CloudFront 経由のリクエストをクライアントの IP アドレスで制限できるか
結論
できました。
- CloudFront 経由でも API Gateway のリソースポリシーでクライアントの IP アドレスでのアクセス制限は可能
- API Gateway は CloudFront の c-ip の IP アドレスで判断している可能性がある
- CloudFront 側で IPv4 と IPv6 のどちらを使用するかで API Gateway のリソースポリシーを変更する必要がある
検証環境
以下の設定で検証環境を構築しました。
- API Gateway
- API タイプ: REST API
- API エンドポイントタイプ: リージョン
- IP アドレスのタイプ: IPv4
- リソース: test
- メソッド: GET
- 統合タイプ: Mock
- ステージ名: test
- CloudFront
- オリジン: API Gateway のドメイン
- Origin IP address type: IPv4-only
パターン 1 CloudFront と API Gateway で IPv4 のみを許可
CloudFront ではデフォルトで IPv6 を使用する設定がオンになっているので、本パターンではオフにして IPv4 のみを使用する設定に変更します。

API Gateway のリソースベースポリシーでは以下の通り IPv4 のアドレスを指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:ap-northeast-1:012345678901:xxx/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "xx.xx.xx.xx/32"
}
}
}
]
}
CloudFront と API Gateway のデプロイ完了後にブラウザから CloudFront 経由でアクセスし、HTTP ステータスコード 200 が返却されることを確認できました。
API Gateway のログには CloudFront-Viewer-Address に IPv4 のアドレスが記録されていました。
Method request headers:
CloudFront-Viewer-Address: xx.xx.xx.xx:xx
CloudFront のログには c-ip に IPv4 のアドレスが記録されていました。
{
"c-ip": "xx.xx.xx.xx",
"x-forwarded-for": "-",
}
クライアントから CloudFront に直接アクセスした場合、クライアントの IP アドレスは c-ip に記録されます。
一方で、クライアントからプロキシなどを通して CloudFront にアクセスした場合、c-ip の値はプロキシの IP アドレスになり、クライアントの IP アドレスは x-forwarded-for に記録されます。
標準ログ記録リファレンス - Amazon CloudFront
c-ip
リクエスト元のビューワーの IP アドレス (192.0.2.183 または 2001:0db8:85a3::8a2e:0370:7334 など)。ビューワーが HTTP プロキシまたはロードバランサーを使用してリクエストを送った場合、このフィールドの値はプロキシまたはロードバランサーの IP アドレスです。
...
x-forwarded-for
ビューワーが HTTP プロキシまたはロードバランサーを使用してリクエストを送信した場合、c-ip フィールドの値はプロキシまたはロードバランサーの IP アドレスです。この場合、このフィールドはリクエスト元のビューワーの IP アドレスです。このフィールドには、複数の IP アドレスをカンマで区切って含めることができます。各 IP アドレスは、IPv4 アドレス (192.0.2.183 など) または IPv6 アドレス (2001:0db8:85a3::8a2e:0370:7334 など) にすることができます。
今回はクライアントから CloudFront に直接アクセスしているので、クライアントの IP アドレスは c-ip に記録されています。
パターン 2 CloudFront と API Gateway で IPv6 のみを許可
本パターンでは CloudFront で IPv6 を使用する設定をオンにします。

API Gateway のリソースベースポリシーでは以下の通り IPv6 のアドレスを指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:ap-northeast-1:012345678901:xxx/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "xx:xx:xx:xx:xx:xx:xx:xx/128"
}
}
}
]
}
CloudFront と API Gateway のデプロイ完了後にブラウザから CloudFront 経由でアクセスし、HTTP ステータスコード 200 が返却されることを確認できました。
API Gateway のログには CloudFront-Viewer-Address に IPv6 のアドレスが記録されていました。
Method request headers:
CloudFront-Viewer-Address=xx:xx:xx:xx:xx:xx:xx:xx:xx
CloudFront のログには c-ip に IPv6 のアドレスが記録されていました。
{
"c-ip": "xx:xx:xx:xx:xx:xx:xx:xx",
"x-forwarded-for": "-",
}
パターン 3 CloudFront でのみ IPv6 のみを許可
本パターンでは CloudFront で IPv6 を使用する設定をオンにする一方、API Gateway のリソースポリシーでは IPv4 のアドレスを指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:ap-northeast-1:012345678901:xxx/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "xx.xx.xx.xx/32"
}
}
}
]
}
API Gateway のデプロイ完了後にブラウザから CloudFront 経由でアクセスしましたが、以下のメッセージとともに HTTP ステータスコードは 403 が返却されました。
{"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:********6805:xxx/test/GET/test because no resource-based policy allows the execute-api:Invoke action"}
API Gateway のログには以下のメッセージのみが記録されていました。
The client is not authorized to perform this operation.
CloudFront のログには c-ip に IPv6 のアドレスが記録されていました。
{
"c-ip": "xx:xx:xx:xx:xx:xx:xx:xx",
"x-forwarded-for": "-",
}
CloudFront には IPv6 でアクセスしているにもかかわらず、API Gateway 側で IPv6 のアドレスが許可されていないことが原因であると思われます。
パターン 4 API Gateway でのみ IPv6 のみを許可
本パターンでは CloudFront で IPv6 を使用する設定をオフにする一方、API Gateway のリソースポリシーでは IPv6 のアドレスを指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:ap-northeast-1:012345678901:xxx/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "xx:xx:xx:xx:xx:xx:xx:xx/128"
}
}
}
]
}
CloudFront と API Gateway のデプロイ完了後にブラウザから CloudFront 経由でアクセスしましたが、以下のメッセージとともに HTTP ステータスコードは 403 が返却されました。
{"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:********6805:xxx/test/GET/test because no resource-based policy allows the execute-api:Invoke action"}
API Gateway のログには以下のメッセージのみが記録されていました。
The client is not authorized to perform this operation.
CloudFront のログには c-ip に IPv4 のアドレスが記録されていました。
{
"c-ip": "xx.xx.xx.xx",
"x-forwarded-for": "-",
}
CloudFront には IPv4 でアクセスしているにもかかわらず、API Gateway 側で IPv4 のアドレスが許可されていないことが原因であると思われます。
まとめ
今回は API Gateway のリソースポリシーで CloudFront 経由のリクエストをクライアントの IP アドレスで制限できるかを試してみました。
どなたかの参考になれば幸いです。
Discussion