こんにちは、インフラエンジニアのさかもとです。
通常、ACM で発行したパブリック証明書*1を利用するには EC2 の前段に ELB あるいは CloudFront ディストリビューションを構築しそれらに適用する必要があります。
しかし、AWS Certificate Manager (ACM) for Nitro Enclaves を利用すれば ACM で発行したパブリック/プライベート証明書を EC2 で利用することができます。
ACM for Nitro Enclaves は AWS Nitro Enclaves に対応したインスタンスしかサポートされませんが、可用性をあまり求められないシステムなどで TLS を終端するためだけに ELB、CloudFront を構築する必要がないのは嬉しいですよね。
今回 Amazon Linux 2023 + Nginx 構成において ACM for Nitro Enclaves を利用する際にハマった点があったので、導入手順を紹介したいと思います。参考になれば幸いです。
前提条件
ACM for Nitro Enclaves を利用するには以下の条件*2があります。(2024年3月11日時点)
- RSA 証明書のみ
- AWS Nitro Enclaves をサポート(※)する Linux インスタンスのみ
- Asia Pacific (Osaka) and Asia Pacific (Jakarta) はサポート外
※ AWS Nitro Enclaves をサポートするインスタンスは以下を参照ください。
https://docs.aws.amazon.com/ja_jp/enclaves/latest/user/nitro-enclave.html#nitro-enclave-reqs
導入手順
基本は以下 AWS 公式ドキュメントを参考に実施していきます。
docs.aws.amazon.com
ACM 証明書の作成
ACM 証明書の作成手順は割愛いたします。以下を参照してください。
docs.aws.amazon.com
なお、EC2 を構築するリージョンと同じリージョンに作成する必要があるのでご留意ください。
IAM Policy および IAM Role の作成
構築する EC2 に以下操作を許可するための IAM Policy を作成します。
- ACM 証明書に IAM Role を紐付ける権限
- IAM Role にインラインポリシーを登録する権限
{region}
および {account_id}
は自身の環境のものに置き換えてください。
{ "Version": "2012-10-17", "Statement": [ { "Action": "ec2:AssociateEnclaveCertificateIamRole", "Resource": [ "arn:aws:acm:{region}:{account_id}:certificate/*", "arn:aws:iam::{account_id}:role/*" ], "Effect": "Allow" }, { "Action": "iam:PutRolePolicy", "Resource": "arn:aws:iam::{account_id}:role/*", "Effect": "Allow" } ] }
別途 IAM Role を作成し、上記 IAM Policy をアタッチしてください。
なお、こちらの IAM Policy は一連の作業が終われば不要となりますので後ほどデタッチ、削除します。
EIP の払い出し、および DNS 登録
グローバル IP を固定化するため Elastic IP アドレス (EIP) を払い出します。
また ACM 証明書を取得したドメイン名で名前解決ができるよう DNS A レコードの設定をします。
手順については割愛いたします。
EC2 の作成
EC2 は前提条件を満たすインスタンスタイプを選択し、[高度な詳細] から Nitro Enclaves*3 の有効化、また IAM Role の割り当てをします。
SecurityGroup は セットアップを行うための SSH、および外部から動作確認をするための HTTPS を開放しておきます。
項目 | 内容 | 備考 |
---|---|---|
AMI | Amazon Linux 2023 (2023.3.20240304.0 arm64 HVM kernel-6.1) | C6g インスタンスを利用するためアーキテクチャは Arm を選択 |
インスタンスタイプ | c6g.large | 2vCPU, 4 GiB メモリ |
VPC/サブネット | ※パブリックサブネットを選択 | |
SecurityGroup | ※ セットアップを行う環境からの SSH および動作確認用の HTTPS を開放したもの | |
IAM インスタンスプロフィール | ※作成した IAM Role | [高度な詳細] で設定 |
Nitro Enclave | 有効化 | [高度な詳細] で設定 |
※ 構築する際にインスタンスタイプは前提条件を満たすもので(おそらく)一番料金の安い c6g.large を選択しましたが、vCPU が2コアの場合においてもハマった点がありましたので後ほど紹介します。
EC2 起動後は EIP を割り当ててください。
ACM for Nitro Enclaves と Nginx のインストール
EC2 にログインし、ACM for Nitro Enclaves と Nginx をインストールします。
ACM for Nitro Enclaves のインストール
$ sudo dnf install aws-nitro-enclaves-acm -y ~略~ Installed: aws-nitro-enclaves-acm-1.2.0-2.amzn2023.aarch64 aws-nitro-enclaves-cli-1.2.3-0.amzn2023.aarch64 containerd-1.7.11-1.amzn2023.0.1.aarch64 docker-25.0.3-1.amzn2023.0.1.aarch64 iptables-libs-1.8.8-3.amzn2023.0.2.aarch64 iptables-nft-1.8.8-3.amzn2023.0.2.aarch64 libcgroup-3.0-1.amzn2023.0.1.aarch64 libnetfilter_conntrack-1.0.8-2.amzn2023.0.2.aarch64 libnfnetlink-1.0.1-19.amzn2023.0.2.aarch64 libnftnl-1.2.2-2.amzn2023.0.2.aarch64 pigz-2.5-1.amzn2023.0.3.aarch64 runc-1.1.11-1.amzn2023.0.1.aarch64 Complete!
Nginx のインストール
$ sudo dnf install nginx -y ~略~ Installed: generic-logos-httpd-18.0.0-12.amzn2023.0.3.noarch gperftools-libs-2.9.1-1.amzn2023.0.3.aarch64 libunwind-1.4.0-5.amzn2023.0.2.aarch64 nginx-1:1.24.0-1.amzn2023.0.2.aarch64 nginx-core-1:1.24.0-1.amzn2023.0.2.aarch64 nginx-filesystem-1:1.24.0-1.amzn2023.0.2.noarch nginx-mimetypes-2.1.49-3.amzn2023.0.3.noarch Complete!
ACM 証明書と IAM Role の紐づけ
次に下記コマンドを実行し、利用する ACM 証明書と EC2 に割り当てている IAM Role を紐づけます。
{region}
、{certificate_ARN}
、{role_ARN}
は自身の環境のものに置き換えてください。
$ aws ec2 --region {region} associate-enclave-certificate-iam-role --certificate-arn {certificate_ARN} --role-arn {role_ARN}
正常にコマンドが通ると以下のような出力が返ってきます。
CertificateS3BucketName
と EncryptionKmsKeyId
キーの値は次の手順で必要ですのでメモしておいてください。
{ "CertificateS3BucketName": "aws-ec2-enclave-certificate-us-east-1", "CertificateS3ObjectKey": "arn:aws:iam::123456789012:role/acm-role/arn:aws:acm:us-east-1:123456789012:certificate/d4c3b2a1-e5d0-4d51-95d9-1927fEXAMPLE", "EncryptionKmsKeyId": "a1b2c3d4-354d-4e51-9190-b12ebEXAMPLE" }
ACM 証明書へのアクセス、復号化などの権限をロールに付与する
EC2 に割り当てている IAM Role に ACM 証明書へのアクセスと KMS キーで暗号化されたオブジェクトの復号化、自身の IAM Role にアクセスするための権限を付与します。
まず、ポリシーを記載した json ファイルを用意します。
{CertificateS3BucketName}
はメモしたCertificateS3BucketName
キーの値{region}
は EC2 を起動したリージョン{EncryptionKmsKeyId}
はメモしたEncryptionKmsKeyId
キーの値{role_ARN}
は EC2 に割り当てている IAM Role の ARN
に置き換えてください。
$ sudo vi acm-role-policies.json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": ["arn:aws:s3:::{CertificateS3BucketName}/*"] }, { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "kms:Decrypt" ], "Resource": "arn:aws:kms:{region}:*:key/{EncryptionKmsKeyId}" }, { "Effect": "Allow", "Action": "iam:GetRole", "Resource": "{role_ARN}" } ] }
次に下記コマンドを実行し、IAM Role にインラインポリシーをアタッチします。
{role_name}
は EC2 に割り当てている IAM Role に置き換えてください。
$ aws iam put-role-policy --role-name {role_name} --policy-name acm-role-policy --policy-document file://acm-role-policies.json
冒頭で作成した IAM Policy はもう不要ですので IAM Role からデタッチした後に削除してください。
ACM for Nitro Enclaves および Nginx の設定
ACM for Nitro Enclaves を Nginx で利用するための設定を行います。
はじめに ACM for Nitro Enclaves の設定を行います。
Nginx 用の設定ファイルのサンプルがあるのでリネームします。
$ sudo mv /etc/nitro_enclaves/acm.example.yaml /etc/nitro_enclaves/acm.yaml
リネームした設定ファイル /etc/nitro_enclaves/acm.yaml
の Acm
セクションの certificate_arn
に利用する ACM 証明書の ARN を設定します。
$ sudo vi /etc/nitro_enclaves/acm.yaml ~略~ tokens: # A label for this PKCS#11 token - label: nginx-acm-token # Configure a managed token, sourced from an ACM certificate. source: Acm: # The certificate ARN # Note: this certificate must have been associated with the # IAM role assigned to the instance on which ACM for # Nitro Enclaves is run. - certificate_arn: "" + certificate_arn: "arn:aws:acm:us-east-1:123456789012:certificate/d4c3b2a1-e5d0-4d51-95d9-1927fEXAMPLE" ~略~
次に、Nginx の設定ファイル /etc/nginx/nginx.conf
に TLS アクセラレーション機能を利用するための ssl_engine
ディレクティブの設定を追加し、pkcs11
を指定します。
$ sudo vi /etc/nginx/nginx.conf
~略~
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
+ ssl_engine pkcs11;
~略~
そして /etc/nginx/nginx.conf
の下部にある TLS サーバの設定箇所のコメントアウトを外し、以下設定を行います。
server_name
の設定。ACM 証明書作成時に指定したホスト名あるいはコモンネーム (CN) を設定ssl_certificate
,ssl_certificate_key
,ssl_ciphers
の削除ssl_protocols TLSv1.2;
の追加include "/etc/pki/nginx/nginx-acm.conf";
の追加
設定例)
# Settings for a TLS enabled server. # server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; root /usr/share/nginx/html; ssl_protocols TLSv1.2; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_prefer_server_ciphers on; # Set this to the stanza path configured in /etc/nitro_enclaves/acm.yaml include "/etc/pki/nginx/nginx-acm.conf"; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; error_page 404 /404.html; location = /404.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } }
ACM for Nitro Enclaves および Nginx の起動
設定が完了したら、まず ACM for Nitro Enclaves を起動します。
$ sudo systemctl start nitro-enclaves-acm.service A dependency job for nitro-enclaves-acm.service failed. See 'journalctl -xe' for details.
なんかエラーがでましたね。ログを確認してみます。(ハマりポイント1)
$ journalctl -xe --no-pager ~略~ nitro-enclaves-allocator[30071]: Auto-generating the enclave CPU pool by using the CPU count... kernel: nitro_enclaves: No CPUs available in CPU pool kernel: nitro_enclaves: Error in setup CPU pool [rc=-22] nitro-enclaves-allocator[30071]: Error: Failed to find suitable CPUs for the Nitro Enclaves CPU pool after checking all NUMA nodes. systemd[1]: nitro-enclaves-allocator.service: Main process exited, code=exited, status=1/FAILURE ~略~
No CPUs available in CPU pool
とあります。 エラーコード (rc=-22
) のようなものもあるのでググってみると以下がヒットしました。
Insufficient CPUs available in the pool. The number of requested vCPUs is greater than the number of available vCPUs. Either specify a number of vCPUs less than or equal to the configured vCPU pool size, or preallocate the environment resources so that the vCPU pool includes the number of vCPUs that you want to use. For more information, see Installing the Nitro Enclaves CLI on Linux.
要求された vCPU コア数が使用可能な vCPU コア数を超えているようです。 さらに引用元のリンク先にある内容を確認します。
Installing the Nitro Enclaves CLI on Linux - AWS
Nitro Enclaves uses an allocator service to preallocate vCPUs and memory to the enclaves. The amount of vCPUs and memory to preallocate are defined in the allocator service configuration file (/etc/nitro_enclaves/allocator.yaml). By default, the configuration file is set up to preallocate 512 MiB of memory and 2 vCPUs for use by the enclaves. In some cases, you might need to manually update the configuration file to preallocate a different number vCPUs or amount of memory. For example:
・If you launched an AWS Graviton-based instance with 2 vCPUs, you must configure the allocate service to preallocate only 1 vCPU.
vCPU が2コアの場合は1コアしか割り当てができないようです。なんと。
なので、vCPU の割り当てを修正します。
/etc/nitro_enclaves/allocator.yaml
および /etc/nitro_enclaves/acm.yaml
の設定を変更します。
$ sudo vi /etc/nitro_enclaves/allocator.yaml ~略~ # How many CPUs to reserve for enclaves. - cpu_count: 2 + cpu_count: 1 ~略~
$ sudo vi /etc/nitro_enclaves/acm.yaml ~略~ # Enclave general configuration enclave: # Number of vCPUs to be assigned to the enclave - cpu_count: 2 + cpu_count: 1 ~略~
では、気を取り直して ACM for Nitro Enclaves を起動します。
$ sudo systemctl start nitro-enclaves-acm.service
いけたか?!ステータスを確認してみます。
$ sudo systemctl status nitro-enclaves-acm.service ~略~ systemd[1]: Starting nitro-enclaves-acm.service - Nitro Enclaves ACM Agent... systemd[1]: Started nitro-enclaves-acm.service - Nitro Enclaves ACM Agent. p11ne-agent[30553]: |INFO | Setting up p11-kit config p11ne-agent[30553]: |INFO | Restarting vsock proxy p11ne-agent[30553]: |INFO | Syncing token nginx-acm-token p11ne-agent[30553]: |INFO | Service: nginx | Force_Start: true | Reload: 1000 | Sync: 600 p11ne-agent[30553]: |INFO | Reloading NGINX configuration. p11ne-agent[30553]: |INFO | NGINX is not running. Starting it now. p11ne-agent[30553]: |ERROR | Unable to reload NGINX: SystemdStartNginxError(Some(1))
Nginx でエラーが出ています。。。(ハマりポイント2)
ログを確認します。
$ journalctl -xe -u nginx --no-pager ~略~ nginx: [emerg] cannot load certificate key "engine:pkcs11:pkcs11:model=p11ne-token;manufacturer=Amazon;token=nginx-acm-token;id=%01;object=acm-key;type=private?pin-value=4caf27fe2c6e9d3ae7b341ed85519096": ENGINE_load_private_key() failed (SSL: error:13000075:engine routines::not initialised) nginx: configuration file /etc/nginx/nginx.conf test failed nginx.service: Control process exited, code=exited, status=1/FAILURE ~略~
ググってみると。。。。
AmazonLinux 2023 & Nginx support · Issue #124 · aws/aws-nitro-enclaves-acm · GitHub
I ran into this myself, and after talking to support was informed that it's simply not supported right yet unless you downgrade openssl-pkcs11 to v0.4.11. I achieved it without a downgrade by adding the following dirty hack to openssl.cnf:
openssl-pkcs11 to v0.4.11. にダウングレードする必要がありそうです。
念のため現在インストールされている openssl-pkcs11 のバージョンを確認します。
$ sudo dnf list --installed openssl-pkcs11 Installed Packages openssl-pkcs11.aarch64 0.4.12-3.amzn2023.0.1
0.4.12 がインストールされていましたので、0.4.11 にダウングレードします。
インストール可能なバージョンを確認します。
$ sudo dnf --showduplicates search openssl-pkcs11 Last metadata expiration check: 2:21:56 ago on Fri Mar 8 02:45:44 2024. ======================================================================================= Name Exactly Matched: openssl-pkcs11 ======================================================================================== openssl-pkcs11-0.4.12-3.amzn2023.0.1.aarch64 : A PKCS#11 engine for use with OpenSSL openssl-pkcs11-0.4.11-8.amzn2023.0.3.aarch64 : A PKCS#11 engine for use with OpenSSL openssl-pkcs11-0.4.12-3.amzn2023.0.1.aarch64 : A PKCS#11 engine for use with OpenSSL
openssl-pkcs11-0.4.11-8.amzn2023.0.3.aarch64
をインストールします。
$ sudo dnf install openssl-pkcs11-0.4.11-8.amzn2023.0.3.aarch64 -y ~略~ Running transaction Preparing : 1/1 Downgrading : openssl-pkcs11-0.4.11-8.amzn2023.0.3.aarch64 1/2 Cleanup : openssl-pkcs11-0.4.12-3.amzn2023.0.1.aarch64 2/2 Running scriptlet: openssl-pkcs11-0.4.12-3.amzn2023.0.1.aarch64 2/2 Verifying : openssl-pkcs11-0.4.11-8.amzn2023.0.3.aarch64 1/2 Verifying : openssl-pkcs11-0.4.12-3.amzn2023.0.1.aarch64 2/2 Downgraded: openssl-pkcs11-0.4.11-8.amzn2023.0.3.aarch64 Complete!
いけました!再度 Nginx を起動します。
$ sudo systemctl start nginx
Nginx のステータスを確認します。
$ sudo systemctl status nginx ● nginx.service - The nginx HTTP and reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; preset: disabled) Active: active (running) since Mon 2024-03-11 06:58:49 UTC; 14s ago Process: 32678 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS) Process: 32681 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS) Process: 32724 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS) Main PID: 32725 (nginx) Tasks: 2 (limit: 4478) Memory: 3.4M CPU: 50ms CGroup: /system.slice/nginx.service tq32725 "nginx: master process /usr/sbin/nginx" mq32726 "nginx: worker process" systemd[1]: Starting nginx.service - The nginx HTTP and reverse proxy server... nginx[32681]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx[32681]: nginx: configuration file /etc/nginx/nginx.conf test is successful systemd[1]: Started nginx.service - The nginx HTTP and reverse proxy server.
いけてそうです!
ACM for Nitro Enclaves を再起動し、
$ sudo systemctl restart nitro-enclaves-acm.service
ステータスを確認します。
$ sudo systemctl status nitro-enclaves-acm.service ● nitro-enclaves-acm.service - Nitro Enclaves ACM Agent Loaded: loaded (/usr/lib/systemd/system/nitro-enclaves-acm.service; disabled; preset: disabled) Active: active (running) since Mon 2024-03-11 07:00:15 UTC; 1min 47s ago Process: 32791 ExecStartPre=/usr/bin/mkdir -p /run/nitro_enclaves/acm (code=exited, status=0/SUCCESS) Main PID: 32792 (p11ne-agent) Tasks: 5 (limit: 4478) Memory: 10.9M CPU: 2.825s CGroup: /system.slice/nitro-enclaves-acm.service tq32792 /usr/bin/p11ne-agent mq32795 nitro-cli run-enclave --eif-path /usr/share/nitro_enclaves/p11ne/p11ne.eif --cpu-count 1 --memory 256 systemd[1]: Starting nitro-enclaves-acm.service - Nitro Enclaves ACM Agent... systemd[1]: Started nitro-enclaves-acm.service - Nitro Enclaves ACM Agent. p11ne-agent[32792]: |INFO | Setting up p11-kit config p11ne-agent[32792]: |INFO | Restarting vsock proxy p11ne-agent[32792]: |INFO | Syncing token nginx-acm-token p11ne-agent[32792]: |INFO | Service: nginx | Force_Start: true | Reload: 1000 | Sync: 600 p11ne-agent[32792]: |INFO | Reloading NGINX configuration.
大丈夫そうですね。
忘れる前に ACM for Nitro Enclaves の自動起動設定を有効化しておきます。
$ sudo systemctl enable nitro-enclaves-acm.service Created symlink /etc/systemd/system/multi-user.target.wants/nitro-enclaves-acm.service → /usr/lib/systemd/system/nitro-enclaves-acm.service.
※ Nginx は ACM for Nitro Enclaves が起動してくれるので Nginx の自動起動設定は不要です。
ブラウザでアクセスしてみる
ブラウザでアクセスし、証明書エラーなどが出ていないか確認してみます。 大丈夫そうですね、証明書も ACM で発行されたものがきちんと適用されています。ハッピー!!!!
最後に
以上が Amazon Linux 2023 および Nginx 構成で ACM for Nitro Enclaves を利用する手順になります。
ACM for Nitro Enclaves では証明書の更新もシームレスに行ってくれる*4とのことなのでありがたいかぎりです。
ちなみに Amazon Linux 2023 + Apache 構成も試してみましたが、Apache に関してはダウングレードとかすることなく、公式手順通りで導入できましたので vCPU コア数のみ意識していただけたらと思います。
*1:ACM プライベート証明書はエクスポート可能
*2:https://docs.aws.amazon.com/ja_jp/enclaves/latest/user/nitro-enclave-refapp.html#acm-considerations
*3:Nitro Enclaves の設定はインスタンスが停止状態であればあとからでも有効化することができます。
*4:"ACM for Nitro Enclaves works with NGINX servers and Apache HTTP servers running on Amazon EC2 instances to install the certificate and seamlessly replace expiring certificates." : https://docs.aws.amazon.com/ja_jp/enclaves/latest/user/nitro-enclave-refapp.html