こんにちは。SRE2課の福島です。
はじめに
今回は、以下のアップデートを実際に試してみましたので、ブログにまとめたいと思います。
今までは、ACMで発行した証明書をEC2で利用することができませんでした。
しかし、今回のアップデートにより、
特定のAMIから作成したEC2に
ACMで発行した証明書(PublicおよびPrivate)を
利用可能となりました。
検証には、以下のAWSのドキュメントを参考にいたしました。
Nitro Enclaves application: AWS Certificate Manager for Nitro Enclaves - AWS Nitro Enclaves
ポイント
- 現時点(10/29時点)では、Nginxのみサポートしております。
※他のWebサーバソフトウェアは、今後追加サポートされる予定のようです。 ACMにIAMロールを関連付けするのですが、現時点(10/29時点)では、AWS CLIv2ではなく、v1からしか実行できませんでした。
(aws-cli/2.0.60には、associate-enclave-certificate-iam-roleコマンドがありませんでした...)- aws-cli/2.0.61からassociate-enclave-certificate-iam-roleが使えるようになりました。
- EC2には、ACMエージェント(/usr/bin/p11ne-agent)を起動します。
- EC2インスタンスに「Enclaves Support」という設定値が追加されていました。
※マネコンから変更するボタンが見つからなかったため、CLIからのみ変更可能そうです。 - 特定のAMIがサポートしているインスタンスタイプは要確認です。
(--dry-runが成功しても、実際に作成すると失敗するインスタンスタイプがありました。)
※--dry-runが成功したインスタンスタイプ一覧は、最後に記載しております。(2020/11/11時点)
検証
では、ここから検証していきます。
①ACMで証明書の発行
今回は、公開証明書を利用しましたので、 発行は以下のドキュメントを参考に実施します。
◆公開証明書の要求
https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/gs-acm-request-public.html
証明書を発行しましたら、この後に証明書のARNを利用するため、変数に定義しておきます。
CERTARN=""
例)
CERTARN="arn:aws:acm:ap-northeast-1:xxxxxxxxxxxxxx:certificate/xxxxxxxxxxxxxxxxxxxxxxxx"
②EC2インスタンスの作成(特定のAMIを利用する。)
リージョンによって、利用できるAMIは以下の通りとなります。
us-east-1—ami-02fa3c4d1f12632a1
us-east-2—ami-000d7dc3e9ccae7d4
us-west-2—ami-057b2b88789d1c84c
eu-central-1—ami-0738562c059302222
eu-west-1—ami-0f6444b7dfa686df6
eu-west-2—ami-08c96941f8b4617da
eu-west-3—ami-0e0e7a03eec2a41b6
eu-north-1—ami-0559b8814edf3321c
ap-east-1—ami-099f011eb57f563d2
ap-northeast-1—ami-088ab55ef296edbb1
ap-southeast-1—ami-0fdbbac04c25021d2
ap-southeast-2—ami-0c8174530d0ec5cbc
ap-south-1—ami-041d0d4bb66b8dcd3
sa-east-1—ami-0ddec972a8d04b740
今回は、東京リージョン(ap-northeast-1)のAMIを利用しました。
また、起動できるインスタンスタイプの記載がドキュメントになく、冒頭に記載しておりますが、
--dry-runで成功しても実際に実行すると作成できないインスタンスタイプもありましたので、
利用するインスタンスタイプが使えるかは、要確認です。
※今回は、たまたま起動できた「m5.xlarge」を使用しました。
環境変数を定義します。 ※デフォルトVPCが存在する必要があります。
AMIID="" INSTANCETYPE="" KEYPEA=""
例)
AMIID="ami-088ab55ef296edbb1" INSTANCETYPE="m5.xlarge" KEYPEA="fk-test-key"
変数を定義したら、以下のコマンドをコピペで実行します。
aws ec2 run-instances --image-id ${AMIID} --count 1 --instance-type ${INSTANCETYPE} --key-name ${KEYPEA} --enclave-options 'Enabled=true'
また、インスタンスには、「Enclaves Support」という設定値が増えており、
この設定を有効にするため、上記コマンドで「--enclave-options 'Enabled=true'」を指定しています。
※マネコンからは設定を変更するボタンが見当たらなかったので、おそらく、CLIからのみ変更ができる設定値のようです。

なお、インスタンスIDはこの後、利用するため、変数に定義しておきます。
INSTANCEID=""
例)
INSTANCEID="i-xxxxxxxxx"
③IAMロールの作成
以下の通り、ファイルを作成します。
ファイル名:acm-role.json
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal":{
"Service":"ec2.amazonaws.com"
},
"Action":"sts:AssumeRole"
}
]
}
以下のコマンドをそのまま実行し、IAMロールを作成します。
※ここでは、信頼関係のみを設定し、実際の権限(ポリシー)は、⑤で行います。
aws iam create-role --role-name acm-role --assume-role-policy-document file://acm-role.json
また、作成したIAMロールのARNをこの後、利用するため、変数に定義しておきます。
ROLEARN=""
例)
ROLEARN="arn:aws:iam::xxxxxxxxxxx:role/acm-role"
④③で作成したIAMロールを証明書に関連付け
①で作成した証明書のARNおよび③で作成したIAMロールのARNを 変数に定義しているため、以下のコマンドをそのまま実行します。
aws ec2 associate-enclave-certificate-iam-role --certificate-arn ${CERTARN} --role-arn ${ROLEARN}
上記コマンドを実行後、出力される 「CertificateS3BucketName」および「EncryptionKmsKeyId」を控えておきます。 (⑤で利用します。)
⑤③で作成したIAMロールにポリシー適用
以下の通り、ファイルを作成します。
ファイル名: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:ap-northeast-1:*:key/EncryptionKmsKeyId" ★編集
}
]
}
※ポリシーのCertificateS3BucketNameおよびEncryptionKmsKeyIdを④で出力された結果に変更します。
以下のコマンドでポリシーを適用します。
aws iam put-role-policy --role-name acm-role --policy-name acm-role-policy --policy-document file://acm-role-policies.json
⑥②で作成したEC2にIAMロールをアタッチ
②で作成したEC2のインスタンスIDを変数に定義しておりますので、以下のコマンドをそのまま、実行します。
aws iam create-instance-profile --instance-profile-name acm-instance-profile
aws iam add-role-to-instance-profile --instance-profile-name acm-instance-profile --role-name acm-role
aws ec2 associate-iam-instance-profile --instance-id ${INSTANCEID} --iam-instance-profile Name=acm-instance-profile
⑦Nginxの設定
ここからNginxの設定を行います。 まず、②で作成したEC2にSSHでログインします。 ※おそらく、デフォルトのSGが付与されているため、適切な通信設定を行う必要があります。
/etc/nitro_enclaves/acm.yamlの編集
sudo mv /etc/nitro_enclaves/acm.example.yaml /etc/nitro_enclaves/acm.yaml
・vi等で「/etc/nitro_enclaves/acm.yaml」の「certificate_arn」を編集します。
設定例)
certificate_arn: "arn:aws:acm:ap-northeast-1:xxxxxxxxxxxxxx:certificate/xxxxxxxxxxxxxxxxxxxxxxxxxx"
/etc/nginx/nginx.confの編集
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.org
vi /etc/nginx/nginx.conf
以下の内容を貼り付けます。 ※server_name(★)のみ、編集します。
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
ssl_engine pkcs11;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# 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 = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
変更点を知りたい場合、以下のコマンドで確認が可能です。
diff /etc/nginx/nginx.conf /etc/nginx/nginx.conf.org
最後に以下のコマンドを実行し、設定完了です!!
※ACMエージェントを起動しています。
sudo systemctl start nitro-enclaves-acm.service
以下のコマンドで起動していることを確認します。
sudo systemctl status nitro-enclaves-acm.service
また、どうでもいいですが、上記サービスには、ACMエージェントを起動後、nginx.serviceを起動するように設定されているようでした。 以下のコマンドでnginxが起動されていることを確認できます。
sudo systemctl status nginx.service
後は、ブラウザからパブリックIPもしくは証明書のドメイン名でアクセスできることを確認します。
https://パブリックIP or https://証明書のドメイン名

終わりに
すぐ検証できるかなと思っていましたが、aws cliv2では、IAMロールをACMの証明書に関連付けできなかったり、 起動できるインスタンスタイプを見つけるのに苦労したりと予想以上にはまってしまいました...
どなたかのお役に立てれば幸いです。
おまけ
dry-runが成功したインスタンスタイプ一覧
確認コマンド
aws ec2 run-instances --image-id ${AMIID} --count 1 --instance-type ${INSTANCETYPE} --key-name ${KEYPEA} --enclave-options 'Enabled=true' --dry-run
| dry-runが成功したインスタンスタイプ | ||||||
|---|---|---|---|---|---|---|
| c5.xlarge | c5.2xlarge | c5.4xlarge | c5.9xlarge | c5.12xlarge | c5.18xlarge | c5.24xlarge |
| c5a.xlarge | c5a.2xlarge | c5a.4xlarge | c5a.8xlarge | c5a.12xlarge | c5a.16xlarge | c5a.24xlarge |
| c5d.xlarge | c5d.2xlarge | c5d.4xlarge | c5d.9xlarge | c5d.12xlarge | c5d.18xlarge | c5d.24xlarge |
| c5n.xlarge | c5n.2xlarge | c5n.4xlarge | c5n.9xlarge | c5n.18xlarge | - | - |
| g4dn.xlarge | g4dn.2xlarge | g4dn.4xlarge | g4dn.8xlarge | g4dn.12xlarge | g4dn.16xlarge | - |
| i3en.xlarge | i3en.2xlarge | i3en.3xlarge | i3en.6xlarge | i3en.12xlarge | i3en.24xlarge | - |
| inf1.xlarge | inf1.2xlarge | inf1.6xlarge | inf1.24xlarge | - | - | - |
| m5.xlarge | m5.2xlarge | m5.4xlarge | m5.8xlarge | m5.12xlarge | m5.16xlarge | m5.24xlarge |
| m5a.xlarge | m5a.2xlarge | m5a.4xlarge | m5a.8xlarge | m5a.12xlarge | m5a.16xlarge | m5a.24xlarge |
| m5ad.xlarge | m5ad.2xlarge | m5ad.4xlarge | m5ad.8xlarge | m5ad.12xlarge | m5ad.16xlarge | m5ad.24xlarge |
| m5d.xlarge | m5d.2xlarge | m5d.4xlarge | m5d.8xlarge | m5d.12xlarge | m5d.16xlarge | m5d.24xlarge |
| m5dn.xlarge | m5dn.2xlarge | m5dn.4xlarge | m5dn.8xlarge | m5dn.12xlarge | m5dn.16xlarge | m5dn.24xlarge |
| m5n.xlarge | m5n.2xlarge | m5n.4xlarge | m5n.8xlarge | m5n.12xlarge | m5n.16xlarge | m5n.24xlarge |
| p3dn.24xlarge | - | - | - | - | - | - |
| r5.xlarge | r5.2xlarge | r5.4xlarge | r5.8xlarge | r5.12xlarge | r5.16xlarge | r5.24xlarge |
| r5a.xlarge | r5a.2xlarge | r5a.4xlarge | r5a.8xlarge | r5a.12xlarge | r5a.16xlarge | r5a.24xlarge |
| r5ad.xlarge | r5ad.2xlarge | r5ad.4xlarge | r5ad.8xlarge | r5ad.12xlarge | r5ad.16xlarge | r5ad.24xlarge |
| r5d.xlarge | r5d.2xlarge | r5d.4xlarge | r5d.8xlarge | r5d.12xlarge | r5d.16xlarge | r5d.24xlarge |
| r5dn.xlarge | r5dn.2xlarge | r5dn.4xlarge | r5dn.8xlarge | r5dn.12xlarge | r5dn.16xlarge | r5dn.24xlarge |
| r5n.xlarge | r5n.2xlarge | r5n.4xlarge | r5n.8xlarge | r5n.12xlarge | r5n.16xlarge | r5n.24xlarge |
| z1d.xlarge | z1d.2xlarge | z1d.3xlarge | z1d.6xlarge | z1d.12xlarge | - | - |