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

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

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

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

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

接続

接続が拒否されました

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

ユーザーサインイン

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

テストにより接続が確認済みであるにもかかわらず、GitLabがLDAPユーザーを出力に表示しない場合、以下のいずれかが原因である可能性が高いです:

  • bind_dnユーザーには、ユーザーツリーをたどるための十分な権限がありません。
  • ユーザーは設定されたbaseの範囲内にありません。
  • 設定されたuser_filterがユーザーへのアクセスをブロックしています。

この場合、/etc/gitlab/gitlab.rb内の既存のLDAP設定を使用してldapsearchを使うことで、上記のうちどれが該当するか確認できます。

ユーザーがサインインできません

ユーザーがサインインできない理由はいくつか考えられます。まず、次の質問をご自身に問いかけてください:

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

前の質問が両方とも問題ない場合は、問題を再現しながらログ自体を調べてください。

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

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

さらに調査するために、ユーザー同期をデバッグすることも役立ちます。

ユーザーにエラーInvalid login or password.が表示されます

このエラーが表示される場合、ユーザーは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. 例えば、デフォルトのプロジェクトの制限またはAllowed domains for new user accountsフィールドを確認し、適切な値が設定されていることを確認してください。

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

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

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はidentitiesテーブルを検索し、このユーザーと設定されたLDAPプロバイダー間の既存のリンクを探します:

  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)

マージリクエスト承認ルール

LDAP接続の問題が発生すると、同期操作中にユーザーがマージリクエスト承認ルールから削除されることがあります。これにより、承認ルールが空になり、無効とマークされる可能性があります。

LDAP接続が失われると、承認ルールは失敗します

LDAPサーバーが一時的に利用できなくなるか、バインドアカウントが失敗した場合:

  • LDAPベースの承認ルールで設定されたユーザーは、次の同期サイクル中に削除されることがあります。
  • 残りのユーザーがいない承認ルールは無効になります。
  • 標準の承認ルールは自動承認とマークされ、マージをブロックしなくなります。
  • マージリクエスト承認ポリシールールはアクションが必要とマークされ、引き続きマージをブロックします。

標準の承認ルールがサイレントにバイパスされるのを防ぐには:

  • LDAPサーバーが高可用性と信頼性の高い接続性を備えていることを確認してください。
  • LDAP同期操作の失敗を監視します。
  • 重要なセキュリティ要件には、標準の承認ルールの代わりにマージリクエスト承認ポリシーを使用してください。承認ポリシーはより強力な強制を提供し、オープンに失敗することはありません。

承認ルールの動作に関する詳細については、無効なルールを参照してください。

LDAPの問題によりユーザーが承認ルールから削除された場合、LDAP接続が復元されても自動的に再追加されません。手動で承認ルールを復元するか、バックアップからリカバリする必要がある場合があります。

グループメンバーシップ

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

メンバーシップが付与されていません

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

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

すべてのチェックが問題ない場合は、Railsコンソールでより高度なデバッグに進んでください。

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

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

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

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

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

LDAPグループに管理者ロールを割り当てる場合でも、設定されたユーザーに正しい管理者権限が付与されない場合は、以下の条件が真であることを確認してください:

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

以前の条件がすべて真であり、ユーザーがまだアクセスできない場合は、Railsコンソールで手動グループ同期を実行し、出力を確認して、GitLabがadmin_groupを同期するときに何が起こるかを確認してください。

Sync nowボタンが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 'Settings > General' page, and check 'Restrict membership by email domain'."]]

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

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

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

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

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

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

全グループを同期

デバッグが不要な場合にすべてのグループを手動で同期するには、代わりに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は単一のLDAPグループのユーザーであり、GitLabグループのユーザーではありません。この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、25はSecurity Manager、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とメールが変更されました

プライマリメール DNの両方がLDAPで変更された場合、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

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

AzureActivedirectoryV2からInvalid grantのため認証できませんでした

LDAPからSAMLに変換するときに、Azureで次のようなエラーが発生する場合があります:

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

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

  • SAMLが設定された後も、ユーザーにLDAP識別子がまだ存在している。
  • それらのユーザーに対して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"]".

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

  • 最初から、GitLab設定のldap_serversmainsecondaryが設定されています。
  • secondary設定が削除またはmainに名前が変更されました。
  • サインインを試みるユーザーはsecondaryidentifyレコードを持っていますが、それはもはや設定されていません。

Railsコンソールを使用して、影響を受けるユーザーを一覧表示し、どの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サーバーを使用してサインインできる場合に適しています。例えば、ロードバランサーがLDAPの高可用性を管理するために使用され、個別のセカンダリサインインオプションが不要になった場合などです。

LDAPサーバーが互いのレプリカでない場合、この解決策は影響を受けるユーザーがサインインできないようにします。

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

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

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

前提条件:

  • auto_link_ldap_userが有効になっていることを確認してください。

この解決策では、識別子が削除された後、影響を受けるユーザーは設定された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を再構成します。

ユーザーがグループから削除され、再度追加される

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

それらの識別子の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

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_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の使用 (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コンソール

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)