はじめに
【スタート】
- Rocky9 を OS とする 4 個の VM(以下 VM1, VM2, VM3, VM4 と表記)
- VM1 のホスト名は vm1.machi.city、他も同様
- 各々の IP アドレスは 172.16.10.n/24 (n=1~4)
- デフォルトゲートウェイおよび DNS は全て 172.16.10.100
【ゴール】
- VM1 を LDAP サーバにし、すべての VM に同じユーザ情報でログインできるようにする
以下、コマンドは全て root ユーザ として実行するものとします。
LDAP サーバの設定【VM1】
まずはこのサイトの流れに従って、ldap ユーザを追加するところまでやります。
今回の例では、
# ip - fqdn - hostname
172.16.10.1 vm1.machi.city vm1
となります。これに合わせて名前を適宜変更しながら実行しました。
また、ldap ユーザのホームディレクトリは「/myfs/home/<ユーザ名>」のようにしたかったので、 adduser.ldif の設定では
- 追加するユーザの名前は ldapuser0
- そのホームディレクトリは homeDirectory: /myfs/home/ldapuser0
としました。
ルート CA(認証局:Certificate Authorities)の作成
ディレクトリ構成
openssl コマンドを使用する際、/etc/pki/tls/openssl.cnfのルールが適用されます。
参考
なのでまずは /etc/pki/tls/openssl.cnf を読んでみます。
めっちゃ大雑把にいうと、
[ req ] は csr を作る用で [ x509 ] は自己署名の crt を作る用、
[ ca ] は CA:TRUE と書かれた証明書を持っている認証局として
他者の証明書に署名してやる用
みたいな感じのことが書かれていると思います。
まず最初に作りたいのは、[ ca ] を使って他人に署名してやるルート CA です。
[ ca ] を見ると、指定されているディレクトリが /etc/pki/CA 以下になっていいます。このディレクトリは最初から存在しないので、とりあえずこれを作成しておきましょう。
※ CA 用のディレクトリを作成して、そこに移動します。
mkdir /etc/pki/CA/
cd /etc/pki/CA/
※ 配下のディレクトリ及びファイルを作っておきます。
mkdir certs
mkdir crl
touch index.txt
mkdir newcerts
echo "00" > serial
mkdir crlnumber
mkdir private
ルートの証明書作成
CA の自己証明書を作成します。
例として、以下では次のような名前で作成します。
- my_root_ca.key:ルート CA の秘密鍵
- my_root_ca.crt:ルート CA の証明書(自己署名)
まず秘密鍵用のディレクトリに「ca_company.key」と名付けた秘密鍵を作成します。
openssl genpkey -out /etc/pki/CA/private/my_root_ca.key \
-algorithm RSA -pkeyopt rsa_keygen_bits:2048
この例だと、
「openssl を用いて秘密鍵を作ります、パスは /etc/pki/CA/private/my_root_ca.key です、RSA 暗号を用いて bit 長は 2048 です」
という意味。
CA 秘密鍵は厳重に管理しましょう。
chmod 700 /etc/pki/CA/private
次はお好みでやらなくてもいいですが、セキュリティが気になるならやっときましょう。これの意味は後ほど出てきます。
$ vi /etc/pki/tls/openssl.cnf
[ v3_ca ] セクションに次の行を追加!
keyUsage = cRLSign, keyCertSign, digitalSignature
次に自己署名証明書「my_root_ca.crt」を作成します。
直感的には分かりづらいステップですが、落ち着いてよく意味を考えながらやりましょう。
方法1か方法2どちらでも同じ結果になります。
※ 秘密鍵から直接 crt を発行(詳しくは $ openssl req -help で -x509 の意味を読む)
openssl req -x509 -new -days 3650 \
-key /etc/pki/CA/private/my_root_ca.key \
-subj "/C=JP/ST=Osaka/L=Nipponbashi/O=My-CA/CN=vm1.machi.city" \
-out /etc/pki/CA/my_root_ca.crt
※ 確認用
cat my_root_ca.crt | openssl x509 -text -noout
※ csr を作ってから
openssl req -new \
-key /etc/pki/CA/private/my_root_ca.key \
-subj "/C=JP/ST=Osaka/L=Nipponbashi/O=My-CA/CN=vm1.machi.city" \
-out /etc/pki/CA/my_root_ca.csr
※ crt を発行(設定ファイルから [ v3_ca ] セクションを参照して CA:TRUE を付ける)
openssl x509 -req -days 3650 \
-in /etc/pki/CA/my_root_ca.csr \
-signkey /etc/pki/CA/private/my_root_ca.key \
-extfile /etc/pki/tls/openssl.cnf -extensions v3_ca \
-out /etc/pki/CA/my_root_ca.crt
※ 確認用
cat my_root_ca.crt | openssl x509 -text -noout
ルート CA の証明書なので、有効期限は長めに 10 年くらいとってみました。
-subj に関してはテスト環境ですし、組織名は適当に「My-CA」と付けてみました。
ただし CN に関してはしっかりつけましょう。ここにはマシンのホスト名をドメインまで省略せずに書きます。
[ ca ] セクションの設定
ルート CA が中間 CA やサーバーに署名する際、さきほど作った証明書および秘密鍵をデフォルトで参照するようにします。
openssl.conf を次のように書き変えます。
$ vi /etc/pki/tls/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 certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.certificate = $dir/my_root_ca.crt # 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/my_root_ca.key # The private key
・・・(略)・・・
これでルート CA の準備は出来ました。
認証して欲しいサーバが署名を依頼してきたら
openssl ca -policy policy_anything -days 〇〇〇 \
-in /(略)/サーバ.csr \
-out /(略)/サーバ.crt
とすれば良いですし、中間 CA になりたい者から署名をせがまれたら
openssl ca -policy policy_anything -days 〇〇〇 \
-extfile /etc/pki/tls/openssl.cnf -extensions v3_ca \
-in /(略)/中間CA.csr \
-out /(略)/中間CA.crt
とすれば OK です。
LDAP サーバの証明書作成
例として、以下では次のような名前で作成します。
- my_ldap.key:LDAP サーバの秘密鍵
- my_ldap.csr:LDAP サーバの署名要求
- my_ldap.crt:LDAP サーバの証明書
LDAP サーバの csr を作成します。
この csr に「My-CA」が署名をすることで、LDAP サーバの提供するディレクトリサービスが「my_root_ca.crt を持つクライアントにとって信頼できるもの」となります。
まず OpenLDAP をインストールした時点で
$ ls /etc/openldap/
certs/ check_password.conf ldap.conf schema/ slapd.d/
のように certs/ もしくはそれに類するフォルダが含まれているかと思います(なければ mkdir コマンドで作ってください)。折角分かりやすい名前を準備してくれているので、ここに証明書を入れることにしましょう。
※ ディレクトリを移動しておきます。
cd /etc/openldap
※ LDAP の秘密鍵用のディレクトリも作っておきましょう。
mkdir private
※ LDAP の秘密鍵
openssl genpkey -out /etc/openldap/private/my_ldap.key \
-algorithm RSA -pkeyopt rsa_keygen_bits:2048
※ csr 作成
openssl req -new \
-key /etc/openldap/private/my_ldap.key \
-subj "/C=JP/ST=Osaka/L=Umeda/O=My-LDAP/CN=vm1.machi.city" \
-out /etc/openldap/certs/my_ldap.csr
今回はLDAPとルートCAが同じVM1内にあるので、
次のコマンドでサーバ証明書の発行&配置をします。
※ ルート CA に csr を渡し、署名して crt を作ってもらう。
openssl ca -policy policy_anything -days 395 \
-in /etc/openldap/certs/my_ldap.csr \
-out /etc/pki/CA/certs/my_ldap.crt
※ crt を /etc/openldap/certs/my_ldap.crt に配置。
cp /etc/pki/CA/certs/my_ldap.crt /etc/openldap/certs/my_ldap.crt
※ 認証済み証明書と LDAP 自身の秘密鍵を LDAP が扱えるようにする。
chown ldap:ldap /etc/openldap/certs/my_ldap.crt
chown ldap:ldap /etc/openldap/private/my_ldap.key
LDAP サーバの設定を修正する。
vi tls.ldif
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/pki/CA/my_root_ca.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/private/my_ldap.key
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/my_ldap.crt
ファイル内の記述は、olcTLSCACertificateFile 達 3 種類を追加(add:)し、秘密鍵や証明書がどこにあるか認識できるように LDAP の設定(dn: cn=config)を修正(changetype: modify)するという意味。
すでに追加した olcTLSCACertificateFile 達を修正したい場合は、「add:」の部分を「replace:」にします。
次のコマンドで設定を反映させます。
ldapadd -Y EXTERNAL -H ldapi:/// -f tls.ldif
では、先ほど作ったルート CA の証明書を各マシンに送っておきましょう。
自分の作った環境に合わせて送り先など変更してください。
※ Rocky Linux9 はセキュリティの関係上外から直接 root にアクセスできないかもしれません。その場合はrootではなくユーザーに送ってください。
cp /etc/pki/CA/my_root_ca.crt /root
scp /etc/pki/CA/my_root_ca.crt root@172.16.10.2:/root
scp /etc/pki/CA/my_root_ca.crt root@172.16.10.3:/root
scp /etc/pki/CA/my_root_ca.crt root@172.16.10.4:/root
参考:
- 今度こそopensslコマンドを理解して使いたい (1) ルートCAをスクリプトで作成する
- とほほのOpenSSL入門
- CA 構築のための OpenSSL の設定
- OpenSSLで作った自己署名証明書でIAM Roles Anywhereを使ってみた
LDAP クライアントの設定【VM1~VM4】
ここまでで VM1 内にルート CA と LDAP サーバを準備してきました。
次は LDAP クライアントの準備です。
なお、LDAP サーバである VM1 内からも当然ディレクトリサービスにアクセスしたいので、VM2~VM4 だけでなく VM1 内でも LDAP クライアント設定もしましょう。まとめると、
- VM2、VM3、VM4 は LDAP クライアント
- VM1 は ルート CA かつ LDAP サーバ かつ LDAP クライアント
です。
ここの設定は VM1 ~ VM4 で共通です。
※ 受け取ったルートの証明書を信頼リストに配置
mv /root/my_root_ca.crt /etc/pki/ca-trust/source/anchors/my_root_ca.crt
※ 情報を反映
update-ca-trust
クライアント用の一式をインストールし、接続方法を sssd を用いるように設定します。
cd ~
dnf -y install openldap-clients sssd sssd-ldap oddjob-mkhomedir
authselect select sssd with-mkhomedir --force
コメントアウトを外して LDAP サーバの URL と Suffix を追記します。
vi /etc/openldap/ldap.conf
URI ldap://vm1.machi.city/
BASE dc=machi,dc=city
太字部分は先程までにつくった LDAP サーバの情報を入力。
ldap_tls_cacertdir は demand にしておきます。
vi /etc/sssd/sssd.conf
[domain/default]
id_provider = ldap
autofs_provider = ldap
auth_provider = ldap
chpass_provider = ldap
ldap_uri = ldap://vm1.machi.city/
ldap_search_base = dc=machi,dc=city
ldap_id_use_start_tls = True
ldap_tls_cacertdir = /etc/openldap/certs
cache_credentials = True
ldap_tls_reqcert = demand[sssd]
services = nss, pam, autofs
domains = default[nss]
homedir_substring = /myfs/home
設定を反映します。
chmod 600 /etc/sssd/sssd.conf
systemctl restart sssd oddjobd
systemctl enable sssd oddjobd
※ 確認用のコマンド
ldapsearch -x -b dc=machi,dc=city -ZZ
確認用のコマンドをうち、
[root@vm1 ~]# ldapsearch -x -b dc=machi,dc=city -ZZ
ldap_start_tls: Connect error (-11)
additional info: error:0A000086:SSL routines::certificate verify failed (self-signed certificate in certificate chain)
のような出力になれば、おそらくルート CA 証明書に
keyUsage = cRLSign, keyCertSign, digitalSignature
が抜けていると考えられます。発行時に openssl.cnf をいじったのはこれを回避するためです。
上手くいかない場合は(テスト環境であれば)ldap_tls_cacertdir を allow にしてエラーを黙らせてもいいです。
では、ldap ユーザ用のホームを準備しましょう。
sssd.conf へ書きこんだ内容に沿って、ここでは /myfs/home を作成します。
mkdir -p /myfs/home
初ログイン時に自動で各ユーザのホームディレクトリが作成されるように /myfs/home に関して SELinux の設定を変更します。
※「/myfs/home」でやると「//home」に直せと文句を言われることがある。
※ ここはまだちょっと理解できていないが、とりあえず今回はこれで行く。
semanage fcontext -a -e / /myfs
semanage fcontext -a -t home_root_t '//home'
restorecon -R /myfs/home
※ 確認用、home_root_t が出れば OK
ls -ldZ /myfs/home
※(追記):説明のため「/」の権限を「権限A」と呼ぶとする。権限Aを「myfs/」に与えた状態を目指している。イメージ的には、
ここで SELinux 的に権限を「/」=「myfs/」と認識するようにすれば myfs/ にも権限A が付くが、その代わり「/myfs/home」ではなく「//home」と書くことになる、
みたいな感じ。
これで、VM1~VM4 に
ssh ldapuser0@172.16.10.n (例では n=1~4)
をすると自動でディレクトリが作成されるようになります。
(若干遠回りしましたが、ホームディレクトリを /home のままにするのであれば SELinux の部分は飛ばせると思います。今回は通常のユーザと LDAP の管理するユーザを分けたいと思い、上記の変更を加えました。)
図であらわすと次のような感じ。
以上でどの VM にも同じ ldap ユーザとパスワードで接続できるようになりました。完成!
参考:
【おまけ】
ここから先は個人的な興味として、実験的にやっていこうと思います。
間違っていましたら教えていただけると幸いです。
NFS の設定
ホームディレクトリをいじってみる
ホームディレクトリの本体を別のディレクトリに変更して NFS で共有し、
ログイン時の位置に本体に繋がるシンボリックリンクを置きます。
mkdir -p /myfs-real/home
mkdir /myfs
ln -s /myfs-real/home/ /myfs/home
semanage fcontext -a -t home_root_t /myfs-real/home
restorecon -R /myfs-real/home
SELinuxの権限については、ホームディレクトリになる/myfsの方に
semanage fcontext -a -e / /myfs
restorecon -R /myfs
シンボリックリンクは自分の権限を参照するので、
/myfs/home --> /myfs-real/home/
の場合は
/ = /myfs
でmyfsの設定をして、
/myfs-real/home に home_root_t を追加すると
ls -ldZ /myfs/home/ に home_root_t が確認できる。
VM1(nfs サーバ、ldap サーバ)
dnf -y install nfs-utils
vi /etc/idmapd.conf
5行目を変更
Domain = machi.city
vi /etc/exports
追加する↓
/myfs-real 172.16.10.0/24(rw,no_root_squash)
※ /myfs-real/home を共有したい
mkdir /myfs-real/home
systemctl enable --now rpcbind nfs-server
※ firewall に nfs を許可、永続化
firewall-cmd --add-service=nfs
firewall-cmd --runtime-to-permanent
VM2~VM4(nfs クライアント、ldap クライアント)
dnf -y install nfs-utils
vi /etc/idmapd.conf
5行目を変更
Domain = machi.city
システム起動時に自動的に NFS 共有をマウントするようにします。
mkdir -p /myfs-real/home
mount -t nfs vm1.machi.city:/myfs-real/home /myfs-real/home
vi /etc/fstab
追加する↓
vm1.machi.city:/myfs-real/home /myfs-real/home nfs defaults 0 0
※ /myfs について SELinux の権限を変更
semanage fcontext -a -e / /myfs
restorecon -R /myfs
※ シンボリックリンクで本体(nfsマウントしたもの)に繋げる
ln -s /myfs-real/home/ /myfs/home
※ nfs マウントしているディレクトリは ls -ldZ /myfs-real/home すると
※ system_u:object_r:nfs_t:s0 と表示される。
※ nfs マウントしているディレクトリにも自動でホームディレクトリを作りたい。
※ getsebool -a | grep nfs コマンドを使うと、use_nfs_home_dirs --> off という表記が見つかる。
※ これを on にする。永続化のために -P をつける。
setsebool -P use_nfs_home_dirs on
これで、初めて使うユーザ情報でログインする際、どの VM にアクセスしても共有済みホームディレクトリが作成されるようになりました。
図にするとこのような感じです。
今回は以上です。