やりたいこと
keytoolでp12ファイルをcacert(Javaのキーストア)にインポートさせたい。
実運用でコマンドラインからのインポートを手動実行するのは、手間がかかって現実的ではないため、稼動しているWebアプリの一処理として盛り込みたい。
事前準備
cacertsの書き換えは管理者でしかできないように設定されていたため、Webアプリを実行しているユーザーにも権限を付与。(コマンドプロンプトを管理者権限で実行しないと、証明書をインポートできないようになっていた)
※これに気づくまで、waitFor()の返り値が1(実行失敗)となってて原因探すのに時間かかりました。。。
サンプルソース
※windowsでの実行を想定
sample1.java
String JRE_PATH = "C:\\Program Files\\Java\\jre1.8.0_144";
String KEYSTORE_PATH = JRE_PATH + "\\lib\\security\\cacerts"; //cacertsのパス
String CERTFILE_PATH = "cert.p12"; //p12ファイルのパス
String ALIAS = "test"; // エイリアス
String KEYSTORE_PASS = "changeit"; // キーストアパスワード
String PRIVATEKEY_PASS = "root"; // 証明書のパスワード
// 証明書をインポートするコマンド
ProcessBuilder importCertPb = new ProcessBuilder( "keytool", "-importkeystore", "-keystore",
"\"" + KEYSTORE_PATH + "\"", "-srckeystore",
CERTFILE_PATH, "-srcstoretype", "PKCS12", "-srcstorepass", PRIVATEKEY_PASS, "-deststorepass",
KEYSTORE_PASS );
// エイリアス「1」でインポートされるため、別名をつける
// XXXX:エイリアス(証明書を一意に識別する名前のようなもの)
ProcessBuilder changeAliasPb = new ProcessBuilder( "keytool", "-changealias", "-alias", "1", "-destalias", XXXX,
"-keystore", "\"" + KEYSTORE_PATH + "\"", "-keypass", PRIVATEKEY_PASS, "-storepass", KEYSTORE_PASS );
// 証明書がインポート済みかチェックするコマンド
ProcessBuilder checkExistCertPb = new ProcessBuilder( "keytool", "-list", "-alias", XXXXX,
"-keystore", "\"" + KEYSTORE_PATH + "\"", "-storepass", KEYSTORE_PASS );
// 外部プロセス実行
Process importCertPbSt = importCertPb.start();
// プロセスが終了するまで待機
importCertPbSt.waitFor();
結果を取得し出力する
:sample2.java
// エイリアス:XXXXに合致する証明書を取得するコマンドを実行
Process checkExistCertPbSt = checkExistCertPb.start();
checkExistCertPbSt.waitFor();
InputStream in = checkExistCertPbSt.getInputStream();
try {
String line = null;
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}