AWS-Certificate-Manager

ACMのSSL証明書(Amazonの無料証明書)をEC2(Apache)で利用してみた

こんにちは、SRE課の栩野です。

ACMに設置したSSL証明書がApacheで使えるようになったという超ありがたい情報をキャッチしたので、実際に使えるのかどうか確認してみました。

AWS Certificate Manager (ACM) for Nitro Enclaves が Apache HTTP ウェブサーバーのサポートを開始

これまでのACMのSSL証明書利用方法

これまでは、Apacheで直接ACMのSSL証明書を利用することは出来ず、EC2の手前にALBやCloudFrontを作成し、そちらに適用して利用する必要がありました。

もしくは、Nginxでは以前からACMのSSL証明書の利用がサポートされていたため、Nginxを使うが必要がありました。

今回のアップデート

今回のアップデートにより、上記のように前段にALBやCloudFrontを作成しなくとも、Apacheに直接ACMのSSL証明書を適用出来るようになりました。

これにより、EC2が1台構成でApacheを利用していてもAmazonの無料SSL証明書が利用できるようになりました。
また、複数のEC2で同じSSL証明書を利用している場合や、ALB/CloudFrontとEC2両方にSSL証明書を適用しているような場合、ACMで一元管理出来そうなので良さげです。

追加料金は無しで利用できます。ありがたい!

利用条件

ただし、利用するためには下記の条件があります。

  1. サポートされているのは、Linuxを利用するEC2インスタンスのみ
  2. Nitro System上に構築されるEC2インスタンスタイプのみで、またCPUが4vCPU以上
    Nitro System 上に構築されたインスタンス

※Nitro Systemについては下記のサイトを参考にしてください。
AWS Nitro System

ちなみに、AWS Certificate Manager (ACM) for Nitro EnclavesについてるNitro Enclavesとはなんぞやですが、機密情報等を安全に保管するために分離されたコンピューティング環境のことを指し、Nitro System上に構築されたEC2であれば、オプションで利用できます。(追加料金無し)

今回の仕組みとして、Nitro EnclavesにACMのSSL証明書と秘密鍵が配布され、EC2から利用できるといった形になります。

↓詳しくは
AWS Nitro Enclaves

実際にApacheから利用してみる

ではでは、実際にApacheからACMのSSL証明書を利用してみたいと思います。
今回はAmazonの無料SSL証明書を利用します。

以下の条件で作成していきます。

  • インスタンスタイプは[m5.xlarge]
  • OSは[Amazon Linux 2]
  • Administrator権限のついたIAMユーザで作業
    ※IAMユーザの権限が絞られている場合は、下記のjsonの【region】【account_id】を置き換えて、IAMユーザへのアタッチが必要
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:AssociateEnclaveCertificateIamRole",
                "ec2:GetAssociatedEnclaveCertificateIamRoles",
                "ec2:DisassociateEnclaveCertificateIamRole"
            ],
            "Resource": [
                "arn:aws:acm:region:account_id:certificate/*",
                "arn:aws:iam::account_id:role/*"
            ],
            "Effect": "Allow"
        }
    ]
}

AWSの公式ドキュメントの手順を参考に進めていきます。
Nitro Enclaves 用の ACM のインストールと設定

1. ACMでSSL証明書を作成する

この辺の詳しい説明は割愛します。

今回東京リージョンのEC2から利用するので、SSL証明書を適用したいドメイン名を使って、東京リージョンでAmazon無料SSL証明書を取得してください。

取得方法が不明な場合、↓公式の手順です。
パブリック証明書をリクエストする

2. Nitro Enclaves対応のEC2インスタンスを作成する

実際にApacheを稼働させて、ACMのSSL証明書を利用するEC2インスタンスを作成します。

OSはLinuxのNitro System上に構築された4vCPU以上のインスタンスである必要があるため、[Amazon Linux 2]の[m5.xlarge]で作成します。

EC2作成画面最下部の[高度な詳細]から[Nitro Enclave]を有効化に設定しておいてください。

後ほどSSH接続とHTTPSでのWEB確認を行うため、22と443ポートに接続できるようセキュリティグループの開放設定と、EC2のパブリックIPをACMでSSL証明書を取得したドメイン名で名前解決できるよう、DNSでAレコードの設定をしておいてください。

EC2が出来たら、SSH接続してACMが利用できるよう下記コマンドでセットアップを行います。

# aws-nitro-enclaves-cli の有効化
sudo amazon-linux-extras enable aws-nitro-enclaves-cli

# Apahceとmod_sslのインストール
sudo yum -y install httpd mod_ssl

# Nitro Enclaves用のACMをインストール
sudo yum -y install aws-nitro-enclaves-acm

3. IAM ロールの準備

EC2インスタンスでACM証明書を利用するために、必要なアクセス許可を付与したIAMロールを作成します。

後ほど、ロールはEC2とACM証明書にアタッチします。

ここからは、CloudShellを開いてCLIで作業を行なっていきます。

まずは、アクセス許可を記載したjsonファイルをviで作成します。

vi acm-role.json

{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Principal":{
            "Service":"ec2.amazonaws.com"
         },
         "Action":"sts:AssumeRole"
      }
   ]
}

※viでペースト時にオートインデントされてしまうので :a を実行してからペーストすると綺麗に出来ます。

次に作成したjsonを使って、IAMロールを作成します。

aws iam create-role --role-name acm-role --assume-role-policy-document file://acm-role.json

コマンドが通ると、jsonが出力されるので、[Arn]の値を後ほど使うのでコピーしておきます。

4. IAMロールをACM証明書にアタッチする

先ほど作成したIAMロールを取得しておいたACMの証明書にアタッチします。

下記コマンドの3ヶ所を置き換えて実行します。

  • 【region】は今回東京リージョンが対象のため ap-northeast-1 に置き換え
  • 【certificate_ARN】はACMで取得したSSL証明書のARNを確認して置き換え
  • 【role_ARN】はIAMロール作成時にコピーしておいた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-ap-northeast-1-prod",
    "CertificateS3ObjectKey": "arn:aws:iam::XXXXXXXXXXXX:role/acm-role/arn:aws:acm:ap-northeast-1:XXXXXXXXXXXX:certificate/d4c3b2a1-e5d0-4d51-95d9-1927fEXAMPLE",
    "EncryptionKmsKeyId": "a1b2c3d4-354d-4e51-9190-b12ebEXAMPLE"
}

5. IAMロールにSSL証明書と暗号化キーにアクセスするための権限を付与する

作成しておいたIAMロールにSSL証明書とKMS暗号化キーにアクセスするための必要な権限を付与します。

ポリシーを記載したjsonファイルをviで作成していきます。
下記の3箇所を置き換えて作成します。

  • 【CertificateS3BucketName】は先ほどコピーしたCertificateS3BucketNameの値
  • 【region】は東京なので ap-northeast-1
  • 【EncryptionKmsKeyId】も同様に先ほどコピーしたEncryptionKmsKeyIdの値
  • 【123456789012】は自分のアカウントIDに置き換え

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": "arn:aws:iam::【123456789012】:role/acm-role"
    }
  ]
}

jsonが作成出来たら、下記のコマンドでIAMロールに権限を付与します。

aws iam put-role-policy --role-name acm-role --policy-name acm-role-policy --policy-document file://acm-role-policies.json

6. IAMロールをEC2インスタンスにアタッチする

次はIAMロールを作成しておいたEC2インスタンスにアタッチします。

EC2にアタッチするためには、まず下記コマンドでインスタンスプロファイルを作成します。

aws iam create-instance-profile --instance-profile-name acm-instance-profile

次に作成したインスタンスプロファイルとIAMロールの関連付けを行います。

aws iam add-role-to-instance-profile --instance-profile-name acm-instance-profile --role-name acm-role

関連付けが出来たら、インスタンスプロファイルをEC2インスタンスにアタッチします。

  • 【region】は東京なので ap-northeast-1
  • 【instance_id】は作成したEC2インスタンスのインスタンスIDを確認して置き換え
aws ec2 --region 【region】 associate-iam-instance-profile --instance-id 【instance_id】 --iam-instance-profile Name=acm-instance-profile

7. ACMを利用できるようApacheのセットアップ

いよいよApacheからACMのSSL証明書を利用できるようにセットアップしていきます。

EC2にSSH接続を行い、デフォルトで作成されているApache用のACMファイルをリネームします。

sudo mv /etc/nitro_enclaves/acm-httpd.example.yaml /etc/nitro_enclaves/acm.yaml

リネームしたら[/etc/nitro_enclaves/acm.yaml]ファイルをviで開き、[certificate_arn]の値が空になっているので、SSL証明書のARNを記載します。

sudo vi /etc/nitro_enclaves/acm.yaml

35 tokens:
36   # A label for this PKCS#11 token
37   - label: httpd-acm-token
38     # Configure a managed token, sourced from an ACM certificate.
39     source:
40       Acm:
41         # The certificate ARN
42         # Note: this certificate must have been associated with the
43         #       IAM role assigned to the instance on which ACM for
44         #       Nitro Enclaves is run.
45         certificate_arn: "【SSL証明書のARNを記載】"
46     target:
47       Conf:
48         # Path to the server configuration file to be written by
49         # the ACM service whenever the certificate configuration changes
50         # (e.g. after a certificate renewal). The SSLCertificateKeyFile and
51         # optionally the SSLCertificateFile directives shall be populated.
52         path: /etc/httpd/conf.d/httpd-acm.conf
53         # Configuration file owner (i.e. the user httpd is configured to run as).
54         user: apache
55     # Attestation period (seconds)
56     refresh_interval_secs: 43200

次に上記ファイルの52行目で読み込まれているファイル名[etc/httpd/conf.d/httpd-acm.conf]を作成します。
viでファイルを作成し、【SSL証明書を取得したドメイン名】の箇所をACMで取得したドメイン名と同じServerNameに書き換えてバーチャルディレクティブを作成します。

sudo vi /etc/httpd/conf.d/httpd-acm.conf

<VirtualHost *:443>
ServerName 【SSL証明書を取得したドメイン名】
SSLEngine on
SSLProtocol -all +TLSv1.2
SSLCertificateKeyFile "/etc/pki/tls/private/localhost.key"
SSLCertificateFile "/etc/pki/tls/certs/localhost.crt"
</VirtualHost>

[SSLCertificateKeyFile]と[SSLCertificateFile]はとりあえずlocalhostで記載しておきます。
この後、自動的にACM証明書のURIへと書き換えられます。

ここまで準備できたら、nitro-enclaves-acmサービスを起動させます。

sudo systemctl enable --now nitro-enclaves-acm

上記コマンドにより、Apacheも一緒に起動してきます。
念の為、起動しているかどうか確認しておきます。

sudo systemctl status httpd
sudo systemctl status nitro-enclaves-acm

// Apacheの自動起動も有効にしておくなら
sudo systemctl enable httpd

また先ほど設定した[/etc/httpd/conf.d/httpd-acm.conf]の中身を見てみると、[SSLCertificateKeyFile]と[SSLCertificateFile]の値が自動的に置き換わっていることが確認できます。

※もし上手くいかない場合は、エラーログを確認して対処してください。

journalctl -u nitro-enclaves-acm.service
journalctl -u httpd.service

これでApacheへのACMのSSL証明書準備は完了しました!

実際にWEBブラウザから、作成したドメインにアクセスして確認してみると...

無事にEC2単体でAmazonの無料証明書が使えています。感動!

おまけ

複数のバーチャルドメインを設定している場合、ACMのSSL証明書を複数利用することも可能です。
[/etc/nitro_enclaves/acm.yaml]ファイルに下記のようにlabelの項目を追加し、適当なlabelを追加しSSL証明書のARNを記載することで追加できます。

  - label: [token_2_name]
    # 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_2_ARN]"
    target:
      Conf:
        # Path to the server configuration file to be written by the ACM service whenever the certificate 
        # configuration changes (e.g. after a certificate renewal). The SSLCertificateKeyFile and optionally 
        # the SSLCertificateFile directives shall be populated.
        path: /etc/httpd/confi.d/httpd-acm-2.conf
        # Configuration file owner (i.e. the user httpd is configured to run as).
        user: apache

設定ファイルを修正したら、nitro-enclaves-acmサービスを再起動します。

sudo systemctl restart nitro-enclaves-acm

さいごに

これまで、EC2で無料のSSL証明書を検討する場合、Let's Encryptであったり、ALBやCloudFrontを無理やり利用していましたが、Apacheで直接利用できるようになったのは非常に嬉しいアップデートです。

以上、最後までありがとうございました。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA