ColdFusionにCA証明書をインストールする

ColdFusionで接続先のWebサーバーやメールサーバー、LDAPサーバー（OpenLDAP、Active Directoryなど）が利用している証明書がプライベートCAから発行された証明書や自己証明書だと通信できないので、それを解決する方法です。

※この記事はColdFusion 2018をデフォルトの設定でインストールしている場合を前提としています。ColdFusion 2016でもパスを読み替えれば使えると思います。

# ぱぱっと知りたい

ColdFusionはJVMで動作しているので、keytoolコマンドを利用してcacertsキーストアに証明書をインポートするJavaの方法がそのまま使えます。付属のJavaランタイム（JRE）にもkeytoolが同梱されています。

- JREは `C:\ColdFusion2018\jre` にあります。
- cacertsキーストアのパスワードは `changeit` がデフォルトです。

基本これだけ分かればあとはググればいろいろと出てきますが、私が良く利用しているWindows環境での方法をまとめてみました。

# 手順

## 1. 証明書を準備

インポートする証明書ファイルを用意します。

- サーバー自身が自己証明書を使用しているならその証明書ファイル
- サーバーがプライベートCAから発行されている証明書を利用しているなら、CAの証明書ファイル（サーバーの証明書ではない）

ファイル形式はDER（バイナリ形式）、PEM（BASE64形式）、P7B（PKCS #7形式）のどれでも出来るようですが、よく利用されているPEM形式で準備ます。

:notebook: ファイル名は `example-ca.cer` として保存した例ですすめます。

## 2. バッチ

運用するときやテスト等で毎回手打ちは手間がかかるのでWindowsバッチ化しておきます。

example-ca.cerを保存したフォルダと同じ場所に以下の内容をコピペした `register-cert.bat` ファイルを作ります。

``` register-cert.bat
@echo off
setlocal

set JRE_HOME=C:\ColdFusion2018\jre
set CERT_FILE=%~dp0example-ca.cer
set CERT_ALIAS=example-ca

echo %CERT_FILE% を別名 %CERT_ALIAS% として登録中...
"%JRE_HOME%\bin\keytool.exe" -importcert -alias "%CERT_ALIAS%" -file "%CERT_FILE%" -keystore "%JRE_HOME%\lib\security\cacerts" -storepass changeit -noprompt

echo.
pause
```

不要になった時に削除用のバッチファイルも用意しておきます。

``` remove-cert.bat
@echo off
setlocal

set JRE_HOME=C:\ColdFusion2018\jre
set CERT_ALIAS=example-ca

echo 別名 %CERT_ALIAS% を削除中...
"%JRE_HOME%\bin\keytool.exe" -delete -alias "%CERT_ALIAS%" -keystore "%JRE_HOME%\lib\security\cacerts" -storepass changeit -noprompt

echo.
pause
```

:notebook: `CERT_FILE` のexample-ca.cer部分がファイル名なので、適宜変えます。
:notebook: `CERT_ALIAS` の指定が証明書のエイリアス名として登録されます。削除時にこの名前を使います。

## 3. フォルダの内容

こんな感じになっていればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3934/b67e7f5e-eea4-c8c5-9abf-f1f37ccf0517.png)

## 4. 登録する

`register-cert.bat` をダブルクリックして実行します。

**実行結果**:

```
C:\cert-test\example-ca.cer を別名 example-ca として登録中...
警告: cacertsキーストアにアクセスするには-cacertsオプションを使用してください
証明書がキーストアに追加されました

続行するには何かキーを押してください . . .
```

「証明書がキーストアに追加されました」と表示されれば登録成功です。

ちなみに既に登録済みだと以下のように失敗します。

```
C:\cert-test\example-ca.cer を登録中...
警告: cacertsキーストアにアクセスするには-cacertsオプションを使用してください
keytoolエラー: java.lang.Exception: 証明書はインポートされませんでした。別名<example-ca>はすでに存在します

続行するには何かキーを押してください . . .
```

## 5. 削除する

`remove-cert.bat` をダブルクリックして実行します。

**実行結果**:

```
別名 example-ca を削除中...
警告: cacertsキーストアにアクセスするには-cacertsオプションを使用してください

続行するには何かキーを押してください . . .
```

成功メッセージは出ないようです。未登録だと以下のように失敗します。

```
別名 example-ca を削除中...
警告: cacertsキーストアにアクセスするには-cacertsオプションを使用してください
keytoolエラー: java.lang.Exception: 別名<example-ca>は存在しません

続行するには何かキーを押してください . . .
```

# 補足

ColdFusion 2018のインストール時期によってJVMが「Java 8ベース」と「Java 11ベース」の2パターンあるようです。

今回の環境ではJava 11で、keytoolで`-cacerts`オプションを使うよう警告がでていますが、追加・削除自体はできました。

`-cacerts` オプションは `-keystore` と排他となっていてcacertsファイルまでのパスを指定しなくても良くなったみたいです。ただ、Java 8ではこのオプションが無いので、複数の環境でバッチを流用させるなら記載したようにkeystoreでパス指定した方が現状では良いように思います。

## Java 11で警告出さないようにするには

各バッチファイルの `-keystore "%JRE_HOME%\lib\security\cacerts"` の部分を `-cacerts` に書き換えるだけでOKでした。

## 参考文献

- [cfhttpタグリファレンス](https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-g-h/cfhttp.html)
- [keytool - Java 8](https://docs.oracle.com/javase/jp/8/docs/technotes/tools/windows/keytool.html)
- [keytool - Java 10](https://docs.oracle.com/javase/jp/10/tools/keytool.htm)