上級 20分 Lesson 22

Lambda & API Gateway — サーバーレスのセキュリティ勘所

Lambda実行ロール、API Gateway認証3方式、mTLSを講義形式で解説

AWS Lambda API Gateway SCS-C03 Security

みなさん、おはようございます。今日は、サーバーレスのセキュリティについてお話しします。

サーバーレスアーキテクチャ(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 の中で実行するです。

具体的には——

  1. Lambda を VPC の subnet に配置
  2. その subnet にも RDS と同じ VPC に属させる
  3. そうすると、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 でセキュリティを実装するなら——

  1. Lambda ロール:関数ごとに最小権限を徹底
  2. VPC Lambda:RDS などプライベートリソースへのアクセスは VPC 内から
  3. 認証方式の選択:
    • 社内 ↔ IAM
    • ユーザー ↔ Cognito
    • カスタム ↔ Lambda オーソライザー
  4. API キーは使うな:認証に使わない。レート制限のみ。
  5. 環境変数の暗号化:Lambda の環境変数は KMS で暗号化
  6. ログの最小化:リクエスト/ レスポンスボディに機密情報を含まない

これらが——全部統合されるとき——

サーバーレスアーキテクチャも、完全にセキュアになるわけです。

では、最後のテーマに行きましょう。