AWS ELB Application Load Balancer にTLSクライアント認証(mTLS)のパススルーを構成する

ALBでTLSクライアント認証(mTLS)のパススルー構成を試した様子をご紹介します
2023.11.27

ども、大瀧です。
re:Inventがまだ始まっていないのにALBがmTLSをサポートする大型のアップデートが来ました。本ブログではパススルー構成をLambdaターゲットグループで試してみた様子をご紹介します。

設定方法

設定は非常にシンプルです。ALB作成ウィザードのHTTPSリスナー選択時に表示されるセキュアリスナーの設定に「クライアント証明書の処理」という項目が増えているので、「相互認証(mTLS)」のチェックをオンにすればOKです。

ALBのmTLS対応には二つの動作モード、「パススルー」と「トラストストアで検証」があります。「パススルー」はALBでクライアント証明書の検証はせず、転送するリクエストヘッダにクライアント証明書を付与してバックエンドターゲットでの検証を期待する動作、「トラストストアで検証」は ALB自身でクライアント証明書を評価する動作です。「トラストストアで検証」を選択すると、以下のように検証のための追加項目が表示されます。

今回は「パススルー」で構成し、以下のLambda関数でヘッダの様子を確認してみました。

import json

def lambda_handler(event, context):
	response = {
		"statusCode": 200,
		"statusDescription": "200 OK",
		"isBase64Encoded": False,
		"headers": {
			"Content-Type": "text/html; charset=utf-8"
	    }
	}

	response['body'] = json.dumps(event, sort_keys=True, indent=4)
	return response

動作確認

では、cURLで試してみます。まずはクライアント証明書なしの場合です。

% curl https://cm.takipone.com/
{
    "body": "",
    "headers": {
        "accept": "*/*",
        "host": "xxxxx.takipone.com",
        "user-agent": "curl/8.0.1",
        "x-amzn-trace-id": "Root=1-6563d9a1-3a0f42f17a3068b93bbe9a7d",
        "x-forwarded-for": "XX.XX.XX.XX",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "httpMethod": "GET",
    "isBase64Encoded": false,
    "path": "/",
    "queryStringParameters": {},
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lambdatg/f3ba8729fd3eee3c"
        }
    }
}%

クライアント証明書なしの場合はヘッダが付与されない形でLambdaバックエンドにリクエストを転送、Lambda関数によるレスポンスが返答されました。パススルーモードではクライアント証明書なしでもバックエンドターゲットにリクエストが転送されるという動作は、アクセス制限の用途でクライアント認証を利用する場合は注意が必要そうです。バックエンドターゲット側できちんとヘッダの有無を検証し、後述のヘッダが無い場合はレスポンスを403にするなど適切な実装を検討しましょう。

続いてクライアント証明書を付与するリクエストです。

% curl --key private.pem --cert cert.pem https://cm.takipone.com/
{
    "body": "",
    "headers": {
        "accept": "*/*",
        "host": "xxxx.takipone.com",
        "user-agent": "curl/8.0.1",
        "x-amzn-mtls-clientcert": "-----BEGIN%20CERTIFICATE-----%0AMIIDxzCCAq+gAwIBAgIUMVXQbAhxFl76vBeniFTKWumTwHgwDQYJKoZIhvcNAQEL%0ABQAwGTEXMBUGA1UEAxMObXktd2Vic2l0ZS5jb20wHhcNMjMxMTI2MjMyMzA1WhcN%0AMjMxMTI5MjMyMzM1WjAdMRswGQxxxxx(略)xxxxxxxxxxxxx%0A-----END%20CERTIFICATE-----%0A",
        "x-amzn-trace-id": "Root=1-6563d68c-5a9446ea6b7bfae57f42210c",
        "x-forwarded-for": "XX.XX.XX.XX",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "httpMethod": "GET",
    "isBase64Encoded": false,
    "path": "/",
    "queryStringParameters": {},
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lambdatg/f3ba8729fd3eee3c"
        }
    }
}%

x-amzn-mtls-clientcertヘッダにクライアント証明書が付与されていることが確認できました。バックエンドではこれを評価すればOKですね。

まとめ

ALBでTLSクライアント認証(mTLS)のパススルー構成を試した様子をご紹介しました。ALBの認証方式の最後のミッシングピースが埋まった感じがして感慨深いです。ガンガン活用していきましょう!