Lambda & API Gateway — サーバーレスのセキュリティ勘所
Lambda実行ロール、API Gateway認証3方式、mTLSを講義形式で解説
みなさん、おはようございます。今日は、サーバーレスのセキュリティについてお話しします。
サーバーレスアーキテクチャ(Lambda、API Gateway)と聞くと、「簡単にスケールする」「サーバー管理が不要」というイメージを持つ人が多いでしょう。ですが、セキュリティの観点からは、かなり気をつけるべき点があります。
理由は単純です。サーバーレスは「手軽」だからこそ、セキュリティを後回しにしやすいのです。最小権限の原則が軽視されたり、API Gateway での認証設定が曖昧になったり、環境変数に秘密情報が平文で保存されたり。こうした落とし穴に対応することが重要です。
Lambda 実行ロール — 「関数ごとの最小権限の徹底」
Lambda でコードを実行するには IAM ロールが必要です。ですが、ここで落ちやすいパターンがあります。
多くの開発者が「Lambda 関数を作った。では、全ての AWS リソースにアクセスできるロールをアタッチしよう」と考えてしまいます。理由は「細かいポリシー設定は面倒。とりあえず全部アクセスさせちゃえ」という安易な判断です。
ですが、これは極めて危険です。もしその Lambda 関数が侵害された場合、攻撃者は「全ての AWS リソースにアクセスできるロール」を持つことになります。結果として、すべてのデータが盗まれたり、削除されたり、改ざんされたりする可能性があります。
実務では、Lambda ロールは「関数が本当に必要な権限だけ」に限定すべきです。例えば、S3 から JSON を読み込んで DynamoDB に結果を書き込む関数なら、s3:GetObject と dynamodb:PutItem だけを特定のリソースに対して許可する形です。これにより、関数が侵害されても被害を限定できます。
実装例
では、具体的に。
あなたが Lambda 関数を作りました。
それが: S3 から JSON ファイルを読む DynamoDB に処理結果を書く
——ならば、ロールには——
JSON形式のIAMポリシーで、S3のmy-bucketのinputフォルダ配下に対するGetObjectアクション、およびDynamoDBのResultsテーブルに対するPutItemアクションだけを許可するという内容です。
「GetObject」だけ。「PutItem」だけ。他のアクションは禁止。
バケットも特定。テーブルも特定。
この関数が侵害されても——できることは限定的なわけです。
最小権限 = 関数ごとに、必要なアクション・リソース・条件を徹底的に絞る。
VPC Lambda — 「プライベート環境での実行」
では、別のシナリオを考えてください。
あなたの Lambda 関数が——RDS データベースにアクセスする必要があるとします。
RDS は普通——VPC の private subnet にあります。
では、Lambda からどうアクセスするのか?
VPC 外での実行(従来)
Lambda は——デフォルトでは VPC の外(AWS managed VPC)で実行されます。
つまり——VPC の private subnet にある RDS には、直接アクセスできないわけです。
では、どうするか?
Option 1: RDS をパブリック公開
RDS にパブリック IP を付与して、インターネット経由でアクセス。
でもね——これ、セキュリティ的には最悪です。
RDS が世界に公開されちゃう。誰でも攻撃できる。
Option 2: NAT Gateway
Lambda 関数が使っている VPC に NAT Gateway を配置。
Lambda からの通信が NAT Gateway 経由で——インターネットに出て——それからプライベートネットワークを通じて RDS に戻る。
これは技術的には成立するんですけど——NAT Gateway はお金がかかります。
VPC Lambda(推奨)
では、推奨される方法は——
Lambda を VPC の中で実行するです。
具体的には——
- Lambda を VPC の subnet に配置
- その subnet にも RDS と同じ VPC に属させる
- そうすると、Lambda は VPC 内部ネットワークで RDS にアクセス可能
——こうするわけです。
ただし——ちょっと気をつけることがあります。
冷却スタート(Cold Start)の遅延:
VPC Lambda は、Lambda を VPC に接続するネットワークインターフェースを作成する必要があるから——VPC なしの Lambda より、起動が遅いんです。
でも——セキュリティ(プライベート通信)> 性能(Cold Start の 1 秒遅延)という場合がほとんどなので——VPC Lambda が推奨されます。
VPC Lambda = 最小権限 + プライベート通信。本番では必須。
API Gateway 認証 — 「3 つの方式を使い分ける」
では、次のテーマ。
Lambda をインターネットに公開するとき——どうするか?
API Gateway を入れます。
API Gateway は、HTTP(S)リクエストを受け付けて——Lambda に転送する仲介役です。
では、API Gateway でね——どのリクエストを許可して、どのリクエストを拒否するか?
認証(Authentication)と認可(Authorization)が必要です。
API Gateway では——3 つの主要な認証方式があります。
方式 1: IAM 認証
API Gateway のエンドポイントに対して——IAM ロールを持つ人 / サービスだけがアクセスできるようにする。
例えば——社内システム同士の通信。
「メールシステム → 通知システム」
みたいなね、AWS 内部での通信の場合に使います。
リクエストに AWS Signature Version 4(AWS4-HMAC-SHA256)という署名を付けることで——リクエストが改ざんされていないことを保証します。
方式 2: Cognito
Amazon Cognito は、ユーザー認証・認可を管理するサービスです。
例えば——Web アプリケーション。
ユーザーが「Gmail でログイン」とかね——ソーシャルログインで認証される。
Cognito がそのトークンを検証して——API Gateway を通す。
このやり方の利点は——ユーザー管理を Cognito に任せられることです。
パスワード忘れ、2 要素認証、ソーシャルログイン——全部、Cognito が仲介してくれる。
Lambda 側では——「このリクエストは認証済み」という情報だけ受け取ればいい。
Cognito 認証 = ユーザー向け。B2C アプリケーション向け。
方式 3: Lambda オーソライザー
では、「IAM でもなく、Cognito でもない、カスタム認証ロジックがしたい」——という場合は?
Lambda オーソライザー(従来は「カスタムオーソライザー」)です。
これはね——API Gateway が——Lambda オーソライザー関数を呼んで——「このリクエスト、許可しますか?」って聞くわけです。
Lambda オーソライザーは——リクエストを受け取って——
リクエストを検査する トークンを検証する カスタムロジックを実行する 「許可」「拒否」を返す
例えば——
API Gatewayが/api/ordersへのリクエストを受けて、Lambda オーソライザーを呼び出します。オーソライザーがAutorizationヘッダーのトークンを検証し、トークンが有効なら許可、無効なら拒否を返すという流れです。
どれを使う?
では、実務的には——どれを選ぶべきか?
社内システム間通信:IAM 認証 ユーザー向け Web アプリケーション:Cognito 独自の認証ロジック(例:API キー検証):Lambda オーソライザー
3 つの方式 = ユースケースに応じて使い分ける。
よくある落とし穴:「API キーは認証ではない」
ここで——非常に重要な警告があります。
API Gateway に「API キー」を設定できます。
「あ、API キーで認証完了」——って思う人が——いるんです。
それは間違いです。
API キー は——“rate limiting”(リクエスト制限)のための仕組みであって——認証ではありません。
なぜなら——API キーは——URL に埋め込まれたり、ログに表示されたり——暗号化されずに平文で流れることがあるからです。
つまり——API キーを盗まれたら——誰でもあなたの API にアクセスできるわけです。
API キー ≠ 認証。単なるレート制限の仕組み。認証には IAM / Cognito / Lambda オーソライザーを使う。
mTLS(相互 TLS)— 「証明書による認証」
では、最後に。
API Gateway の上位レイヤーでの認証。
mTLS(Mutual TLS)です。
通常の HTTPS は——サーバーが証明書を持ってます。
「あ、あなたは example.com ですね」——ブラウザがサーバーを検証する。
でも mTLS は——サーバーも、クライアントも——両方が証明書を持ちます。
クライアントがサーバーに接続し、サーバーがクライアントに証明書を求めます。クライアントが証明書を提示し、サーバーがそれを検証して接続を許可するという流れです。
API Gateway での mTLS
API Gateway では、CloudFront の mTLS 機能と組み合わせることで——クライアント証明書の検証ができます。
例えば——
「この API は、特定の企業パートナーだけが呼べる」
——という要件があるとき。
パートナー企業のクライアント証明書を指定して——その証明書を持つクライアントだけからのリクエストを許可。
mTLS = 証明書ベースの相互認証。B2B API 向け。
実務的なセキュリティ設定チェックリスト
では、まとめます。
Lambda + API Gateway でセキュリティを実装するなら——
- Lambda ロール:関数ごとに最小権限を徹底
- VPC Lambda:RDS などプライベートリソースへのアクセスは VPC 内から
- 認証方式の選択:
- 社内 ↔ IAM
- ユーザー ↔ Cognito
- カスタム ↔ Lambda オーソライザー
- API キーは使うな:認証に使わない。レート制限のみ。
- 環境変数の暗号化:Lambda の環境変数は KMS で暗号化
- ログの最小化:リクエスト/ レスポンスボディに機密情報を含まない
これらが——全部統合されるとき——
サーバーレスアーキテクチャも、完全にセキュアになるわけです。
では、最後のテーマに行きましょう。