AWS Certificate Manager(ACM)でクライアント証明書を発行してnginxに設定する方法

# はじめに
ACMでプライベートCA(認証局)を立てて、有効期限を指定してクライアント証明書を発行してnginxに設定する方法をまとめます。
プライベートCAの構築には400USD/月の費用が発生するので気をつけてください。

# 1. ACMでプライベートCAを立てる
ACMのコンソールにアクセスし、プライベート認証機関の「今すぐ始める」からプライベートCAを作成します。
ルートCAを選択し、認証機関名の設定をします。
全ての項目の入力が完了するとプライベートCAが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270692/23089be2-5178-11a5-6306-bc53017cf478.png)

# 2. ルート CA 証明書をインストールする
ルートCA証明書の有効期限を10年に設定して作成します。
後ほど作成するクライアント証明書の有効期限はルートCA証明書の有効期限を超えることはできません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270692/a9f00778-3dab-c81c-9d21-b24f929af7a8.png)

# 3a. クライアント証明書の発行(有効期限13ヵ月固定)
プライベートCAが作成されたので、Certificate Managerで証明書のリクエストをするときに「プライベート証明書のリクエスト」が選択できるようになります。
認証機関 (CA) の選択で先ほど作成したプライベートCAを選択し、クライアント証明書を発行します。
ACMのコンソールで証明書を発行した場合は有効期限が13ヵ月で固定されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270692/b0c458d6-6b6b-0f6d-49b9-da92f8e8fb26.png)

クライアント証明書が発行されると、ACMのコンソールに表示されるので選択してアクション⇨エクスポートを選択します。
パスフレーズを入力します。
証明書本文、秘密鍵が表示されるので、ダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270692/231a0ad7-a0fc-2cf6-bbc2-0a65dc295390.png)
ダウンロードした秘密鍵のパスフレーズを解除するために下記コマンドを実行します。

```sh
openssl rsa -in private_key.txt -out private_key.pem
```

# 3b クライアント証明書の発行(任意の有効期限を指定)
ACMのコンソールの代わりにAWS CLIを使用してクライアント証明書を発行します。
まずは、クライアント証明書の秘密鍵を生成します。

```sh
openssl genrsa 2048 > private-key.pem
```

生成した秘密鍵からプライベートCAに署名してもらうためのCSRを生成します。
-daysでクライアント証明書に任意の有効期限を設定します。

```sh
openssl req -new -key private-key.pem -out Client-csr.pem  -days 730
```

プライベートCAでCSRを署名してクライアント証明書を発行します。
クライアント証明書の発行が成功すると、証明書のARNが出力されます。
--certificate-authority-arnにはプライベートCAのARNを指定します。
ValueにはCSRと同じ有効期限を設定します。

```sh
aws acm-pca issue-certificate --certificate-authority-arn arn:aws:acm-pca:us-west-2:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012 --csr file://Client-csr.pem --signing-algorithm "SHA256WITHRSA" --validity Value=730,Type="DAYS" --idempotency-token 1234
```

発行したクライアント証明書本文と証明書チェーンを取得します。
--certificate-authority-arnにはプライベートCAのARNを指定します。
--certificate-arnには先ほど発行したクライアント証明書のARNを指定します。

```sh
aws acm-pca get-certificate --certificate-authority-arn  arn:aws:acm-pca:Region:Account:certificate-authority/12345678-1234-1234-1234-123456789012 --certificate-arn arn:aws:acm-pca:Region:Account:certificate-authority/12345678-1234-1234-1234-123456789012/certificate/66506378eb4e296c59b41bbb7b8dd068 --output text --query Certificate > certfile.pem
aws acm-pca get-certificate --certificate-authority-arn  arn:aws:acm-pca:Region:Account:certificate-authority/12345678-1234-1234-1234-123456789012 --certificate-arn arn:aws:acm-pca:Region:Account:certificate-authority/12345678-1234-1234-1234-123456789012/certificate/66506378eb4e296c59b41bbb7b8dd068 --output text --query CertificateChain > certchain.pem
```

発行したクライアント証明書をACMにインポートする際は下記のコマンドを実行します。

```sh
aws acm import-certificate --certificate file://certfile.pem --certificate-chain file://certchain.pem --private-key file://private-key.pem
```

# 4 nginxにプライベートCAの証明書を登録
ACMのコンソールからプライベートのCAの証明書を取得します。
構築したプライベートCAを選択し、アクション⇨CA証明書の取得を選択します。
証明書本文の内容をprivateCA.pemファイルにコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270692/6197844e-72d9-c813-22fd-d3e5140eeb3e.png)

nginxの設定ファイルにプライベートCAの証明書を指定します。

```
    server {
        listen 443 ssl;
        ssl_certificate ssl/allcert.pem
        ssl_certificate_key ssl/private.pem;

        ssl_verify_client on;
        ssl_client_certificate /path/to/privateCA.pem; #プライベートCAの証明書
        ...
    }
```

# 5 動作確認
最後にcurlコマンドでクライアント証明書を指定してリクエストを送り、クライアント認証できていることを確認します。

```sh
curl --key ./private-key.pem --cert ./certfile.pem https://localhost --insecure
```


#　参考資料
https://aws.amazon.com/jp/premiumsupport/knowledge-center/resolve-acm-certificate-failed-error/
http://www2.matsue-ct.ac.jp/home/kanayama/text/nginx/node101.html