389 Directory ServerでTLS設定を行ってみる
はじめに
株式会社テイクーワンS.Nです。
前回は簡単なセットアップを行いましたので,今回はTLSの設定を行いたいと思います。
LDAPの扱う情報の性質上,LDAPS(636)での利用シーンは多いかと思いますので公式ドキュメントを確認しつつ進めていこうと思います。
【前回:OpenLDAPしか触ってなかった人が389 Directory Serverを触ってみる】
https://www.tk-1.co.jp/tech_blog/linux/openldap389-directory-server.html
【公式:Configuring TLS/SSL Enabled 389 Directory Server】
https://www.port389.org/docs/389ds/howto/howto-ssl.html
参考情報としては,公式ドキュメントをはじめとして,ChatGPTやCopilotなどのAIにも若干助けてもらっています。
とりあえずアップデートとインスタンスの再作成
前回からだいぶ時間が立ちましたのでdnfコマンドで最新のバージョンにします。
【前回】
インストール:
389-ds-base x86_64 2.2.4-5.el9_2 appstream 2.9 M
【今回】
アップグレード:
389-ds-base x86_64 2.6.1-10.el9_6 appstream 2.8 M
389-ds-base-libs x86_64 2.6.1-10.el9_6 appstream 1.5 M
389 Directory Serverは「2.6.1」で,
OSは「Rocky Linux release 9.6 (Blue Onyx)」になりました。結構あがりましたね...
念の為,このバージョンでインスタンスも再作成し,設定も投入しなおします。
~停止~
# dsctl tk-1 stop
# dsctl tk-1 remove --do-it
~再作成~
# cd /etc/dirsrv/tk1_work/
# dscreate from-file 389ds_take1.inf
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_system4_ou.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_nomura.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_kanri_users.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_syain1.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_aci_system4.ldif
※やってることは前回記事のコマンド実行です
証明書の扱いについて
OpenLDAPでは用意した証明書や秘密鍵のファイルをそのまま指定していましたが
どうやら389dsでは違うようでして,Network Security Services(NSS)データベースを利用するようです。
【OpenLDAPでの設定値例】
dn: cn=config
changetype: modify
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/certs/ca.crt ←中間CA証明書など
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/server.crt ←サーバ証明書
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/server.key ←サーバ秘密鍵
【389dsでのNetwork Security Services(NSS)データデータベースを使った管理】
# certutil -L -d .
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
Self-Signed-CA CT,,
Server-Cert u,u,u
※NSSデータベースでの管理などの情報はRed Hat社のドキュメントなど参考にしていただければと思います
ひとまず,「証明書や鍵をこのNSSデータベースとやらに放り込めば良いんだな」
ということで作業を実施していきます。
証明書をどうするか問題
この手の作業を行うにあたり,証明書をどう入手するか悩みます。
簡単なのは自己証明書を使うことですね。基本的な流れは掴めますので確認としては十分かと思います。
今回は,OpenLDAPで使っていた証明書と鍵のセットをそのまま移行することを目的として自己証明書と鍵のセットを用いて作業しました。
※最後に補足情報として,認証局で署名された証明書と中間CA証明書を使った方法も記載しています。
TLS設定前の状態の確認
では,ドキュメントを参考に現状を確認してみます。
certutil コマンドで作成したインスタンスを指定し,NSSデータベースを確認します。
最初からなにか存在しているのが確認できました。
# certutil -L -d /etc/dirsrv/slapd-tk-1/
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
Self-Signed-CA CT,,
Server-Cert u,u,u
どうやら, dscreate を行った際に自動で自己証明書セットを作成してくれているようです。
ディレクトリの中をみてみますと,証明書っぽい名前のものと
NSSデータベースのファイルを見ることができます。
# ls -l /etc/dirsrv/slapd-tk-1/
合計 356
lrwxrwxrwx 1 root root 6 7月 10 12:58 18a51399.0 -> ca.crt
lrwxrwxrwx 1 root root 15 7月 10 12:58 840143be.0 -> Server-Cert.crt
-rw-rw---- 1 dirsrv root 2129 7月 10 12:58 Server-Cert.crt
-rw-rw---- 1 dirsrv root 2144 7月 10 12:58 Server-Cert.csr
-rw-rw---- 1 dirsrv root 1959 7月 10 12:58 ca.crt
-rw------- 1 dirsrv root 36864 7月 10 12:58 cert9.db
-r--r----- 1 dirsrv dirsrv 1676 7月 10 12:58 certmap.conf
-rw-r----- 1 dirsrv dirsrv 73881 7月 10 12:58 dse.ldif
-rw-r----- 1 dirsrv dirsrv 72841 7月 10 12:58 dse.ldif.bak
-rw-r----- 1 dirsrv dirsrv 76853 7月 10 12:58 dse.ldif.startOK
-rw------- 1 dirsrv root 45056 7月 10 12:58 key4.db
-rw------- 1 dirsrv root 257 7月 10 12:58 noise.txt
-rw------- 1 dirsrv root 91 7月 10 12:58 pin.txt
-rw------- 1 dirsrv dirsrv 555 7月 10 12:58 pkcs11.txt
-rw------- 1 dirsrv root 65 7月 10 12:58 pwdfile.txt
drwxrwx--- 2 dirsrv dirsrv 4096 7月 10 12:58 schema
-r--r----- 1 dirsrv dirsrv 15142 7月 10 12:58 slapd-collations.conf
さらに openssl s_client コマンドでldapsポートを確認すると詳細がわかりました。
# openssl s_client -connect localhost:636
Connecting to 127.0.0.1
CONNECTED(00000003)
Can't use SSL_get_servername
depth=1 C=AU, ST=Queensland, L=389ds, O=testing, CN=ssca.389ds.example.com
verify error:num=19:self-signed certificate in certificate chain
verify return:1
depth=1 C=AU, ST=Queensland, L=389ds, O=testing, CN=ssca.389ds.example.com
verify return:1
depth=0 C=AU, ST=Queensland, L=389ds, O=testing, GN=9f108ee3-efb5-4b57-b007-580b459dfcd9, CN=hogehoge.co.jp
verify return:1
~略~
ということは,TLS設定をするまでもなく出来ていたんですね...
ですが,それでは確認になりませんので
ひとまずこの情報は削除して作業を進めたいと思います。
デフォルト情報の削除
NSSデータベースを管理する certutil コマンドを使い
最初からある証明書情報を削除します。
# certutil -D -d /etc/dirsrv/slapd-tk-1/ -n "Self-Signed-CA"
# certutil -D -d /etc/dirsrv/slapd-tk-1/ -n "Server-Cert"
確認すると何もない状態になりました。
# certutil -L -d /etc/dirsrv/slapd-tk-1/
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
自己証明書のインポート
公式ドキュメントでは certutil コマンドを使って自己証明書の発行登録を行ってますが,これだと鍵は自動で登録されるので参考になりません。
OpenLDAP時代の「証明書」「鍵」のファイルが手元にあるので,こちらを使いたいですね。
この場合どうすれば良いかわからなかったのですが,調べてみるとどうやらNSSデータベースに「鍵」を登録するには証明書と一緒に PKCS#12形式 にする必要があるようです。
【NSS tools : pk12util】
https://nss-crypto.org/reference/security/nss/legacy/tools/pk12util/index.html
というわけで,手元にある自己証明書と鍵のセットを「server.p12」ファイルにしてみます。 ※自己証明書の作成は割愛します
server.key・・・秘密鍵 server.crt・・・自己証明書 server.p12・・・出力する「.p12」ファイル名 "tk1_self_CERT"・・・出力するファイルのニックネーム
# openssl pkcs12 -export -inkey server.key -in server.crt -out server.p12 -name "tk1_self_CERT"
Enter Export Password:(任意)
Verifying - Enter Export Password:(任意)
次にできあがった「server.p12」をインポートしますが,インポートの際にPINを求められます。
あらかじめ下記ファイルの中身を確認しておきます。
389dsはこのファイルをつかってNSSデータベースとやり取りしているようですね。
# cat /etc/dirsrv/slapd-tk-1/pin.txt
Internal (Software) Token:kKO9Dszo7fDb7yaZD5sL**********0bm.SbiufOeSh2UK
では,インポートします。
# pk12util -i server.p12 -d /etc/dirsrv/slapd-tk-1/
Enter Password or Pin for "NSS Certificate DB":(ここにPIN)
Enter password for PKCS12 file:(server.p12作成時に指定したもの)
pk12util: PKCS12 IMPORT SUCCESSFUL
確認すると,インポートできていました。
# certutil -L -d /etc/dirsrv/slapd-tk-1/
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
tk1_self_CERT u,u,u
利用設定
証明書のインポートができましたので,これを使う設定に変更します。
デフォルトのニックネームである「Server-Cert」で作成していたら,この作業は必要ないかもしれません
今回は別の名前にしましたのでLDIFファイルを作って変更したいと思います。
現在の設定値チェックすると,インスタンス作成時に用意してあった「Server-Cert」が指定されています。
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b 'cn=encryption,cn=config' -W nsSSLPersonalitySSL
Enter LDAP Password:
dn: cn=encryption,cn=config
dn: cn=RSA,cn=encryption,cn=config
nsSSLPersonalitySSL: Server-Cert
変更用のLDIFを作成し。
# vim mod_ldaps.ldif
# cat mod_ldaps.ldif
dn: cn=RSA,cn=encryption,cn=config
changetype: modify
replace: nsSSLPersonalitySSL
nsSSLPersonalitySSL: tk1_self_CERT
ldapmodifyを使い適応します。
# ldapmodify -x -H ldap://localhost -D "cn=Directory Manager" -f mod_ldaps.ldif -W
Enter LDAP Password:
modifying entry "cn=RSA,cn=encryption,cn=config"
これで適応できましたので,ldapsearchで変更されていることを確認しましょう。
無事「tk1_self_CERT」になりました。
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b 'cn=encryption,cn=config' -W nsSSLPersonalitySSL
Enter LDAP Password:
dn: cn=encryption,cn=config
dn: cn=RSA,cn=encryption,cn=config
nsSSLPersonalitySSL: tk1_self_CERT
サービス再起動しておきます。
# systemctl restart dirsrv@tk-1.service
【おまけ情報】
もしニックネーム指定を間違えてしまい起動しなくなった場合は,インスタンス内の dse.ldif を直接編集すれば良いようです。
最初からこちらを触ればいいのでは?とも思いますが,非推奨のようですね。
# vim nsSSLPersonalitySSL /etc/dirsrv/slapd-tk-1/dse.ldif
# grep nsSSLPersonalitySSL /etc/dirsrv/slapd-tk-1/dse.ldif
nsSSLPersonalitySSL: tk1_self_CERT
反映の確認
最後に反映されているか確認したいと思います。
まずは openssl s_client コマンドでLDAPSポートをつついてみます。
自己証明書ですので一部エラーがでますが,自分で用意した証明書であることが確認できます。
# openssl s_client -connect localhost:636
~略~
---
Certificate chain
0 s:C=JP, ST=Osaka, L=Osaka, O=tk1, CN=hogehoge.co.jp
i:CN=rootca
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Jul 7 02:39:16 2025 GMT; NotAfter: Nov 22 02:39:16 2052 GMT
---
~略~
subject=C=JP, ST=Osaka, L=Osaka, O=tk1, CN=hogehoge.co.jp
issuer=CN=rootca
次に実際にLDAPSでの利用を見てみます。
ldapsearchコマンドで「-d 1」を指定し詳細を出します。
こちらも自己証明書なので怒られてるメッセージが出てますがエントリはひけているのでOKです。
# ldapsearch -d1 -H ldaps://localhost -D "cn=Directory Manager" -b "uid=syain1,ou=system4,dc=tk-1,dc=co,dc=jp" -W
ldap_url_parse_ext(ldaps://localhost)
ldap_create
ldap_url_parse_ext(ldaps://localhost:636/??base)
Enter LDAP Password:)
ldap_sasl_bind
ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP localhost:636
ldap_new_socket: 3
ldap_prepare_socket: 3
ldap_connect_to_host: Trying 127.0.0.1:636
ldap_pvt_connect: fd: 3 tm: -1 async: 0
attempting to connect:
connect success
TLS trace: SSL_connect:before SSL initialization
TLS trace: SSL_connect:SSLv3/TLS write client hello
TLS trace: SSL_connect:SSLv3/TLS write client hello
TLS trace: SSL_connect:SSLv3/TLS read server hello
TLS trace: SSL_connect:TLSv1.3 read encrypted extensions
TLS trace: SSL_connect:SSLv3/TLS read server certificate request
TLS certificate verification: depth: 1, err: 79, subject: /CN=rootca, issuer: /CN=rootca
TLS certificate verification: Error, invalid CA certificate
TLS trace: SSL_connect:SSLv3/TLS read server certificate
TLS trace: SSL_connect:TLSv1.3 read server certificate verify
TLS trace: SSL_connect:SSLv3/TLS read finished
TLS trace: SSL_connect:SSLv3/TLS write change cipher spec
TLS trace: SSL_connect:SSLv3/TLS write client certificate
TLS trace: SSL_connect:SSLv3/TLS write finished
ldap_open_defconn: successful
~略~
エントリ情報など
~略~
TLSバージョンの許容範囲について
TLS1.1以下は非推奨の流れですので
バージョン2.6.1の389dsでも以下の通りの許容範囲のようです。
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b 'cn=encryption,cn=config' -W | grep TLS1
Enter LDAP Password:
nsTLS1: on
sslVersionMin: TLS1.2
sslVersionMax: TLS1.3
状況によってはTLS1.1を許容するシーンはあるかと思いますので
このあたりをLDIFを用いて変更かければ対応はできそうですね。
おまけ:認証局で発行された証明書のインポート
手持ちのものは中間CA証明書があるタイプなのでそちらを例にします。
これも自己証明書と同様に,PKCS#12形式にして1つにまとれば良いようです。
違いは中間CAは「-certfile」で指定することでしょうか。
2025_privatekey.pem・・・秘密鍵 2025_hogehoge.cer・・・サーバ証明書 subca1.cer・・・中間CA証明書 server_signed.p12・・・出力する「.p12」ファイル名 tk1_signed_CERT・・・出力するファイルのニックネーム
# openssl pkcs12 -export -inkey 2025_privatekey.pem -in 2025_hogehoge.cer -certfile subca1.cer -out server_signed.p12 -name "tk1_signed_CERT"
インポートの方法も変わりません。
# pk12util -i server_signed.p12 -d /etc/dirsrv/slapd-tk-1/
Enter Password or Pin for "NSS Certificate DB":(ここにPIN)
Enter password for PKCS12 file:(server_signed.p12作成時に指定したもの)
pk12util: PKCS12 IMPORT SUCCESSFUL
確認すると以下のようになります
# certutil -L -d /etc/dirsrv/slapd-tk-1/
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
tk1_signed_CERT u,u,u
~~中間CAの証明書情報が勝手に入ってました~~ ,,
opensslコマンドで確認すると認証局で署名された証明書の場合は,中間証明書とルートCA証明書が正しくチェインしていることが確認できるかと思います。
# openssl s_client -connect localhost:636
~略~
depth=2 C=JP, O=SECOM Trust Systems CO.,LTD., OU=~ルートCA~
verify return:1
depth=1 C=JP, O=SECOM Trust Systems CO.,LTD., CN=~中間CA~
verify return:1
depth=0 C=JP, ST=hoge, L=hoge-shi, O=hoge, CN=hogehoge.co.jp
verify return:1
---
Certificate chain
0 s:C=JP, ST=hoge, L=hoge-shi, O=hoge, CN=hogehoge.co.jp
i:C=JP, O=SECOM Trust Systems CO.,LTD., CN=~中間CA~
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Mar 15 02:18:11 2025 GMT; NotAfter: Apr 15 02:18:11 2026 GMT
1 s:C=JP, O=SECOM Trust Systems CO.,LTD., CN=~中間CA~
i:C=JP, O=SECOM Trust Systems CO.,LTD., OU=~ルートCA~
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Dec 15 08:46:22 2020 GMT; NotAfter: May 29 05:00:39 2029 GMT
---
~略~
おわりに
管理方法が違うので少し焦りましたが,
OpenLDAPで使っていた証明書を無事に389dsでも使えるようになりました。
あと運用シーンとしてありそうなのは,スキーマ拡張などでしょうか
機会があればそちらについても触れていければと思います。