ACMの証明書をEC2で利用可能になりました

記事タイトルとURLをコピーする

こんにちは。SRE2課の福島です。

はじめに

今回は、以下のアップデートを実際に試してみましたので、ブログにまとめたいと思います。

Announcing SSL/TLS certificates for Amazon EC2 instances with AWS Certificate Manager (ACM) for Nitro Enclaves

今までは、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からのみ変更ができる設定値のようです。

f:id:swx-fukushima:20201030010204p:plain

なお、インスタンス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://証明書のドメイン名

f:id:swx-fukushima:20201030005201p:plain

終わりに

すぐ検証できるかなと思っていましたが、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 - -

福島 和弥 (記事一覧)

SRE2課

2019/10 入社