API Gateway REST APIでのキャッシュデータが暗号化について

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。

今回は、Amazon API Gateway REST APIのキャッシュデータが暗号化されずに保管されている状態について、そのリスクと対策を解説します。

ポリシーの説明

Amazon API Gateway の Security Hub コントロール – AWS Security Hub

[APIGateway.5] API Gateway REST API のキャッシュデータは、保管中に暗号化する必要があります

このコントロールは、キャッシュが有効になっている API Gateway REST API ステージ内のすべてのメソッドが暗号化されているかどうかをチェックします。API Gateway REST API ステージ内のメソッドのキャッシュ機能が設定されており、そのキャッシュが暗号化されていない場合、コントロールは失敗します。Security Hub は、特定のメソッドのキャッシュが有効になっている場合にのみ、そのメソッドの暗号化を評価します。

リスク

Amazon API Gatewayは、開発者がAPIを作成、公開、保守、監視、保護するためのフルマネージドサービスです。REST APIやWebSocket APIをサポートし、バックエンドサービス(Lambda、EC2、DynamoDBなど)へのセキュアなアクセスポイントを提供します。API Gatewayには、パフォーマンス向上のためにレスポンスをキャッシュする機能がありますが、このキャッシュデータが暗号化されていない場合、以下のような重大なセキュリティリスクが発生します。

  • 機密データの露出リスク: APIレスポンスには、ユーザーの個人情報(PII)、認証トークン、セッションデータ、ビジネス上の機密情報などが含まれることがあります。これらのデータが暗号化されずにキャッシュに保管されている場合、キャッシュストレージへの不正アクセスや、AWS内部でのデータ漏洩によって、機密データが平文で露出するリスクがあります。
  • 不正アクセス時の被害拡大: もしAPI Gatewayの基盤や関連サービスが侵害された場合、キャッシュ内の暗号化されていないデータが直接的な標的となり、被害が拡大する可能性があります。暗号化されていれば、データが読み取られる前に復号化の許可が必要となるため、不正アクセス時の防御層が増えます。
  • データアクセス制御の不十分さ: 暗号化は、データのアクセス制御に追加の層を提供します。データが暗号化されている場合、それを読み取るためには復号化の権限が必要となり、権限のないユーザーによるデータへのアクセスをさらに制限できます。暗号化されていない場合、この重要な制御メカニズムが欠如します。
  • 監査証跡の不備: キャッシュデータの暗号化と復号化に関連する操作は、AWS CloudTrailに記録されます。暗号化を有効にしないと、これらの操作に関する詳細な監査証跡が残らず、セキュリティインシデント発生時の調査やフォレンジックが困難になります。

対策

API Gateway REST APIのキャッシュデータを保管時に暗号化することは、上記のすべてのリスクを軽減し、データセキュリティを大幅に強化するための重要なベストプラクティスです。API Gatewayは、AWS KMS (Key Management Service) を利用してキャッシュデータを暗号化します。

  • API Gatewayキャッシュの有効化と設定: API Gatewayのステージ設定において、キャッシュを有効化します。キャッシュのサイズやTTL(Time To Live)などを適切に設定し、機密データが不要に長くキャッシュされないようにします。
  • KMS カスタマー管理キー (CMK) の使用: キャッシュ暗号化には、KMSのカスタマー管理キー (CMK) を使用することを強く推奨します。これにより、鍵の生成、ローテーション、無効化、削除、およびアクセス権限(キーポリシー)をユーザー自身が完全に制御できるようになります。AWS管理キー(aws/apigateway)を使用することも可能ですが、CMKの方がより厳格なセキュリティ制御を提供します。
  • 最小特権の原則に基づくキーポリシー: CMKのキーポリシーを設定する際には、API Gatewayサービスプリンシパル(apigateway.amazonaws.com)が、キャッシュデータの暗号化と復号化に必要な最小限の権限(kms:Encrypt, kms:Decrypt, kms:GenerateDataKeyなど)のみを持つようにします。
  • AWS CloudTrailとの統合: KMS CMKの使用状況はAWS CloudTrailに記録されます。これにより、誰がいつ暗号化/復号化操作を行ったかを監査し、セキュリティイベントを監視できます。

修復方法

Amazon API Gateway REST APIのキャッシュデータを保管時に暗号化する方法は、AWSコンソールまたはTerraformで行えます。

AWSコンソールでの修復手順

AWSコンソールを使用して、API Gateway REST APIのステージ設定でキャッシュを有効にし、KMS CMKで暗号化を設定します。

前提:

  • API Gatewayキャッシュの暗号化に使用するAWS KMS カスタマー管理キー (CMK) が既に存在すること。
    • CMKのキーポリシーには、API Gatewayサービス (apigateway.amazonaws.com) がキーを使用するための適切な権限(kms:Encrypt, kms:Decrypt, kms:GenerateDataKey など)が付与されている必要があります。
  1. API Gatewayサービスへ移動: AWSコンソールにログインし、API Gateway サービスを開きます。
  2. REST APIを選択: 左側のナビゲーションペインで「API」の下の「REST API」を選択し、設定を変更したいAPIを選択します。
  3. ステージへ移動: 左側のナビゲーションペインで「ステージ」を選択し、キャッシュ設定を有効にしたいステージ(例: prod, dev)を選択します。
  4. キャッシュ設定の編集:
    • ステージの詳細ページで、「キャッシュ」タブをクリックします。
    • 設定の編集」ボタンをクリックします。
  5. キャッシュと暗号化の有効化:
    • ステージキャッシュの有効化」にチェックを入れます。
    • キャッシュ設定」で、必要に応じて「キャッシュ容量」(ギガバイト)を選択します。
    • 暗号化オプション」セクションまでスクロールします。
    • キャッシュを暗号化する」にチェックを入れます。
    • AWS KMS カスタマー管理キー」のドロップダウンメニューから、使用したい既存のKMS CMKを選択します。
      • もし適切なCMKがリストに表示されない場合は、正しいIAM権限があるか、またはCMKが作成されているか確認してください。
  6. 変更を保存: 設定内容を確認し、「変更を保存」をクリックします。

Terraformでの修復手順

TerraformでAPI Gateway REST APIのキャッシュデータを保管時に暗号化するには、aws_api_gateway_stage リソースの cache_cluster_enabled, cache_cluster_size, cache_data_encrypted, および cache_cluster_key パラメータを設定します。

# (前提) API Gateway REST APIとデプロイメントは別途定義
resource "aws_api_gateway_rest_api" "my_api" {
  name        = "MySecureAPI"
  description = "A secure REST API"
}

resource "aws_api_gateway_resource" "my_resource" {
  rest_api_id = aws_api_gateway_rest_api.my_api.id
  parent_id   = aws_api_gateway_rest_api.my_api.root_resource_id
  path_part   = "items"
}

resource "aws_api_gateway_method" "get_items" {
  rest_api_id   = aws_api_gateway_rest_api.my_api.id
  resource_id   = aws_api_gateway_resource.my_resource.id
  http_method   = "GET"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "get_items_integration" {
  rest_api_id = aws_api_gateway_rest_api.my_api.id
  resource_id = aws_api_gateway_resource.my_resource.id
  http_method = aws_api_gateway_method.get_items.http_method
  type        = "MOCK" # 例としてMOCK integrationを使用
  request_templates = {
    "application/json" = "{}"
  }
}

resource "aws_api_gateway_deployment" "my_api_deployment" {
  rest_api_id = aws_api_gateway_rest_api.my_api.id
  triggers = {
    redeployment = sha1(jsonencode(aws_api_gateway_rest_api.my_api.body))
  }
  lifecycle {
    create_before_destroy = true
  }
}

# API Gatewayキャッシュ暗号化用のKMSカスタマー管理キー (CMK)
resource "aws_kms_key" "apigw_cmk" {
  description             = "KMS key for API Gateway cache encryption"
  deletion_window_in_days = 10
  enable_key_rotation     = true
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Sid    = "Enable IAM User Permissions",
        Effect = "Allow",
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
        },
        Action   = "kms:*",
        Resource = "*"
      },
      {
        Sid = "Allow API Gateway service to use the key"
        Effect = "Allow",
        Principal = {
          Service = "apigateway.amazonaws.com"
        },
        Action = [
          "kms:Encrypt",
          "kms:Decrypt",
          "kms:ReEncrypt*",
          "kms:GenerateDataKey*",
          "kms:DescribeKey"
        ],
        Resource = "*" # 特定のKMSキーARNに制限を推奨
      }
    ]
  })
  tags = {
    Name = "APIGW_CMK"
  }
}

# API Gateway ステージにキャッシュと暗号化を有効化
resource "aws_api_gateway_stage" "prod_stage" {
  deployment_id = aws_api_gateway_deployment.my_api_deployment.id
  rest_api_id   = aws_api_gateway_rest_api.my_api.id
  stage_name    = "prod"

  # キャッシュを有効化
  cache_cluster_enabled = true
  cache_cluster_size    = "0.5" # 0.5 GB, 1.6 GB, 6.1 GB, 13.5 GB, 28.4 GB, 58.2 GB, 118 GB, 237 GB

  # **重要: キャッシュデータを暗号化**
  cache_data_encrypted = true

  # **重要: 暗号化にカスタムKMSキーを指定**
  variables = { # cache_cluster_keyはvariablesではなく、直接ステージに設定
    # 例: "cache_cluster_key" = aws_kms_key.apigw_cmk.arn
  }

  # NOTE: Terraformのaws_api_gateway_stageリソースでは、
  # KMSキーの直接指定が`cache_cluster_key`パラメータとして存在しません。
  # `cache_data_encrypted`をtrueにすると、デフォルトで`aws/apigateway`キーが使用されます。
  # カスタムCMKを使用するには、AWSコンソールで手動で設定するか、
  # API GatewayのRest APIを直接操作するAPI呼び出し (カスタムリソースなど) が必要になる場合があります。
  # または、今後のTerraformプロバイダのアップデートを待つことになります。
  # 現状、Terraformで直接CMKを指定する方法は提供されていませんが、
  # `cache_data_encrypted = true`を有効にすることは強く推奨されます。

  tags = {
    Environment = "Production"
  }
}

# 現在のAWSアカウント情報を取得
data "aws_caller_identity" "current" {}

Terraformの現時点での制限事項に関する注意点:

上記のTerraformコードのコメントにも記載していますが、aws_api_gateway_stageリソースには、執筆時点(2025年7月)で、API Gatewayキャッシュの暗号化に使用するKMSキー(cache_cluster_keyに相当するもの)を直接指定するパラメータがありません。

cache_data_encrypted = true を設定すると、API GatewayはデフォルトでAWS管理キー(aws/apigateway)を使用してキャッシュデータを暗号化します。これはセキュリティを向上させますが、理想状態である「カスタマー管理キー以上のレベルで暗号化」をTerraformのみで直接実現することは難しいです。

この問題を回避するには、以下のいずれかを検討してください。

  1. デプロイ後にAWSコンソールで手動でKMSキーを変更する。
  2. Terraformのlocal-execプロビジョナーやLambdaカスタムリソースを使用してAWS CLIを呼び出し、ステージのキャッシュ設定を更新する。
    • これはより複雑であり、状態管理に注意が必要です。
    • 例: aws apigateway update-stage コマンドで patchOperations を使用して cacheClusterKey を更新する。

しかし、cache_data_encrypted = true を設定するだけでも、暗号化を有効にできるため、まずはこの設定を行うことを強く推奨します。

最後に

この記事では、Amazon API Gateway REST APIのキャッシュデータを保管時に暗号化することの重要性について解説しました。この設定は、キャッシュに一時的に保存される機密情報を保護し、不正アクセスやデータ漏洩のリスクを低減し、コンプライアンス要件を満たす上で不可欠です。 貴社のAPI Gateway REST APIのキャッシュデータは、保管時に暗号化されていますか?この機会にぜひ設定を確認・強化してみてください。 こちらの内容の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。運用が非常にラクに出来る製品になっていますのでぜひ興味がある方はお問い合わせお待ちしております。

最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。

この記事をシェアする

クラウドセキュリティ対策実践集一覧へ戻る

貴社の利用状況に合わせた見積もりを作成します。

料金プランを詳しく見る