ACMを使ってインポート証明書の期限管理したい

### やりたいこと
AWS Certificate Manager(ACM)は証明書を使ってサーバ証明書の発行をすることができるが、EV証明書など一部の証明書形式は発行できない。
仕事で使う場合は上記のような外部証明書を使う必要があるが、その場合は証明書の期限管理をExcelでやる必要がある場合も出てきて、証明書の再発行が遅れるリスクがある。
こういった問題に対してACｍを使って証明書の期限管理だけやりたいというのがお題。

### 検証
#### 1.自己証明書作成
本来はEV証明書を使って検証できると良いが、顧客の持ち物だったりするとそれを検証に使うのは調整などがいるのでここは自己証明書を作成していく。
おそらくもっともリソース準備が不要で費用をかけずできるのがCloud Shellを使った方法なので、AWS上で作成していく。
といっても下記のコマンドをCloud Shellで実行するだけ。
①OpenSSLインストール
```Shell:
sudo yum install openssl -y
```
②ルート証明書作成
適当なディレクトリに移動して
```Shell:
openssl genrsa -out ./testrootca.key 2048
openssl req  -new -x509 -key ./testrootca.key -sha256  -days 366 -extensions v3_ca  -out ./testrootca.pem  -subj "/C=JP/ST=Tokyo/O=testcorp./CN=testCN"
```
③中間証明書の作成とルート証明書による署名
```Shell:
openssl genrsa -out ./testintermediateca.key 2048
openssl req -new -key ./testintermediateca.key -sha256 -outform PEM -keyform PEM -out ./testintermediateca.csr  -subj "/C=JP/ST=Tokyo/O=testcorp./CN=testCN"
touch ./testintermediateca.cnf
echo "[ v3_ca ]" >> ./testintermediateca.cnf
echo "basicConstraints = CA:true, pathlen:0" >> ./testintermediateca.cnf
echo "keyUsage = cRLSign, keyCertSign" >> ./testintermediateca.cnf
echo "nsCertType = sslCA, emailCA" >> ./testintermediateca.cnf
openssl x509 -extfile ./testintermediateca.cnf -req -in ./testintermediateca.csr -sha256 -CA ./testrootca.pem -CAkey ./testrootca.key -set_serial 01  -extensions v3_ca  -days 366 -out ./testintermediateca.pem
```

③サーバ証明書の作成と中間証明書による署名
```Shell:
openssl genrsa 2048 > ./testserver.key
openssl req -new -key ./testserver.key -outform PEM -keyform PEM  -sha256 -out ./testserver.csr  -subj "/C=JP/ST=Tokyo/O=testcorp./CN=*.example.com"
openssl x509 -req -in ./testserver.csr -sha256 -CA ./testintermediateca.pem -CAkey ./testintermediateca.key -set_serial 01 -days 15 -out ./testserver.pem
```

作業ディレクトリにサーバ証明書(testserver.pem)とサーバ証明書の秘密鍵(testserver.key)、中間証明書(testintermediateca.pem)が出力されるので、ダウンロードしてくる。

#### 2.ACM登録
①AWS Certificate Managerに移動して証明書の「インポート」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/124ca42a-899d-7bb0-fe0d-0e14b9cfb8bc.png)

②登録
証明書本文：サーバ証明書(testserver.pem)
証明書のプライベートキー：サーバ証明書の秘密鍵(testserver.key)
証明書チェーン - オプション：中間証明書(testintermediateca.pem)
を登録する。
登録方法はテキストエディタで下記をすべてコピペするだけ。
```
-----BEGIN CERTIFICATE-----
～～中略～～
-----END CERTIFICATE-----
```

必要に応じてタグ付けを行い登録する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/2848601c-3d15-b944-b2e5-a4f3d4d2226d.png)

その後下記のように登録できていることを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/39778884-117c-7e99-dc6f-f00e38d45a44.png)


③証明書期限切れの通知
いくつか方法があるが今回はAWS Configで検証し、ルール違反があればEventBridgeを経由してSNS通知する方法を採用する。

#### 3.通知設定
①SNSトピック設定
下記を参考に行う。
[Amazon SNS の開始方法](https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-getting-started.html)

②EventBridge設定

「イベントパス」をデフォルトとして、下記の画像のように設定していく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/a5cd4c0b-d7c7-a351-285b-8be46859e8ce.png)

イベントパターンを下記の用に設定する。
イベントソース：AWS イベントまたは EventBridge パートナーイベント
メソッド：カスタムパターン (JSON エディタ)
```json:イベントパターン(json)
{
  "source": [
    "aws.config"
  ],
  "detail-type": [
    "Config Rules Compliance Change"
  ],
  "detail": {
    "messageType": [
      "ComplianceChangeNotification"
    ],
    "configRuleName": [
      "acm-certificate-expiration-check"
    ],
    "resourceType": [
      "AWS::ACM::Certificate"
    ],
    "newEvaluationResult": {
      "complianceType": [
        "NON_COMPLIANT"
      ]
    }
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/e1089073-8983-fe13-db3b-518b5ac9e3c4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/ad13e6d5-a221-b467-63c0-e9a7642218b6.png)



ターゲットには事前に作成していたSNSトピックを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/17eafd75-a109-6295-a0d5-c6df5e409427.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/a1332b3b-15d1-d0fb-1797-ddb56fa8759d.png)


入力トランスフォーマについては下記のように設定しておく。
```json:インプットパス
{
  "awsRegion": "$.detail.awsRegion",
  "resourceId": "$.detail.resourceId",
  "awsAccountId": "$.detail.awsAccountId",
  "compliance": "$.detail.newEvaluationResult.complianceType",
  "rule": "$.detail.configRuleName",
  "time": "$.detail.newEvaluationResult.resultRecordedTime",
  "resourceType": "$.detail.resourceType"
}
```

```json:インプットテンプレート
"On <time> AWS Config rule <rule> evaluated the <resourceType> with Id <resourceId> in the account <awsAccountId> region <awsRegion> as <compliance>."

"For more details open the AWS Config console at https://console.aws.amazon.com/config/home?region=<awsRegion>#/timeline/<resourceType>/<resourceId>/configuration."
```



最後に確認して作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/79e907b4-ba34-f966-c0c7-f2c819186df8.png)
![qiita_2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/b2239d60-1ffa-5cd4-52ef-71453b1ce511.png)


#### 4.AWS Config設定
①ルール作成
証明書の有効期限チェックはマネージドルールがあるので活用していく。
下記のようにフォームを埋める
ルールタイプ：AWS によって管理されるルールの追加
AWS マネージド型ルール：acm-certificate-expiration-check
変更範囲：リソース
リソース：AWS ACM Certificate
頻度：任意の時間
daysToExpiration：証明書の通知期限

②確認
下記のように正常にルールが作成されていることを確認する。
![qiita_2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/cc982598-d3af-97d0-4082-6cdace30e830.png)


#### 5.通知確認
通知が来てれば検証成功！！！
![qiita_2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561522/664d9b47-7763-a665-47b2-650253452cfc.png)


### まとめ
ACMでインポート証明書の期限切れ通知を行うことは可能。
文面は要検討。
コンソールとSNS通知を利用すれば管理表は不要になる。
管理表の作成が必要な場合は別途CloudShellを利用してCLIから一覧をエクスポート、jqにて整形して、csvエクスポートなどが良さげ？