LDAPのトラブルシューティング

管理者の場合は、以下の情報を使用してLDAPのトラブルシューティングを行います。

よくある問題とワークフロー

接続

接続拒否

LDAP サーバーに接続しようとしたときにConnection Refused エラーメッセージが表示される場合は、GitLab が使用する LDAPportencryption の設定をレビューしてください。一般的な組み合わせは、encryption: 'plain'port: 389 、あるいはencryption: 'simple_tls'port: 636です。

接続がタイムアウトします

GitLabがLDAPエンドポイントに到達できない場合、このようなメッセージが表示されます:

Could not authenticate you from Ldapmain because "Connection timed out - user specified timeout".

設定したLDAPプロバイダやエンドポイントがオフラインであるか、GitLabが到達できない場合、LDAPユーザーは認証やサインインができません。GitLabは、LDAP停止中に認証を提供するために、LDAPユーザーの認証情報をキャッシュしたり保存したりしません。

このエラーが表示される場合は、LDAPプロバイダーまたは管理者にお問い合わせください。

参照エラー

ログにLDAP search error: Referral が表示される場合、または LDAP グループ同期のトラブルシューティング中にこのエラーが表示される場合は、設定に問題がある可能性があります。LDAP 設定/etc/gitlab/gitlab.rb (Omnibus) またはconfig/gitlab.yml (ソース) は YAML 形式で、インデントに敏感です。group_base およびadmin_group の設定キーが、サーバー識別子を 2 つ空白インデントしていることを確認してください。デフォルトの識別子はmain で、スニペット例は以下のようになります:

main: # 'main' is the GitLab 'provider ID' of this LDAP server
  label: 'LDAP'
  host: 'ldap.example.com'
  ...
  group_base: 'cn=my_group,ou=groups,dc=example,dc=com'
  admin_group: 'my_admin_group'

LDAPクエリ

以下では、Railsコンソールを使ってLDAPの検索を行うことができます。何をしようとしているかにもよりますが、ユーザーや グループを直接クエリする方が理にかなっているかもしれませんし、 ldapsearch を代わりに使うこともできます。

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base is required
    # use .base or .group_base
    base: adapter.config.group_base,

    # :filter is optional
    # 'cn' looks for all "cn"s under :base
    # '*' is the search string - here, it's a wildcard
    filter: Net::LDAP::Filter.eq('cn', '*'),

    # :attributes is optional
    # the attributes we want to get returned
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

フィルタでOIDを使用する場合は、Net::LDAP::Filter.eqNet::LDAP::Filter.construct に置き換えてください:

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base is required
    # use .base or .group_base
    base: adapter.config.base,

    # :filter is optional
    # This filter includes OID 1.2.840.113556.1.4.1941
    # It will search for all direct and nested members of the group gitlab_grp in the LDAP directory
    filter: Net::LDAP::Filter.construct("(memberOf:1.2.840.113556.1.4.1941:=CN=gitlab_grp,DC=example,DC=com)"),

    # :attributes is optional
    # the attributes we want to get returned
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

この実行方法の例については、 Adapter モジュール をレビューしてください。

ユーザーのサインイン

ユーザーが見つかりません

LDAPへの接続が確立できることを確認したにもかかわらず、GitLabの出力にLDAPユーザーが表示されない場合は、次のいずれかの可能性が高いです:

  • bind_dn ユーザーはユーザーツリーを走査するのに十分な権限を持っていません。
  • ユーザーは設定されたbase に該当しません。
  • 設定されたuser_filter はユーザーへのアクセスをブロックします。

この場合、/etc/gitlab/gitlab.rb の既存の LDAP 設定でldapsearch を使用して、上記のどちらが正しいかを確認します。

ユーザーがサインインできない

ユーザーがサインインできない理由はさまざまです。手始めに、以下の質問を自問してみてください:

  • ユーザーはLDAPで設定された base に該当しますか?サインインするには、ユーザーがこのbase に該当する必要があります。
  • ユーザーはで設定されたuser_filter を通過しますか?設定されていない場合、この質問は無視できます。設定されている場合、サインインを許可されるには、ユーザーはこのフィルタも通過する必要があります。
    • user_filter のデバッグに関する文書を参照してください。

上記の両方に問題がない場合、次に問題を探す場所は、イシューを再現しながらログそのものです。

  • ユーザーにサインインしてもらい、失敗させてください。
  • サインインに関するエラーやその他のメッセージが出力されていないか確認してください。このページの他のエラーメッセージが表示されるかもしれませんが、その場合はそのセクションが問題解決に役立ちます。

ログから問題の根源にたどり着けない場合は、Railsコンソールを使って このユーザーにクエリを発行し、GitLabがLDAPサーバー上でこのユーザーを読み込めるかどうかを確認してください。

また、ユーザー同期をデバッグしてさらに詳しく調べることもできます。

サインイン時に無効な認証情報

使用されているサインイン認証情報が LDAP 上で正確である場合、問題のユーザーについて以下が真であることを確認してください:

  • バインドするユーザーが、ユーザー・ツリーを読み取り、それを横断するのに十分な権限を持っていることを確認してください。
  • user_filter が他の有効なユーザーをブロックしていないか確認してください。
  • LDAPチェックコマンドを実行して、LDAP設定が正しく、GitLabがユーザーを確認できることを確認してください。

LDAPアカウントへのアクセスが拒否されました。

監査役レベルのアクセス権を持つユーザーに影響する可能性のあるバグがあります。Premium/Ultimateからダウングレードした場合、監査役ユーザーがサインインしようとすると、以下のメッセージが表示されることがあります:Access denied for your LDAP account.

影響を受けるユーザーのアクセスレベルを切り替えることで、回避策があります:

  1. 管理者として、左のサイドバーで「検索」を選択するか、「検索」にアクセスしてください。
  2. Admin Areaを選択します。
  3. 左側のサイドバーで、[概要] > [ユーザー]を選択します。
  4. 該当するユーザー名を選択します。
  5. 右上の [編集] を選択します。
  6. ユーザーのアクセスレベルをRegular からAdministrator (またはその逆)に変更します。
  7. ページの下部で、「変更を保存」を選択します。
  8. 右上隅で、もう一度編集を選択します。
  9. ユーザーの元のアクセスレベル(Regular またはAdministrator )に戻し、[Save changes(変更を保存)]を再度選択します。

これでユーザーはサインインできるはずです。

Eメールはすでに送信されています。

ユーザーが正しい LDAP 認証情報を使用してサインインしようとすると、アクセスが拒否され、production.logに以下のようなエラーが表示されます:

(LDAP) Error saving user <USER DN> (email@example.com): ["Email has already been taken"]

このエラーは、LDAP のメールアドレスについて言及していますemail@example.com。 メールアドレスは GitLab 内で一意でなければならず、LDAP はユーザーのプライマリメール (多数のセカンダリメールとは異なります) にリンクして email@example.comいます。email@example.com別のユーザー(あるいは同じユーザー)がそのメールを email@example.comセカンダリメールとして設定しているためにこのエラーが発生しているのです。

Railsコンソールを使って、この競合するメールアドレスがどこから来ているのかを確認することができます。コンソールで以下を実行します:

# This searches for an email among the primary AND secondary emails
user = User.find_by_any_email('email@example.com')
user.username

これで、どのユーザーがこのメールアドレスを持っているかがわかります。ここでは2つのステップのうちどちらかを実行する必要があります:

  • LDAP でサインインするときにこのユーザー用の GitLab ユーザー/ユーザー名を新しく作成する、セカンダリ E メールを削除してコンフリクトをなくす、です。
  • LDAPで使用するために、このユーザー用の既存のGitLabユーザー/ユーザー名を使用するには、GitLabがこのプロファイルをLDAPアイデンティティに関連付けるように、セカンダリEメールとしてこのEメールを削除し、プライマリEメールにします。

これらの手順はユーザーが自分のプロファイルで行うか、管理者が行うことができます。

プロジェクト制限エラー

以下のエラーは、リミットまたは制限がアクティビティになっているが、関連するデータフィールドにデータが含まれていないことを示します:

  • Projects limit can't be blank.
  • Projects limit is not a number.

これを解決するには

  1. 左のサイドバーで、Search を選択するか、次のページに進んでください。
  2. Admin Areaを選択します。
  3. 左サイドバーの「設定」>「一般」を選択します。
  4. 以下の両方を展開します:
    • アカウントとリミット
    • 登録の制限
  5. 例えば、「デフォルトのプロジェクト制限」や「サインアップの許可ドメイン」フィールドを確認し、該当する値が設定されていることを確認します。

LDAPユーザーフィルタのデバッグ

ldapsearch を使用すると、設定したユーザフィルタをテストして、期待するユーザが返されることを確認することができます。

ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt  -b "$base" "$user_filter" sAMAccountName
  • $ で始まる変数は、設定ファイルの LDAP セクションの変数を参照します。
  • プレーン認証方式を使用している場合は、ldaps://ldap:// に置き換えてください。ポート389 はデフォルトのldap:// ポートで、636 はデフォルトのldaps:// ポートです。
  • bind_dn ユーザのパスワードはbind_dn_password.txt にあると仮定しています。

全ユーザーの同期

GitLabがLDAPに対してユーザーを同期させようとしたときに何が起こるかは、手動でユーザーを同期させたときの出力でわかります。Rails コンソールに入り、実行します:

Rails.logger.level = Logger::DEBUG

LdapSyncWorker.new.perform

次に、出力の読み方を学びましょう

ユーザー同期後のコンソール出力例

手動ユーザー同期の出力は非常に冗長で、一人のユーザーが同期に成功すると次のようになります:

Syncing user John, email@example.com
  Identity Load (0.9ms)  SELECT  "identities".* FROM "identities" WHERE "identities"."user_id" = 20 AND (provider LIKE 'ldap%') LIMIT 1
Instantiating Gitlab::Auth::Ldap::Person with LDIF:
dn: cn=John Smith,ou=people,dc=example,dc=com
cn: John Smith
mail: email@example.com
memberof: cn=admin_staff,ou=people,dc=example,dc=com
uid: John

  UserSyncedAttributesMetadata Load (0.9ms)  SELECT  "user_synced_attributes_metadata".* FROM "user_synced_attributes_metadata" WHERE "user_synced_attributes_metadata"."user_id" = 20 LIMIT 1
   (0.3ms)  BEGIN
  Namespace Load (1.0ms)  SELECT  "namespaces".* FROM "namespaces" WHERE "namespaces"."owner_id" = 20 AND "namespaces"."type" IS NULL LIMIT 1
  Route Load (0.8ms)  SELECT  "routes".* FROM "routes" WHERE "routes"."source_id" = 27 AND "routes"."source_type" = 'Namespace' LIMIT 1
  Ci::Runner Load (1.1ms)  SELECT "ci_runners".* FROM "ci_runners" INNER JOIN "ci_runner_namespaces" ON "ci_runners"."id" = "ci_runner_namespaces"."runner_id" WHERE "ci_runner_namespaces"."namespace_id" = 27
   (0.7ms)  COMMIT
   (0.4ms)  BEGIN
  Route Load (0.8ms)  SELECT "routes".* FROM "routes" WHERE (LOWER("routes"."path") = LOWER('John'))
  Namespace Load (1.0ms)  SELECT  "namespaces".* FROM "namespaces" WHERE "namespaces"."id" = 27 LIMIT 1
  Route Exists (0.9ms)  SELECT  1 AS one FROM "routes" WHERE LOWER("routes"."path") = LOWER('John') AND "routes"."id" != 50 LIMIT 1
  User Update (1.1ms)  UPDATE "users" SET "updated_at" = '2019-10-17 14:40:59.751685', "last_credential_check_at" = '2019-10-17 14:40:59.738714' WHERE "users"."id" = 20

ここでは、デバッグの際に役立つことを説明します。

まず、GitLab は LDAP でサインインしたことのあるユーザーをすべて探し、それを繰り返します。各ユーザーの同期は、GitLab に存在するユーザー名とメールアドレスをコンテナにした次の行から始まります:

Syncing user John, email@example.com

特定のユーザーの GitLab メールアドレスを出力しない場合は、そのユーザーはまだ LDAP でサインインしていないことになります。

次に、GitLabはこのユーザーと設定されたLDAPプロバイダ間の既存のリンクをidentities

  Identity Load (0.9ms)  SELECT  "identities".* FROM "identities" WHERE "identities"."user_id" = 20 AND (provider LIKE 'ldap%') LIMIT 1

ID オブジェクトには、GitLab が LDAP でユーザーを探すときに使う DN が格納されています。DN が見つからない場合は、代わりに電子メールが使われます。このユーザーが LDAP で見つかったことがわかります:

Instantiating Gitlab::Auth::Ldap::Person with LDIF:
dn: cn=John Smith,ou=people,dc=example,dc=com
cn: John Smith
mail: email@example.com
memberof: cn=admin_staff,ou=people,dc=example,dc=com
uid: John

ユーザがLDAPでDNまたは電子メールで見つからなかった場合、代わりに以下のメッセージが表示されることがあります:

LDAP search error: No Such Object

…この場合、ユーザーはブロックされます:

  User Update (0.4ms)  UPDATE "users" SET "state" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["state", "ldap_blocked"], ["updated_at", "2019-10-18 15:46:22.902177"], ["id", 20]]

LDAP でユーザーが見つかったら、残りの出力で GitLab データベースを更新します。

LDAPでユーザーをクエリする

これは、GitLabがLDAPにアクセスして特定のユーザーを読み込めるかどうかをテストします。GitLab UIでは静かに失敗しているように見えるLDAPへの接続やクエリの潜在的なエラーを明らかにすることができます。

Rails.logger.level = Logger::DEBUG

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # If `main` is the LDAP provider
Gitlab::Auth::Ldap::Person.find_by_uid('<uid>', adapter)

グループメンバーシップ

付与されない会員資格

LDAPグループ同期によって特定のユーザーがGitLabグループに追加されているはずなのに、なぜかそうなっていないことがあります。この状況をデバッグするために、いくつかのことをチェックすることができます。

  • LDAP設定にgroup_baseこの設定はグループ同期が正しく機能するために必要です。
  • 正しいLDAPグループリンクがGitLabグループに追加されていることを確認してください。
  • ユーザーが LDAP ID を持っていることを確認してください:
    1. GitLab に管理ユーザーとしてサインインしてください。
    2. 左のサイドバーで、Search を選択するか、次のページに進んでください。
    3. Admin Areaを選択します。
    4. 左側のサイドバーで、[概要] > [ユーザー]を選択します。
    5. ユーザーを検索します。
    6. ユーザー名を選択してユーザーを開きます。編集は選択しないでください。
    7. Identities]タブを選択します。Identifier に LDAP DN を持つ LDAP ID があるはずです。ない場合は、このユーザはまだ LDAP でサインインしていないため、最初にサインインする必要があります。
  • グループが同期されるまで1時間または設定された間隔を待ちました。このプロセスを早めるには、GitLabグループのManage > Membersで Sync now(1つのグループを同期)を押すか、グループ同期Rakeタスク(すべてのグループを同期)を実行してください。

上記がすべてうまくいったら、Railsコンソールでもう少し高度なデバッグをしてみましょう。

  1. railsコンソールに入ります。
  2. テストする GitLab グループを選択します。このグループにはLDAPグループリンクが設定されているはずです。
  3. デバッグログを有効にして、上記の GitLab グループを見つけ、LDAP と同期します。
  4. 同期の出力を見てみましょう。出力の読み方については、ログの出力例を参照してください。
  5. それでもユーザーが追加されない理由がわからない場合は、LDAP グループに直接クエリを実行して、どのメンバーがリストされているかを確認します。
  6. ユーザーのDNまたはUIDが、上記の出力のリストのいずれかに含まれていますか?ここにあるDNSまたはUIDのいずれかが、先に確認したLDAP IDの「Identifier」と一致するはずです。一致しない場合、ユーザーはLDAPグループにいないようです。

管理者権限が付与されていません

管理者同期が設定されているにもかかわらず、設定されたユーザーに正しい管理者権限が付与されていない場合は、以下の点を確認してください:

  • group_base も設定されている
  • gitlab.rb の設定admin_group は、DN や配列ではなく CN です。
  • このCNは、設定されたgroup_base の範囲に属します。
  • admin_group のメンバーは、すでにLDAP認証情報でGitLabにサインインしています。GitLabは、LDAPに接続済みのアカウントを持つユーザーにのみ管理者アクセスを許可します。

上記のことがすべて当てはまり、それでもユーザーがアクセスできない場合は、rails コンソールで手動グループ同期を実行し、GitLab がadmin_groupを同期したときに何が起こるか出力を見てみましょう。

同期ボタンがUIで動かない

グループの[グループ] > [メンバー]ページにある[今すぐ同期]ボタンが動かなくなることがあります。ボタンが押された後、ページが再読み込みされると、ボタンは動かなくなります。その後、ボタンを再度選択することはできません。

さまざまな理由で同期ボタンが動かなくなることがあり、特定のケースではデバッグが必要です。以下の2つの原因が考えられます。

無効なメンバーシップ

グループのメンバーまたはリクエストメンバーの一部が無効な場合、[今すぐ同期] ボタンが押せなくなります。この問題の可視性改善の進捗は関連イシューで確認できます。この問題が原因でSync nowボタンが動かなくなるかどうかは、Rails コンソールを使って確認できます:

# Find the group in question
group = Group.find_by(name: 'my_gitlab_group')

# Look for errors on the Group itself
group.valid?
group.errors.map(&:full_messages)

# Look for errors among the group's members and requesters
group.requesters.map(&:valid?)
group.requesters.map(&:errors).map(&:full_messages)
group.members.map(&:valid?)
group.members.map(&:errors).map(&:full_messages)

表示されたエラーは問題を特定し、解決策を示すことができます。例えば、サポートチームは以下のようなエラーを確認しました:

irb(main):018:0> group.members.map(&:errors).map(&:full_messages)
=> [["The member's email address is not allowed for this group. Go to the group's &#39;Settings &gt; General&#39; page, and check &#39;Restrict membership by email domain&#39;."]]

このエラーは、管理者が電子メールドメインでグループメンバーシップを制限することを選択しましたが、ドメインにタイプミスがあったことを示しています。ドメイン設定が修正された後、[今すぐ同期]ボタンは再び機能しました。

SidekiqノードにLDAP設定がありません。

GitLabが複数のノードにスケールされ、Sidekiqを実行しているノードで/etc/gitlab/gitlab.rb のLDAP設定が欠落している場合、Sync nowボタンが動かなくなります。この場合、Sidekiqのジョブは消えてしまうようです。

LDAPにはローカルLDAP設定を必要とする非同期で実行される複数のジョブがあるため、SidekiqノードにはLDAPが必要です:

Sidekiqを実行している各ノードでLDAPをチェックするRakeタスクを実行することで、LDAP設定の欠落が問題であるかどうかをテストできます。このノードでLDAPが正しく設定されていれば、LDAPサーバーに接続し、ユーザーを返します。

このイシューを解決するには、SidekiqノードでLDAPを設定します。設定したら、LDAPをチェックするRakeタスクを実行して、GitLabノードがLDAPに接続できることを確認します。

すべてのグループを同期

note
デバッグが不要なときに手動で全グループを同期するには、代わりにRakeタスクを使います。

手動グループ同期からの出力は、GitLabがLDAPに対してLDAPグループメンバーシップを同期したときに何が起こるかを示すことができます。

Rails.logger.level = Logger::DEBUG

LdapAllGroupsSyncWorker.new.perform

次に、出力の読み方を学びましょう

グループ同期後のコンソール出力例

ユーザー同期の出力と同様、手動グループ同期の出力も非常に冗長です。しかし、有益な情報がたくさん含まれています。

同期が実際に開始されるポイントを示します:

Started syncing 'ldapmain' provider for 'my_group' group

次のエントリは、GitLabがLDAPサーバーで見ているすべてのユーザーDNSの配列を示します。これらのDNSはGitLabグループではなく、一つのLDAPグループのユーザーです。このGitLabグループに複数のLDAPグループがリンクされている場合、このように複数のログエントリが表示されます。このログエントリーにLDAPユーザーのDNが表示されていない場合は、LDAPがユーザーをルックアップしていません。ユーザーが実際にLDAPグループにいることを確認してください。

Members in 'ldap_group_1' LDAP group: ["uid=john0,ou=people,dc=example,dc=com",
"uid=mary0,ou=people,dc=example,dc=com", "uid=john1,ou=people,dc=example,dc=com",
"uid=mary1,ou=people,dc=example,dc=com", "uid=john2,ou=people,dc=example,dc=com",
"uid=mary2,ou=people,dc=example,dc=com", "uid=john3,ou=people,dc=example,dc=com",
"uid=mary3,ou=people,dc=example,dc=com", "uid=john4,ou=people,dc=example,dc=com",
"uid=mary4,ou=people,dc=example,dc=com"]

上記の各エントリのすぐ後に、解決されたメンバーのアクセス・レベルのハッシュが表示されます。このハッシュは、GitLabがこのグループにアクセスすべきだと考えるすべてのユーザーDNSを、どのアクセスレベル(ロール)で表しています。このハッシュは追加可能で、LDAP グループ検索によって DNS を追加したり既存のエントリを変更したりすることができます。このエントリの最後の出現は、GitLabがどのユーザーをこのグループに追加すべきと考えているかを示しています。

note
10 はGuest、20 はReporter 、30 はDeveloper、40 はMaintainer 、50 はOwnerです。
Resolved 'my_group' group member access: {"uid=john0,ou=people,dc=example,dc=com"=>30,
"uid=mary0,ou=people,dc=example,dc=com"=>30, "uid=john1,ou=people,dc=example,dc=com"=>30,
"uid=mary1,ou=people,dc=example,dc=com"=>30, "uid=john2,ou=people,dc=example,dc=com"=>30,
"uid=mary2,ou=people,dc=example,dc=com"=>30, "uid=john3,ou=people,dc=example,dc=com"=>30,
"uid=mary3,ou=people,dc=example,dc=com"=>30, "uid=john4,ou=people,dc=example,dc=com"=>30,
"uid=mary4,ou=people,dc=example,dc=com"=>30}

以下のような警告が表示されることも珍しくありません。これらは、GitLabがユーザーをグループに追加したはずなのに、そのユーザーがGitLabで見つからなかったことを示しています。通常、これは心配することではありません。

特定のユーザーがすでにGitLabに存在しているはずなのにこのようなエントリーが表示される場合は、GitLabに保存されているDNが不一致である可能性があります。ユーザーのLDAP IDを更新するには、User DN and email has changedをご覧ください。

User with DN `uid=john0,ou=people,dc=example,dc=com` should have access
to 'my_group' group but there is no user in GitLab with that
identity. Membership will be updated when the user signs in for
the first time.

最後に、以下のエントリではこのグループの同期が終了したと表示されています:

Finished syncing all providers for 'my_group' group

設定されたすべてのグループリンクが同期されると、GitLabは同期する管理者や外部ユーザーを探します:

Syncing admin users for 'ldapmain' provider

出力は単一のグループの場合と同じようになり、この行は同期が終了したことを示します:

Finished syncing admin users for 'ldapmain' provider

管理者同期が設定されていない場合は、このようなメッセージが表示されます:

No `admin_group` configured for 'ldapmain' provider. Skipping

同期するグループ

すべてのグループを同期させると出力にノイズが多くなり、GitLab のひとつのグループだけをトラブルシューティングしたいときに邪魔になります。そんなときは、このグループだけを同期してデバッグ出力を見る方法を紹介しましょう:

Rails.logger.level = Logger::DEBUG

# Find the GitLab group.
# If the output is `nil`, the group could not be found.
# If a bunch of group attributes are in the output, your group was found successfully.
group = Group.find_by(name: 'my_gitlab_group')

# Sync this group against LDAP
EE::Gitlab::Auth::Ldap::Sync::Group.execute_all_providers(group)

この出力は、すべてのグループを同期した場合と同じです。

LDAPのグループへのクエリ

GitLabがLDAPグループを読み込んですべてのメンバーを確認したい場合は、次のようにします:

# Find the adapter and the group itself
adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # If `main` is the LDAP provider
ldap_group = EE::Gitlab::Auth::Ldap::Group.find_by_cn('group_cn_here', adapter)

# Find the members of the LDAP group
ldap_group.member_dns
ldap_group.member_uids

LDAP同期はグループからグループ作成者を削除しません。

LDAP同期では、グループにユーザーが存在しない場合、LDAPグループの作成者をそのグループから削除する必要があります。LDAP同期を実行してもこれが実行されない場合:

  1. ユーザーをLDAPグループに追加します。
  2. LDAPグループの同期が終了するまで待ちます。
  3. ユーザーをLDAPグループから削除します。

ユーザーのDNとEメールが変更されました。

LDAPでプライマリEメールとDNの両方が変更された場合、GitLabはユーザーの正しいLDAPレコードを特定できません。その結果、GitLabはそのユーザーをブロックします。GitLabがLDAPレコードを見つけられるように、ユーザーの既存のGitLabプロファイルを少なくともどちらかで更新してください:

  • 新しいプライマリEメール。
  • DNの値。

次のスクリプトは、提供されたすべてのユーザーの電子メールを更新し、ブロックされたり、アカウントにアクセスできなくなったりしないようにします。

note
以下のスクリプトでは、新しいメールアドレスのアカウントを最初に削除する必要があります。メールアドレスは GitLab 内で一意でなければなりません。

Rails コンソールに移動して実行します:

# Each entry must include the old username and the new email
emails = {
  'ORIGINAL_USERNAME' => 'NEW_EMAIL_ADDRESS',
  ...
}

emails.each do |username, email|
  user = User.find_by_username(username)
  user.email = email
  user.skip_reconfirmation!
  user.save!
end

そしてUserSyncを実行して、各ユーザの最新のDNを同期することができます。

Could not authenticate you from Ldapmain because "Unknown provider"

LDAPサーバとの認証時に以下のエラーが発生することがあります:

Could not authenticate you from Ldapmain because "Unknown provider (ldapsecondary). available providers: ["ldapmain"]".

このエラーは、GitLabの設定から名前を変更したり削除したりしたLDAPサーバーで以前認証していたアカウントを使用した場合に発生します。例えば

  • 初期状態では、mainsecondary がGitLab設定のldap_servers に設定されています。
  • secondary の設定は削除されるか、main に名前が変更されます。
  • サインインしようとするユーザーには、secondaryidentify レコードがありますが、これはもう設定されていません。

Railsコンソールを使って該当するユーザーをリストアップし、どのLDAPサーバーのIDを持っているかを確認してください:

ldap_identities = Identity.where(provider: "ldapsecondary")
ldap_identities.each do |identity|
  u=User.find_by_id(identity.user_id)
  ui=Identity.where(user_id: identity.user_id)
  puts "user: #{u.username}\n   #{u.email}\n   last activity: #{u.last_activity_on}\n   #{identity.provider} ID: #{identity.id} external: #{identity.extern_uid}"
  puts "   all identities:"
  ui.each do |alli|
    puts "    - #{alli.provider} ID: #{alli.id} external: #{alli.extern_uid}"
  end
end;nil

このエラーを解決するには2つの方法があります。

LDAPサーバーへの参照の名前を変更します。

この解決策は、LDAPサーバーが互いのレプリカであり、影響を受けるユーザーが設定されたLDAPサーバーを使用してサインインできる必要がある場合に適しています。例えば、LDAPの高可用性を管理するためにロードバランサーが使用されるようになり、別のセカンダリサインインオプションが不要になった場合などです。

note
LDAPサーバーが互いのレプリカでない場合、このソリューションによって、影響を受けるユーザーがサインインできなくなります。

設定されていないLDAPサーバーへの参照の名前を変更するには、以下を実行します:

sudo gitlab-rake gitlab:ldap:rename_provider[ldapsecondary,ldapmain]

削除された LDAP サーバーに関連するidentity レコードを削除します。

このソリューションでは、影響を受けるユーザーは設定されたLDAPサーバーでサインインすることができ、GitLabによって新しいidentity レコードが作成されます。Rails コンソールでldapsecondary ID を削除します:

ldap_identities = Identity.where(provider: "ldapsecondary")
ldap_identities.each do |identity|
  puts "Destroying identity: #{identity.id} #{identity.provider}: #{identity.extern_uid}"
  identity.destroy!
rescue => e
  puts 'Error generated when destroying identity:\n ' + e.to_s
end; nil

期限切れのライセンスが複数の LDAP サーバーでエラーを引き起こす問題

複数のLDAPサーバーを使用するには、有効なライセンスが必要です。有効期限切れのライセンスは、次のような問題を引き起こす可能性があります:

  • 502 Webインターフェイスのエラー。
  • ログに以下のようなエラーが表示されます(実際のストラテジー名は/etc/gitlab/gitlab.rb で設定された名前に依存します):

     Could not find a strategy with name `Ldapsecondary'. Please ensure it is required or explicitly set it using the :strategy_class option. (Devise::OmniAuth::StrategyNotFound)
    

このエラーを解決するには、GitLabインスタンスにWebインターフェイスを使わずに新しいライセンスを適用する必要があります:

  1. プライマリーでない LDAP サーバーすべての GitLab 設定行を削除するか、コメントアウトします。
  2. GitLabが一時的に一つのLDAPサーバーだけを使うように再設定します。
  3. Railsコンソールに入り、ライセンスキーを追加します。
  4. GitLabの設定で追加のLDAPサーバーを再度有効にして、GitLabを再設定します。

ユーザーがグループから削除され、再度追加されています。

グループ同期中にユーザーがグループに追加され、次の同期で削除されるという現象が何度も発生している場合は、そのユーザーが複数のLDAP IDまたは冗長なLDAP IDを持っていないことを確認してください。

これらのIDの1つが、現在使用されていない古いLDAPプロバイダ用に追加されたものである場合は、、削除されたLDAPサーバに関連するidentity レコードを削除してください。

デバッグツール

LDAPチェック

LDAPをチェックするRakeタスクは、GitLabがLDAPへの接続に成功し、ユーザーを読み込めるかどうかを判断するのに役立つツールです。

接続が確立できない場合は、設定に問題があるか、ファイアウォールが接続をブロックしている可能性があります。

  • ファイアウォールで接続がブロックされていないこと、LDAPサーバーがGitLabホストからアクセスできることを確認してください。
  • Rakeのチェック出力でエラーメッセージを探し、LDAPの設定値(具体的にはhost,port,bind_dn,password )が正しいことを確認してください。
  • 接続の失敗をさらにデバッグするために、ログの エラーを探します。

もしGitLabがLDAPにうまく接続できてもユーザーを返さない場合は、ユーザーが見つからないときの対処法を参照してください

GitLab のログ

LDAP設定によってユーザーアカウントがブロックされたり解除されたりした場合、application_json.log にメッセージが記録されます。

LDAPルックアップ中に予期せぬエラー(設定エラー、タイムアウト)が発生した場合、サインインは拒否され、にメッセージが記録されますproduction.log

ldapsearch

ldapsearch は LDAP サーバにクエリを発行するユーティリティです。LDAP 設定をテストし、使用している設定が期待通りの結果を得ることを確認するために使用できます。

ldapsearchを使用する場合は、gitlab.rb の設定ですでに指定したものと同じ設定を使用するようにしてください。これにより、それらの設定を正確に使用した場合に何が起こるかを確認できます。

GitLabホスト上でこのコマンドを実行することで、GitLabホストとLDAPの間に障害物がないことを確認することもできます。

例えば、次のようなGitLabの設定を考えてみましょう:

gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' # remember to close this block with 'EOS' below
   main: # 'main' is the GitLab 'provider ID' of this LDAP server
     label: 'LDAP'
     host: '127.0.0.1'
     port: 389
     uid: 'uid'
     encryption: 'plain'
     bind_dn: 'cn=admin,dc=ldap-testing,dc=example,dc=com'
     password: 'Password1'
     active_directory: true
     allow_username_or_email_login: false
     block_auto_created_users: false
     base: 'dc=ldap-testing,dc=example,dc=com'
     user_filter: ''
     attributes:
       username: ['uid', 'userid', 'sAMAccountName']
       email:    ['mail', 'email', 'userPrincipalName']
       name:       'cn'
       first_name: 'givenName'
       last_name:  'sn'
     group_base: 'ou=groups,dc=ldap-testing,dc=example,dc=com'
     admin_group: 'gitlab_admin'
EOS

bind_dn ユーザーを見つけるために次のようにldapsearch を実行します:

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -p 389 \
  -h 127.0.0.1 \
  -b "dc=ldap-testing,dc=example,dc=com"

bind_dn,password,port,host,base はすべてgitlab.rbで設定されているものと同じです。

start_tls 暗号化で ldapsearch を使用します。

前述の例では、ポート 389 に対してプレーンテキストで LDAP テストを実行しています。start_tls 暗号化 を使用している場合は、ldapsearch コマンドに以下を含めます:

  • -Z フラグ。
  • LDAP サーバーの FQDN。

TLS ネゴシエーション中に LDAP サーバーの FQDN が証明書と照合されるためです:

ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -p 389 \
  -h "testing.ldap.com" \
  -b "dc=ldap-testing,dc=example,dc=com" -Z

simple_tls 暗号化で ldapsearch を使用します。

simple_tls 暗号化 (通常はポート 636)を使用している場合は、ldapsearch コマンドに以下を含めます:

  • LDAP サーバーの FQDN と-H フラグ、ポート。
  • 完全に構築された URI。
ldapsearch -D "cn=admin,dc=ldap-testing,dc=example,dc=com" \
  -w Password1 \
  -H "ldaps://testing.ldap.com:636" \
  -b "dc=ldap-testing,dc=example,dc=com"

詳しくは公式ドキュメントldapsearch ドキュメント をご覧ください。

AdFindの使用 (Windows)

AdFind ユーティリティ (Windows ベースのシステム) を使用して、LDAP サーバーにアクセスでき、認証が正しく機能していることをテストできます。AdFind は、Joe Richardsによって作られたフリーウェアのユーティリティです。

すべてのオブジェクトを返します

フィルタobjectclass=* を使用すると、すべてのディレクトリオブジェクトを返すことができます。

adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f (objectClass=*)

フィルタを使用して単一のオブジェクトを返します

オブジェクト名または完全なDN指定して、単一のオブジェクトを取得することもできます。この例では、オブジェクト名のみCN=Leroy Foxを指定しています。

adfind -h ad.example.org:636 -ssl -u "CN=GitLabSRV,CN=Users,DC=GitLab,DC=org" -up Password1 -b "OU=GitLab INT,DC=GitLab,DC=org" -f "(&(objectcategory=person)(CN=Leroy Fox))"

Rails コンソール

caution
Railsコンソールを使ってデータを作成、読み込み、変更、破棄するのはとても簡単です。記載されているとおりにコマンドを実行するようにしてください。

rails コンソールは、LDAP の問題をデバッグするための貴重なツールです。コマンドを実行して GitLab がどのように反応するかを見ることで、アプリケーションと直接対話することができます。

rails consoleの使い方については、このガイドを参照してください。

デバッグ出力の有効化

GitLabが何をしているのか、何を使っているのかを示すデバッグ出力を提供します。この値は永続化されず、Rails コンソールのこのセッションでのみ有効になります。

Railsコンソールでデバッグ出力を有効にするには、railsコンソールに入り、実行します:

Rails.logger.level = Logger::DEBUG

グループ、サブグループ、メンバ、リクエスタに関連するすべてのエラーメッセージを取得します。

グループ、サブグループ、メンバー、および要求者に関連するエラーメッセージを収集します。これは、Webインターフェイスに表示されないエラーメッセージをキャプチャします。これは、LDAPグループ同期のイシューや、ユーザーとそのグループおよびサブグループのメンバーシップに関する予期しない動作のトラブルシューティングに特に役立ちます。

# Find the group and subgroup
group = Group.find_by_full_path("parent_group")
subgroup = Group.find_by_full_path("parent_group/child_group")

# Group and subgroup errors
group.valid?
group.errors.map(&:full_messages)

subgroup.valid?
subgroup.errors.map(&:full_messages)

# Group and subgroup errors for the members AND requesters
group.requesters.map(&:valid?)
group.requesters.map(&:errors).map(&:full_messages)
group.members.map(&:valid?)
group.members.map(&:errors).map(&:full_messages)
group.members_and_requesters.map(&:errors).map(&:full_messages)

subgroup.requesters.map(&:valid?)
subgroup.requesters.map(&:errors).map(&:full_messages)
subgroup.members.map(&:valid?)
subgroup.members.map(&:errors).map(&:full_messages)
subgroup.members_and_requesters.map(&:errors).map(&:full_messages)