API Gateway(REST API) のアクセス元を CloudFront のみに許可するには
API Gateway のアクセス元を CloudFront のみに許可したい
Cloudfront の オリジンとして API Gateway を使用する構成において、API Gateway 側で CloudFront からのアクセスのみを許可したい場合に、どんな方法があるか調べてみた。
API Gateway(REST API) のアクセス元を CloudFront のみに許可する 2 つの方法
方法その 1: API Gateway の API キー認証を使う
API Gateway にて API の実行に API キーを必須に設定し、CloudFront のカスタムヘッダーとして API キーを送信するように設定することで、特定の CloudFront ディストリビューションからのアクセスのみ許可する方法となります。1
方法その 2: API Gateway のリソースポリシーと AWS:Referer を使う
API Gateway のリソースポリシーにて API の実行に AWS
API Gateway(REST API) のアクセス元を CloudFront のみに許可する 2 つの方法の留意点
方法その 1 (API Gateway の API キー認証を使う)の留意点
- API キーは API Gateway のリソースとメソッドの組み合わせ毎に設定する必要があります。
自分が調べた限り、現時点(2022/09)時点で全てのリソースとメソッドの組み合わせに一括で API キーを必須にすることはできません。
そのため、リソースとメソッドの組み合わせが追加されるたびに、都度その API キーの設定を有効にする必要があります。 - 使用できない一例: API キーを複数発行し、顧客に配布し、顧客はその API キーを使って API を実行するといった API キー及び使用量プランの本来の使い方?をする場合
方法その 2 (API Gateway のリソースポリシーと AWS:Referer を使う)の留意点
- API キー認証の時と違い、こちらの方法では、API 全体に対して制限をかけることが可能なため、リソースとメソッドの組み合わせが追加される度に設定を行う必要がありません。
一方で、特定のリソースとメソッドの組み合わせに対してアクセス制限を適用したくないなどの場合は、リソースポリシーの変更が必要となります。 - 使用できない一例: オリジンリクエストポリシーにて Referer リクエストヘッダーをオリジン(API Gateway)へ送信し、Lambda などのバックエンド側でクライアント側で設定された Referer リクエストヘッダーを参照する必要がある場合
事前準備
API Gateway の作成
API タイプは REST API で API Gateway を作成します。
リソース設定は、ルートパスに GET メソッドを作成します。
統合リクエストは、統合タイプとして [Mock] 選択して作成します。
API を任意のステージにデプロイします。
デプロイ後、 ステージエディター画面の上部にある Invoke URL
(API Gateway API を呼び出すための URL) をメモしておきます。
ここまでの設定に問題がなければ API が実行できるはずです。
一旦、curl など API が 200 OK レスポンスを返すことを確認しておきます。
$ curl -X GET -I https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod
HTTP/2 200
date: Sun, 06 Mar 2022 02:39:23 GMT
content-type: application/json
content-length: 0
x-amzn-requestid: 46533423-7524-481e-9b47-9a48a83e9aa4
x-amz-apigw-id: OinCTHqDNjMFftQ=
CloudFront の作成とカスタムヘッダー(Referer)の設定
オリジンリクエストポリシーを作成後、CloudFront ウェブディストリビューションを作成します。
[オリジンドメイン]は API の invoke URL
を指定します。
因みに、選択肢として invoke URL
は表示されないので、直接入力する必要があります。
[オリジンパス]は省略可能です。
ここでは、API のステージ名(prod)を指定しています。
これは、API 呼び出し時にステージ名を指定したいか否かで変わります。
API を呼び出すときにステージ名を自分で入力する場合は、[オリジンパス]を入力する必要はありません。
API キーを使って API Gateway のアクセス元を CloudFront のみに許可する手順
API キー必須化
事前準備の API Gateway で作成した GET メソッドの[メソッドリクエスト]で [API キーの必要性] を true
に設定し、API キーの使用を有効化しておきます。
使用量プランの設定と API キーの作成
使用量プランを作成します。
スロットリング2とクォータ2それぞれの制限はデフォルトで有効化されていますが、顧客に API を公開して制限をかけるなどの要件がなく、特に制限する必要がなければ無効化することもできます。
[API ステージの追加]ボタンをクリックして、API キーの作成と使用量プランへの紐付けを行います。
設定完了後に作成した API キーの画面で [表示] をクリックして表示される API キー値をメモしておきます。
一旦ここで設定がうまくいっているか動作確認してみます。
まず、API キーをしているパターンを実行し、200 OK レスポンスを返すことを確認します。
API キーは HTTP ヘッダーに x-api-key
というヘッダー名で付与します。
$ curl -I -X GET https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod -H 'x-api-key: <API キー値>'
HTTP/2 200
date: Sun, 06 Mar 2022 04:06:26 GMT
content-type: text/html
content-length: 1310
x-amzn-requestid: 27cf9c40-a378-48c4-aa42-a293ac5e5f99
x-amz-apigw-id: OizyaHnGNjMFSxQ=
因みに、x-api-key
ヘッダーを付与していない場合、ステータスコードが 403
の ForbiddenException
エラーを返します。
$ curl -I -X GET https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod
HTTP/2 403
date: Sun, 06 Mar 2022 04:06:24 GMT
content-type: application/json
content-length: 23
x-amzn-requestid: 7fca17f5-f15c-4c7b-98aa-a6e802f91ed4
x-amzn-errortype: ForbiddenException
x-amz-apigw-id: OizyLF_LtjMF30w=
CloudFront のカスタムヘッダー(x-api-key)の設定
[カスタムヘッダーを追加]で x-api-key
というヘッダー名で API キー値を追加します。
API キーの動作確認
動作確認してみます。
CloudFront の URL で API を呼び、200 OK レスポンスを返ってくれば成功です。
$ curl -I -X GET https://xxxxxxxxxxxxx.cloudfront.net -H 'x-api-key: <API キー値>'
HTTP/2 200
content-type: text/html
content-length: 1310
vary: Accept-Encoding
date: Sun, 06 Mar 2022 05:12:30 GMT
x-amzn-requestid: bd9d0322-ba24-44ed-9553-de4858ec9536
x-amz-apigw-id: Oi9duGUWtjMFm8g=
x-cache: Miss from cloudfront
via: 1.1 fcdc790e9970e122cf39adadda463c14.cloudfront.net (CloudFront)
x-amz-cf-pop: NRT20-C4
x-amz-cf-id: 4z_1D1-ecgMQKc7plvtbL-c1e0Vx9dosRbklBpr3HRmWoqdGLoA1uw==
を使って API Gateway のアクセス元を CloudFront のみに許可する手順
API Gateway のリソースポリシーと AWSリソースポリシーの設定
API Gateway のリソースポリシーを以下のように設定します。
コンソール上から入力せいて保存すると Resouce
の部分が自動的に以下のような arn
に変換してくれます。
arn:aws:execute-api:<Region>:<AWS アカウント ID>:<API ID>/*
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "execute-api:/*",
"Condition": {
"StringNotEquals": {
"aws:Referer": "<適当な文字列>"
}
}
},
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "execute-api:/*"
}
]
}
一旦ここで設定がうまくいっているか動作確認してみます。
まず、Referer リクエストヘッダーを設定しているパターンを実行し、200 OK レスポンスを返すことを確認します。
$ curl -I -X GET https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod -H 'referer: <リソースポリシーに設定した適当な文字列>'
HTTP/2 200
date: Tue, 20 Sep 2022 08:46:56 GMT
content-type: application/json
content-length: 0
x-amzn-requestid: 53309964-1549-48c9-8e5f-512a282f03a8
x-amz-apigw-id: YwCgFGHVtjMFieg=
因みに、Referer ヘッダーを付与していない場合、ステータスコードが 403 の ForbiddenException エラーを返します。
$ curl -I -X GET https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod
HTTP/2 403
date: Tue, 20 Sep 2022 08:47:16 GMT
content-type: application/json
content-length: 182
x-amzn-requestid: 0e2809c8-2295-44f0-b3b5-6db8fdca4b1f
x-amzn-errortype: AccessDeniedException
x-amz-apigw-id: YwCjKF8jNjMFTfg=
CloudFront のカスタムヘッダー(Referer)の設定
[カスタムヘッダーを追加]で Referer
というヘッダー名でリソースポリシーに設定した適当な文字列値を追加します。
なお、オリジンリクエストポリシーにて Referer リクエストヘッダーを設定している場合、以下のようなエラーが発生します。
The paramater Header Name with value Referer is not allowed as both as origin custom header and a forward header
Referer の動作確認
動作確認してみます。
CloudFront の URL で API を呼び、200 OK レスポンスを返ってくれば成功です。
$ curl -I -X GET https://xxxxxxxxxxxxx.cloudfront.net/
HTTP/2 200
content-type: application/json
content-length: 0
date: Tue, 20 Sep 2022 08:49:51 GMT
x-amzn-requestid: e4752a73-95b0-462a-b643-512198da6475
x-amz-apigw-id: YwC7dGMCNjMFS-w=
x-cache: Hit from cloudfront
via: 1.1 1ec5c4b165968f8e5c872b374a497e8e.cloudfront.net (CloudFront)
x-amz-cf-pop: NRT57-P2
x-amz-cf-id: TjTMUnRNKNCro-IifX67z5YnW3L0CcinXiTr0UAEMt6FPhDWXpKU_Q==
age: 46
Footnotes
個人開発したサービス
個人開発したサービス
目次
個人開発したサービス