【オレオレ証明書】JenkinsのインストールからSSL/TLS証明書を反映させるまで


保護されていない通信

Chrome 68以降からSSL対応をしていないサイトにアクセスした場合、保護されていない通信という警告が表示されるようになりました。

ローカル環境なのですが、上記画像のようになってしまうのは、誰かに見せる時に気になるかと思ったので、これを機会に対応しようと思います。

やること

今回は、CentOS7(vagrant+virtualbox)に構築したJenkinsをhttps化し証明書を適用するまでをやっていきたいと思います。

前提

Vagrantfileで以下を設定しています。

Vagrantfile
config.vm.network "private_network", ip: "192.168.33.10"

大まかな流れ

  • Jenkinsインストール
  • 認証局(CA)の作成
  • SSL/TLSサーバ証明書作成
  • Jenkinsのhttps化(ポート変更、証明書適用等)

利用した環境

OS - Software version
CentOS 10.13.6
vagtant 2.1.2
virtualbox 5.2.18
openjdk 1.8.0
jenins 2.138.1

1. jenkinsのインストール準備

OpenJDK1.8のインストール

$ sudo su - # 以降の手順もrootユーザーで実施します
# yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel

環境変数に設定

/etc/profile
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5.x86_64
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar

dirname $(readlink $(readlink $(which java)))`Javaのインストール先を確認できます。

設定反映

# source /etc/profile
# echo $JAVA_HOME

JAVA_HOMEに設定した「/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5」が表示されれば反映されています。

Jenkinsが含まれるRPMを追加

# wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
# rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

2. Jeninsのインストール

# yum -y install jenkins

起動/自動起動設定

# service jenkins start
# chkconfig jenkins on

インストール用のパスワードを確認

# cat /var/lib/jenkins/secrets/initialAdminPassword

ChromeでJenkinsへアクセス

表示にしたがってインストールを進めます。

インストールが完了し、ログインするとこんな感じになります。

※jenkinsの画面が真っ白な場合、systemctl restart jenkinsで再起動してみると治ることがあります。

hosts設定 (ホスト側)

仮想マシンへのアクセスとDNSに変更します。

/etc/hosts
# 追記
192.168.33.10 jenkinsci.com

確認

$ ping jenkinsci.com
PING jenkinsci.com (192.168.33.10): 56 data bytes
64 bytes from 192.168.33.10: icmp_seq=0 ttl=64 time=0.364 ms
64 bytes from 192.168.33.10: icmp_seq=1 ttl=64 time=0.405 ms

リクエストが返ってくればOK

3. 認証局(CA)の作成

openssl.cnfのバックアップ

cp -pr /etc/pki/tls/openssl.cnf /etc/pki/tls/openssl.cnf.org

openssl.cnfの設定

openssl.cnfの変更箇所
[ CA_default ]
private_key    = $dir/private/cakey.pem #pemと[#]の間に半角スペースを入れる

default_md = sha256

[ req ]
default_md = sha256

[usr_cert ]
# add
subjectAltName = @alt_names # Chrome 58対応

CAの秘密鍵作成

RSA方式で2048bitのcakey.pemを作成。

# openssl genrsa \
   -aes256 \
   -passout 'pass:oreoreca' \ 
  -out /etc/pki/CA/private/cakey.pem 2048 \
   -days 3650

Generating RSA private key, 2048 bit long modulus
..........................................................................+++
...........................................................................................+++
e is 65537 (0x10001)
  • -aes256 :Advanced Encryption Standard (
    高度暗号化標準)。 古くなってきたDESの代わりに考案された暗号化方式。
    米国政府によって認められ、推奨されている暗号化標準。

  • -passout 'pass:設定するパスワード':ターミナルでのパスワード入力を省略できる。

  • -days:有効期間の設定。今回は、3650日(約10年)で設定。[CA_default]セクションのdefault_daysで設定してもOK。

注意:各ファイルの名称は、「openssl.cnf」に合わせて設定しています。
[ CA_default ]

dir     = /etc/pki/CA       # Where everything is kept
certs       = $dir/certs        # Where the issued certs are kept
crl_dir     = $dir/crl      # Where the issued crl are kept
database    = $dir/index.txt    # database index file.
#unique_subject = no            # Set to 'no' to allow creation of
                    # several ctificates with same subject.
new_certs_dir   = $dir/newcerts     # default place for new certs.

certificate = $dir/cacert.pem   # The CA certificate
serial      = $dir/serial       # The current serial number
crlnumber   = $dir/crlnumber    # the current crl number
                    # must be commented out to leave a V1 CRL
crl     = $dir/crl.pem      # The current CRL
private_key = $dir/private/cakey.pem # The private key
RANDFILE    = $dir/private/.rand    # private random number file

秘密鍵からCSR(証明書発行要求のファイル)を作成

# openssl req \
  -new \
  -key /etc/pki/CA/private/cakey.pem \
  -passout 'pass:oreoreca' \
  -out /etc/pki/CA/cacert.csr \
  -subj "/C=JP/ST=Tokyo/L=Shibuya-ku/O=OreOreCA inc./OU=OreOreCA labo/CN=oreoreca.com"

Enter pass phrase for /etc/pki/CA/private/cakey.pem: <-- 秘密鍵のパスワードを入力

CSRを使用してオレオレ証明書を作成

認証局の秘密鍵を使って、自分で証明書に署名する。

# openssl x509 \
    -req \
   -in /etc/pki/CA/cacert.csr \
  -signkey /etc/pki/CA/private/cakey.pem \
  -out /etc/pki/CA/cacert.pem \
    -days 3650

Signature ok
subject=/C=JP/ST=Tokyo/L=Shibuya-ku/O=OreOreCA inc./OU=OreOreCA labo/CN=oreoreca.com
Getting Private key
Enter pass phrase for /etc/pki/CA/private/cakey.pem:  <-- 秘密鍵のパスワードを入力

認証局運用に必要なファイルの生成

touch /etc/pki/CA/index.txt
echo 00 > /etc/pki/CA/serial
  • index.txt:履歴情報。
  • serial:証明書のカウンタ。次に発行する番号を記載。

4. SSL/TLSサーバ証明書作成

先ほど作成したCAでJenkinsに適用するSSL/TLSサーバ証明書を発行します。

秘密鍵作成

# openssl genrsa \
  -aes256 \
  -passout 'pass:jenkinscipass' \
  -out /etc/pki/tls/private/jenkinscikey.pem 2048

Generating RSA private key, 2048 bit long modulus
..........................................................................+++
...........................................................................................+++
e is 65537 (0x10001)

パスフレーズなしの秘密鍵にする

# openssl rsa \
  -passin 'pass:jenkinscipass' \
  -in /etc/pki/tls/private/jenkinscikey.pem \
  -out /etc/pki/tls/private/jenkinscikey.pem

writing RSA key

※jenkinsで利用する際にパスフレーズを聞かれないようにする為。

CSR作成

O=はオレオレ証明書と同じにすること。
CN=にhostsで設定した値を入れること。

# openssl req \
 -new \
 -sha256 \
 -key /etc/pki/tls/private/jenkinscikey.pem \
 -out /etc/pki/tls/certs/jenkinsci.csr \ 
 -subj "/C=JP/ST=Tokyo/L=Shibuya-ku/O=OreOreCA inc./OU=jenkinscilabo/CN=jenkinsci.com"

Chrome 58対応(san.ext作成)

Chrome 58 以降で、ドメイン名と証明書の照合にcommonNameが使われず、subjectAlternativeNameのみを使用するようになったとのこと。
回避策としてサーバ証明書発行する際に-extfile san.extを指定して実行する。

san.ext
subjectAltName=DNS:jenkinsci.com

オレオレ認証局でサーバ証明書作成

# openssl ca \
   -in /etc/pki/tls/certs/jenkinsci.csr \
   -out /etc/pki/tls/certs/jenkinsci.com.crt.pem \
   -days 3650 \
   -extfile san.ext

Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: ~~~
            Not After : ~~~
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = OreOreCA inc.
            organizationalUnitName    = jenkinsci labo
            commonName                = jenkinsci.com
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:jenkinsci.com
Certificate is to be certified until ~~~ (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

5. Jenkinsのhttps化(証明書適用、ポート変更等)

キーストア配置先を作成

# mkdir -p /var/lib/jenkins/.ssl

※jenkinsが/var/lib/jenkins/にインストールされている前提

PKCS#12形式変換(秘密鍵とサーバ証明書をまとめる)

# openssl pkcs12 \
   -export \
  -in /etc/pki/tls/certs/jenkinsci.com.crt.pem \
    -inkey /etc/pki/tls/private/jenkinscikey.pem \
   -out /var/lib/jenkins/.ssl/jenkins_keystore.p12


Enter Export Password: <-- 任意のパスワード
Verifying - Enter Export Password: <-- 再入力

PKCS#12形式からJKS形式のキーストアを作成

# keytool \
   -importkeystore \
  -srckeystore /var/lib/jenkins/.ssl/jenkins_keystore.p12 \
  -srcstorepass 'zamapass' -srcstoretype pkcs12 \
  -destkeystore /var/lib/jenkins/.ssl/jenkins_keystore.jks \
  -deststorepass 'zamapass' -deststoretype JKS

※パスワードをzamapassにした場合の例です

キーストアのオーナー権限変更

# chown -R jenkins:jenkins /var/lib/jenkins/.ssl

Jenkinsのconfig設定

/etc/sysconfig/jenkins
JENKINS_PORT=-1
JENKINS_HTTPS_PORT="55443"
JENKINS_HTTPS_KEYSTORE="var/lib/jenkins/.ssl/jenkins_keystore.jks"
JENKINS_HTTPS_KEYSTORE_PASSWORD="zamapass"

jenkins の再起動

# systemctl restart jenkins

サーバ証明書を共有ディレクトリ(ホスト側とゲスト側)にコピー

cp jenkinsci.com.crt.pem /共有ディレクトリ/jenkinsci.com.crt

6. ホスト側で証明書を信頼させる

  1. /共有ディレクトリ/jenkinsci.com.crt をダブルクリックし、キーチェーンアクセスへ証明書を追加。
  2. 追加したキーチェーンアクセスをダブルクリックし、「信頼」の「この証明書を使用するとき」で常に信頼を選択。

7. Jenkinsのシステム設定

https://jenkinsci.com:55443 にアクセス。

[Jenkinsの設定] - [システムの管理] - [Jenkins URL] の設定値を
https://jenkinsci.com:55443/ に変更。

最後に

勉強の為に手動で色々調べながら設定しましたが、いくつも証明書を作成する場合は大変だと思います。
実際に運用するのであれば、ちゃんとお金を使いドメイン取得とDNS設定をして
Let's Encryptで証明書を取得した方が楽だったなーと思いました。

参考文献