8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS WAFでLambdaからのアクセスを制御してみた!

Last updated at Posted at 2025-12-15

はじめに

WAFでLambdaからのアクセス制御を行ったことはありますか?

WAFでのアクセス制御といえば、IPアドレスやAWSが提供するマネージドルールを使用することが多いかと思います。

しかし、LambdaのIPアドレスは固定ではなく動的であり、そのIPレンジは非常に広範囲です。
そのため、 Lambdaからのアクセス制限をIPベースで行うことはほぼ不可能 です。

そこで、 今回は カスタムヘッダーを利用して、特定のLambdaからのアクセスだけに制限 してみました!

実際にどんな場面で使用したか

つい最近まで、CognitoはVPCエンドポイントに対応しておりませんでした。
そのため、プライベートな環境からインターネットを経由せずCognitoにアクセスするためには、CognitoのProxyのような役割を果たすLambdaを作成し、API Gatewayから呼び出すことで、Cognitoへのアクセスを行っていました。
そのため、CognitoのWAFで、前段のLambdaからのアクセスだけに絞りたかったのです。

image.png

現在はCognitoのVPCエンドポイントがサポート開始されておりますので、上記のような迂回構成は不要になるかと思います。
アップデート情報:Amazon Cognito ユーザープールが AWS PrivateLink とのプライベート接続のサポートを開始(2025/11/7)
https://aws.amazon.com/jp/about-aws/whats-new/2025/11/amazon-cognito-user-pools-private-connectivity-aws-privatelink/

実装

早速、実装に入っていきたいと思います!

①Parameter Store

Lambdaのカスタムヘッダーの値は、WAFで許可/拒否の判定に使用するため、言ってしまえば 「鍵」 のようなものになります。
そのため、カスタムヘッダーの値はLambdaのコードに直接記載するのではなく、Parameter Storeで保管するようにします。

カスタムヘッダーの値の取り扱いには十分注意してください。
必要に応じて、SecretManagerを使用してください。

Parameter Storeに/test/lambdaを作成し、[test123]という値を保存します。

image.png

②Lambda

次に、LambdaのコードでParameter Storeから文字列(test123)を取得して、カスタムヘッダー(x-lambda-auth)に埋め込みます。
get_parameterという関数を作成して、Parameter Storeから値を取り出しています。

index.py
ssm = boto3.client("ssm")

def get_parameter(name: str) -> str:
    resp = ssm.get_parameter(Name=name, WithDecryption=True)
    return resp["Parameter"]["Value"]

def lambda_handler(event, context):
    token = None
    try:
        token = get_parameter("/test/lambda")
    except Exception as e:
        print(f"warn: failed to load token from parameter store: {e}")

    headers = {
        "User-Agent": "waf-checker/1.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    }
    if token:
        headers["x-lambda-auth"] = token

LambdaのIAMロールにParameter Storeの"ssm:GetParameter"の権限を付与しておきます。

{
    "Statement": [
        {
            "Action": [
                "ssm:GetParameter"
            ],
            "Effect": "Allow",
            "Resource": <Parameter StoreのARN>
        }
    ],
    "Version": "2012-10-17"
}

③WAF

WAFでは、「AllowLambdaHeader」というルールを作成し、x-lambda-authヘッダーが[test123]と完全に一致した場合にALLOWするように設定します。

image.png

ここで、忘れてはいけないのは デフォルトアクションをBLOCKにする ことです。
私がコンソールから作成した際には、デフォルトでデフォルトアクションがALLOWになっていました。
本来はヘッダーが一致すればALLOW、一致しなければBLOCKとなるはずが、デフォルトアクションをALLOWにすると、WAFルールが意味をなさず全てのアクセスが通過してしまいます。

image.png

アクセス確認

Lambdaを実行して、WAFで許可されるのか確認してみます。

WAFのログを確認すると、「AllowLambdaHeader」のルールでALLOWされていることが分かります!
image.png

試しに、以下のようにヘッダーに誤った値("xxxxxxxxx")を入れて実行してみると、
image.png

しっかりデフォルトアクションでBLOCKされます!
image.png

セキュリティ上の注意

セキュリティを強化する上では、以下のことに注意してください。

  • カスタムヘッダーの値は秘密情報として扱い、コードに直接書かず Parameter Store や Secrets Manager を利用する
  • WAF のデフォルトアクションは BLOCK に設定する
  • カスタムヘッダーの値がログに出力される可能性があるため、ログの取り扱いにも注意する

また、本記事の内容を実装する際は、必ず最新の公式ドキュメントを確認し、セキュリティリスクを十分に理解した上で対応してください。

まとめ

今回は、WAFでLambdaのアクセス制御を行いました。
特に、カスタムヘッダーを利用したWAFルールは、Lambdaに限らず活用機会があると思いますので、参考にしていただけたら嬉しいです!

We Are Hiring!

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?