{{< details >}}

  • Tier: 基础版,专业版,旗舰版
  • Offering: 私有化部署

{{< /details >}}

如果您是管理员,请使用以下信息来排查 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 群组同步时看到 LDAP search error: Referral,此错误可能表示配置问题。LDAP 配置 /etc/gitlab/gitlab.rb (Omnibus) 或 config/gitlab.yml (source) 是 YAML 格式的,对缩进敏感。检查 group_baseadmin_group 配置键是否缩进了服务器标识符后 2 个空格。默认标识符是 main,示例如下:

main: # 'main' 是极狐 GitLab 的这个 LDAP 服务器的 'provider ID'
  label: 'LDAP'
  host: 'ldap.example.com'
  # ...
  group_base: 'cn=my_group,ou=groups,dc=example,dc=com'
  admin_group: 'my_admin_group'

查询 LDAP

{{< details >}}

  • Tier: Premium, Ultimate
  • Offering: GitLab Self-Managed

{{< /details >}}

以下内容允许您使用 Rails 控制台在 LDAP 中执行搜索。根据您的需求,可能更有意义直接查询用户群组,或者直接使用 ldapsearch

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base 是必需的
    # 使用 .base 或 .group_base
    base: adapter.config.group_base,

    # :filter 是可选的
    # 'cn' 查找在 :base 下的所有 "cn"
    # '*' 是搜索字符串 - 这里是一个通配符
    filter: Net::LDAP::Filter.eq('cn', '*'),

    # :attributes 是可选的
    # 我们想要返回的属性
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

当在过滤器中使用 OID 时,用 Net::LDAP::Filter.construct 替换 Net::LDAP::Filter.eq

adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain')
options = {
    # :base 是必需的
    # 使用 .base 或 .group_base
    base: adapter.config.base,

    # :filter 是可选的
    # 此过滤器包含 OID 1.2.840.113556.1.4.1941
    # 它将在 LDAP 目录中搜索群组 gitlab_grp 的所有直接和嵌套成员
    filter: Net::LDAP::Filter.construct("(memberOf:1.2.840.113556.1.4.1941:=CN=gitlab_grp,DC=example,DC=com)"),

    # :attributes 是可选的
    # 我们想要返回的属性
    attributes: %w(dn cn memberuid member submember uniquemember memberof)
}
adapter.ldap_search(options)

有关如何运行此命令的示例,查看 Adapter 模块。

用户登录

没有找到用户

如果您已经确认可以建立与 LDAP 的连接,但极狐 GitLab 没有在输出中显示 LDAP 用户,可能是以下原因之一:

在这种情况下,您可以使用现有的 LDAP 配置在 /etc/gitlab/gitlab.rb 中使用 ldapsearch 确认上述哪个情况为真。

用户无法登录

用户可能由于多种原因无法登录。首先,请问自己以下问题:

  • 用户是否在 LDAP 中 配置的 base 下?用户必须在此 base 下才能登录。
  • 用户是否通过 配置的 user_filter?如果未配置,可以忽略此问题。如果配置了,则用户还必须通过此过滤器才能允许登录。

如果以上都没问题,下一个要查看的问题是重现问题时的日志本身。

  • 让用户登录并让它失败。
  • 查看输出 中的任何错误或其他有关登录的消息。您可能会看到此页面上的其他错误消息之一,在这种情况下,该部分可以帮助解决问题。

如果日志没有找到问题的根源,请使用 rails 控制台 查询此用户 以查看极狐 GitLab 是否可以在 LDAP 服务器上读取此用户。

这也可能有助于调试用户同步以进一步调查。

用户看到错误 “Invalid login or password.”

{{< history >}}

  • 引入于GitLab 16.10。

{{< /history >}}

如果用户看到此错误,可能是因为他们尝试使用 Standard 登录表单而不是 LDAP 登录表单登录。

要解决此问题,请要求用户将其 LDAP 用户名和密码输入 LDAP 登录表单。

登录时凭据无效

如果在 LDAP 上使用的登录凭据是准确的,请确保以下几点对于相关用户是正确的:

您的 LDAP 帐户访问被拒绝

有一个问题可能会影响具有审计员级别访问权限的用户。当从专业版/旗舰版降级时,尝试登录的审计员用户可能会看到以下消息:Access denied for your LDAP account

我们有一个解决方法,基于切换受影响用户的访问级别:

  1. 在左侧边栏的底部,选择 管理员
  2. 选择 概览 > 用户
  3. 选择受影响用户的名称。
  4. 在右上角,选择 编辑
  5. 将用户的访问级别从 Regular 更改为 Administrator(或反之亦然)。
  6. 在页面底部,选择 保存更改
  7. 在右上角再次选择 编辑
  8. 恢复用户的原始访问级别(RegularAdministrator),然后再次选择 保存更改

现在用户应该能够登录。

邮件地址已被占用

用户尝试使用正确的 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

这将显示哪个用户拥有此邮件地址。此处必须采取以下两个步骤之一:

  • 要为此用户在使用 LDAP 登录时创建新的极狐 GitLab 用户/用户名,请删除次要邮件以消除冲突。
  • 要使用现有的极狐 GitLab 用户/用户名让此用户使用 LDAP,请删除此邮件作为次要邮件并将其设为主要邮件,以便极狐 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 中。

同步所有用户

{{< details >}}

  • Tier: Premium, Ultimate
  • Offering: GitLab Self-Managed

{{< /details >}}

手动用户同步的输出可以显示极狐 GitLab 尝试与 LDAP 同步其用户时发生了什么。进入 rails 控制台,然后运行:

Rails.logger.level = Logger::DEBUG

LdapSyncWorker.new.perform

接下来,了解如何读取输出

用户同步后的示例控制台输出

{{< details >}}

  • Tier: Premium, Ultimate
  • Offering: GitLab Self-Managed

{{< /details >}}

手动用户同步的输出非常详细,单个用户的成功同步可能如下所示:

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') # 如果 `main` 是 LDAP 提供者
Gitlab::Auth::Ldap::Person.find_by_uid('<uid>', adapter)

群组成员资格

{{< details >}}

  • Tier: Premium, Ultimate
  • Offering: GitLab Self-Managed

{{< /details >}}

成员资格未授予

有时您可能认为某个特定用户应通过 LDAP 群组同步添加到极狐 GitLab 群组,但由于某种原因它没有发生。您可以检查几件事来调试此情况。

  • 确保 LDAP 配置有指定的 group_base此配置 是群组同步正常工作的必要条件。
  • 确保正确的 LDAP 群组链接已添加到极狐 GitLab 群组
  • 检查用户是否有 LDAP 身份:
    1. 以管理员用户身份登录极狐 GitLab。
    2. 在左侧边栏的底部,选择 管理员
    3. 在左侧边栏中选择 概览 > 用户
    4. 搜索用户。
    5. 通过选择他们的姓名打开用户。不要选择 编辑
    6. 选择 身份 标签。应该有一个 LDAP 身份,其 LDAP DN 为 Identifier。如果没有,这个用户还没有使用 LDAP 登录,必须先登录。
  • 您已经等待了一个小时或配置的间隔来同步群组。要加快此过程,可以前往极狐 GitLab 群组 管理 > 成员 并按 立即同步(同步一个群组)或 运行群组同步 Rake 任务(同步所有群组)。

如果以上所有看起来都不错,请进入 Rails 控制台进行更高级的调试。

  1. 进入 rails 控制台
  2. 选择一个要测试的极狐 GitLab 群组。该群组应已配置了 LDAP 群组链接。
  3. 启用调试日志,找到上述极狐 GitLab 群组,并与 LDAP 同步
  4. 查看同步的输出。请参阅示例日志输出了解如何读取输出。
  5. 如果您仍然无法看到为什么用户没有被添加,直接查询 LDAP 群组以查看列出的成员。
  6. 用户的 DN 或 UID 是否在上述输出的列表中之一?这里的一个 DN 或 UID 应与之前检查的 LDAP 身份的 ‘Identifier’ 匹配。如果没有,则用户似乎不在 LDAP 群组中。

启用 LDAP 同步时无法将服务帐户用户添加到群组

当为群组启用 LDAP 同步时,您无法使用“邀请”对话框邀请新群组成员。

在极狐 GitLab 16.8 及更高版本中,您可以使用群组成员 API 端点邀请服务帐户到群组并将其移除以解决此问题。

管理员权限未授予

管理员同步已配置但配置的用户没有获得正确的管理员权限时,请确认以下几点为真:

  • 配置了 group_base
  • gitlab.rb 中配置的 admin_group 是 CN,而不是 DN 或数组。
  • 此 CN 在配置的 group_base 范围内。
  • admin_group 的成员已使用其 LDAP 凭据登录到极狐 GitLab。极狐 GitLab 仅向帐户已连接到 LDAP 的用户授予管理员访问权限。

如果以上所有都为真,而用户仍然无法获得访问权限,请在 Rails 控制台中运行手动群组同步查看输出以查看极狐 GitLab 同步 admin_group 时发生了什么。

UI 中的立即同步按钮卡住

群组的 群组 > 成员 页面上的 立即同步 按钮可能会卡住。按下按钮并重新加载页面后,按钮会卡住。然后无法再次选择按钮。

立即同步 按钮可能由于多种原因卡住,并且需要对特定情况进行调试。以下是两个可能的原因和可能的解决方案。

无效成员资格

如果群组的成员或请求成员中有无效项,则 立即同步 按钮会卡住。您可以使用 Rails 控制台 确认此问题是否导致 立即同步 按钮卡住:

# 找到相关群组
group = Group.find_by(name: 'my_gitlab_group')

# 查找群组本身的错误
group.valid?
group.errors.map(&:full_messages)

# 查找群组成员和请求者的错误
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 在多个节点上进行扩展并且 LDAP 配置缺失时,立即同步 按钮会卡住 在运行 Sidekiq 的节点上的 /etc/gitlab/gitlab.rb。在这种情况下,Sidekiq 作业似乎消失了。

LDAP 在 Sidekiq 节点上是必需的,因为 LDAP 有多个异步运行的作业,需要本地 LDAP 配置:

您可以通过在运行 Sidekiq 的每个节点上运行 Rake 任务以检查 LDAP 来测试 LDAP 配置缺失是否是问题所在。如果在此节点上正确设置了 LDAP,则它将连接到 LDAP 服务器并返回用户。

要解决此问题,请在 Sidekiq 节点上配置 LDAP。配置后,运行 Rake 任务以检查 LDAP 以确认极狐 GitLab 节点可以连接到 LDAP。

同步所有群组

{{< alert type=”note” >}}

在不需要调试时手动同步所有群组,使用 Rake 任务

{{< /alert >}}

手动群组同步的输出可以显示极狐 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 群组。如果您有多个 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 认为应具有此群组访问权限的所有用户 DN,以及其访问级别(角色)。此哈希是累加的,并且可以根据其他 LDAP 群组查找添加更多的 DN,或修改现有条目。此条目的最后一个出现应指示极狐 GitLab 认为应添加到群组的用户。

{{< alert type=”note” >}}

10 是 Guest,20 是 Reporter,30 是 Developer,40 是 Maintainer 和 50 是 Owner

{{< /alert >}}

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 不匹配。请参阅用户 DN 和邮件已更改以更新用户的 LDAP 身份。

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

# 找到极狐 GitLab 群组。
# 如果输出为 `nil`,则无法找到群组。
# 如果输出中有一堆群组属性,则表示您的群组成功找到。
group = Group.find_by(name: 'my_gitlab_group')

# 根据 LDAP 同步此群组
EE::Gitlab::Auth::Ldap::Sync::Group.execute_all_providers(group)

输出类似于 您从同步所有群组中获得的输出

在 LDAP 中查询群组

当您想确认极狐 GitLab 可以读取 LDAP 群组并查看其所有成员时,您可以运行以下命令:

# 找到适配器和群组本身
adapter = Gitlab::Auth::Ldap::Adapter.new('ldapmain') # 如果 `main` 是 LDAP 提供者
ldap_group = EE::Gitlab::Auth::Ldap::Group.find_by_cn('group_cn_here', adapter)

# 找到 LDAP 群组的成员
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 值。

以下脚本更新所有提供用户的邮件,以便它们不会被阻止或无法访问其帐户。

{{< alert type=”note” >}}

以下脚本要求首先删除具有新邮件地址的任何新帐户。邮件地址在极狐 GitLab 中必须是唯一的。

{{< /alert >}}

转到 rails 控制台,然后运行:

# 每个条目必须包括旧用户名和新邮件
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 中生成错误。

针对单个用户的解决方法是从 Admin > Identities 中删除用户的 LDAP 身份。

要删除多个 LDAP 身份,请使用 无法从 Ldapmain 进行身份验证,因为 "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
  • 尝试登录的用户有一个 identify 记录为 secondary,但不再配置。

使用 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

您可以通过两种方式解决此错误。

重命名对 LDAP 服务器的引用

当 LDAP 服务器相互为副本,并且受影响的用户应该能够使用配置的 LDAP 服务器登录时,此解决方案适用。 例如,如果现在使用负载均衡器来管理 LDAP 高可用性并且不再需要单独的辅助登录选项。

{{< alert type=”note” >}}

如果 LDAP 服务器不是彼此的副本,此解决方案将阻止受影响的用户登录。

{{< /alert >}}

重命名不再配置的 LDAP 服务器的引用,请运行:

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

删除与已移除的 LDAP 服务器相关的 identity 记录

先决条件:

  • 确保启用了 auto_link_ldap_user

使用此解决方案,在身份被删除后,受影响的用户可以使用配置的 LDAP 服务器登录,并且极狐 GitLab 会创建新的 identity 记录。

由于已移除的 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. 删除或注释掉极狐 GitLab 配置中所有非主 LDAP 服务器的配置行。
  2. 重新配置极狐 GitLab,使其暂时仅使用一个 LDAP 服务器。
  3. 进入 Rails 控制台并添加许可证密钥
  4. 在极狐 GitLab 配置中重新启用其他 LDAP 服务器并再次重新配置极狐 GitLab。

用户正在从群组中移除并重新添加

如果用户在群组同步期间被添加到群组,并在下一次同步时被移除,并且这种情况反复发生,请确保用户没有多个或冗余的 LDAP 身份。

如果这些身份之一是为不再使用的旧 LDAP 提供者添加的,请删除与已移除的 LDAP 服务器相关的 identity 记录

调试工具

LDAP 检查

Rake 任务检查 LDAP 是一个有价值的工具,有助于确定极狐 GitLab 是否可以成功建立与 LDAP 的连接,并能读取用户。

如果无法建立连接,可能是因为配置问题或防火墙阻止了连接。

  • 确保没有防火墙阻止连接,并且 LDAP 服务器对极狐 GitLab 主机可访问。
  • 在 Rake 检查输出中查找错误消息,这可能会导致您确认 LDAP 配置,确保配置值(特别是 hostportbind_dnpassword)是正确的。
  • 日志中查找错误,以进一步调试连接失败。

如果极狐 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' 是极狐 GitLab 的这个 LDAP 服务器的 'provider ID'
     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_dnpasswordporthostbase 都与 gitlab.rb 中配置的相同。

使用 ldapsearch 和 start_tls 加密

前面的示例在明文下执行了 LDAP 测试,端口为 389。如果您使用 start_tls 加密,在 ldapsearch 命令中包括:

  • -Z FLAG。
  • 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

使用 ldapsearch 和 simple_tls 加密

如果您使用 simple_tls 加密(通常在端口 636 上),在 ldapsearch 命令中包括以下内容:

  • 使用 -H FLAG 和端口指定 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 控制台

{{< alert type=”warning” >}}

使用 rails 控制台创建、读取、修改和销毁数据非常简单。请务必按照列表中的命令运行。

{{< /alert >}}

rails 控制台是帮助调试 LDAP 问题的有力工具。它允许您通过运行命令直接与应用程序交互,查看极狐GitLab对此的响应。

有关如何使用 rails 控制台的说明,请参阅此 指南

启用调试输出

这提供了调试输出,显示极狐GitLab正在做什么以及用什么。此值不会持久化,仅在 Rails 控制台中为此会话启用。

要在 rails 控制台中启用调试输出,进入 rails 控制台 并运行:

Rails.logger.level = Logger::DEBUG

获取与群组、子群组、成员和请求者相关的所有错误消息

收集与群组、子群组、成员和请求者相关的错误消息。这将捕获可能不会在 Web 界面中出现的错误消息。这对于排查 LDAP 群组同步 和用户及其在群组和子群组中的成员身份的意外行为问题特别有帮助。

# 查找群组和子群组
group = Group.find_by_full_path("parent_group")
subgroup = Group.find_by_full_path("parent_group/child_group")

# 群组和子群组错误
group.valid?
group.errors.map(&:full_messages)

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

# 群组和子群组的成员及请求者的错误
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)