はじめに
Amazon Cognitoでユーザー登録後、Lambda関数からFargateで動作するバックエンドAPIへユーザー情報を登録する構成について、セキュリティ上の課題と対策を解説します。
現状の構成
-
システムの基本フロー
・Cognitoでユーザーが新規登録を行う
・Lambda関数が起動し、test.jp/user
へPOSTリクエストを送信
・ALBがリクエストを受け付け、Fargateのコンテナへ転送
・FargateのコンテナでユーザーデータをDBへ登録 -
要件の矛盾
・アプリケーションからALBへのアクセスを許可する必要がある
・同時に、POST処理はLambdaからのみ許可したい
・ALBのインバウンドルールを0.0.0.0/0
にする必要があるが、それではセキュリティ上の問題が発生 -
セキュリティ上の課題(POSTリクエスト: test.jp/user)
・アプリケーションユーザーからのアクセスを維持しつつ、POST処理は制限したい
・Lambda以外からのPOSTリクエストを防ぐ必要がある
・通常の認証機構が使用できない(ユーザー登録時のため)
解決アプローチ
これらの課題に対して、以下の2つのアプローチで対策を実装します
-
グローバルIPアドレスによる制限
・Lambda関数からのリクエスト送信元IPを固定化
・WAF、あるいはバックエンド側で特定のパスやメソッドに対してIPベースのアクセス制御を実装 -
カスタムヘッダーによる制御
・Lambda関数からのリクエストに特別なヘッダーを付与
・WAF、あるいはバックエンド側でヘッダーの検証を実装
・アプリケーションからの通常アクセスとLambdaからのPOSTリクエストを区別
これにより、アプリケーションの一般的なアクセスを維持しながら、特定の処理(ユーザー登録後のPOST処理)のみを安全に制限することが可能となります。
グローバルIPアドレス
Lambda関数からAPIを実行する際、送信元IPアドレスを固定することで、適切なセキュリティ制御を実装できます。
グローバルIPの固定により、バックエンド側で制限をかける方法
アプローチの概要
- Lambda関数をVPC内に配置
- NAT Gatewayを使用してグローバルIPを固定
- WAF、あるいはバックエンド側で、IPからのみアクセスを許可
カスタムヘッダーによる制御
カスタムヘッダーは、HTTPリクエストに独自の識別情報を付加する仕組みです。Lambda関数から送信される特定のリクエストのみを許可するため、事前に定義したランダムな文字列をヘッダー値として使用します。
API実行時に、カスタムヘッダーを追加して制御する方法
アプローチの概要
- Lambda関数からのリクエスト時に、事前に定義したランダム値をヘッダーに付与
- WAF あるいはバックエンド側で、そのランダム値を持つリクエストのみを許可
制御例
- ヘッダー名:
X-Custom-Auth
- ヘッダー値:事前に生成した32文字のランダム文字列(例:
a1b2c3d4e5f6g7h8i9j0...
) - WAFまたはバックエンド側で、このヘッダーと値の組み合わせが一致する場合のみ処理を許可
まとめ
未認証状態でのAPI実行におけるセキュリティ制御には、reCAPTCHAなど、様々な方法が存在しますが、今回は以下の2つのアプローチを紹介しました
-
グローバルIPアドレスの固定
・Lambda関数をVPC内に配置し、NAT Gatewayを使用
・特定のIPからのアクセスのみを許可することで、不正アクセスを防止 -
カスタムヘッダーによる制御
・事前定義したランダム値をヘッダーに付与
・WAFまたはバックエンド側での検証により、正規のリクエストのみを許可
これらの方法を組み合わせることで、アプリケーションの一般利用を妨げることなく、特定のAPIエンドポイントに対するセキュリティを強化することができます。