はじめに
re:invent2023でALBがmTLS認証をサポートすることが発表されました。
Application Load Balancer での TLS を使用した相互認証
ALBのmTLS認証を実装し、mTLS認証のログを出力する場合は、以下3点を実装する必要があります。
- CA証明書をトラストストアにあげる
- ALB Listenerの設定
- Connections Logsの有効化
※Connections Logsの有効化は必須ではありません
今回は、CDKを用いたALBのmTLS認証の実装を上記3つのポイントに分けてご紹介させて頂きます。
※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。
CA証明書をトラストストアにあげる
ALBのListenerでmTLS認証を有効化するために、検証先としてトラストストアを指定します。
そのために、CA証明書が格納されたトラストストアを作成する必要があります。
このトラストストアを作成するために以下3ステップ踏む必要があります。
- CA証明書格納用のS3バケットの作成
- 作成したCA証明書格納用のS3バケットにCA証明書を格納
- CA証明書格納用のS3バケットをCA証明書のソースとしたトラストストアを作成
それぞれのパーツでサンプルと共にご紹介します。
CA証明書格納用のS3バケットの作成
これは普通にS3バケットを作成すれば大丈夫です。
const myCertBucket = new s3.Bucket(this, "certBucket", {
bucketName: `cert-bucket-hogehoge`,
enforceSSL: true,
autoDeleteObjects: true,
encryption: s3.BucketEncryption.S3_MANAGED,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
CA証明書格納用のS3バケットをCA証明書のソースとしたトラストストアを作成
S3にCA証明書を上げるのには、BucketDeployment Constructsを使用します。
このConstructsを利用するとCDK実行環境にあるファイルをDeployプロセスの中でアップロードしてくれます。
const caCertupload = new s3deploy.BucketDeployment(this, "caCertupload", {
sources:[
s3deploy.Source.data(
"CA_cert.pem",
fs.readFileSync(path.join(__dirname, "../../ssl/CA_cert.pem"), "utf8")
),
],
destinationBucket: myCertBucket,
});
sourcesのところでS3にアップロードするファイルを指定しています。
s3deploy.Source.data()の第一引数でS3に配置する際のObject名を指定しています。
第二引数では、アップロードしたいファイルのローカル格納先を指定しています。
ここでは、Node.jsのfsとpathモジュールを活用しています。
path.join(__dirname, "../../ssl/CA_cert.pem")
__dirnameはこのコードが配置されているディレクトリパスとなります。ここからの相対パスとして、 ../../ssl/CA_cert.pemを結合し、最終的なファイルパスを生成しています。
fs.readFileSync(path, "utf8")
ファイルをutf8形式でテキストとして読み込んでいます。
CA証明書のソースをCA証明書格納用のS3バケットとしてトラストストアを作成
トラストストアは現在L1のみ提供されているため、L1 Constructsを利用します。
CDK Constructsに関して
const trustStore = new elb.CfnTrustStore(this, "cATrustStore",{
caCertificatesBundleS3Bucket: caCert.deployedBucket.bucketName,
caCertificatesBundleS3Key: "cA_cert.pem",
name :"CA-trust-store"
});
CA証明書の格納されているS3をソースバケットとして、アップロードした際のobject名をkeyとして指定します。
以上で、「CA証明書をトラストストアにあげる」部分は完了です。
ALB Listenerの設定
mTLS認証の有効化は、Listener毎に行います。
そのうえで、現在mTLS認証の設定は、L1 Constructsのみの提供となります。
そのため、L2で作成したListenerをエスケープハッチで追加設定をしてきます。
設定には、以下2ステップを踏む必要があります。
- ALB Listenerの作成
- 作成したListenerにエスケープハッチで追加設定
それぞれのパーツでサンプルと共にご紹介します。
ALB Listenerの作成
これは普通にListenerを作成すれば大丈夫です。
今回のサンプルでは、前段にALBを構成していたため、addListener Methodを利用しています。
const sListener = alb.addListener("HttpsListener",{
port: 443,
protocol: elb.ApplicationProtocol.HTTPS,
certificates: [acmCert],
sslPolicy: cdk.aws_elasticloadbalancingv2.SslPolicy.RECOMMENDED_TLS,
defaultTargetGroups: [fargateTG],
});
作成したListenerにエスケープハッチで追加設定
L2の「ApplicationListener」では現状mTLSに関連する設定はありません。
そのため、作成したListenerからL1 Constructsを取り出し(エスケープハッチ)、追加設定する必要があります。
const cfnSListener = sListener.node.defaultChild as elb.CfnListener;
cfnSListener.mutualAuthentication = {
ignoreClientCertificateExpiry: true,
mode: "verify",
trustStoreArn: trustStore.ref,
};
const cfnSLister = sListener.node.defaultChild as elb.CfnListener;
ListenerのdefaultchildをCfnListenerとして、取り出します。
これでL1 ConstructsのCfnListenerを活用出来ます。
cfnSLister.mutualAuthentication
CfnListenerのmutualAuthenticationを設定し、mTLS認証を実装します。
トラストストアは、L1 Constructsで作っているため、trustStoreArnはClouFormationのRef関数経由で設定します。
以上で、「ALB Listenerの設定」部分は完了です。
Connections Logsの有効化
必須ではありませんが、クライアント認証ログは欲しいですよね。
そのためのログが、Connections Logsです。
Connection LogsはALBの属性を編集することにより、実装されます。
ログの配信先も必要なので、以下2ステップを踏む必要があります。
- Conndection Logs配信先バケットの作成
- ALB属性の追加
それぞれのパーツでサンプルと共にご紹介します。
Conndection Logs配信先バケットの作成
これは普通にS3バケットを作成すれば大丈夫です。
const albConnectionLogBucket = new s3.Bucket(this, "albConnectionLogBucket", {
bucketName: `alb-connectionlog-bucket-hogehoge`,
enforceSSL: true,
autoDeleteObjects: true,
encryption: s3.BucketEncryption.S3_MANAGED,
objectLockEnabled: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
ALB属性の追加
追加する必要のある属性は以下3種類です。
Key | Value |
---|---|
connection_logs.s3.enabled | true |
connection_logs.s3.bucket | Conndection Logs配信先バケット名 |
connection_logs.s3.prefix | prefix |
interface connnectionLogSet {
Key: string,
Value: string
};
const connnectionLogSets:connnectionLogSet[] = [
{Key: "connection_logs.s3.enabled", Value: "true"},
{Key: "connection_logs.s3.bucket", Value: albConnectionLogBucket.bucketName},
{Key: "connection_logs.s3.prefix", Value: "hoge"}
];
connnectionLogSets.forEach((param) => {
alb.setAttribute(param.Key, param.Value)
});
ALBの属性追加は、ALBのsetAttribute Methodを利用しています。
以上で、「Connections Logsの有効化」部分は完了です。
まとめ
ALBのmTLS認証はリリースされてから日が浅いこともあり、CDKでの実装はちょっとめんどくさいです。
トラストストア作成したり、L1 CfnListenerを使う必要があったり、ALBの属性いじったり。。。
Constructsなり、Methodなり早めにリリースされることを祈ります。
直近で、ALBのmTLS認証の実装をご検討の方は参考にして頂けると幸いです。
※ 本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。