メインコンテンツまでスキップ

API Gateway

API Gatewayは、APIの公開・管理・保護を一元的に行うフルマネージドサービスです。バックエンドのアプリケーションへのリクエストを仲介し、認証、スロットリング、キャッシュ、変換といった横断的な関心事をAPI の手前で処理します。


所要時間

約40分

学べること

  • API Gatewayの基本概念と2つのAPI タイプ(REST API / HTTP API)
  • スロットリングの仕組み(Rate / Burst / 使用量プラン)
  • クライアント別のクォータ管理とAPIキー運用
  • WAFレート制限との使い分けと多層防御の設計
  • IDサービスにおけるAPI保護パターン

前提知識


目次

  1. API Gatewayの位置付け
  2. REST API vs HTTP API
  3. スロットリングの仕組み
  4. 使用量プランとAPIキー
  5. キャッシュ
  6. 認証と認可
  7. WAFレート制限との使い分け
  8. IDサービスでの活用

1. API Gatewayの位置付け

クライアント → CloudFront → WAF → API Gateway → ALB → アプリケーション
│ │
│ ├── スロットリング(流量制御)
│ ├── APIキー検証
│ ├── リクエスト検証
│ └── レスポンスキャッシュ

└── レート制限(攻撃遮断)
SQLi/XSSフィルタ

WAFが「悪意のあるリクエストを遮断する」のに対し、API Gatewayは「正常なリクエストの流量を制御する」サービスです。両者は排他ではなく、組み合わせて多層防御を構成します。

ALBとの違い

ALBとAPI Gatewayはどちらも「バックエンドの手前に置く」サービスですが、役割が異なります。

観点ALBAPI Gateway
主な役割トラフィックの分散APIの管理・保護
スロットリングなしあり(Rate/Burst)
APIキー管理なしあり(使用量プラン)
レスポンスキャッシュなしあり(REST APIのみ)
リクエスト変換なしあり(マッピングテンプレート)
料金モデル時間 + LCUリクエスト数

小規模では「ALB直接」で十分ですが、APIの流量制御・クライアント別の利用制限が必要になったタイミングでAPI Gatewayの導入を検討します。


2. REST API vs HTTP API

API Gatewayには2つのAPIタイプがあります。

比較項目REST APIHTTP API
料金$3.50 / 100万リクエスト$1.00 / 100万リクエスト
レイテンシやや高い(~30ms追加)低い(~10ms追加)
スロットリングステージ別 + メソッド別ルート別
使用量プランありなし
APIキーありなし
レスポンスキャッシュありなし
WAF統合ありなし
リクエスト検証ありあり
Lambda Authorizerありあり
OIDC/JWT認証Lambda Authorizer経由ネイティブ対応
選定の判断基準:

クライアント別のクォータ管理が必要?
├── Yes → REST API(使用量プラン + APIキー)
└── No
├── レスポンスキャッシュが必要?
│ ├── Yes → REST API
│ └── No
│ ├── WAF統合が必要?
│ │ ├── Yes → REST API
│ │ └── No → HTTP API(コスト1/3、レイテンシ低)
└──

IDサービスの場合、スロットリングとWAF統合が重要なためREST APIが適しています。


3. スロットリングの仕組み

API Gatewayのスロットリングは、トークンバケットアルゴリズムで実装されています。

Rate と Burst

Rate(定常レート): 1秒あたりに処理するリクエスト数
Burst(バースト): 一時的に許容するリクエストの上限

例: Rate=100, Burst=200 の場合

時刻 バケット残量 受信 処理 拒否(429)
──── ────────── ──── ──── ─────────
0.0s 200 0 0 0
0.1s 200 250 200 50 ← バースト上限まで処理
0.2s 10 30 30 0 ← 前回で消費、10回復+受信30
0.3s 80 0 0 0 ← 100/s のペースで回復
1.0s 200 100 100 0 ← 定常状態

スロットリングの階層

┌─────────────────────────────────────────────────┐
│ アカウントレベル(リージョン単位) │
│ デフォルト: 10,000 req/s │
│ │
│ ├── ステージレベル │
│ │ 設定例: 5,000 req/s │
│ │ │
│ │ ├── ルート/メソッドレベル │
│ │ │ 設定例: │
│ │ │ POST /token → 1,000 req/s │
│ │ │ GET /jwks → 3,000 req/s │
│ │ │ POST /authorize → 2,000 req/s │
│ │ │ │
│ │ └── 使用量プラン(クライアント別) │
│ │ Client A → 500 req/s │
│ │ Client B → 100 req/s │
│ │ Client C → 50 req/s │
│ │ │
│ └── 未設定のルートはステージレベルを継承 │
└─────────────────────────────────────────────────┘

適用順序: クライアント別 → ルート別 → ステージ別 → アカウント別
(最も厳しい制限が優先)

スロットリング設定例(CDK)

const api = new apigateway.RestApi(this, 'IdpApi', {
deployOptions: {
// ステージレベルのスロットリング
throttlingRateLimit: 5000, // 5,000 req/s
throttlingBurstLimit: 10000, // バースト 10,000

// メソッドレベルのスロットリング
methodOptions: {
'POST/token': {
throttlingRateLimit: 1000,
throttlingBurstLimit: 2000,
},
'POST/authorize': {
throttlingRateLimit: 2000,
throttlingBurstLimit: 4000,
},
'GET/jwks': {
throttlingRateLimit: 3000,
throttlingBurstLimit: 5000,
},
},
},
});

429レスポンスの処理

スロットリング超過時、API Gatewayは 429 Too Many Requests を返します。

HTTP/1.1 429 Too Many Requests
Retry-After: 1
Content-Type: application/json

{"message": "Too Many Requests"}

クライアント側の対処:

  • Retry-After ヘッダーを尊重する(指数バックオフではなく、指定された秒数を待つ)
  • SDKを使っている場合は自動リトライが組み込まれていることが多い
  • リトライにはジッター(ランダムな揺らぎ)を追加して、復旧時の同時リクエスト集中を防ぐ

4. 使用量プランとAPIキー

使用量プランは、クライアント別にリクエスト数を制限する仕組みです。REST API専用の機能です。

使用量プランの構成

使用量プラン
├── スロットリング設定(Rate / Burst)
├── クォータ設定(日/週/月あたりの上限)
└── 紐付けるAPIステージ + APIキー

例:
┌──────────────────────────────────────────────────────────┐
│ プラン名: "Standard" │
│ Rate: 100 req/s, Burst: 200 │
│ クォータ: 1,000,000 req/月 │
│ APIキー: client-a-key, client-b-key │
├──────────────────────────────────────────────────────────┤
│ プラン名: "Premium" │
│ Rate: 500 req/s, Burst: 1000 │
│ クォータ: 10,000,000 req/月 │
│ APIキー: client-c-key │
├──────────────────────────────────────────────────────────┤
│ プラン名: "Internal" │
│ Rate: 2000 req/s, Burst: 5000 │
│ クォータ: 無制限 │
│ APIキー: internal-service-key │
└──────────────────────────────────────────────────────────┘

APIキーの仕組み

リクエスト:
POST /token HTTP/1.1
x-api-key: abcdef12345...

API Gateway:
1. x-api-key ヘッダーからAPIキーを取得
2. APIキーに紐付いた使用量プランを特定
3. クォータ残量を確認
4. スロットリング制限内かチェック
5. すべてOKならバックエンドに転送

重要: APIキーは認証ではなくクォータ管理の識別子です。APIキーだけでアクセス制御をしてはいけません。認証には別途 Lambda Authorizer やIAM認証を組み合わせます。

設定例(CDK)

// 使用量プランの作成
const standardPlan = api.addUsagePlan('StandardPlan', {
name: 'Standard',
throttle: {
rateLimit: 100, // 100 req/s
burstLimit: 200,
},
quota: {
limit: 1000000, // 100万 req/月
period: apigateway.Period.MONTH,
},
});

// APIキーの作成と紐付け
const clientAKey = api.addApiKey('ClientAKey', {
apiKeyName: 'client-a',
});
standardPlan.addApiKey(clientAKey);

クォータの監視

使用量プランのクォータ消費状況はAPIで取得できます。

# クライアントの使用量を取得
aws apigateway get-usage \
--usage-plan-id abc123 \
--key-id xyz789 \
--start-date 2025-03-01 \
--end-date 2025-03-31

CloudWatchメトリクスで監視する場合:

  • Count: リクエスト総数
  • 4XXError: 429を含むクライアントエラー数
  • Throttle: スロットリングされたリクエスト数(これが増えたらプラン見直し)

5. キャッシュ

REST APIではレスポンスキャッシュを有効にでき、バックエンドへの負荷を軽減できます。

キャッシュの設定

パラメータ設定値説明
キャッシュサイズ0.5GB 〜 237GB大きいほど高価だが多くのレスポンスをキャッシュ
TTL0〜3600秒(デフォルト300秒)キャッシュの有効期間
暗号化有効/無効キャッシュデータの暗号化
キャッシュキーパラメータ、ヘッダー何をキーにキャッシュを分離するか

IDサービスでのキャッシュ候補

キャッシュ適性:

GET /.well-known/openid-configuration
→ TTL 300s、全リクエスト共通の応答 → 最もキャッシュ効果が高い

GET /jwks
→ TTL 60s、鍵ローテーション時は Cache-Control: no-cache で無効化

GET /userinfo
→ キャッシュ不可(ユーザーごとに異なる、アクセストークン必須)

POST /token
→ キャッシュ不可(POSTはキャッシュ対象外、毎回異なるトークン発行)

POST /authorize
→ キャッシュ不可(状態を持つフロー)

6. 認証と認可

API Gatewayでバックエンドに到達する前にリクエストを認証できます。

認証方式の比較

方式対象仕組みREST APIHTTP API
Lambda Authorizer独自トークンLambda関数で検証ロジックを実装ありあり
IAM認証AWSサービス間SigV4署名で認証ありあり
Cognito AuthorizerCognitoユーザーJWTトークンを自動検証ありなし
JWT AuthorizerOIDC準拠IdPJWTを自動検証(issuer, audience)なしあり

Lambda Authorizer

IDサービスの場合、自身が発行したアクセストークンを検証するLambda Authorizerが最も汎用的です。

リクエスト


API Gateway → Lambda Authorizer

├── トークン検証(署名、有効期限、スコープ)
├── 認可ポリシー生成
└── 結果をキャッシュ(TTL設定可能)


バックエンド
// Lambda Authorizer の例(TOKEN 型)
exports.handler = async (event) => {
const token = event.authorizationToken.replace('Bearer ', '');

// トークンの検証(署名、有効期限、issuer等)
const decoded = await verifyToken(token);

return {
principalId: decoded.sub,
policyDocument: {
Version: '2012-10-17',
Statement: [{
Action: 'execute-api:Invoke',
Effect: decoded.scope.includes('admin') ? 'Allow' : 'Deny',
Resource: event.methodArn,
}],
},
context: {
tenantId: decoded.tenant_id,
scope: decoded.scope,
},
};
};

認可結果のキャッシュ: Lambda Authorizerの結果はTTL(最大3600秒)でキャッシュでき、同じトークンの再検証を省略できます。ただし、トークン失効とキャッシュTTLのずれに注意が必要です。


7. WAFレート制限との使い分け

WAFのレート制限とAPI Gatewayのスロットリングは、どちらも「リクエスト数を制限する」機能ですが、目的と粒度が異なります。

比較

観点WAF レート制限API Gateway スロットリング
目的攻撃の遮断正常トラフィックの流量制御
判断基準IPアドレスAPIキー(クライアント別)
粒度IPあたり N回/5分クライアント別 Rate/Burst + 月間クォータ
超過時の応答403 Forbidden429 Too Many Requests
Retry-Afterなしあり
クライアントへの意味「あなたはブロックされた」「少し待ってからリトライして」
設定対象CloudFront, ALB, API GatewayAPI Gatewayのステージ/メソッド

多層防御の構成

リクエスト


┌─────────────┐ 「攻撃か?」
│ WAF │ ・同一IPから100回/5分超 → 403 Block
│ レート制限 │ ・SQLi/XSSパターン → 403 Block
└──────┬──────┘
│ 通過(正常なリクエスト)

┌─────────────┐ 「容量内か?」
│ API Gateway │ ・Client Aは100 req/s超 → 429 Retry
│ スロットリング│ ・月間クォータ超過 → 429 Retry
└──────┬──────┘
│ 通過(制限内のリクエスト)

┌─────────────┐
│ ALB │ トラフィック分散
│ バックエンド │
└─────────────┘

どちらを先に導入すべきか

判断フロー:

公開APIがある?
├── Yes
│ └── WAFレート制限を先に導入(攻撃対策は最優先)
│ │
│ └── 外部クライアントにAPIを提供する?
│ ├── Yes → API Gateway(使用量プラン)を追加
│ └── No → WAFだけで十分なことが多い
└── No(内部APIのみ)
└── API Gateway のスロットリングのみで十分

8. IDサービスでの活用

エンドポイント別の保護設計

┌──────────────────────────────────────────────────────────────┐
│ IDサービス API保護設計 │
├──────────┬───────────────┬───────────────┬──────────────────┤
│ エンドポイント│ WAF ルール │ API GW スロットリング│ キャッシュ │
├──────────┼───────────────┼───────────────┼──────────────────┤
│ POST │ IP: 100回/5分 │ 1,000 req/s │ なし │
│ /token │(ブルートフォース│ Burst: 2,000 │(毎回異なるトークン)│
│ │ 対策) │ │ │
├──────────┼───────────────┼───────────────┼──────────────────┤
│ GET │ IP: 30回/分 │ 2,000 req/s │ なし │
│ /authorize│(自動化ツール │ Burst: 4,000 │(状態を持つフロー)│
│ │ 対策) │ │ │
├──────────┼───────────────┼───────────────┼──────────────────┤
│ GET │ なし │ 5,000 req/s │ TTL 60s │
│ /jwks │(公開情報) │ Burst: 10,000 │(鍵ローテーション時│
│ │ │ │ Cache-Control で │
│ │ │ │ 無効化) │
├──────────┼───────────────┼───────────────┼──────────────────┤
│ GET │ なし │ 5,000 req/s │ TTL 300s │
│ /.well- │(公開情報) │ Burst: 10,000 │(変更頻度が低い) │
│ known/ │ │ │ │
├──────────┼───────────────┼───────────────┼──────────────────┤
│ POST │ IP: 60回/5分 │ 500 req/s │ なし │
│ /introspect│(内部利用中心)│ Burst: 1,000 │(トークン状態確認)│
├──────────┼───────────────┼───────────────┼──────────────────┤
│ /api/v1/*│ IPホワイトリスト│ 200 req/s │ なし │
│ (管理API) │(管理者NWのみ)│ Burst: 500 │(状態変更操作) │
└──────────┴───────────────┴───────────────┴──────────────────┘

マルチテナント環境での使用量プラン

テナント規模別のプラン設計:

┌── Small テナント ──────────────────┐
│ Rate: 50 req/s │
│ Burst: 100 │
│ 月間クォータ: 500,000 req │
│ 対象: 〜1万ユーザーのテナント │
└────────────────────────────────────┘

┌── Medium テナント ─────────────────┐
│ Rate: 200 req/s │
│ Burst: 500 │
│ 月間クォータ: 5,000,000 req │
│ 対象: 1万〜10万ユーザーのテナント │
└────────────────────────────────────┘

┌── Large テナント ──────────────────┐
│ Rate: 1,000 req/s │
│ Burst: 2,000 │
│ 月間クォータ: 50,000,000 req │
│ 対象: 10万ユーザー超のテナント │
└────────────────────────────────────┘

1テナントの暴走が他テナントに影響しない = Noisy Neighbor対策

料金目安

API Gateway REST API(東京リージョン):

リクエスト料金: $4.25 / 100万リクエスト(最初の3.33億)
キャッシュ: $0.028/時間(0.5GB)〜 $3.80/時間(237GB)

コスト試算(IDサービス):
┌────────────────────────────────────────────────────────┐
│ 小規模(100 req/s = 約260万req/月) │
│ リクエスト: $11/月 │
│ キャッシュ 0.5GB: $20/月 │
│ 合計: 約 $31/月 │
├────────────────────────────────────────────────────────┤
│ 中規模(500 req/s = 約1,300万req/月) │
│ リクエスト: $55/月 │
│ キャッシュ 1.6GB: $45/月 │
│ 合計: 約 $100/月 │
├────────────────────────────────────────────────────────┤
│ 大規模(5,000 req/s = 約1.3億req/月) │
│ リクエスト: $550/月 │
│ キャッシュ 6.1GB: $130/月 │
│ 合計: 約 $680/月 │
└────────────────────────────────────────────────────────┘

※ CloudFrontで/.well-knownとJWKSをオフロードすると
リクエスト数を30-50%削減でき、API Gatewayコストも下がる

まとめ

機能説明IDサービスでの用途
スロットリングRate/Burstによる流量制御エンドポイント別のリクエスト制限
使用量プランクライアント別のクォータ管理テナント別のNoisy Neighbor対策
キャッシュレスポンスの一時保存JWKS、well-known設定のオフロード
Lambda Authorizerカスタム認証ロジックアクセストークン検証
WAFとの多層防御攻撃遮断 + 流量制御総当たり攻撃防止 + 正常トラフィック管理

重要なポイント:

  • スロットリングはトークンバケットで動作する。Rate(定常)とBurst(瞬間)の両方を設計する
  • 使用量プランはREST API専用。クライアント別のクォータが不要ならHTTP APIのほうが安い
  • APIキーはクォータ管理の識別子であり、認証の代わりにはならない
  • WAFレート制限は「攻撃遮断(403)」、API Gatewayスロットリングは「流量制御(429)」。目的が違う

次のステップ


参考リソース