(ヽ´ω`) < 助けてほしいマン

わからないことを助けてほしいマンが書くブログ

(ヽ´ω`) < OpenLDAP + SSSDでLinuxログインアカウント一元管理がさっぱりわからん - 3. SSSDの設定 -

(ヽ´ω`) < SSSDが特によくわからん

そもそもSSSDってなんなのよ、という話になるが、RedHatがメインで開発しているオープンソースの統合認証基盤FreeIPAに付随して作成されたソフトウェアとのこと。

じゃあそのFreeIPAって何? となるとこれはもう下記の記事でも読んでくれとしか言えないぐらい、色々な機能を持っている。

thinkit.co.jp

ちなみに記事の題名が「Linuxの認証を簡単にする」と書いてあるが、機能てんこ盛りの構成要素てんこ盛りなので、最初の稼働させるまでは簡単かもしれないのだが、軽い気持ちで実際に運用し始めると軽く地獄を見ると思う。見た。見ている。

そんな重厚でイケてるFreeIPAという基盤に、認証要求元のサーバから実際に問い合わせを行う役割を担うのがSSSDとなる。

実際にはその前にPAMとNSSが入っていて、PAM・NSSから投げられた処理要求をSSSDがキャッシュやらなんやらでうまいこと処理しつつ、更に後ろのFreeIPAやらOpenLDAPやらActiveDirectoryに問い合わせを行ってくれる。

下記のサイトの一番上の図を引用する。

www.certdepot.net

f:id:tsugi-hagi:20191125144438p:plain
Quote From https://www.certdepot.net/rhel8-identity/

この図で左側の "Client" はLinux(より厳密に言うとLinux上のNSSとPAM)で、真ん中にSSSD。右側の "Identity Server" と "Authentication Server" はOpenLDAP, FreeIPA, ActiveDirectoryなどになる。

そう、実はFreeIPAだけではなくOpenLDAP(特にOpenLDAPだけでもないが)やActiveDirectoryも認証のバックエンドとして設定が可能で、今回はOpenLDAPを使った設定を行っていく。

(ヽ´ω`) < パッケージインストール

ここからの作業は、前の記事までで作成したOpenLDAPサーバではなく、実際の認証を行うStagingサーバに対して実施する。
(テストとしてOpenLDAPと同じサーバで設定しても問題なし)

必要になるパッケージをインストールする。

# yum install sssd sssd-client sssd-ldap sssd-tools sssd-common oddjob-mkhomedir

(ヽ´ω`) < SSSDの有効化

SSSDサービスの有効化とNSS, PAMの設定ファイルへの組み込みを行う。

上にも書いた通り、SSSDはNSSとPAMから呼び出されてユーザ情報をバックエンドに拾いに行くので、 /etc/nsswitch.conf/etc/pam.d 以下のファイルにエントリを追加する必要がある。

nsswitch.confはまだいいとして、PAM関連の設定ファイルは触りたくないという人も多いと思うがご安心を。
このための authconfig というコマンドが用意されている。(RHEL8からは非推奨パッケージとなっていて authselect で代替するように言われているが…)

# authconfig --enablesssd --enablesssdauth --enablemkhomedir --update

これにより /etc/nsswitch.conf/etc/pam.d 以下のファイルにSSSDを使用するための設定が追記される。

また --enablemkhomedir により、ユーザログイン時にホームディレクトリが存在しない場合は、自動で作成されるようにPAMの system-authsession にエントリが追加される。

(ヽ´ω`) < sssd.confの作成

/etc/sssd/sssd.conf を作成して、SSSDの動作を定義する。
このファイルの中でOpenLDAPのサーバIPアドレスや、バインドユーザ情報、どのグループに対してログイン・sudoを許可するかを指定していく。

不親切なことにSSSDパッケージをインストールしても、サンプルファイルのようなものは作成してくれないので、0から入力していく必要がある。 流石に面倒なので下記の内容をまるっとコピーして必要な箇所だけ修正していく。

[sssd]
config_file_version = 2
services = nss, pam, sudo, ssh
domains = default

[domain/default]
id_provider = ldap
chpass_provider = none

ldap_uri = ldap://172.16.1.177
ldap_search_base = dc=tsugihagi,dc=local
ldap_id_use_start_tls = False
ldap_tls_reqcert = allow

ldap_default_bind_dn = cn=Manager,dc=tsugihagi,dc=local
ldap_default_authtok_type = password
ldap_default_authtok = hogehoge

ldap_user_ssh_public_key = sshPublicKey

access_provider = simple
simple_allow_groups = managers,sre

ldap_sudo_search_base = cn=staging-server,ou=Sudoers,dc=tsugihagi,dc=local

[nss]
memcache_timeout = 300
filter_groups = root
filter_users = root
entry_cache_nowait_percentage = 75

[pam]

[ssh]

[sudo]

下記のmanを参考にしながら、上から確認していく。(下記のリンクを見ての通り、設定可能な項目が非常に多い。最低限必要と思われる箇所だけ設定していく)

sssd.conf(5): config file for SSSD - Linux man page

sssd-ldap(5): config file for SSSD - Linux man page

sssd-sudo(5): config file for SSSD - Linux man page

sssd-simple(5) - Linux man page

(ヽ´ω`) < Special Section

[sssd]
config_file_version = 2
services = nss, pam, sudo, ssh
domains = default

[sssd] から始まるセクションはSpecial Sectionと呼ばれる。

実はSSSDは単一のサービスではなく、複数の、それぞれの処理を担当するサービスから成り立っている。
それら複数のサービスをまとめて管理するためのサービスはmonitorと呼ばれ、そのmonitorサービスの設定を行うのがこのセクション。


config_file_version = 2

設定ファイルの文法を指定する。SSSD 0.6.0以降は2となる。


services = nss, pam, sudo, ssh

先程複数のサービスから成り立っていると書いたが、どのサービスを使用するかを指定する。

ここで指定したサービスが sssd.service の起動と同時に起動される。
systemdのUnitファイルも確認可能。

# ls /usr/lib/systemd/system/sssd*.service
/usr/lib/systemd/system/sssd-autofs.service  /usr/lib/systemd/system/sssd-pac.service      /usr/lib/systemd/system/sssd.service
/usr/lib/systemd/system/sssd-ifp.service     /usr/lib/systemd/system/sssd-pam.service      /usr/lib/systemd/system/sssd-ssh.service
/usr/lib/systemd/system/sssd-nss.service     /usr/lib/systemd/system/sssd-secrets.service  /usr/lib/systemd/system/sssd-sudo.service

domains = default

SSSDではユーザ情報を保持するデータベースのことをdomainと呼ぶ。またdomainは複数定義することができる。
domains ではdomainが複数存在する場合、どの順番でドメインに対して問い合わせを行うかを指定する。

今回はdomainは1つしか使用しない想定なので、どのdomainにdefaultという名前をつけて定義する。

(ヽ´ω`) < Domain Section

[domain/default]
id_provider = ldap
chpass_provider = none

ldap_uri = ldap://172.16.1.177
ldap_search_base = dc=tsugihagi,dc=local
dap_tls_reqcert = allow

ldap_default_bind_dn = cn=Manager,dc=tsugihagi,dc=local
ldap_default_authtok_type = password
ldap_default_authtok = hogehoge

ldap_user_ssh_public_key = sshPublicKey

access_provider = simple
simple_allow_groups = managers,sre

ldap_sudo_search_base = cn=staging-server,ou=Sudoers,dc=tsugihagi,dc=local

上で記載したとおり、SSSDではユーザ情報を格納するデータベースをdomainと呼ぶが、そのdomainの情報を設定するセクションが Domain Section。
基本的にはこのセクションの設定が一番多くなる。


[domain/default]

domainの名前を記載する。

defaultという名前をつけてあるが、これは別に予約されたキーワードでもなんでもないため特にこの名前にしないといけないということはない。(hogeみたいな名前でもOK)


id_provider = ldap

ユーザ情報をどこから取得するのかを設定する。

今回はOpenLDAPなので ldap と設定。他の値としては、FreeIPAの ipa 、ActiveDirectoryを使用する際の ad がある。


chpass_provider = none

パスワード変更要求が来た場合、どのデータベースで処理するのかを指定する。

今回は公開鍵認証を行うので、ユーザのパスワードは取り扱わない。そのため明示的に none を設定しておく。


ldap_uri = ldap://172.16.1.177

LDAPサーバのURI。

LDAPSを使う場合は ldaps:// を指定する。


ldap_search_base = dc=tsugihagi,dc=local

LDAPサーバに対して問い合わせ(クエリ)を発行する際のベースDN。

規模が大きくなる場合は分けたほうが管理がしやすいかもしれないが、今回はサフィックスを使用。


ldap_id_use_start_tls = False

LDAPサーバに接続した後にSTARTTLSで通信の暗号化を開始するか否か。

本番環境で扱うには暗号化は必須なのだが、その場合証明書の管理から考えないといけないので、今回は一旦暗号化は考慮せずに話をすすめる。


ldap_tls_reqcert = allow

LDAPサーバのサーバ証明書チェックの挙動。

デフォルトは hard で証明書が確認できなかった場合は接続を切断する。
allow は証明書が確認できない、不正な証明書であっても、そのまま接続を続行する。


ldap_default_bind_dn = cn=Manager,dc=tsugihagi,dc=local

LDAPサーバに接続する際のバインドユーザのDN。


ldap_default_authtok_type = password

バインドパスワードの形式。 password は平文でのパスワード記載となる。
obfuscated_password を指定することで難読化することが可能。
実際に設定するには、一旦この値を password と指定してsssd.confを作成後に sss_obfuscate コマンドを実行してやる。

# sss_obfuscate --domain=default

これによって /etc/sssd/sssd.conf の中身が書き換えられて

# diff sssd.conf.bak sssd.conf -u
--- sssd.conf.bak   2019-11-21 09:06:03.103978668 +0000
+++ sssd.conf   2019-11-21 09:06:27.139753597 +0000
@@ -5,7 +5,6 @@
<-- snip -->
-ldap_default_authtok_type = password
-ldap_default_authtok = hogehoge
+ldap_default_authtok_type = obfuscated_password

+ldap_default_authtok = AAAQAEHorIy2fGqSEof7f3erz5FNMvY+0xJsat5MEIFwprl9JwzghKumq3VbkJzkVHAM/8PdCM0fXSfB/EtiA8DJbn4AAQID

<-- snip -->

こんな感じになるのだが… なぜか他のエントリを巻き込んで内容を消してしまったりする。(あるいはsssd.confの内容全てが消えてしまう)

実行する際には sssd.conf のバックアップを取っておいて、コマンド実行後に該当箇所だけコピペをして復元してやる必要がある。

理想を言うならパスワード認証ではなく、クライアント証明書認証を使うべきなので、これは通信経路のTLS化も含めて後から変更する。


ldap_default_authtok = hogehoge

LDAP接続に使用するパスワード。

平文で保存したくない場合は上記の方法で難読化をする。

sssd.conf はパーミッションが 600 でないとSSSDサービスの起動に失敗するので、OS内の他のユーザにパスワードを見られるという危険性はないのだが、構成管理ツール等で構築している場合はソースを閲覧可能なユーザには見られてしまう。

またこの設定ではサーバに接続する際に平文でパスワードを流してしまうので、LDAPSで接続するのが好ましい。この設定については一旦動作確認が取れたあとで追加設定として実施する。


ldap_user_ssh_public_key = sshPublicKey

SSH公開鍵の値が格納されている属性名。


access_provider = simple
simple_allow_groups = managers,sre

SSSDによるアクセスコントロールの方法。

SSSDが認証を行う場合、どのユーザ/グループに対してアクセスを許可するかを制御することができる。
ここでは対象のサーバがstagingサーバであると仮定して simple_allow_groupsmanagers,sre グループに対してアクセスを許可している。

この値を設定することで、どのグループに対してサーバへのログインを許可するかを設定している。( ldap_search_baseou=Groups に設定してあるためそのレベルでのフィルタリングは行っていない)


ldap_sudo_search_base = cn=staging-server,ou=Sudoers,dc=tsugihagi,dc=local

sudoRoleエントリを探すベースDN。

cn=dev-server まで指定してやる。
ou=Sudoers で終わると ou=Sudoers 以下にある全てのsudoRoleエントリが対象となってしまい、サーバ別でのsudoグループが管理できなくなってしまう。(全てのsudoRoleオブジェクトクラスを継承したエントリが検索対象となってしまう)

厳密に言うと sudoHost の値がALLではなく、正確に対象となるホスト名を指定してあればそちらでコントロールが可能なのだが、下記の理由から sudoHost での管理ではなく、この ldap_sudo_search_base の設定による管理としている。

  • AutoScalingGroup管理下のEC2インスタンスではデフォルトのホスト名がインスタンスIDとなる。
  • 上記のような動的に作成・削除されるインスタンスに対して、全て同じホスト名を設定してしまうのは、メトリクス収集システムと相性が悪いケースが多い。例えばDatadogではデフォルトのホスト名がhostnameコマンドの戻り値。
  • sudoHost の値は完全一致で、例えば "ServiceA-*" のようなワイルドカード指定ができない。

ちなみにmanの ldap_sudo_hostname についての記載

Space separated list of hostnames or fully qualified domain names that should be used to filter the rules. If this option is empty, SSSD will try to discover the hostname and the fully qualified domain name automatically.

これを見ると sudoHost の評価に使用されるホスト名を hostname コマンドの出力とは別で、このオプションで指定できるように見えるのだが、

bugzilla.redhat.com

The option ldap_sudo_hostname may be used to change what rules are cached but its useless without changing the system hostname at this moment, so it is more for testing purpose. There is currently no sudo RFE to support changing the hostname AFAIK.

とのこと。

(ヽ´ω`) < sudoersの設定

authconfig コマンドの実行で /etc/nsswitch.conf の内容が書き換えられるのだが、sudoersの検索については手動でエントリを追加してやる必要がある。

echo "sudoers: files sss" >> /etc/nsswitch.conf

(ヽ´ω`) < サービスの有効化・起動

sssd.conf の作成が完了したら、オーナーをrootでパーミッションを600に設定してやる。

chown root:root /etc/sssd/sssd.conf
chmod 600 /etc/sssd/sssd.conf

で、サービスの有効化と起動。ついでに自動でホームディレクトリを作成する処理をしてくれるoddjob-mkhomedirを管理するoddjobdも。

systemctl enable sssd
systemctl start sssd
systemctl enable oddjobd
systemctl start oddjobd

(ヽ´ω`) < 動作確認

id コマンドでユーザ情報が引けるかを確認する。

# id dev-member
uid=10004(dev-member) gid=10002(dev) groups=10002(dev)

# id sre-member
uid=10003(sre-member) gid=10001(sre) groups=10001(sre)

# id sre-senior-member
uid=10002(sre-senior-member) gid=10001(sre) groups=10001(sre)

# id sre-manager
uid=10001(sre-manager) gid=10000 groups=10000,10001(sre),10003(managers)

# id hoge
id: hoge: no such user

ここではサーバへのログイン可・不可を問わず( simple_allow_groups の設定を問わず)対象ユーザのid情報を引くことができる。

これが気持ち悪い場合は ldap_group_search_base オプションで、グループを検索するベースDNを設定する。ここでは最低限のsssd.confの設定とするため省略した。

また、同様に sudo -l -U でsudo権限についても確認する。

# sudo -l -U dev-member
User dev-member is not allowed to run sudo on ip-172-16-1-158.

# sudo -l -U sre-member
User sre-member is not allowed to run sudo on ip-172-16-1-158.

# sudo -l -U sre-senior-member
Matching Defaults entries for sre-senior-member on ip-172-16-1-158:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE
    KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION
    LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE
    LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

User sre-senior-member may run the following commands on ip-172-16-1-158:
    (root) ALL

# sudo -l -U sre-manager
Matching Defaults entries for sre-manager on ip-172-16-1-158:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE
    KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION
    LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE
    LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

User sre-manager may run the following commands on ip-172-16-1-158:
    (root) ALL

意図したとおり、 Stagingサーバについては sre-senior-member , sre-manager にのみsudo権限が付与されていることが確認できる。

(ヽ´ω`) < 次は?

グループとsudo権限の確認が出来たので、最後にsshd側の設定を行ってOSの認証をコントロールする。

(ヽ´ω`) < OpenLDAP + SSSDでLinuxログインアカウント一元管理がさっぱりわからん - 2. ユーザエントリとか作成 -

(ヽ´ω`) < ユーザとグループとsudoers設定

前回のエントリでOpenLDAPの初期設定が完了し、 dc=tsugihagi,dc=local に対してデータを挿入できるようになったので、実際にログイン可能なユーザと、ユーザをまとめるグループ、さらにsudoersに該当するエントリを作成していく。

どのようにOUを設計していくかは、組織構成によって色んなパターンがあると思うので、ここではすごく簡単に下記のように作成していく。

  • ユーザはou=Users,dc=tsugihagi,dc=local 配下にフラットに作成していく。 (例 cn=sre-user1,ou=Users,dc=tsugihagi,dc=local
  • グループは ou=Groups,dc=tsugihagi,dc=local 配下にフラットに作成していく。 (例 `cn=SRE,ou=Groups,dc=tsugihagi,dc=local' , 'cn=Dev,ou=Groups,dc=tsugihagi,dc=local )
  • sudoersは ou=Sudoers,dc=tsugihagi,dc=local 配下に〜

(ヽ´ω`) < 想定するサーバ構成とユーザ情報、アクセス権

ここでは下記の条件を想定してユーザ情報を作成していく。

  • サーバは3台 Produciton, Staging, Development
  • グループは3つ managers, sre, dev
  • ユーザは4人 sre-manager, sre-senior-member, sre-member, dev-member
  • それぞれのユーザのアクセス権は下記の通り
    • ◎ ログイン可 sudo可
    • ○ ログイン可 sudo不可
    • ☓ ログイン不可
ユーザ グループ Production Staging Development
sre-manager managers, sre
sre-senior-member sre
sre-member sre
dev-member dev

上記の表より、下記の通りのポリシーを設定する。

  • managersグループは全てのサーバに対してログイン/sudo可
  • sreグループは全てのサーバに対してログイン可、加えてDevelopmentサーバにsudo可
  • devグループはStagingサーバに対してログインのみ可、Developmentサーバに対してログイン/sudo可
  • sre-senior-memberはsreグループの権限に加え、ユーザ個人に対してStagingサーバに対してsudo可を追加

(ヽ´ω`) < ベースドメインとOU

まずはベースDNの設定とOUの作成。 ベースDNは前回設定した dc=tsugihagi,dc=local を使用する。(base.ldif)

dn: dc=tsugihagi,dc=local
objectClass: dcObject
objectClass: organization
dc: tsugihagi
o: tsugihagi

dn: ou=Users,dc=tsugihagi,dc=local
objectClass: organizationalUnit
ou: Users

dn: ou=Groups,dc=tsugihagi,dc=local
objectClass: organizationalUnit
ou: Groups

dn: ou=Sudoers,dc=tsugihagi,dc=local
objectClass: organizationalUnit
ou: Sudoers

(ヽ´ω`) < ユーザ

自分が一番最初にOpenLDAPでユーザの一元管理を試してみたとき(もう10年近く前かな…)に感じた疑問が 「(ヽ´ω`) < そもそもLDAPのエントリは任意の場所(DITツリーでの位置)に任意の形式で作成できるんだけど、その中で何をもってユーザ情報と見做すの?」 だった記憶。

そんな昔の自分への回答。 ユーザは posixAccount , inetOrgPerson , ldapPublicKey の3つのオブジェクトクラスをもつエントリとなる。場所についてはどこでもOK。(今回の場合は認証情報を見に来るサーバ側で検索する位置・範囲を設定するため) それぞれに必要な属性を、各オブジェクトクラスのスキーマ定義を見て確認していく。

posixAccount のスキーマ定義は下記の通り。

objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount'
        DESC 'Abstraction of an account with POSIX attributes'
        SUP top AUXILIARY
        MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
        MAY ( userPassword $ loginShell $ gecos $ description ) )

MUSTなのが cn, uid, uidNumber, gidNumber, homeDirectory なのでこれは必須。 SSSDでは loginShell もうまいこと扱ってくれるので、こちらも入力しておく。 userPassword は公開鍵認証を使用するので不要。 gecosdescrption は、まぁ入れておいてもいいかな。

続いて inetOrgPerson のスキーマ定義。

# inetOrgPerson
# The inetOrgPerson represents people who are associated with an
# organization in some way.  It is a structural class and is derived
# from the organizationalPerson which is defined in X.521 [X521].
objectclass     ( 2.16.840.1.113730.3.2.2
    NAME 'inetOrgPerson'
        DESC 'RFC2798: Internet Organizational Person'
    SUP organizationalPerson
    STRUCTURAL
        MAY (
                audio $ businessCategory $ carLicense $ departmentNumber $
                displayName $ employeeNumber $ employeeType $ givenName $
                homePhone $ homePostalAddress $ initials $ jpegPhoto $
                labeledURI $ mail $ manager $ mobile $ o $ pager $
                photo $ roomNumber $ secretary $ uid $ userCertificate $
                x500uniqueIdentifier $ preferredLanguage $
                userSMIMECertificate $ userPKCS12 )
        )

実は、見ての通り全て属性がMAYなので inetOrgPerson は必須ではない。が、ユーザ管理という面から便利な属性を持っているので、オブジェクトクラスとして追加する。 今回は例として mail を入力しておく。

また上位のオブジェクトクラスであるorganizationalPersonのMUST属性として sn が指定されているので、こちらについても必須となる。

ここまでは、いわゆる一般的なOpenLDAPでユーザ情報を保持する属性の定義。 今回はパスワード認証ではなく、公開鍵認証のための公開鍵をOpenLDAP側で保持する。そのための属性が sshPublicKey で、その値を保持するオブジェクトクラスが ldapPublicKey となる。

# octetString SYNTAX
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
        DESC 'MANDATORY: OpenSSH Public key'
        EQUALITY octetStringMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )

# printableString SYNTAX yes|no
objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
        DESC 'MANDATORY: OpenSSH LPK objectclass'
        MUST ( sshPublicKey $ uid )
        )

必要な属性が設定され、作成したユーザ追加用LDIFはこんな感じ。(users.ldif)

dn: cn=sre-manager,ou=Users,dc=tsugihagi,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: ldapPublicKey
uid: sre-manager
uidNumber: 10001
gidNumber: 10000
homeDirectory: /home/user1
loginShell: /bin/bash
mail: sre-manager@tsugihagi.local
sn: sre
gecos: sre manager
sshPublicKey: ssh-rsa 11111
sshPublicKey: ssh-rsa 22222
sshPublicKey: ssh-rsa 33333

dn: cn=sre-senior-member,ou=Users,dc=tsugihagi,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: ldapPublicKey
uid: sre-senior-member
uidNumber: 10002
gidNumber: 10001
homeDirectory: /home/sre-senior-member
loginShell: /bin/bash
mail: sre-senior-member@tsugihagi.local
sn: sre
gecos: sre-senior-member
sshPublicKey: ssh-rsa 44444

dn: cn=sre-member,ou=Users,dc=tsugihagi,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: ldapPublicKey
uid: sre-member
uidNumber: 10003
gidNumber: 10001
homeDirectory: /home/sre-member
loginShell: /bin/bash
mail: sre-member@tsugihagi.local
sn: sre
gecos: sre-member
sshPublicKey: ssh-rsa 55555

dn: cn=dev-member,ou=Users,dc=tsugihagi,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: ldapPublicKey
uid: dev-member
uidNumber: 10004
gidNumber: 10002
homeDirectory: /home/dev-member
loginShell: /bin/bash
mail: dev-member@tsugihagi.local
sn: dev
gecos: dev-member
sshPublicKey: ssh-rsa 66666

(ヽ´ω`) < グループ

グループについては posixGroup オブジェクトクラスを持つエントリを作成する。

objectclass ( 1.3.6.1.1.1.2.2 NAME 'posixGroup'
        DESC 'Abstraction of a group of accounts'
        SUP top STRUCTURAL
        MUST ( cn $ gidNumber )
        MAY ( userPassword $ memberUid $ description ) )

cn , gidNumber は必須なので入力。 memberUid もMAYとなっているが所属しているユーザを指定するために必要なので、ユーザが存在しないグループを定義する場合以外は設定が必要。

ということで実際のエントリはこんな感じ。(groups.ldif)

dn: cn=sre,ou=Groups,dc=tsugihagi,dc=local
objectClass: posixGroup
gidNumber: 10001
cn: sre
memberUid: sre-manager
memberUid: sre-senior-member
memberUid: sre-member

dn: cn=dev,ou=Groups,dc=tsugihagi,dc=local
objectClass: posixGroup
cn: dev
gidNumber: 10002
memberUid: dev-member

dn: cn=managers,ou=Groups,dc=tsugihagi,dc=local
objectClass: posixGroup
cn: managers
gidNumber: 10003
memberUid: sre-manager

実はLDAPでグループを扱う際には"RFC2307 or RFC2307bis"というテーマについて考えないといけないのだが、これは独立したエントリで扱わないと長くなりそうなので… とりあえずここでは 「グループはposixGroupオブジェクトクラスを持ったエントリ内に、ユーザ名(memberUid)が列挙されて定義される」 と覚えておく。

(ヽ´ω`) < sudoers

sudoersはダウンロードした sudo.schema に定義されている sudoRole オブジェクトクラスを持つエントリを作成。

objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
    DESC 'Sudoer Entries'
    MUST ( cn )
    MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $
        description )
    )

cn のみがMUSTとなっているが、sudoersファイルに記載されるような、こんな内容

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       NOPASSWD: ALL

を実現するには sudoHost , sudoCommand , sudoOption のような他の属性を入力していく必要がある。

linuxjm.osdn.jp

ここで NOPASSWD: ALL を実現するためには

sudoOption: NOPASSWD

と書けば良さそうに思えるが、これはNG。正しくは

sudoOption: !authenticate

と書く必要がある。 困ったことに、この設定は sudoers.ldap のmanにも記載がなかったので、どうしたものか戸惑ったのだが、下記のページがすごく参考になった。

pig.made-it.com

このページに下記のような記載があったので、

The sudoers package contains a perl-script called sudoers2ldif, this script is provided in the /usr/share/doc/sudoers/ directory.

早速使ってみようと思って調べてみたが見当たらない。

sudo パッケージの内容を見てみると、 cvtsudoers と何やらそれらしい名前が。

# rpm -ql sudo
<-- snip -->
/usr/bin/cvtsudoers
<-- snip -->
/usr/share/man/man1/cvtsudoers.1.gz
<-- snip -->

man cvtsudoers してみるとDescriptionには

cvtsudoers can be used to convert between sudoers security policy file formats. The default input format is sudoers. The default output format is LDIF. It is only possible to convert a sudoers file that is syntactically correct.

とのことなので、早速試してみる。 -b オプションでベースとなるDNを指定してやる。ここでは ou=Sudoers,dc=tsugihagi,dc=local の配下にエントリを作成していくので、こんな感じ。

# cvtsudoers -b "ou=Sudoers,dc=tsugihagi,dc=local" /etc/sudoers
dn: cn=defaults,ou=Sudoers,dc=tsugihagi,dc=local
objectClass: top
objectClass: sudoRole
cn: defaults
description: Default sudoOption's go here
sudoOption: !visiblepw
sudoOption: always_set_home
sudoOption: match_group_by_gid
sudoOption: always_query_group_plugin
sudoOption: env_reset
sudoOption: env_keep=COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS
sudoOption: env_keep+=MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE
sudoOption: env_keep+=LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES
sudoOption: env_keep+=LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE
sudoOption: env_keep+=LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY
sudoOption: secure_path=/sbin:/bin:/usr/sbin:/usr/bin

dn: cn=root,ou=Sudoers,dc=tsugihagi,dc=local
objectClass: top
objectClass: sudoRole
cn: root
sudoUser: root
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
sudoOrder: 1

dn: cn=%wheel,ou=Sudoers,dc=tsugihagi,dc=local
objectClass: top
objectClass: sudoRole
cn: %wheel
sudoUser: %wheel
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
sudoOrder: 2

dn: cn=ec2-user,ou=Sudoers,dc=tsugihagi,dc=local
objectClass: top
objectClass: sudoRole
cn: ec2-user
sudoUser: ec2-user
sudoHost: ALL
sudoRunAsUser: ALL
sudoOption: !authenticate
sudoCommand: ALL
sudoOrder: 3

3つ目のエントリを見て分かる通り、sudoersファイルでの指定と同様に % をプレフィックスとして付与することで、グループに対してsudo権を設定することができる。 ここで指定するグループは /etc/group で管理されるグループは当然として、前項で定義したOpenLDAP上のグループに対しても適用が可能。

cvtsudoers の出力は上記のとおりだが、ローカルで定義されているユーザ・グループ対するsudoersはローカルのファイルで定義すべきで、ここでは実際に追加するエントリは下記の通りとなる。

dn: cn=production-server,ou=Sudoers,dc=tsugihagi,dc=local
objectClass: sudoRole
cn: production-server
sudoHost: ALL
sudoCommand: ALL
sudoUser: %managers

dn: cn=staging-server,ou=Sudoers,dc=tsugihagi,dc=local
objectClass: sudoRole
cn: staging-server
sudoHost: ALL
sudoCommand: ALL
sudoUser: %managers
sudoUser: sre-senior-member

dn: cn=dev-server,ou=Sudoers,dc=tsugihagi,dc=local
objectClass: sudoRole
cn: dev-server
sudoHost: ALL
sudoCommand: ALL
sudoUser: %managers
sudoUser: %sre
sudoUser: dev-member

cnの値がサーバ名になっていることがわかると思う。
権限をどの単位で管理するかは既存のポリシーや組織によってまちまちだと思うが、ここではファイルによるsudoers管理と同様に、サーバからみてどのユーザ・グループに権限を付与するか、という視点で設定する。

(ヽ´ω`) < LDIF流し込み

作成された base.ldif , users.ldif , groups.ldif , sudoers.ldif をOpenLDAPに流し込んでいく。

ここで注意、改めて olcDatabase={2}hdb,cn=config の設定を見てもわかるとおり、 olcAccess 属性が設定されていない。

[root@ip-172-16-1-209 ~]# ldapsearch -Y EXTERNAL -H ldapi:/// -b "olcDatabase={2}hdb,cn=config"
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <olcDatabase={2}hdb,cn=config> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# {2}hdb, config
dn: olcDatabase={2}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {2}hdb
olcDbDirectory: /var/lib/ldap
olcDbIndex: objectClass eq,pres
olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
olcSuffix: dc=tsugihagi,dc=local
olcRootDN: cn=Manager,dc=tsugihagi,dc=local
olcRootPW: {SSHA}SFlHUkAMFkH6xUPA61IEqDnTY2lN2YwF

この状況では、全てのユーザはread権限を持つが書き込み権限を持つのはRootDNのみとなる。

そのため書き込みのために発行する ldapadd に渡すオプションは下記のとおりとなる。

# ldapadd -D "cn=Manager,dc=tsugihagi,dc=local" -whogehoge -H ldap://127.0.0.1 -f base.ldif
# ldapadd -D "cn=Manager,dc=tsugihagi,dc=local" -whogehoge -H ldap://127.0.0.1 -f users.ldif
# ldapadd -D "cn=Manager,dc=tsugihagi,dc=local" -whogehoge -H ldap://127.0.0.1 -f groups.ldif
# ldapadd -D "cn=Manager,dc=tsugihagi,dc=local" -whogehoge -H ldap://127.0.0.1 -f sudoers.ldif

実際にエントリが書き込まれたかを確認。

# ldapsearch -Y EXTERNAL -H ldapi:/// -b "dc=tsugihagi,dc=local"

ここまででOpenLDAP側の設定は完了。

続いて実際に認証が行われる側、SSHDが稼働しているサーバ側のSSSD設定を行っていく。

(ヽ´ω`) < OpenLDAP + SSSDでLinuxログインアカウント一元管理がさっぱりわからん - 1. OpenLDAP初期設定 -

(ヽ´ω`) < ログインアカウント一元管理したいよね、公開鍵で

多分Linuxのアカウントを一元管理したい、あるいはできるようにしろと上から命令されてググってみたけど古い情報も多くて涙目の人に送る。

何回かのエントリに分けて投稿するが、最終的にこんな感じのことができるようになる想定。

  • 複数台のLinuxサーバに対して、それぞれユーザを作成しなくてもログインが可能になる
  • ログイン情報はOpenLDAPで一元管理
  • ユーザの所属グループも
  • 各サーバのsudoersも
  • もう今更パスワード認証にも戻れないので公開鍵認証でお願いします

(ヽ´ω`) < まずはOpenLDAP側の設定について

実際に設定するにはSSSDやらNSSやらPAMやらといろいろと設定が必要になるのだが、それは後回しにしておいてOpenLDAP側の設定。

OSはみんな大好きAmazon Linux2で。多分、CentOS7までならほとんど一緒なはず。8からは389 Directory Serverに置き換えられてるかも。

(ヽ´ω`) < インストール

サーバの設定を流し込んだり確認するのに ldap*** 系のコマンドを使用するので、 openldap-clients もインストールしておく。

# yum install openldap-servers openldap-clients

(ヽ´ω`) < 管理者ユーザのパスワード作成とルートサフィックス変更

下記の記事でも書いたのだが、ちょっと前のバージョンまでは /etc/openldap/slapd.conf に設定を記載する素直な子だったのだが、2.3以降では ldifファイルからデータを読み込ませる方式に変わってしまった。

www.tsugihagi.net

slapd.conf による設定も完全に無効というわけではなく、推奨しないながらも可能なようなので、ディストリビューションによっては slapd.conf が残されているようだが、Amazon Linux2では消えているようだ。

インストール直後のデフォルト設定から、自分の環境に合わせた内容に変更。
と簡単に言ってしまったが、そもそもOpenLDAPなんてよくわからんという人が多いと思うので、一旦は小難しいことは置いておいて、

  • tsugihagi.local というグループのようなものを作る(デフォルトではmy-domain.comに設定されている)
  • 管理者はManagerという名前(これはデフォルトと同じ)

という設定を行う。

まずはパスワード作成 slappasswd コマンドでパスワードを生成してメモしておく。

# slappasswd
New password: (パスワードを入力)
Re-enter new password: (パスワードを再入力)
{SSHA}SFlHUkAMFkH6xUPA61IEqDnTY2lN2YwF (ここでは hogehoge というパスワード設定)

次にルートサフィックスを dc=tusgihagi, dc=local 、管理者を cn=Manager,dc=tsugiahgi,dc=local としたLDIFファイルを作成。

# 下記内容をinit.ldifという名前で保存

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=tsugihagi,dc=local

dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,dc=tsugihagi,dc=local

dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}SFlHUkAMFkH6xUPA61IEqDnTY2lN2YwF

作成した init.ldif を流し込む。(デフォルトでローカルのrootユーザは各Backendに対して書き込みが可能)

# ldapmodify -Y EXTERNAL -H ldapi:/// -f init.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={2}hdb,cn=config"

modifying entry "olcDatabase={2}hdb,cn=config"

modifying entry "olcDatabase={2}hdb,cn=config"

(ヽ´ω`) < スキーマ追加

インストール直後の状態では、Linuxのユーザ情報を保持するためのスキーマ情報が読み込まれていないので、手動で読み込んでやる必要がある。

基本的なスキーマファイルは /etc/openldap/schema ディレクトリに存在するのだが、今回はさらに

  • sudo権限を管理するためのオブジェクト用スキーマ
  • 公開鍵認証のための属性用スキーマ

が必要となる。

cosine, inetorgperson, nisスキーマのインストール

基本的なスキーマファイルは /etc/openldap/schema ディレクトリ以下に揃っているので、下記の通り ldapadd で追加してやる。

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
sudo用スキーマのインストール

ありがたいことにスキーマファイルからLDIFに変換されたものがGithub上に存在するのでそちらを使わせてもらう。

# curl -L https://raw.githubusercontent.com/Lullabot/openldap-schema/master/sudo.ldif -o /etc/openldap/schema/sudo.ldif
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/sudo.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=sudo,cn=schema,cn=config"

ちなみにsudo用のスキーマは sudo パッケージに付属している。

linuxjm.osdn.jp

下記のスキーマは OpenLDAP 用の形式になっており、 sudo のソースやバイナリの配布には schema.OpenLDAP として収録されている。その schema.OpenLDAP ファイルをスキーマ・ディレクトリ (たとえば /etc/openldap/schema) にそのままコピーし、適切な include 行を slapd.conf に追加して、 slapd をリスタートすればよい。

## バージョンが違うかもしれないのでそれぞれの環境で場所チェック
# rpm -ql sudo | grep schema.OpenLDAP
/usr/share/doc/sudo-1.8.23/schema.OpenLDAP

すでに説明したとおり slapd.conf は存在せず、ldifファイルをschemaファイルから変換しなくてはいけないので、今回はそのままダウンロードして楽をさせてもらった。

公開鍵認証用スキーマのインストール

公開鍵認証に必要な openssh-lpk-openldap.ldifopenssh-ldap パッケージに付属している。

yum install openssh-ldap
rpm -ql openssh-ldap | grep openssh-lpk-openldap.ldif
cp /usr/share/doc/openssh-ldap-7.4p1/openssh-lpk-openldap.ldif /etc/openldap/schema

パッケージがインストールできたら流し込み。

# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/openssh-lpk-openldap.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=openssh-lpk,cn=schema,cn=config"

これにてOpenLDAPの初期設定は完了。

ぶっちゃけそんなに大したことはやってなくて、スキーマの追加が少し特殊なぐらい。

(ヽ´ω`) < slapd.confはオワコン

流石にお金払ってProにしたのに記事を書かないのもアレなので、まずは一本目。

(ヽ´ω`) < っていうかolcってなんだよ

数年ぶりにOpenLDAPを触ってみたところ、slapd.confによる設定がオワコンになっていた。 代わりになにやらolcというのを使う必要があるらしい。 これはなんだと調べてみると、どうやらOpenLDAPサーバの設定値をOpenLDAPサーバ自体で保持する仕組みらしい。

www.openldap.org

OpenLDAP 2.3 and later have transitioned to using a dynamic runtime configuration engine, slapd-config(5). slapd-config(5)

  • is fully LDAP-enabled
  • is managed using the standard LDAP operations
  • stores its configuration data in an LDIF database, generally in the /usr/local/etc/openldap/slapd.d directory.
  • allows all of slapd's configuration options to be changed on the fly, generally without requiring a server restart for the changes to take effect.

という感じでOpenLDAPの設定をLDAP操作で、LDIF形式で、さらに設定変更の反映をサーバの再起動無しで行えるとのこと。 MySQLのVARIABLESみたいなものか。

olcとはOpenLDAP Configurationの略で動的コンフィグで使用されるobjectClassやattributeのprefixの値らしい。

Configuration directives are specified as values of individual attributes. Most of the attributes and objectClasses used in the slapd configuration have a prefix of "olc" (OpenLDAP Configuration) in their names.

(ヽ´ω`) < 実際の設定方法は?

さて、olcというか動的コンフィグが何かはわかったのでその設定方法だ。 ということで、みんな大好きCentOS7に試しに入れてみると、 /etc/openldap/ 配下に slapd.d というディレクトリが存在する。

slapd.conf残っとるやんけ! と思ったらldap.confだった。

slapd.dを覗いて見ると、何やらよくわからない命名規則のディレクトリとファイルが並んでいる。 ファイルの中身を見てみると、たしかにLDIFファイルだ。 なるほど、ではこのファイルを編集して初期設定を行うのかと思ったらどうやらそうではないらしい。

Note: Although the slapd-config(5) system stores its configuration as (text-based) LDIF files, you should never edit any of the LDIF files directly. Configuration changes should be performed via LDAP operations, e.g. ldapadd(1), ldapdelete(1), or ldapmodify(1).

で、多くの日本語の解説ページは「エラーは出ますけど直接編集します」とか書いてあったりするので、このあたりもうちょい調べてみた。

www.openldap.org

上記Quick Start Guideの項番9によると

Import the configuration database You are now ready to import your configration database for use by slapd(8), by running the command: su root -c /usr/local/sbin/slapadd -n 0 -F /usr/local/etc/slapd.d -l /usr/local/etc/openldap/slapd.ldif

LDIFファイルの内容を元にconfiguration databaseを作成できるとのこと。

しかし /etc/openldap/ にそれらしいLDIFファイルは見当たらない、ということで探してみると /usr/share/openldap-servers/slapd.ldif がそれっぽい。 試しにolcSuffixとolcRootDNの値を変更してみる。

--- /usr/share/openldap-servers/slapd.ldif.org   2019-08-22 13:46:45.604588841 +0000
+++ /usr/share/openldap-servers/slapd.ldif  2019-08-22 13:48:50.928660767 +0000
@@ -141,8 +141,8 @@
 objectClass: olcDatabaseConfig
 objectClass: olcHdbConfig
 olcDatabase: hdb
-olcSuffix: dc=my-domain,dc=com
-olcRootDN: cn=Manager,dc=my-domain,dc=com
+olcSuffix: dc=tsugihagi,dc=net
+olcRootDN: cn=Manager,dc=tsugihagi,dc=net
 olcDbDirectory:    /var/lib/ldap
 olcDbIndex: objectClass eq,pres
 olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub

更新したLDIFファイルはslapaddコマンドで、slapd.dディレクトリ配下に書き出しできる。 のだが、どうやら上書きはできないらしく、予めslapd.dの中を消さないとだめっぽい。 slapaddで書き出しを行う際にはslapd、つまりOpenLDAPのプロセスは停止しておいたほうが良いとのこと。(初期設定のタイミングのみ。設定の変更は稼働中のOpenLDAPに対してldapadd/ldapmodifyを使う)

slapadd -n0 -l /usr/share/openldap-servers/slapd.ldif -F /etc/openldap/slapd.d

-l オプションでLDIFファイルを、-F オプションで書き出し先のディレクトリを指定する。 -n0 はLDAPデータベースの設定順序とかそのあたりの理解が必要なので、また別のエントリで。殆どの場合では -n0 で設定しておけばOK。

で、上記コマンドで生成されたファイルから、変更箇所のdiffを抜き出しものがこちら。

diff -ur slapd.d/cn=config/olcDatabase={2}hdb.ldif slapd.d.new/cn=config/olcDatabase={2}hdb.ldif
--- slapd.d/cn=config/olcDatabase={2}hdb.ldif   2019-08-22 13:18:29.316749668 +0000
+++ slapd.d.new/cn=config/olcDatabase={2}hdb.ldif   2019-08-22 13:52:34.375781992 +0000
@@ -1,18 +1,18 @@
 # AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
-# CRC32 e7a20b3c
+# CRC32 78d1520c
 dn: olcDatabase={2}hdb
 objectClass: olcDatabaseConfig
 objectClass: olcHdbConfig
 olcDatabase: {2}hdb
 olcDbDirectory: /var/lib/ldap
-olcSuffix: dc=my-domain,dc=com
-olcRootDN: cn=Manager,dc=my-domain,dc=com
+olcSuffix: dc=tsugihagi,dc=net
+olcRootDN: cn=Manager,dc=tsugihagi,dc=net
 olcDbIndex: objectClass eq,pres
 olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub
 structuralObjectClass: olcHdbConfig
-entryUUID: 13823ef0-592b-1039-9ce6-2f4b436ed340
+entryUUID: d6756af0-592f-1039-83ee-d772cea2dae7
 creatorsName: cn=config
-createTimestamp: 20190822131829Z
-entryCSN: 20190822131829.327604Z#000000#000#000000
+createTimestamp: 20190822135234Z
+entryCSN: 20190822135234.386164Z#000000#000#000000
 modifiersName: cn=config
-modifyTimestamp: 20190822131829Z
+modifyTimestamp: 20190822135234Z

CRCやUUID、タイムスタンプが更新されて、その差分が出ているため少し見にくいが、想定通りolcSuffixとolcRootDNが指定した値に書き換わっている。

ということで、これで起動すれば ldif_read_file: checksum error on "/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif" などと怒られなくて済む。

(ヽ´ω`) < slapd.confからの移行はどうしたらええの?

ちなみに、slapd.confでの設定も実はできたりする。

The older style slapd.conf(5) file is still supported, but its use is deprecated and support for it will be withdrawn in a future OpenLDAP release. Configuring slapd(8) via slapd.conf(5) is described in the next chapter.

とのことで2.4ではまだサポートするけど、Deprecatedだし将来的には廃止するよとのこと。

実際に slapd --help を実行してみると。

slapd --help
slapd: invalid option -- '-'
usage: slapd options
    -4      IPv4 only
    -6      IPv6 only
    -T {acl|add|auth|cat|dn|index|passwd|test}
            Run in Tool mode
    -c cookie   Sync cookie of consumer
    -d level    Debug level
    -f filename Configuration file
    -F dir  Configuration directory
    -g group    Group (id or name) to run as
    -h URLs     List of URLs to serve
    -l facility Syslog facility (default: LOCAL4)
    -n serverName   Service name
    -o <opt>[=val] generic means to specify options; supported options:
        slp[={on|off|(attrs)}] enable/disable SLP using (attrs)
    -r directory    Sandbox directory to chroot to
    -s level    Syslog level
    -u user     User (id or name) to run as
    -V      print version info (-VV exit afterwards, -VVV print
            info about static overlays and backends)

と、 -f オプションでslapd.confを指定することで使えるようだが、いつ使用できなくなるかわからないものを使い続けるのも心臓に悪い。 slapd.confの内容を元に、slapd.ldifを書き直すのが無難だろう。

実は

Configuration directives are specified as values of individual attributes. Most of the attributes and objectClasses used in the slapd configuration have a prefix of "olc" (OpenLDAP Configuration) in their names. Generally there is a one-to-one correspondence between the attributes and the old-style slapd.conf configuration keywords, using the keyword as the attribute name, with the "olc" prefix attached.

とあるように、slapd.confのキーワードをパスカルケースにして olc をprefixとして付与してやることで、ほとんどの設定はそのまま移行が可能。( suffix -> olcSuffix,rootdn->olcRootDN`)

更にもっと簡単な方法として、slapd.confを元にslapd.dディレクトリに書き出す方法がある。 先述のslapaddコマンドでは -l オプションでLDIFファイルを指定したが、これを -f でslapd.confを渡してやればOK。

linux.die.net

-f slapd.conf specify an alternative slapd.conf(5) file.

-F confdir specify a config directory. If both -f and -F are specified, the config file will be read and converted to config directory format and written to the specified directory.

さらにさらに、既に初期設定を完了して運用してしまっているが、万が一の再構築に備えてLDIFに落としておきたい場合は slapcat -n0 で、現在の設定を元にLDIFファイルを出力してくれる。

(ヽ´ω`) < 結局、動的コンフィグは嬉しいのか

confファイルを廃してLDIFの文法一本に絞れること、ldapmodifyなどの統一されたツールで操作が行えること、特に再起動不要で設定が反映できることなんかは良いと思う。 OpenLDAPは歴史が長く、slapd.conf時代の解説ページが多いので少し戸惑うかもしれないが、次のバージョンでslapd.confのサポートが完全に切られたりしても大丈夫なように備えておきましょう。

(ヽ'ω`) < 明日から本気を出す

(ヽ'ω`) < もう4年も前なのか…

OpenLDAP絡みの調べ物をしていて、それなりに色々と動かせるようになったので、せっかくなのでブログに書こうと思って久しぶりに開いてみたら最終更新が4年前だった…

ということで、再度はてなブログProにアップグレードして、独自ドメインを設定してみる。

肝心の記事は明日… いや、週末には…

(ヽ'ω`) < iOS8.4にしたらSMTP AUTHでSSL接続ができない…

(ヽ'ω`) < さすがAppleさんやでぇ…

みんな大好きAppleのソフトウェアアップデート。iOS8での802.1xのWEP暗号化サポートの時もそうだったけど、基本的にえげつないぐらいバッサリいく。「俺らがやらねぇとテメーらいつまでたってもセキュリティガバガバで使い続けるじゃねぇか!」 というポリシーには共感ができる。

で、今回の問題。 「iOS8.4、OS X v10.10.4にしたらSSLを使っているサービスに接続できなくなった。」

(ヽ'ω`) < 何が起こった?

まず自分が確認したのが、SMTP AUTHのサービスに突然接続できなくなったとの相談を受けた。 その人が使ってるSMTP AUTHのサーバを見せてもらうと、何やらSSLのエラーが大量に出ている。

で、Appleのフォーラムを見てみると同じ症状で悩んでる管理者の人がPostしていた。ユーザじゃなくて管理者ってのが泣ける。

SMTP with SSL completely broken after iOS 8.4 u... | Apple Support Communities

そこからのリンクで、これ

Use modern cryptographic practices when setting up SSL and TLS services on your server - Apple Support

Logjam攻撃への対策として、DHパラメータの長さが2048bit以上じゃないとダメになったっぽい。

(ヽ'ω`) < んで、どうしたらいいのさ

このサイトを参考にしてDHパラメータのファイルを作成して、オプションで追加してやる。 Logjam: PFS Deployment Guide

自分ところに相談があったのと、上記フォーラムではたまたまSMTPのSSL接続だったけど、Appleのアナウンスからは

Services that might use these types of connections include:
* Enterprise Wi-Fi (802.1X)
* Secure email connections
* Secure web connections (HTTPS)
* Secure Internet printing (IPP over TLS/SSL)

ということで、SSL/TLSが絡むサービスほぼすべてが対象っぽいです。

記事の題名ではSMTP AUTHと書いたものの、別に暗号化は強制ではないので後ろ向きな解決方法としてはクライアント側で暗号化を無効にするというのも(サーバ側が対応していれば)ありと言えば… いや、無いだろ。

(ヽ'ω`) < Javaの例外サイト・リストが追加できない

(ヽ'ω`) < なんでボタンが押せないんだよ!!!

網走刑務所も真っ青の鬼実行制限で有名なブラウザ上のJava実行。セキュリティレベルが「非常に高い」「高い」しか設定項目がないのことに狂気を感じるところですが、カレーを食べに行ったら激辛と超辛しかなかったみたいな。

で、その制限を回避させるためには例外サイト・リストに追加しなければいけないわけなんですが、何故かサイトリストの追加・削除ボタンがグレイアウト(無効化)されいて押せない。(したの画面SSは他のPCで撮ったので押せるように見えています)

f:id:tsugi-hagi:20150709132447p:plain

(ヽ'ω`) < 設定ファイルを直接編集

色々と設定を変更してもどーもうまく行かないので、直接例外サイト・リストの情報が保存されているファイルを編集する。

Exception Site List

このページの最下部、"Manage Access to the Exception Site List"の情報を元に調べてみると、

C:\Users\<ユーザ名>\AppData\LocalLow\Sun\Java\Deployment\security\exception.sites

このファイルがそれらしい。で、このファイルを右クリック→プロパティで「読み込み専用」にチェックが入っていると、編集ができない、時もあるらしいのだが、今回は該当せず。

1行1URLのフォーマットでファイルに

https://*.google.co.jp/
http://*.yahoo.co.jp/

みたいな感じで、追加・保存。これで改めて、確認してみるがやっぱりダメ。

(ヽ'ω`) < 設定ファイルの場所を明示的に指定してやる

他の正常に動作するPCで同じ操作を試してみると、問題なく情報が更新されるので、ファイルの場所と内容自体に問題はないはず。ひょっとすると、別のファイルを読み込みにいってるのか? と思い、exception.sitesファイルの場所を指定するオプションを探してみた。

すると、Deployment Configuration File and Propertiesに記載されている、deployment.user.security.exception.sitesがそれっぽい。

ということで、

C:\Users\<ユーザ名>\AppData\LocalLow\Sun\Java\Deployment\deployment.properties

に、下記の内容を追記。

deployment.user.security.exception.sites=C\:\\Users\\<ユーザ名>\\AppData\\LocalLow\\Sun\\Java\\Deployment\\security\\exception.sites

\を重ねてエスケープするのと、:もバックスラッシュでエスケープする点に注意。

これで確認するとOKだけれども、結局、追加・削除ボタンが押せない理由は不明のまま。

(ヽ'ω`) < tsugi☆hagi

ところで、なんでサイトリストじゃなくて、サイト・リストなんですかね。つのだ☆ヒロ的な。そういえば虎舞流も一時期THE TRA☆BRYUとかって改名してたけど、どんな判断だ。