正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

LDAPの問題を解決する

  • プラン: Free、Premium、Ultimate
  • 提供形態: GitLab Self-Managed

管理者の方は、以下の情報を利用してLDAPのトラブルシューティングを行ってください。

一般的な問題とワークフロー

接続

接続拒否

LDAPサーバーへの接続を試みるときにConnection Refusedエラーメッセージが表示される場合は、GitLabで使用されているLDAPのportおよびencryptionの設定を確認してください。一般的な組み合わせは、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のクエリ

  • プラン: Premium、Ultimate
  • 提供形態: GitLab Self-Managed

以下を使用すると、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を通過しますか?構成されていない場合は、この質問を無視できます。構成されている場合は、サインインを許可されるには、ユーザーもこのフィルターを通過する必要があります。

上記の両方の質問に問題がない場合、問題の根本を探す次の場所は、問題を再現しながらログ自体を確認することです。

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

ログが問題の根本原因につながらない場合は、Railsコンソールを使用してこのユーザーをクエリすることで、GitLabがLDAPサーバー上でこのユーザーを読み取りできるかどうかを確認してください。

ユーザー同期をデバッグすると、さらに調査に役立つ場合があります。

ユーザーに「ログインまたはパスワードが無効です」というエラーが表示される

このエラーがユーザーに表示される場合、標準サインインフォームではなく、LDAPサインインフォームを使用してサインインしようとしていることが原因である可能性があります。

解決するには、ユーザーにLDAPのユーザー名とパスワードをLDAPサインインフォームに入力するように依頼してください。

サインイン時の認証情報が無効

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

  • バインドしているユーザーに、ユーザーのツリーを読み取り、走査するのに十分な権限があることを確認してください。
  • user_filterが、それ以外の場合は有効なユーザーをブロックしていないことを確認してください。
  • LDAPの設定が正しいことを確認するためにLDAPチェックコマンドを実行し、GitLabがユーザーを認識できることを確認します。

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

バグがあり、監査担当者レベルのアクセスを持つユーザーに影響を与える可能性があります。Premium/Ultimateプランからダウングレードすると、サインインしようとする監査担当者ユーザーに次のメッセージが表示される場合があります。Access denied for your LDAP account

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

  1. 左側のサイドバーの下部で、管理者を選択します。
  2. 概要 > ユーザーを選択します。
  3. 影響を受けるユーザーの名前を選択します。
  4. 右上隅で、編集を選択します。
  5. ユーザーのアクセスレベルをRegularからAdministratorに変更します (またはその逆)。
  6. ページの下部にある変更を保存を選択します。
  7. 右上隅で、もう一度編集を選択します。
  8. ユーザーの元のアクセスレベル (RegularまたはAdministrator) を復元し、もう一度変更を保存を選択します。

これで、ユーザーはサインインできるようになります。

メールアドレスがすでに取得されています

ユーザーが正しい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メールをセカンダリメールとして設定しているため、このエラーが発生しています。

この競合するメールアドレスの出所を、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ユーザー/ユーザー名を作成するには、セカンダリメールを削除して競合を解消します。
  • このユーザーがLDAPで使用するために既存のGitLabユーザー/ユーザー名を使用するには、このメールをセカンダリメールとして削除し、プライマリメールにして、GitLabがこのプロファイルをLDAPの識別子に関連付けるようにします。

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

プロジェクトの制限エラー

次のエラーは、制限が有効になっているものの、関連するデータフィールドにデータが含まれていないことを示しています:

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

これを解決するには:

  1. 左側のサイドバーの下部で、管理者を選択します。
  2. 設定 > 一般を選択します。
  3. 次の両方を展開します:
    • アカウントと制限
    • 新規登録の制限
  4. たとえば、デフォルトのプロジェクトの制限フィールドまたはサインアップに許可されたドメインフィールドを確認し、関連する値が構成されていることを確認します。

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にあることを前提としています。

すべてのユーザーを同期する

  • プラン: Premium、Ultimate
  • 提供形態: GitLab Self-Managed

手動によるユーザー同期からの出力は、GitLabがそのユーザーをLDAPと照合して同期しようとするときに何が起こるかを示します。Railsコンソールを入力し、以下を実行します:

Rails.logger.level = Logger::DEBUG

LdapSyncWorker.new.perform

次に、出力の読み取り方を学びます。

ユーザー同期後のコンソールの出力例
  • プラン: Premium、Ultimate
  • 提供形態: GitLab Self-Managed

手動によるユーザー同期からの出力は非常に詳細であり、1人のユーザーの同期が成功すると、次のようになります:

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

識別子オブジェクトには、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

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

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)

グループメンバーシップ

  • プラン: Premium、Ultimate
  • 提供形態: GitLab Self-Managed

許可されていないグループメンバーシップ

特定のユーザーがLDAPグループ同期を介してGitLabグループに追加されるべきであると考えているのに、何らかの理由でそうならない場合があります。状況をデバッグするために、いくつかのことを確認できます。

  • LDAPの設定にgroup_baseが指定されていることを確認してください。この設定は、グループ同期が適切に機能するために必要です。
  • 正しいLDAPグループリンクがGitLabグループに追加されていることを確認します。
  • ユーザーがLDAPの識別子を持っていることを確認してください:
    1. 管理者ユーザーとしてGitLabにサインインします。
    2. 左側のサイドバーの下部で、管理者を選択します。
    3. 左側のサイドバーで、概要 > ユーザーを選択します。
    4. ユーザーを検索します。
    5. 名前を選択してユーザーを開きます。編集を選択しないでください。
    6. 識別子タブを選択します。IdentifierとしてLDAP DNを持つLDAP識別子があるはずです。そうでない場合、このユーザーはまだLDAPでサインインしていないため、最初にサインインする必要があります。
  • 1時間、または設定された間隔だけグループが同期されるのを待ちました。プロセスを高速化するには、GitLabグループの管理 > メンバーに移動してSync now (1つのグループを同期する) を押すか、グループ同期Rakeタスクを実行 (すべてのグループを同期する) します。

すべてのチェックが問題ないように見える場合は、Railsコンソールでより高度なデバッグに飛び込みます。

  1. Railsコンソールを使用します。
  2. テストするGitLabグループを選択します。このグループには、すでに設定されているLDAPグループリンクが必要です。
  3. デバッグログを有効にし、選択したGitLabグループを見つけて、LDAPと同期します
  4. 同期の出力を調べます。出力の読み取り方法については、ログ出力例を参照してください。
  5. ユーザーが追加されない理由がまだわからない場合は、LDAPグループに直接クエリを実行して、リストされているメンバーを確認します。
  6. ユーザーのDNまたはUIDは、クエリされたグループからのリストの1つにありますか?ここにあるDNまたはUIDの1つは、以前にチェックしたLDAP識別子からの「識別子」と一致する必要があります。そうでない場合、ユーザーはLDAPグループに存在しないようです。

LDAP同期が有効になっている場合、サービスアカウントユーザーをグループに追加できません

LDAP同期がグループに対して有効になっている場合、「招待」ダイアログを使用して新しいグループメンバーを招待することはできません。

GitLab 16.8以降でこの問題を解決するには、グループメンバーAPIエンドポイントを使用して、サービスアカウントをグループに招待したり、削除することができます。

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

管理者同期が設定されているのに、構成されたユーザーに正しい管理者権限が付与されない場合は、次の条件が満たされていることを確認してください:

  • group_baseも設定されています
  • admin_groupの設定されたgitlab.rbは、DNまたは配列ではなく、CNです。
  • このCNは、設定されたgroup_baseのスコープに該当します。
  • admin_groupのメンバーは、すでにLDAPの認証情報でGitLabにサインインしています。GitLabは、アカウントがすでにLDAPに接続されているユーザーにのみ管理者アクセス権を付与します。

上記のすべての条件が満たされていても、ユーザーがアクセス権を取得できない場合は、Railsコンソールで手動グループ同期を実行し、出力を調べて、GitLabがadmin_groupを同期するときに何が起こるかを確認します。

UIで今すぐ同期ボタンが停止している

グループのグループ > メンバーページにあるSync nowボタンが停止することがあります。ボタンを押してページがリロードされると、ボタンが停止します。ボタンは再び選択できなくなります。

Sync nowボタンがさまざまな理由で停止することがあり、特定のケースではデバッグが必要です。以下は、2つの考えられる原因と問題の考えられる解決策です。

無効なグループメンバーシップ

Sync nowボタンは、グループのメンバーまたはリクエスターの一部が無効な場合、停止します。この問題の表示レベルを改善する進捗状況は、関連イシューで追跡するできます。Railsコンソールを使用して、この問題がSync nowボタンが停止する原因になっているかどうかを確認できます:

# 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;."]]

このエラーは、管理者がメールメールドメインでグループメンバーシップを制限することを選択したが、ドメインにタイプミスがあったことを示していました。ドメイン設定を修正した後、Sync nowボタンが再度機能しました。

SidekiqノードでのLDAP設定の欠落

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

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

不足しているLDAP設定が問題であるかどうかをテストするには、Sidekiqを実行している各ノードでLDAPをチェックするRakeタスクを実行します。このノードでLDAPが正しくセットアップされている場合、LDAPサーバーに接続してユーザーを返します。

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

すべてのグループを同期

デバッグが不要な場合にすべてのグループを手動で同期するには、代わりにRakeタスクを使用します。

手動グループ同期からの出力は、GitLabがLDAPグループのグループメンバーシップをLDAPと同期するときに何が起こるかを示すことができます。Railsコンソールを入力し、以下を実行します:

Rails.logger.level = Logger::DEBUG

LdapAllGroupsSyncWorker.new.perform

次に、出力の読み取り方を学びます。

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

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

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

Started syncing 'ldapmain' provider for 'my_group' group

次のエントリは、GitLabがLDAPサーバーで認識するすべてのユーザーDNの配列を示しています。これらのDNは、GitLabグループではなく、単一のLDAPグループのユーザーです。このGitLabグループにリンクされているLDAPグループが複数ある場合は、LDAPグループごとに1つずつ、このようなログエントリが複数表示されます。このログエントリに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がこのグループへのアクセスレベル(ロール)を持つ必要があると考えるすべてのユーザーDNを表しています。このハッシュは加算的であり、追加のLDAPグループの検索に基づいて、より多くのDNが追加されたり、既存のエントリが変更されたりする可能性があります。このエントリの最後のオカレンスは、GitLabがグループに追加する必要があると考えるユーザーを正確に示すはずです。

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アイデンティティを更新するには、ユーザーDNとメールアドレスが変更されたを参照してください。

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

1つのグループを同期

すべてのグループを同期すると、出力に多くのノイズが発生する可能性があり、単一の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とメールアドレスが変更されました

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

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

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

次のスクリプトでは、新しいメールアドレスを持つ新しいアカウントを最初に削除する必要があります。メールアドレスは、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

次に、ユーザー同期を実行して、これらの各ユーザーの最新のDNを同期できます。

「無効な許可」が原因でAzureActivedirectoryV2から認証できませんでした

LDAPからSAMLに変換するときに、Azureで次のエラーが発生する可能性があります:

Authentication failure! invalid_credentials: OAuth2::Error, invalid_grant.

この問題は、次の両方が当てはまる場合に発生します:

  • SAMLがこれらのユーザーに設定された後も、LDAPIDがユーザーに存在します。
  • これらのユーザーのLDAPを無効にします。

ログにLDAPとAzureの両方のメタデータが表示され、Azureでエラーが生成されます。

単一ユーザーの回避策は、管理者 > 識別子でユーザーからLDAPアイデンティティを削除することです。

複数のLDAPアイデンティティを削除するには、Could not authenticate you from Ldapmain because "Unknown provider"エラーのいずれかの回避策を使用します。

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に名前が変更されます。
  • サインインしようとしているユーザーは、identifysecondaryレコードを持っていますが、これは設定されていません。

Railsコンソールを使用して、影響を受けるユーザーをリストし、IDを持つLDAPサーバーを確認します:

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サーバーを使用してサインインできる必要がある場合に適しています。たとえば、ロードバランサーがHAを管理するために使用されるようになり、個別のセカンダリサインインオプションが不要になった場合などです。

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

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

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

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

前提要件:

  • auto_link_ldap_userが有効になっていることを確認します。

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

削除されたLDAPサーバーがldapsecondaryであったため、Railsコンソールですべてのldapsecondaryアイデンティティを削除します:

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サーバーを使用するには、有効なライセンスが必要です。期限切れのライセンスにより、次の問題が発生する可能性があります:

  • Webインターフェースでの502エラー。

  • ログの次のエラー(実際のストラテジ名は、/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)

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

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

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

ユーザーがグループ同期中にグループに追加され、次回の同期で削除され、これが繰り返し発生している場合は、ユーザーに複数のLDAPIDまたは冗長なLDAPIDがないことを確認してください。

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

デバッグツール

LDAPチェック

LDAPをチェックするためのRakeタスクは、GitLabがLDAPへの接続を正常に確立し、ユーザーを読み取ることができるかどうかを判断するのに役立つ貴重なツールです。

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

  • ファイアウォールが接続をブロックしておらず、LDAPサーバーがGitLabホストにアクセスできることを確認してください。
  • Rakeタスクチェック出力のエラーメッセージを探します。これにより、LDAP設定(具体的にはhostportbind_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

次のldapsearchを実行して、bind_dnユーザーを見つけます:

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_dnpasswordporthost、および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コマンドに以下を含めます:

  • -Hフラグとポートを使用したLDAPサーバーのFQDN。
  • 完全に構築された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(AdFind)(Windows)を使用する

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

Return all objects(すべてのオブジェクトを返す)

フィルター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=*)

Return single object using filter(フィルターを使用した単一オブジェクトの返却)

オブジェクト名または完全なDN(DN)をspecifying(指定)して、単一のオブジェクトを取得することもできます。この例では、オブジェクト名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コンソール

Railsコンソールを使用すると、データの作成、読み取り、変更、および削除が非常に簡単に行えます。リストされているとおりにコマンドを実行してください。

Railsコンソールは、LDAPの問題をデバッグするのに役立つ貴重なツールです。コマンドを実行し、GitLabがどのように応答するかを確認することで、アプリケーションを直接操作できます。

Railsコンソールの使用方法については、このガイドを参照してください。

デバッグ出力を有効にする

これにより、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)