AWSクライアントVPNエンドポイントとCertificate Manager(ACM)を用いて証明書を発行・再発行・更新・失効する

#概要
無料でSSL証明書が利用できるAWS Certificate Manager（以下ACM）を使用してサーバ証明書とクライアント証明書の発行手順を解説します。
状況に応じて、証明書の更新や再発行、失効させる作業もあると想定し、手順を説明します。

# 前提

- クライアントVPNエンドポイントをVPC上に設定し、クライアントとVPCとの間でVPNを作る。
- クライアントからのアクセスに対しては認証に利用するサーバ証明書とクライアント証明書をACMに登録する。
- クライアントにはOpenVPNクライアントをインストールし、OpenVPN公式の`easy-rsa`を利用し、クライアント証明書をセットする。
- ALB(アプリケーションロードバランサー)などにACMで発行した証明書をセットし、HTTPS化するという方法は今回は説明しない。

#手順
1. easy-rsaインストール
1. PKI環境の初期化
1. 認証機関（CA）の作成し、CA証明書を作成
1. サーバ・クライアント証明書とキーを作成
1. ACMにCA証明書・証明書とキーをインポート


#1. 証明書発行作業
VPN接続時に使用するクライアント証明書の発行・設定は、使用者が増える度に実施する作業です。
基本的に以下の公式ドキュメントに準じて説明いたします。

https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html


ルートユーザーになっておいてください。（一応）

```
sudo su -
```

## easy-rsaインストール

ここからが本番です。
まずは、easy-rsaをインストールします。

```
git clone https://github.com/OpenVPN/easy-rsa.git 
```

easyrsa3まで移動します。

```
cd easy-rsa-master/easyrsa3
```

`vars.example`という証明書の有効期限の設定ファイルがあるので、リネームして`vars`を作成しておきます。

```
cp -p vars.example vars
```

証明書の有効期限の中を確認します。

```
# cat vars

(略)

# In how many days should certificates expire?

#set_var EASYRSA_CERT_EXPIRE	825

# How many days until the next CRL publish date?  Note that the CRL can still be
# parsed after this timeframe passes. It is only used for an expected next
# publication date.
#set_var EASYRSA_CRL_DAYS	180

# How many days before its expiration date a certificate is allowed to be
# renewed?
#set_var EASYRSA_CERT_RENEW	30

# Random serial numbers by default, set to no for the old incremental serial numbers

(略)
```

デフォルトでは、
証明書の有効期限が`#set_var EASYRSA_CERT_EXPIRE	825`で825日
期限の何日前から証明書を更新できるかの日数が`#set_var EASYRSA_CERT_RENEW	30`で30日
となっているので、変更する場合はコメントアウト外して数値を変更します。

変更する場合はviなどで変更しましょう。

## PKI環境を初期化
以下のコマンドを入力してPKI環境を初期化します。

```
./easyrsa init-pki
```

成功するとpkiディレクトリができあがります。

## CA(認証機関)証明書を発行

```
./easyrsa build-ca nopass
```

成功するとpkiディレクトリ配下に`ca.crt`ができあがります。
このファイルがCA(認証機関)のルート証明書です。


## サーバ証明書とクライアント証明書発行
CA証明書ができると証明書とキーが発行できるようになります。
それではそれぞれの証明書とキーを発行します。

- サーバ証明書の発行

```
./easyrsa build-server-full server nopass
```

成功すると、`pki/issued/`配下に証明書が、
`pki/private/`配下にキーが作成されます。


- クライアント証明書の発行

```
./easyrsa build-client-full client1.domain.tld nopass
```

同様に`pki/issued/`配下に証明書が、
`pki/private/`配下にキーが作成されます。


## ACMに証明書をインポートする
AWS Certificate Managerコンソールから、「インポート」を選択します。
![証明書インポート.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/9e411339-6294-d5fc-ccaa-228bfdee91a8.jpeg)

証明書の詳細入力画面において３つの入力欄があります。

- 証明書本文
- 証明書のプライベートキー
- 証明書チェーン

![証明書の詳細を入力.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/a85c83ed-64cd-e2b8-5bec-241d827eb19b.jpeg)

それぞれについて説明します。

### 証明書本文

以下のコマンドを実行してください。

```
cat /easy-rsa-master/easyrsa3/pki/issued/server.crt
```

`server.crt`ファイル内の「-----BEGIN CERTIFICATE-----」から「-----END CERTIFICATE-----」までをコピーし貼り付けます。


### 証明書のプライベートキー

以下のコマンドを実行してください。

```
cat /easy-rsa-master/easyrsa3/pki/private/server.key
```

`server.key`ファイル内の「-----BEGIN PRIVATE KEY-----」から「-----END PRIVATE KEY-----」をコピーし貼り付けます。



### 証明書チェーン

以下のコマンドを実行してください。

```
cat /easy-rsa-master/easyrsa3/pki/ca.crt
```

`ca.crt`ファイル内の「-----BEGIN CERTIFICATE-----」から「-----END CERTIFICATE-----」までをコピーし貼り付けます。



タグの追加は必要に応じて入力してください。（必須ではありません）
![タグを追加.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/aa6597fd-d7a3-ded6-bc3e-5b559f73b4a8.jpeg)

次へ押すと確認画面が表示されるので、問題なければインポートを押下してインポート完了です。
![レビューおよびインポート.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/1a643890-4dec-68fe-27d4-cdcad26bcefc.jpeg)

# 2. 証明書更新作業
サーバ証明書とクライアント証明書の有効期限が切れてしまった場合の更新作業です。

## 有効期限設定ファイルの確認

以下のコマンドで有効期限ファイルの設定を確認します。

```
# cat vars

(略)
# In how many days should certificates expire?

set_var EASYRSA_CERT_EXPIRE     365

# How many days until the next CRL publish date?  Note that the CRL can still be
# parsed after this timeframe passes. It is only used for an expected next
# publication date.
#set_var EASYRSA_CRL_DAYS       180

# How many days before its expiration date a certificate is allowed to be
# renewed?
set_var EASYRSA_CERT_RENEW      30

(略)
```
※有効期限が365日、変更可能日が期限から30日の場合。

有効期限を変える必要があれば、任意の数値に変更し、
問題なければ、そのまま更新作業に入ります。

## 証明書の更新

easyrsa3ディレクトリで以下のコマンドを実行し、証明書の更新を行います。

```
./easyrsa renew <更新対象の証明書ドメイン名> nopass
```

※<更新対象の証明書ドメイン名>はACMのコンソール画面よりドメイン名が記載されていますので、そちらに置き換えてください。
※renewコマンドを実行すると途中で「Continue with renew: 」とプロンプトが出るので、「yes」と入力

## 更新後の期限の確認

```
cat /easy-rsa-master/easyrsa3/pki/issued/<更新対象の証明書ドメイン名>.crt
```

コマンドを実行すると、

```
# cat /opt/easy-rsa-master/easyrsa3/pki/issued/test.server.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            de:*****************
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=Easy-RSA CA
        Validity
            Not Before: Jan  7 06:16:54 2022 GMT
            Not After : Jan  7 06:16:54 2023 GMT
(略)
```

`Not Before:`と`Not After :`で開始日と期限日を確認することができます。


## 証明書の再インポート

更新した証明書はACMコンソール画面より、再インポートが可能です。
対象の証明書のIDをクリックすると、再インポートがあるのでそれを選択します。
あとは、発行作業と同様の手順です。

# 3. 証明書再発行作業
新しい証明書を再度発行する場合に発生する作業です。
基本的には新規で発行する手順と同様ですが、再発行しようとしている証明書が失効していることが前提です。

easyrsa3ディレクトリで以下のコマンドを実行してください。


- サーバ証明書とキーの再発行

```
./easyrsa build-server-full <失効した証明書のドメイン名> nopass
```

- クライアント証明書とキーの再発行

```
./easyrsa build-client-full <失効した証明書のドメイン名> nopass
```

再発行した証明書とキーは再インポートを行います。
手順は2. 更新作業の再インポートと同様です。

# 4. 証明書失効作業
VPN接続で使用している証明書が紛失や漏洩してしまったり、クライアントVPNを使用しなくなったユーザがいた場合に実施する作業です。

## クライアント失効リストを生成
以下のコマンドを実行し、証明書削除とクライアント失効リストを生成します。

```
./easyrsa revoke <失効対象のクライアント証明書のドメイン名>
```
※revokeコマンドを実行すると途中で「Continue with revoke: 」とプロンプトが出るので、「yes」と入力します。


成功すると、「Revocation was successful.」と表示が出ます。※下図は一例

![revoke.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/cfb870d6-9bf4-0d7b-b265-6df499f64cd3.jpeg)

失効リストは「easyrsa-master/easyrsa3/pki/crl.pem」に作成されます。※下図は一例

![crl.pem.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/75b7945e-3abd-9c70-2bd8-e20ceda54987.jpeg)

## 証明書失効リスト（CRL）を更新
以下コマンドを実行し、証明書失効リスト（CRL）を更新します。

```
./easyrsa gen-crl
```

成功すると、更新が成功した旨のメッセージが表示されます。
![gen-crl.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/80479f82-0af2-b278-ed7d-703b785b0a21.jpeg)

## 証明書失効リストをクライアントVPNエンドポイントにインポート
以下コマンドを実行し、上記の作業で生成した証明書失効リストをクライアントVPNエンドポイントにインポートしましょう。

```
aws ec2 import-client-vpn-client-certificate-revocation-list --certificate-revocation-list file:///easy-rsa-master/easyrsa3/pki/crl.pem --client-vpn-endpoint-id <クライアントVPNエンドポイントID>
```
クライアントVPNエンドポイントIDは「VPC」コンソール内の「クライアントVPNエンドポイント」に記載されています。
![スクリーンショット 2022-01-11 130814.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1186674/b6496384-d627-dd4c-9268-0a1c5b238325.jpeg)

成功すると、以下のメッセージになります。

```
{
      "Return": true
}
```

# まとめ
クライアントVPNエンドポイント経由でのアクセスに関しての、証明書の発行などについて説明しました。
ご指摘等ありましたらよろしくお願いいたします。