GNU C ライブラリのネームサービススイッチ(NSS)は、アプリケーションの検索 API と、それに応答するデータソースを分離します。コードは getpwnam(3)、getgrnam(3)、getaddrinfo(3)、または getservbyname(3) を呼び出し、glibc は /etc/nsswitch.conf に従ってサービスを選択し、組み合わせます。したがって、呼び出し元を変更しなくても、ローカルファイル、DNS サーバー、ディレクトリサービス、またはシステムサービスから同じ種類の情報を提供できます。
データベースファミリー #
glibc は、passwd、group、shadow、hosts、networks、protocols、services、rpc、ethers、netgroup、aliases、publickey、initgroups などのデータベースを認識します。それぞれに固有の libc インターフェースとレコード形式があります。
| データベース | 代表的なインターフェース | 一般的なローカルソース |
|---|---|---|
passwd, group, shadow | getpwnam, getgrnam, getspnam | /etc/passwd, /etc/group, /etc/shadow |
hosts, networks | getaddrinfo, getnetbyname | /etc/hosts, /etc/networks |
services, protocols, rpc | getservbyname, getprotobyname, getrpcbyname | /etc/services, /etc/protocols, /etc/rpc |
列挙インターフェースも同じポリシーに従います。たとえば、setpwent、getpwent、endpwent が列挙するのは実効的な passwd データベースであり、必ずしも /etc/passwd ではありません。したがって、列挙によってディレクトリサーバーへの問い合わせが発生することがあり、ローカルファイルを読み取る場合よりも大きな、または変化する集合が返される可能性があります。
並行処理を行うコードでは、リエントラントなインターフェースを使用してください。getpwnam_r および同種の関数は、呼び出し元が所有する結果用オブジェクトと文字バッファーを受け取り、エラー番号を返します。また、該当なしの場合は、成功したレコードとして扱うのではなく、結果ポインターを null にして通知します。結果に関する厳密な規約はインターフェースごとに異なるため、すべての失敗を errno に集約せず、該当するマニュアルを確認してください。従来の非リエントラントなインターフェースは、後続の呼び出しによって上書きされる記憶領域へのポインターを返すのが一般的です。
検索順序の設定 #
コメント以外の各エントリーには、データベース名、コロン、サービスの順序付きリストを記述します。
passwd: files systemd sss
group: files systemd sss
shadow: files sss
hosts: files resolve [!UNAVAIL=return] dns
services: filesfiles は対応するローカルデータベースを読み取ります。dns はホスト検索に使用されます。resolve と mymachines は、それらを提供する環境で利用できる systemd のホストサービスです。sss、ldap、winbind、mdns は、個別にインストールされるプロバイダーによって提供されます。設定されたサービスが利用できない場合も運用時の動作の一部であり、そのライブラリが必ず存在するという宣言ではありません。
各サービスは、次の 4 種類の NSS ステータスのいずれかを返します。
| ステータス | 意味 | デフォルトのアクション |
|---|---|---|
success | レコードが見つかった | return |
notfound | 検索は完了したがレコードが見つからなかった | continue |
unavail | サービスが応答できない | continue |
tryagain | サービスが一時的に応答できない | continue |
角括弧で囲んだ条件は、直前のサービスに対するデフォルトを上書きします。
hosts: files [NOTFOUND=return] dnsこの設定では、/etc/hosts での否定的な検索結果を意図的に最終結果とします。[!UNAVAIL=return] は unavail 以外のすべてのステータスに一致します。merge のサポート範囲は限定的です。glibc は [SUCCESS=merge] を使用して一致するグループエントリーを統合しますが、任意のデータベースや getgrent による列挙には適用しません。
設定された動作をテストするときは、ローカルファイルを直接読み取るのではなく NSS を使用する getent を実行してください。
getent passwd root
getent hosts example.com
getent services httpsモジュール境界 #
SERVICE という名前のサービスに対して、従来の glibc NSS モジュールは libnss_SERVICE.so.2 という名前の共有オブジェクトです。設定されたデータベースが必要とした時点で、動的ローダーを介して読み込まれます。モジュールは _nss_files_getpwnam_r のようなデータベースおよび操作ごとのシンボルをエクスポートします。モジュールが内部 NSS ステータスを返すと、glibc が nsswitch.conf のアクションを適用します。
モジュール ABI は、意図的に公開検索 API より低水準に設計されています。リエントラントな検索エントリーポイントは、呼び出し元が提供したオブジェクトとバッファーに値を格納し、該当なしとバックエンド利用不可を区別し、そのデータベースの規約に従ってエラー出力を設定する必要があります。モジュールの作成者は、対象のリリースおよびアーキテクチャにおける glibc NSS インターフェースに適合させる必要があります。名前が似た公開 libc 関数をエクスポートしても、NSS バックエンドにはなりません。
NSS は汎用の設定言語ではありません。glibc は自身が実装していないデータベース名を無視しますが、アプリケーションが独自の名前を定義して解析する場合があります。sudoers と subid がその例です。したがって、標準外のエントリーを変更する前に、そのコンシューマーとモジュール ABI の両方を特定してください。
リゾルバーとディレクトリサービスの動作 #
ホスト名解決は files、resolve、dns を経由でき、アイデンティティー解決はローカルファイル、systemd の動的ユーザーサービス、SSSD、LDAP、または Active Directory アダプターを経由できます。そのため、検索が IPC やネットワークのラウンドトリップを待ってブロックする可能性があります。サービスの順序、否定的な結果に対するアクション、デーモンの可用性、ディレクトリのタイムアウト、およびキャッシュは、ログインのレイテンシーと障害時の動作に影響するため、一体として設計する必要があります。
glibc NSS のドキュメントと nsswitch.conf(5) では、設定と libc 側から見た動作を定義しています。
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)