[2023/11/26 AWSアップデート]ALBでmTLSを試してみた

## はじめに
### 背景・本記事の目的
- 2023年11月26日のアップデートにより、ALBがmTLSをサポートするようになりました!
- 自己署名証明書及びALBでのmTLSについて、構築及び動作確認してみようと思います。

### 対象読者
- ALBをはじめとしたAWSネットワーク系サービスや、mTLSの概要を理解している方を対象読者として想定しています。


## やってみた
### CA証明書の生成
- opensslコマンドを用いて、CA証明書を生成します。
```bash
# 秘密鍵の生成
openssl genrsa -out rootCA.key 2048
# CA証明書の生成
openssl req -x509 -new -nodes \
    -key rootCA.key \
    -sha256 \
    -days 3650 \
    -out rootCA.pem
```
- AWSコンソールを用いて、生成したCA証明書をAmazon S3に格納します。


### クライアント証明書の生成
- X.509 v3証明書を生成するために、`v3_req.txt`ファイルを作成します。[^1]
```text
extendedKeyUsage = serverAuth, clientAuth, codeSigning, emailProtection
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
```
[^1]: クライアント証明書のVersionが3でないと`Failed:ClientCertTypeUnsupported`エラーが発生するなど、試行錯誤しながらの構築・執筆でした。これらの試行錯誤については、別途記事執筆予定です。

- opensslコマンドを用いて、クライアント証明書を生成します。
```bash
# 秘密鍵の生成
openssl genrsa -out client.key 2048

# CSRの生成
openssl req -new \
    -key client.key \
    -out clientCA.csr

# クライアント証明書の生成
openssl x509 -req\
    -in clientCA.csr \
    -CA rootCA.pem \
    -CAkey rootCA.key \
    -CAcreateserial \
    -out clientCert.pem \
    -days 3650 \
    -sha256 \
    -extfile v3_req.txt
```

### ALBターゲットとなるLambda関数の作成
- AWSコンソールを用いて、単純なレスポンスを返却するだけのLambda関数を作成します。
```python
import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps('mTLS Success!!!')
    }

```

### ACMの作成
- AWSコンソールを用いて、ALBにひも付けるパブリック証明書をリクエストします。

### ALBの作成・mTLS設定
- AWS CLIを用いて、ロードバランサー、トラストストア、リスナー、ターゲットグループを作成します。
```bash
# ロードバランサー作成
aws elbv2 create-load-balancer --name poc-alb-mtls  \
--subnets <albを配置するサブネット1> <albを配置するサブネット2> --security-groups <セキュリティグループ>

# ターゲットグループ作成
aws elbv2 create-target-group \
    --name poc-alb-tg-mtls \
    --target-type lambda

# ALBがLambdaを呼び出すための権限設定
aws lambda add-permission \
    --function-name <Lambda関数名> \
    --statement-id load-balancer \
    --principal elasticloadbalancing.amazonaws.com \
    --action lambda:InvokeFunction \
    --source-arn <ターゲットグループのARN>

# ターゲットグループにLambdaを登録
aws elbv2 register-targets \ 
    --target-group-arn <ターゲットグループのARN> \ 
    --targets Id=<LambdaのARN>

# トラストストア作成
aws elbv2 create-trust-store --name poc-trust-store \
    --ca-certificates-bundle-s3-bucket poc-s3-mtls01 \
    --ca-certificates-bundle-s3-key rootCA.pem \
    --ca-certificates-bundle-s3-object-version <CA証明書のS3バージョン>

# リスナー作成
aws elbv2 create-listener --load-balancer-arn <value> \
    --protocol HTTPS \
    --port 443 \
    --certificates CertificateArn=<ACMのARN> \
    --mutual-authentication Mode=verify,
      TrustStoreArn=<トラストストアのARN>　\
    --default-actions Type=forward,TargetGroupArn=<ターゲットグループのARN>
```

### Route53の設定
- AWSコンソールを用いて、ALBにA(エイリアス)レコードを設定します。


## 動作確認
- 秘密鍵及びクライアント証明書を用いて、無事mTLSに成功しました！
```bash
# 秘密鍵及びクライアント証明書を指定してアクセスした場合、正常にレスポンス返却される
curl --key client.key --cert clientCert.pem https://<ALBのカスタムドメイン>
"mTLS Success!!!"

# 何も指定せずアクセスした場合、エラー返却される
curl https://<ALBのカスタムドメイン>
"curl: (35) LibreSSL SSL_connect: Connection reset by peer in connection to"
```


## 参考資料
- [Mutual authentication for Application Load Balancer reliably verifies certificate-based client identities](https://aws.amazon.com/jp/blogs/aws/mutual-authentication-for-application-load-balancer-to-reliably-verify-certificate-based-client-identities/)
- [AWS CLI を使用して、Lambda 関数を Application Load Balancer の背後にあるターゲットとして登録する方法を教えてください。
](https://repost.aws/ja/knowledge-center/elb-register-lambda-as-target-behind-alb)
- [チュートリアル: AWS CLI を使用した Application Load Balancer の作成](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/tutorial-application-load-balancer-cli.html)
- [証明書に x509v3 拡張属性を追加する](https://access.redhat.com/ja/solutions/2586691)

## 注意事項
- 本記事は万全を期して作成していますが、お気づきの点がありましたら、ご連絡よろしくお願いします。
- なお、本記事の内容を利用した結果及び影響について、筆者は一切の責任を負いませんので、予めご了承ください。