- 连接问题
- 用户登录
- 无效的登录凭据
- 群组成员关系
- 用户 DN 和邮箱发生了变化
- 因为 “Invalid grant” 导致无法从 AzureActivedirectoryV2 进行认证
-
Could not authenticate you from Ldapmain because "Unknown provider"
- 过期许可证引起多个 LDAP 服务器错误
- 用户从群组中被移除并被再次添加
- 调试工具
- 极狐GitLab 技术支持
LDAP 故障排查指南
如果您是管理员,使用如下信息进行 LDAP 故障排查。 ## 常见问题 & 工作流
连接问题
连接拒绝
当您尝试连接到 LDAP 服务器时,可能会遇到 Connection Refused
错误信息,在极狐GitLab 上检查 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 用户进行身份验证和登录。在 LDAP 无法使用期间,极狐GitLab 无法缓存或存储 LDAP 用户的凭据。
如果看到此错误,请联系您的 LDAP 提供商或管理员。
Referral 错误
如果您在日志中看到 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 中执行搜索。根据你想要做的事情,直接查询 LDAP 中的用户或者 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)
当在过滤器中使用 OIDs 时,用 Net::LDAP::Filter.construct
替换 Net::LDAP::Filter.eq
:
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 的连接已经建立,但是却没有在输出中看到 LDAP 用户,可能的原因有:
-
bind_dn
用户没有足够的权限来遍历用户树。 - 这些用户不在已配置的
base
范围内。 -
配置的
user_filter
阻止了用户的访问。
在这种情况下,您可以在 /etc/gitlab/gitlab.rb
中使用 ldapsearch 和既有配置来确定到底是上面的哪个问题导致。
用户无法登录
用户可能有多种登录问题。开始之前,您需要询问自己:
- 在 LDAP 中,用户是否在配置的
base
下?用户必须要在此base
下才能登录。 - 用户是否传递了配置的
user_filter
?如果没有配置此项,则可忽略此问题。如果是,则用户必须传递此过滤器以允许登录。- 参考我们的调试
user_filter
文档。
- 参考我们的调试
如果上述内容都 OK,下一步就是要查看问题产生时的日志了。
- 让用户登录并让登录失败。
- 对于任何错误或其他任何关于登录的信息,都要查看输出。您可能会在页面上看到其他错误,这些都可能帮助您解决此问题。
如果日志无法分析错误根因,使用 Rails 控制台来查询此用户以查看极狐GitLab 是否可以从 LDAP 服务器读取此用户。
调试用户同步对于进一步调查也是非常有帮助的。
用户看见错误 “Invalid login or password.”
- 引入极狐GitLab 16.10。
如果用户看到此错误,可能是因为他们在使用 标准的 登录表单而非 LDAP 登录表单。
要解决此问题,让用户将他们的 LDAP 用户名和密码输入进 LDAP 登录表单。
无效的登录凭据
如果在 LDAP 中,使用的登录凭据是准确的,确保如下问题中的内容对用户来说是正确的:
- 确保您绑定的用户有足够的权限来读取用户树并遍历它。
- 检查
user_filter
没有阻挡本来有效的用户。 - 运行 LDAP 检查命令 来确保 LDAP 设置是正确的并且极狐GitLab 可以看到您的用户。
LDAP 账号访问拒绝
有一个缺陷可能会影响具有审计者访问权限的用户。当从专业版/旗舰版降级时,尝试登录的审计者用户可能会看到如下信息:Access denied for your LDAP account
。
我们有一个解决方案,基于受影响用户的访问级别开关:
- 在左侧导航栏,底部,选择 管理员。
- 选择 概览 > 用户。
- 选择受影响用户的名称。
- 在右上角,选择 编辑。
- 将用户的访问级别从
Regular
修改为Administrator
(反之亦然)。 - 在页面底部,选择 保存更改。
- 在右上角,再次选择 编辑。
- 恢复用户的原始访问级别(
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
此命令会展示到底是哪个用户在使用此邮箱。以下两个步骤必须要执行其一:
- 当使用 LDAP 登录时,必需为此用户创建一个新的极狐GitLab 用户/用户名,然后移除次要邮箱以解决冲突。
- 为使用 LDAP 的此用户使用既有的极狐GitLab 用户/用户名,将此邮箱在次要邮箱中移除,并将其设置为主要邮箱,这样极狐GitLab 就会将此个人资料和 LDAP 身份识别进行关联了。
用户可以在[他们的个人资料]](../../../user/profile/index.md#access-your-user-profile)中完成这些步骤,或者管理员也可以完成此事。
项目限制错误
以下错误意味着某些限制被触发了,但是相关联的数据字段却不包含任何数据:
-
Projects limit can't be blank
. -
Projects limit is not a number
.
要解决此问题:
- 在左侧导航栏,底部,选择 管理员。
- 选择 设置 > 通用。
- 同时展开如下内容:
- 账号和限制。
- 注册限制。
- 检查,比如,默认项目限制 或 注册允许的域名 字段并确保配置了相关值。
调试 LDAP 用户过滤器
ldapsearch
允许您测试您配置的用户过滤器以确认它返回了您期望的那些用户。
ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$base" "$user_filter" sAMAccountName
- 以
$
开头的变量引用你配置文件的 LDAP 部分的一个变量。 - Variables beginning with a
$
refer to a variable from the LDAP section of your configuration file. - 如果您正在使用明文认证方式,将
ldaps://
替换为ldap://
。ldaps//
的默认端口为389
,而ldaps://
的默认端口为636
。 - 我们假定
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
如果您在LDAP 中找不到此用户的极狐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 没有找到,那么极狐GitLab 会使用邮箱来查找用户。我们可以在 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 并读取特定用户。它可以暴露在连接和/或查询 LDAP 时可能出现的潜在错误,这些错误在极狐GitLab 用户界面中可能看似悄无声息地失败了。
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 身份识别:
- 以管理员身份登录极狐GitLab。
- 在左侧导航栏,底部,选择 管理员。
- 在左侧导航栏,选择 概览 > 用户。
- 搜索用户。
- 通过选择他们的用户名开发用户。不要选择 编辑。
- 选择 身份识别 选项卡。这儿应该有一个以 LDAP 专有名称(DN)作为
Identifier
的 LDAP 身份标识。如果没有,说明此用户还未登录极狐GitLab,因此必需首先先登录一下。
- 您已经等待了一个小时或等待了群组同步的配置间隔时长。为了加速进度,要么前往极狐GitLab 群组的 管理 > 成员 并点击 现在同步 (同步一个群组)或运行群组同步 Rake 任务(同步所有群组)。
如果上述的一切都没问题,可以进一步的在 Rails 控制台上进行调试了:
- 进入 Rails 控制台。
- 选择要测试的极狐GitLab群组。次群组应该有一个已经配置好的 LDAP 群组连接。
- 启用调试日志,找到上述的群组并用 LDAP 同步。
- 查看同步输出。关于如何读取输出,可以查看示例日志输出。1
- 如果您依旧未看到为什么用户没有被添加进来,直接查询 LDAP 群组来查看列出了哪些成员。
- 要查看在上面的输出中,用户的 DN 或 UID 是否在里面?这里的 DN(专有名称)或 UID(用户标识)之一,应与之前检查的 LDAP 身份标识中的“标识符”相匹配。 如果它并不存在,则用户就不会出现在 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 控制台上确认是否是该问题导致了 现在同步 按钮卡住:
# 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'."]]
此错误展示了管理员选择通过邮箱限制群组成员关系,但是在域名中有一个错误。在修复域名问题后,现在同步 按钮再次可用。
在 Sidekiq 节点上丢失了 LDAP 配置
当极狐GitLab 扩容为多个节点并从运行 Sidekiq 节点的 /etc/gitlab/gitlab.rb
中丢失了 LDAP 配置,现在同步 按钮就会卡住。在此情况下,Sidekiq 作业看起来消失了。
Sidekiq节点上需要安装LDAP,因为LDAP有多个异步运行的任务,这些任务需要本地的LDAP配置。
您可以通过在每个运行 Sidekiq 的节点上运行 Rake 任务检查 LDAP来测试是否是丢失的 LDAP 配置引起了按钮不可用的问题。如果在节点上正确设置了 LDAP,它就能连接到 LDAP 服务器并返回用户。
要解决此问题,在 Sidekiq 节点上配置 LDAP。当配置时,运行 Rake 任务检查 LDAP来确认极狐GitLab 节点可以连接到 LDAP。
同步所有群组
手动群组同步中的输出可以为您展示当极狐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 群组一个。如果您在日志条目中没有看到 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"]
在上述每一项记录之后不久,您会看到一个已解析的成员访问级别的哈希值。 此哈希代表了所有用户 DN,用户是极狐GitLab 认为应该能访问此群组的,而且以何种级别(角色)进行访问。这个哈希是可累加的,基于额外的 LDAP 组查找,可能会添加更多的 DN,或者修改现有的条目。 此条目的最后一次出现应该确切表明极狐GitLab 认为哪些用户应该被添加到该组中。
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 不匹配导致。查看用户 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
# 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 群组。
- 等待,直到 LDAP 群组同步完成。
- 从 LDAP 群组移除用户。
用户 DN 和邮箱发生了变化
如果 LDAP 中的主邮箱 和 DN 发生了变化,极狐GitLab 就不能够正确识别 LDAP 用户记录。结果就是,极狐GitLab 会阻塞用户。如要极狐GitLab 能够找到 LDAP 记录,则用如下内容更新既有的极狐GitLab 用户个人资料:
- 新的主邮箱。
- DN 值。
下面的脚本能够更新所有创建用户的邮箱,以便他们不能够被阻塞或者无法访问他们的账号。
前往 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。
因为 “Invalid grant” 导致无法从 AzureActivedirectoryV2 进行认证
当从 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"]".
当使用已经在极狐GitLab 配置中重命名或被移除的LDAP 服务器时进行认证时,就会出现此错误。比如:
- 最开始,在极狐GitLab 配置中,
main
和secondary
被设置在ldap_servers
。 -
secondary
设置被移除或重命名为main
。 - 尝试登录的用户有一个针对
secondary
的identify
记录,但该记录已不再配置。
使用 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 的高可用,而且不再需要单独的 secondary 登录选项。
要重命名不再配置的 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)
要解决此错误,您需要为极狐GitLab 实例应用新的许可证:
- 删除或注释掉所有非主 LDAP 服务器的极狐GitLab 配置行。
- 重新配置极狐GitLab以便它暂时仅使用一个 LDAP 服务器。
- 进入 Rails 控制台和添加许可证。
- 在极狐GitLab 配置中重新启用额外的 LDAP 服务器并再次重新配置极狐GitLab。
用户从群组中被移除并被再次添加
如果在群组同步期间,有用户被添加到群组中,但是在下次同步期间被移除,而且这种情况重复发生,那么您需要确保用户没有多个或冗余的 LDAP 身份。
如果被添加的其中一个身份识别已经不再使用,您需要移除与移除的 LDAP 服务器相关的 identity
记录。
调试工具
LDAP 检查
Rake 任务检查 LDAP 是一个极具价值的工作,能够帮助确定极狐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
您还可以运行如下 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_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
命令中包含如下内容:
- 使用
-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 控制台是一个非常有价值的工具,可以帮助调试 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)
极狐GitLab 技术支持
如果您在迁移过程中遇到任何问题,您可以在极狐GitLab 官方论坛上发帖求助,您也可以直接扫描下方二维码咨询专业人员: