根本原因是GitLab分支保护与LDAP组映射为两套独立机制,需显式启用LDAP组同步、创建同名GitLab群组并授予权限,且群组保护规则必须手动配置“Allowed to push/merge”,否则LDAP用户仅同步身份而无实际分支操作权限。
根本原因不是配置漏了,而是 GitLab 的分支保护规则和 LDAP 组映射是两套独立机制,不会自动联动。即使你在 LDAP 中把用户归入 dev-team 组,GitLab 默认也不会把这个组映射成项目里的 Developer 角色——更不会让它自动获得对某分支的 Allowed to merge 权限。
protected branches 页面里,“Allowed to merge” 和 “Allowed to push” 下拉菜单只显示角色(如 Developer、Maintainer),不显示 LDAP 组名group_protected_branches)在 17.6+ 已 GA,但仅支持顶级群组,且必须由群组所有者配置,项目维护者无法覆盖必须启用并正确配置 GitLab 的 LDAP Group Sync 功能,否则 LDAP 用户永远只是“未分配角色”的状态。关键点在于:不是同步用户,而是同步组到 GitLab 群组,并把群组权限映射为角色。
/etc/gitlab/gitlab.rb 中启用 group sync:gitlab_rails['ldap_group_sync_enabled'] = true
ldap_group_sync_base 和 ldap_group_sync_filter,确保能查到你的组织单位(OU),例如:base: "ou=groups,dc=corp,dc=com",filter: "(cn=gitlab-devs)"
Admin Area → LDAP → Groups)确认目标 LDAP 组已出现在同步列表中,并勾选 “Sync groups as GitLab groups”gitlab-devs),将该群组添加为项目成员,角色设为 Developer —— 此时 LDAP 用户才真正获得项目级 Developer 权限因为群组级保护规则只作用于“匹配的分支名”,且默认不开放 Allowed to push 权限给 Developer。GitLab 的设计逻辑是:即使你是群组 Developer,也必须显式允许你向特定分支推送。
Developers 或 Maintainers 才生效main 和 * 两条规则,main 规则优先;但 feature-* 和 * 共存时,GitLab 会合并所有匹配规则的权限,取最宽松结果 —— 这反而可能造成越权Settings → Repository → Branch rules,看是否有更高优先级的项目级规则覆盖了群组规则git push --force-with-lease)默认禁用,但老版本或自定义配置可能开着,需确认 Allow force push 是否已关闭不能。所有分支保护逻辑都在 GitLab 服务端执行,客户端 hook 只能提示,无法拦截。
.git/hooks/pre-push 可以读取当前分支名并 warn,但用户删掉 hook 或绕过(git push --no-verify)就完全失效if [[ $(git rev-parse --abbrev-ref HEAD) == "main" ]]; then exit 1; fi)仅适用于 merge request pipeline,对直接 push 无效protected branches 开关 + LDAP Group Sync 正确落地GitLab 分支保护和 LDAP 权限绑定的复杂点不在界面操作,而在于三处隐性依赖:LDAP 组能否被 GitLab 识别、GitLab 群组是否与 LDAP 组完成角色映射、群组保护规则是否显式授予了 push 权限——漏掉任一环,都会导致“看着配好了,实际不生效”。