外道父の匠
技術はゲーム感覚
コンテンツへスキップ
  • 目次
  • 質問箱
  • Linux
  • Infrastructure
  • Cloud
  • Container
  • MySQL
  • Python
  • BigData
  • Hardware
  • 負荷試験
  • 育成
  • 育児
  • 鉄拳
← SSSDとnslcd+nscdの比較
MySQL5.7 / RDS / Aurora / Cloud SQL の性能比較 →

SSSDでLDAPデータが使われない事例

先日、SSSD+LDAPネタを連投しましたが、ローカルアカウントとLDAPの2つのデータにおいて、少々変わった挙動がありましたのでメモっておきます。

今回の話はローカルユーザー/ローカルグループどちらも対象なのですが、発見時の操作がグループだったのと、作成・削除がよりシンプルなのでグループメインで説明していきます。OSはCentOS7です。



問題点

とある環境でGIDを指定せずに groupadd した時、新規グループのGIDは、ローカルグループ・LDAPグループの両方の中から、利用中の最大GID+1 で登録されました。

別の環境で同様に groupadd すると、GIDは 1000番で登録されました。

この違いを探るのに最初はディストリビューションの違いを疑いましたが、軽く調べているうちに nslcd の場合は最大GID+1 を、SSSD+LDAPの場合は 1000番以降で使われていない最も若いIDを使うことがわかったので、groupadd について潜っていくことにしました。

ローカルアカウントのIDについて復習

と、その前にIDのルールについて復習しておきます。数値はディストリビューションによって異なりますが、/etc/login.defs に使用可能なIDの範囲が記述されています。

CentOS7の /etc/login.defs から抜粋
1
2
3
4
5
6
7
8
UID_MIN                  1000
UID_MAX                 60000
GID_MIN                  1000
GID_MAX                 60000
SYS_UID_MIN               201
SYS_UID_MAX               999
SYS_GID_MIN               201
SYS_GID_MAX               999

この場合、一般ユーザーは 1000~60000 のIDを使い、システムユーザーは 201~999 を。0~200 はOSの予約済みIDってことで、予約済みIDはこちらで確認できます。

/usr/share/doc/setup-2.8.71/uidgid
1
2
3
4
5
6
7
8
9
10
11
NAME    UID     GID     HOME            SHELL   PACKAGES
root    0       0       /root           /bin/bash       setup
bin     1       1       /bin            /sbin/nologin   setup
daemon  2       2       /sbin           /sbin/nologin   setup
~snip~
systemd-journal-gateway 191     191     /               /sbin/nologin   systemd
gnats   ?       ?       ?               ?       gnats, gnats-db
listar  ?       ?       ?               ?       listar
nfsnobody       65534   65534   /var/lib/nfs            /sbin/nologin   nfs-utils
 
# Note: nfsnobody is 4294967294 on 64-bit platforms (-2)

システムユーザーは useradd/groupadd の時に -r (–system) オプションを付与することで指定できるのですが、何故か man useradd, man groupadd に載っていなく、不便な感じです。-r オプションについてはこちらに載っています。

  • groupadd(8): create new group – Linux man page

  • 一般ユーザーは 1000 から始まって 1001, 1002 と使用され、システムIDは 999 から使用され、998, 997 と下っていくことになります。

    SSSDでLDAPデータの最終IDを考慮していない原因を探る

    こんな時はソースを見るのが手っ取り早いので、groupadd コマンド周辺を追っていきます。まずは、ソースを取得します。groupadd は shadow-utils パッケージに入っています。

    yumdownloaderでソースを取得
    1
    2
    3
    yum install yum-utils
    cd /usr/local/src
    yumdownloader --source shadow-utils

    次に解凍します。

    shadowソースの準備
    1
    2
    3
    4
    5
    rpm -i shadow-utils-4.1.5.1-18.el7.src.rpm
    cd ~/rpmbuild/SOURCES/
    yum install bzip2
    tar xf shadow-4.1.5.1.tar.bz2
    cd shadow-4.1.5.1

    src/gruopadd.c を見ると、find_new_gid で新GIDを取得しています。

    src/gruopadd.c
    C
    611
    612
    613
    614
    615
            if (!gflg) {
                    if (find_new_gid (rflg, &group_id, NULL) < 0) {
                            exit (E_GID_IN_USE);
                    }
            }

    次に find_new_gid を見ると、システムグループか一般グループかで分けて処理されていますが、一般の方ではこんな感じで使用中IDを整理するついでに group_id を決定し、

    src/find_new_gid.c
    C
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
            } else {
                    group_id = gid_min;
                    setgrent ();
                    while ((grp = getgrent ()) != NULL) {
                            if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
                                    group_id = grp->gr_gid + 1;
                            }
                            /* create index of used GIDs */
                            if (grp->gr_gid <= gid_max) {
                                    used_gids[grp->gr_gid] = true;
                            }
                    }
                    endgrent ();

    その後で、GID_MAXを超えていたら再度範囲内に空きがないかチェックして確定する、といった流れになっています。

    普通に考えて、GID群を取得している getgrent (Man page of GETGRENT) に問題があるのかな?と調べてみたらすぐ見つかりました。

  • getgrent() does not return LDAP group when SSSD is used – Red Hat Customer Portal

  • この説明では Red Hat Enterprise Linux 5/6 での SSSD となっていますが、CentOS7 も対象ということになります。ということで、原因はわかりました。useradd の場合は getpwent で取得していて、こちらも同様に SSSD ではLDAPから取得してくれないようです。

    そのため、getent passwd コマンドでユーザー一覧を取得してみると、nslcd ならLDAPユーザーもリストされるのに、SSSD だとローカルユーザーだけになります。

    しかし、作成の際の既存チェックはしっかりされていて、LDAPに既存の名前やIDで作成しようとするとエラーになります。これは、既存チェックが getgrnam と getgrgid でされているからで、こちらはSSSDの場合もLDAPデータを見てくれる、ということなのでしょう。

    運用にあたって

    この問題による影響範囲がどのくらいかはわかりませんが、useradd/groupadd 周りだけでいえば、結局どちらの挙動が良いかというと、実はSSSD+LDAPのような LDAPデータを考慮しないMaxIDの取り方 が使いやすいと思っています。

    なぜなら、LDAPデータは日々追加される可能性が高いものであり、ローカルに末尾IDで作成した、その近い未来にLDAP管理画面などで追加されると、IDが被ってしまうからです。そうなると、所属グループの表示が意図しないモノになったり、ファイルシステムに対する動作にも不安要素ができてしまいます。

    だからというわけではないですが、設定の利便性も相まって気分的には SSSD+LDAP がより優位になったのですが、わりと信頼していた /etc/nsswitch.conf も結局はカーネルのシステムコールなどの周辺システム次第なんだなと実感したのが、今回の大きな収穫であり、

    エンジニアサイクルの1つとして、たまには普段関わらないソースを読み込むというのが、良いエンジニアストレッチになるなと感じた次第であります。

    Posted on 2015/10/02   カテゴリー: Linux タグ: account, LDAP, SSSD パーマリンク
    ← SSSDとnslcd+nscdの比較
    MySQL5.7 / RDS / Aurora / Cloud SQL の性能比較 →
    • 外道父
      ドリコムで主にインフラエンジニアをやっている何でも屋。

    • 質問箱

      様々な質問を受け付ける『質問箱』を設置しました。詳しい内容は 質問箱を設置しました を御覧ください

    • SNS

      Follow @GedowFather

      Twitter
      Facebook

    • 記事リンク集

      全記事の目次
      最新順はてブ
      人気順はてブ
      人気資料

    • 著書

      fun walk on infrastructure
    • 勉強会

      2015/06/17
      市ヶ谷Geek★Night #2
      (発表資料)
      2013/07/23
      Drecom×gloops合同勉強会
      (発表資料)
      2013/04/26
      Amazon/LIVESENCE/Drecom 目黒合同勉強会
      (発表資料)
      2012/12/17
      知的ヘンタイ六番勝負 第三戦 大規模インフラ・解析勉強会
      (発表資料)
      2012/12/14
      社内勉強会 キャパシティプランニング
      (発表資料)
      2012/11/26
      Hadoopソースコードリーディング第13回
      (発表資料)
      2012/08/27
      ioDrive+mySQLユーザーによる『ioDrive使い倒し勉強会』
      (発表資料)
      2012/08/22
      Fluentd meetup in Japan #2
      (発表資料)
    • アーカイブ

    • ◆問い合わせへ
    • @GedowFather のツイート

    外道父の匠
    Proudly powered by WordPress.