はじめに (対象読者・この記事でわかること)

この記事は、すでにopenLDAP環境を運用しており、複数のLinuxサーバーにおけるsudo権限の管理に課題を感じているシステム管理者や、LDAPのスキーマ拡張に興味がある方を対象としています。

この記事を読むことで、以下のことがわかるようになります。

  • sudoスキーマの概要とその必要性
  • openLDAPサーバーにsudoスキーマを導入する具体的な手順
  • Linuxのsudo設定をLDAPと連携させる方法
  • LDAP経由でsudo権限を一元管理するための設定方法

複数のサーバーで個別にsudoersファイルを管理する手間を削減し、セキュリティと管理効率の向上を目指しましょう。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。

  • LDAPの基本的な概念と操作(ユーザー・グループの追加、検索など)
  • Linuxコマンドラインの基本的な操作(ファイルの編集、サービス再起動など)
  • openLDAPサーバーがすでに稼働しており、管理者権限で操作できること
  • sudoコマンドの基本的な利用方法

sudoスキーマとは? なぜLDAPでsudo権限を管理するのか?

sudoスキーマの概要

sudoは、特定のユーザーが別のユーザー(通常はroot)の権限でコマンドを実行できるようにする強力なツールです。通常、その設定は/etc/sudoersファイルに記述されます。

sudoスキーマは、この/etc/sudoersファイルに記述される権限情報(どのユーザーが、どのホストで、どのコマンドを、どのユーザーとして実行できるか)をLDAPディレクトリサービスに保存するためのスキーマ定義です。これにより、sudoの設定をLDAPのオブジェクトとして管理できるようになります。

なぜLDAPでsudo権限を管理するのか?

LDAPでsudo権限を管理することには、多くのメリットがあります。

  1. 一元管理: 複数のLinuxサーバーがある場合、それぞれのサーバーで個別に/etc/sudoersファイルを管理するのは非常に手間がかかります。LDAPで一元管理することで、設定変更やユーザー追加・削除の際に、すべてのサーバーに反映させる作業が劇的に簡素化されます。
  2. 管理コストの削減: 設定ファイルを配布したり、個別に編集したりする時間と労力を削減できます。
  3. セキュリティの向上: 権限設定がLDAPサーバーに集約されるため、設定ミスによるセキュリティホール発生のリスクを低減できます。また、LDAPサーバーへのアクセスを厳密に制御することで、設定の改ざんを防ぎやすくなります。
  4. 監査の容易性: 誰がどのような権限を持っているかをLDAPのデータベースから検索できるため、監査が容易になります。
  5. 柔軟性: ユーザー、グループ、ホスト、コマンドなどの要素をLDAPオブジェクトとして管理できるため、複雑な権限ポリシーも柔軟に設定可能です。

これらの理由から、特に大規模な環境や、多くのLinuxサーバーを運用している組織では、sudo権限のLDAP管理が推奨されます。

openLDAPでsudoスキーマを導入する具体的な手順

ここでは、openLDAPサーバーにsudoスキーマを読み込ませ、実際にsudo権限をLDAP経由で管理するための具体的な手順を解説します。

ステップ1: sudoスキーマファイルの準備

まず、sudoのLDAPスキーマファイルを取得します。これは通常、sudoパッケージのドキュメントに含まれています。

多くのLinuxディストリビューションでは、以下のパスに存在します。

Bash
# CentOS/RHEL系の場合 sudo find / -name "sudo.schema" # 例: /usr/share/doc/sudo-XXXX/schema.OpenLDAP # Ubuntu/Debian系の場合 sudo find / -name "sudo.schema" # 例: /usr/share/doc/sudo/examples/schema.OpenLDAP

見つかったsudo.schemaファイルを、作業しやすい場所にコピーしておきましょう。ここでは/tmp/sudo.schemaにコピーしたと仮定します。

Bash
cp /usr/share/doc/sudo/examples/schema.OpenLDAP /tmp/sudo.schema

ステップ2: openLDAPへのスキーマ登録

openLDAP 2.4以降のバージョンでは、動的構成データベース(cn=config)を使用してスキーマを管理します。sudo.schemaを直接読み込むのではなく、LDIF形式に変換して登録する必要があります。

2-1. sudo.schemaからLDIFへの変換

sudo.schemaファイルをLDIF形式に変換します。変換ツールとしてslaptestや手動での変換が考えられますが、ここでは一般的なcn=config形式のLDIFファイルを手動で作成する方法を説明します。

まず、変換用のLDIFファイルを作成します。例えば/tmp/sudo_add.ldifという名前でファイルを作成し、以下の内容を記述します。

Ldif
# /tmp/sudo_add.ldif dn: cn=sudo,cn=schema,cn=config objectClass: olcSchemaConfig cn: sudo olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoHost' DESC 'Host(s) an entry is valid for' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoCommand' DESC 'Command(s) an entry is valid for' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoUser' DESC 'User(s) an entry is valid for' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAsUser' DESC 'User(s) an entry can run commands as' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoRunAsGroup' DESC 'Group(s) an entry can run commands as' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoOption' DESC 'Options for sudo' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoOrder' DESC 'Order in which sudoers entries are evaluated' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoRunAs' DESC 'User(s) or group(s) an entry can run commands as' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoers' DESC 'Sudoers entries' SUP top AUXILIARY MUST cn MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoRunAs ) )

このLDIFファイルは、sudo.schemaの内容をcn=configデータベースで認識可能なolcSchemaConfig形式に変換したものです。

注意点: 上記LDIFは一般的な例ですが、正確な内容は使用しているsudo.schemaファイルに依存します。sudo.schemaの内容を丁寧にLDIFに変換してください。特にolcObjectClassesSUPAUXILIARYMUST/MAYは元のスキーマに合わせることが重要です。

2-2. sudo_add.ldifの適用

作成したLDIFファイルをldapaddコマンドでopenLDAPサーバーに適用します。cn=configへの変更なので、管理者権限が必要です。通常はldapi:///ソケット経由でEXTERNAL認証を使います。

Bash
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp/sudo_add.ldif

コマンドが成功すると、何も出力されないか、「adding new entry "cn=sudo,cn=schema,cn=config"」のようなメッセージが表示されます。

2-3. スキーマ登録の確認

スキーマが正しく登録されたかを確認します。

Bash
ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" -LLL "(cn=sudo)"

sudoスキーマに関する情報が表示されれば成功です。特にolcObjectClassesolcAttributeTypesが正しく登録されているか確認しましょう。

ステップ3: nsswitch.conf と ldap.conf の設定

次に、システムがsudoers情報をLDAPから取得できるように設定を変更します。

3-1. /etc/nsswitch.confの変更

/etc/nsswitch.confファイルは、システムがユーザー、グループ、パスワードなどの情報をどこから取得するかを定義します。ここにsudoersに関する記述を追加し、LDAPから情報を取得するように指定します。

Diff
# /etc/nsswitch.conf ... passwd: files systemd group: files systemd shadow: files hosts: files dns networks: files protocols: files services: files ethers: files rpc: files +sudoers: files ldap

sudoers: files ldapを追加することで、まずローカルの/etc/sudoersを検索し、見つからなければLDAPを検索するようになります。ldapを先にすると、LDAPが優先されますが、緊急時にローカルのsudoersで対応できなくなる可能性があるため、files ldapが一般的です。

3-2. /etc/ldap.conf または /etc/sudo-ldap.conf の設定

sudoコマンドがLDAPサーバーと通信するための設定を行います。これは通常/etc/ldap.confまたは/etc/sudo-ldap.confに記述します(ディストリビューションやsudoのバージョンによって異なります)。/etc/ldap.confはシステム全体のLDAP設定にも使われるため、sudo専用の設定を/etc/sudo-ldap.confに記述する方が望ましい場合もあります。

ここでは/etc/ldap.confに設定を追加する例を示します。

Ini
# /etc/ldap.conf # LDAPサーバーのホスト名またはIPアドレス host ldap.example.com # LDAPのバージョン (2または3) ldap_version 3 # ベースDN base dc=example,dc=com # 接続タイムアウト (秒) bind_timelimit 30 # 検索タイムアウト (秒) timelimit 30 # sudoersエントリが格納されているベースDNを指定 # ここでは "ou=SUDOers,dc=example,dc=com" 配下にsudoersエントリを配置すると仮定 sudoers_base ou=SUDOers,dc=example,dc=com # (オプション) LDAPへのバインドDNとパスワード # 匿名バインドを許可しない場合は設定 # binddn cn=admin,dc=example,dc=com # bindpw your_admin_password # (オプション) TLS/SSL設定 # TLSを有効にする場合 # ssl start_tls # tls_cacertdir /etc/openldap/certs # tls_cacert /etc/openldap/certs/ca.pem

sudoers_baseは非常に重要です。この設定がなければ、sudoはどこにsudoers情報があるかを見つけられません。自身のLDAPツリー構造に合わせて変更してください。

ステップ4: LDAPにsudoersエントリの追加

スキーマを登録し、システムがLDAPを参照するように設定したら、実際にsudoersエントリをLDAPに追加します。

4-1. SUDOers組織単位(OU)の作成(必要であれば)

sudoers_baseで指定したDN(例: ou=SUDOers,dc=example,dc=com)が存在しない場合は、まずそのOUを作成します。

Ldif
# /tmp/add_sudoers_ou.ldif dn: ou=SUDOers,dc=example,dc=com objectClass: organizationalUnit ou: SUDOers
Bash
ldapadd -x -D "cn=admin,dc=example,dc=com" -w your_admin_password -f /tmp/add_sudoers_ou.ldif

4-2. sudoersエントリの作成と追加

sudoersオブジェクトクラスを使用して、LDAPにsudo権限を定義します。 例えば、「johndoeユーザーが、どのホストでも、rootとして/usr/bin/aptを実行できるようにする」という設定を考えてみましょう。

Ldif
# /tmp/add_johndoe_sudo.ldif dn: cn=johndoe-apt-access,ou=SUDOers,dc=example,dc=com objectClass: top objectClass: sudoers cn: johndoe-apt-access sudoUser: johndoe sudoHost: ALL sudoCommand: /usr/bin/apt sudoRunAsUser: root sudoOrder: 10

sudoOrderは、複数のルールがある場合に評価される順序を指定します(小さい値が優先)。 このLDIFファイルをldapaddコマンドでLDAPサーバーに追加します。

Bash
ldapadd -x -D "cn=admin,dc=example,dc=com" -w your_admin_password -f /tmp/add_johndoe_sudo.ldif

ステップ5: 動作確認

すべての設定が完了したら、実際にsudoがLDAPから情報を取得しているか確認します。

まず、設定を反映させるためにNSSキャッシュをクリアします。

Bash
sudo systemctl restart nscd # nscdサービスが稼働している場合 # または sudo update-ca-certificates (TLSを使用している場合)

johndoeユーザーでログインし、以下のコマンドを実行します。

Bash
sudo -l

出力結果にLDAPで設定した権限が表示されていれば成功です。

Matching Defaults entries for johndoe on this host:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User johndoe may run the following commands on this host:
    (root) /usr/bin/apt

次に、実際にLDAPで許可されたコマンドを実行してみます。

Bash
sudo /usr/bin/apt update

パスワード入力後、apt updateが実行されれば、LDAP経由でのsudo権限管理が正しく機能していることになります。

ハマった点やエラー解決

スキーマ登録時のエラー

  • エラーメッセージ: invalid objectClass "olcSchemaConfig"attribute type undefined など
    • 原因: sudo_add.ldifの記述ミス(OID、属性名、構文など)。特にsudo.schemaからLDIFへの変換時に間違えやすい。
    • 解決策: 元のsudo.schemaファイルとLDIFファイルを比較し、記述が正しいか再度確認する。openLDAPのログ(/var/log/syslogslapdのデバッグログ)を確認し、具体的なエラー箇所を特定する。

ldapadd権限不足

  • エラーメッセージ: ldap_add: Insufficient access (50)
    • 原因: cn=configへのスキーマ追加はroot権限またはldapi:///EXTERNAL認証で行う必要がある。または、LDAPツリーへのsudoersエントリ追加時に指定したバインドDNに権限がない。
    • 解決策: sudo ldapadd -Y EXTERNAL -H ldapi:/// -f ... を使用するか、適切な管理用DNとパスワードでバインドする。

sudo -lでLDAP情報が表示されない

  • 原因1: /etc/nsswitch.confsudoers: files ldapが正しく設定されていないか、nscdサービスがキャッシュしている。
    • 解決策1: sudoers:行を確認し、ldapが含まれているか確認。sudo systemctl restart nscdでキャッシュをクリア。
  • 原因2: /etc/ldap.confまたは/etc/sudo-ldap.confの設定ミス。特にhost, base, sudoers_baseの記述間違い。
    • 解決策2: 設定ファイルのパス、ホスト名、ベースDNがLDAPサーバーと一致しているか徹底的に確認する。ldapsearchコマンドでsudoers_baseに指定したDNが存在し、その配下にエントリがあるか確認する。
  • 原因3: ファイアウォールによってLDAPサーバーへの通信がブロックされている。
    • 解決策3: firewalldufwの設定を確認し、LDAPポート(389/tcp, 636/tcp)を開放する。telnet ldap.example.com 389などで接続性を確認する。
  • 原因4: TLS/SSLを使用している場合、証明書の設定が正しくない。
    • 解決策4: /etc/ldap.conftls_cacerttls_cacertdirが正しいCA証明書を指しているか確認する。

解決策

問題が発生した際は、以下の手順で原因を特定しましょう。

  1. openLDAPサーバーのログ確認: slapdのログレベルを上げて、エラーや警告が出力されていないか確認します。
    • sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/loglevel.ldif ldif # /tmp/loglevel.ldif dn: cn=config changetype: modify replace: olcLogLevel olcLogLevel: stats,config,args,filter,conn,ber,acl
  2. ldapsearchでの確認: スキーマやLDAPエントリが期待通りに登録されているか確認します。
    • ldapsearch -x -D "cn=admin,dc=example,dc=com" -w your_admin_password -b "ou=SUDOers,dc=example,dc=com" objectClass=sudoers
  3. sudo -Vでのデバッグ: sudo -Vsudoのバージョン情報やNSSの設定状況などを確認できる場合があります。
  4. straceでのトレース: strace sudo -l を実行して、sudoがどのファイルを開こうとしているか、どのシステムコールで失敗しているかを確認します。これにより、設定ファイルのパス間違いや権限問題を特定できることがあります。

まとめ

本記事では、openLDAP環境においてsudoスキーマを導入し、LDAP経由でsudo権限を一元管理する手順を解説しました。

  • sudoスキーマの導入: sudo.schemacn=config形式のLDIFに変換し、ldapaddでopenLDAPサーバーに登録することで、sudoers情報をLDAPで扱えるようになります。
  • システム連携の設定: /etc/nsswitch.confsudoers: files ldapを追加し、/etc/ldap.conf(または/etc/sudo-ldap.conf)でLDAPサーバーの接続情報とsudoers_baseを指定することで、システムがLDAPからsudoers情報を参照できるようになります。
  • LDAPエントリの追加と動作確認: sudoersオブジェクトクラスを使ってLDAPに権限エントリを追加し、sudo -lコマンドで正しく権限が取得できることを確認しました。

この記事を通して、複数のサーバーにおけるsudo権限の管理が、LDAPの一元管理機能によって格段に効率化され、セキュリティと運用の手間を削減できるようになったことでしょう。

今後は、より高度な権限設定(グループ単位での権限付与、コマンドエイリアスの利用など)、複数のLDAPサーバーでの冗長化、そしてLDAPS(TLS/SSL)によるセキュリティ強化についても検討し、記事にする予定です。

参考資料