JS7® JobScheduler https接続用KeyStore、TrustStore準備


概要

JS7 各コンポーネント間の通信を https で行う際に必要となるKeyStore、TrustStore の作成方法についてのメモ。
2パターン書きますが、どちらでも通信できることは確認済みです。

動作確認環境

JS7 JobScheduler 2.2.1
OpenSSL 1.0.2k-fips
java-11-openjdk.x86_64 1:11.0.13.0.8-1.el7_9

その1 Root CA のTrustStore、サーバー毎のKeyStoreを生成

各サーバーの証明書は、Root CA が発行する。
Root CA の証明書をTrustStoreに格納することで、各サーバー証明書のチェックが可能となる。

最も素直なパターン

Root CA 証明書(自己署名)作成

各サーバー証明書の発行用のRoot CA 証明書を自己署名で作成
あわせて TrustStore用に、PKCS#12形式証明書を作成

COMMONNAME="JS7 Root CA"
COMPANY="Saitamano KUSA Inc."
COUNTRY="JP"
CRTFILE="js7_ca.crt"
KEYFILE="js7_ca.key"
TRUSTSTORE="https-truststore.p12"
KEYPASS="LKJ87-kjuS%esa"
P12PASS="jobscheduler"
TRUSTALIAS="${COMMONNAME}"


# 自己署名証明書、秘密鍵を作成
openssl req \
   -new \
   -x509 \
   -newkey rsa:2048 \
   -out $CRTFILE \
   -keyout $KEYFILE \
   -days 3650 \
   -subj "/C=${COUNTRY}/O=${COMPANY}/CN=${COMMONNAME}" \
   -passout pass:$KEYPASS


# 上記証明書より、TrustStore用にPKCS$12形式証明書を作成
[ -f $TRUSTSTORE ] && rm $TRUSTSTORE
keytool -importcert -noprompt \
    -file $CRTFILE \
    -alias "$TRUSTALIAS" \
    -keystore $TRUSTSTORE \
    -storepass $P12PASS \
    -storetype PKCS12 \
    -trustcacerts

サーバー証明書を作成

各サーバー用の証明書を発行
このとき、認証用にSANを追加する。
あわせてKeyStore用に、PKCS#12形式証明書を作成

#!/bin/bash

gen_keystore() {
    # SAN 対応のPEM形式証明書を作成し、CA証明書で署名。
    # あわせてKeyStore用のPKCS#12形式証明書を作成
    # $1 ホスト名
    # $2 ドメイン名
    # $3 IPアドレス

    JS7HOSTNAME="$1"
    JS7DOMAIN="$2"
    JS7IP="$3"

    COMMONNAME="${JS7HOSTNAME}.${JS7DOMAIN}"
    KEYFILE="${JS7HOSTNAME}.key"
    CSRFILE="${JS7HOSTNAME}.csr"
    CRTFILE="${JS7HOSTNAME}.crt"
    KEYSTORE="${JS7HOSTNAME}-keystore.p12"
    KEYPASS="jobscheduler"
    P12PASS="jobscheduler"
    KEYALIAS="${JS7HOSTNAME}"

    # あらかじめ用意しておいた Root CA 証明書、秘密鍵
    CA_KEYFILE="js7_ca.key"
    CA_CRTFILE="js7_ca.crt"
    CA_KEYPASS="LKJ87-kjuS%esa"

    # SANの設定を別ファイルで作っておく
    echo "subjectAltName = DNS:*.${JS7DOMAIN},DNS:${JS7HOSTNAME},IP:${JS7IP}" > my.cnf


    # 秘密鍵、CSR生成
    openssl req \
    -new \
    -newkey rsa:2048 \
    -out $CSRFILE \
    -keyout $KEYFILE \
    -subj "/CN=$COMMONNAME" \
    -passout pass:$KEYPASS


    # CSRより証明書をPEM形式で作成、CA証明書で署名
    # このときSANも追加する
    openssl x509 \
        -req \
        -CA $CA_CRTFILE \
        -CAkey $CA_KEYFILE \
        -in $CSRFILE \
        -out $CRTFILE \
        -days 3650 \
        -CAcreateserial \
        -passin pass:$CA_KEYPASS \
        -extfile my.cnf


    # 上記証明書と秘密鍵を使ってPKCS#12 形式に変換(KeyStore用)
    openssl pkcs12 \
        -export \
        -inkey $KEYFILE \
        -in $CRTFILE \
        -out $KEYSTORE \
        -name $KEYALIAS \
        -passin pass:$KEYPASS \
        -password pass:$P12PASS

}


gen_keystore js7joc  saitamanokusa.com  192.168.11.101
gen_keystore js7controller  saitamanokusa.com  192.168.11.102
gen_keystore js7agent  saitamanokusa.com  192.168.11.103

これにより作られた https-truststore.p12をTrustStoreとして、
js7joc-keystore.p12 js7controller-keystore.p12 js7agent-keystore.p12 を各サーバーのKeyStoreとして使用する。

この手段を用いた場合は、Root CA の証明書、秘密鍵、パスワードを適切に管理してください。
※証明書の追加発行時に使います。紛失した場合は再作成、TrustStoreの置き換えが必要

その2 各サーバー毎のKeyStore、統合TrustStoreを生成

サーバー毎に自己署名証明書を発行し、KeyStoreを作成
生成した各証明書を、共通のTrustStoreに格納する。

Root CA を使用しないため、Root CA 証明書管理の手間はないが、構成変更時にTrustStore の更新が発生する。

gen_storefiles() {
    # SAN 対応のPEM形式証明書を自己署名で作成
    # あわせてKeyStore用のPKCS#12形式証明書を作成
    # 証明書は共通のTrustStoreファイルに格納する
    # $1 ホスト名
    # $2 ドメイン名
    # $3 IPアドレス

    JS7HOSTNAME="$1"
    JS7DOMAIN="$2"
    JS7IP="$3"

    COMMONNAME="${JS7HOSTNAME}.${JS7DOMAIN}"
    KEYFILE="${JS7HOSTNAME}.key"
    CSRFILE="${JS7HOSTNAME}.csr"
    CRTFILE="${JS7HOSTNAME}.crt"
    KEYSTORE="${JS7HOSTNAME}-keystore.p12"
    TRUSTSTORE="https-truststore.p12"
    KEYPASS="jobscheduler"
    P12PASS="jobscheduler"
    KEYALIAS="${JS7HOSTNAME}"
    TRUSTALIAS="${JS7HOSTNAME}"

    # SANの設定を別ファイルで作っておく
    echo "subjectAltName = DNS:*.${JS7DOMAIN},DNS:${JS7HOSTNAME},IP:${JS7IP}" > my.cnf


    # 秘密鍵、CSR生成
    openssl req \
    -new \
    -newkey rsa:2048 \
    -out $CSRFILE \
    -keyout $KEYFILE \
    -subj "/CN=$COMMONNAME" \
    -passout pass:$KEYPASS


    # CSRより証明書をPEM形式で作成、自己署名
    # このときSANも追加する
    openssl x509 \
        -req \
        -in $CSRFILE \
        -signkey $KEYFILE \
        -out $CRTFILE \
        -days 3650 \
        -passin pass:$KEYPASS \
        -extfile my.cnf


    # 証明書と秘密鍵を使ってPKCS#12 形式に変換(KeyStore用)
    openssl pkcs12 \
        -export \
        -inkey $KEYFILE \
        -in $CRTFILE \
        -out $KEYSTORE \
        -name $KEYALIAS \
        -passin pass:$KEYPASS \
        -password pass:$P12PASS


    # 証明書をTruststore に追加
    keytool -importcert -noprompt \
        -file $CRTFILE \
        -keystore $TRUSTSTORE \
        -alias $TRUSTALIAS \
        -storepass $P12PASS \
        -storetype PKCS12 \
        -trustcacerts

}


gen_storefiles js7joc  saitamanokusa.com  192.168.11.101
gen_storefiles js7controller  saitamanokusa.com  192.168.11.102
gen_storefiles js7agent saitamanokusa.com 192.168.11.103

これにより作られた https-truststore.p12をTrustStoreとして、
js7joc-keystore.p12 js7controller-keystore.p12 js7agent-keystore.p12 を各サーバーのKeyStoreとして使用する。

おまけ HashiCorp Vault 連携用のTrustStore作成

今後 vault 連携機能が随時追加されそうな気がしますので、その際に必要となるTrustStoreの作成方法です。

# vault のサーバー証明書を取得
# vault に https://192.168.11.105:8200 で接続できる前提
openssl s_client -connect 192.168.11.105:8200 -showcerts < /dev/null 2>/dev/null | openssl x509 -outform PEM -out vault.crt

# vault のサーバー証明書を、PKCS#12形式(TrustStore用)に変換
keytool -importcert -noprompt -file vault.crt \
    -keystore vault-truststore.p12 -alias vault \
    -storepass jobscheduler -storetype PKCS12 \
    -trustcacerts

これにより作られた vault-truststore.p12 をTrustStoreとして使います。

用語

KeyStore

証明書+秘密鍵を PKCS#12形式で保存したもの
自サーバーの情報を表すために使用

TrustStore

発行者の証明書を PKCS#12形式で保存したもの
証明書認証時に、接続相手サーバーの証明書が信用できることを確認するために使用

SAN(Subject Alternative Name)

CommonNameの別名として、自サーバーの情報を表す。
複数のドメイン、ホスト名、IPアドレスなどの情報を格納できる。
JOC、Controller、Agentとの接続時に、接続先と指定した値(IP、ホスト名など)と、接続先サーバー証明書上のSANに記載された情報が一致する必要がある。

本例では、SANにホスト名、ドメイン名(ワイルドカード使用可)、IPアドレスを指定する

※接続先がSANに含まれていない場合、認証エラーとなる。
※接続時に常にドメイン名を使う場合は、CommonNameにワイルドカード付ドメイン名などを指定することで、SANは指定しなくても接続可能。ただしこの場合、IP指定での接続はできない

keytool

証明書の生成、管理を行うコマンド
TrustStore 生成時に必須 ( openssl では不可 )
OpenJDK インストールで利用可能
※JS7 インストール環境であれば、OpenJDK が入っている

KeyStore Explorer

https://keystore-explorer.org/
GUIでの証明書管理が可能。
KeyStore 、TrustStore の内容を確認する際に、インストールしてあると便利。

参考