我们在 Gerrit 设置上对新用户进行身份验证时遇到问题。
我们在专用 nginx 服务器后面使用代理 HTTP 运行 Gerrit 2.16。nginx 服务器监听端口 8080,执行基本身份验证,然后将请求通过环回接口上的端口 9080 中继到 Gerrit。
此设置对我们所有现有用户都适用。最近我们添加了两个新用户,一个运行正常,但另一个身份验证失败。用户添加的方式不同,我猜身份验证失败的用户存在问题或缺失。
第一个用户(有效的)是按照以下步骤添加的:
- 用户名和密码首先添加到 nginx 的 htpasswd 文件中
- 然后使用新的用户名和密码登录到 Gerrit 的 8080 端口(即 nginx)
- nginx 验证成功,并将登录请求转发给 Gerrit
- Gerrit 之前从未见过该用户名,因此它启动新账户创建,账户就创建好了
- 新用户可以通过 GUI 编辑帐户资料,添加其全名和电子邮件地址
第二个用户(不起作用)是这样添加的:
- 再次,用户名和密码首先添加到 nginx 的 htpasswd 文件中
- 然后使用“gerrit”CLI 命令创建一个 Gerrit 帐户,使用“ssh -p 29418 localhost gerrit create-account --full-name "'User XXXX'" --email[电子邮件保护]xxxxuser”(非真实姓名和邮箱!)
- 然后,新用户尝试通过 nginx 的 8080 端口登录 Gerrit
- nginx 身份验证成功,并将登录请求传递到端口 9080,但 Gerrit 以错误 403 拒绝了它
我检查了 logs/error_log,这是用户 2 的身份验证错误日志:
[2022-09-29 12:28:19,839] [HTTP-163217] ERROR com.google.gerrit.httpd.auth.container.HttpLoginServlet : Unable to authenticate user "xxxxuser"
com.google.gerrit.server.account.AccountException: Cannot assign external ID "username:xxxxuser" to account 1000186; external ID already in use.
at com.google.gerrit.server.account.AccountManager.create(AccountManager.java:306)
at com.google.gerrit.server.account.AccountManager.authenticate(AccountManager.java:140)
at com.google.gerrit.httpd.auth.container.HttpLoginServlet.doGet(HttpLoginServlet.java:118)
....
我尝试使用“ssh -p 29418 localhost gerrit set-account xxxxuser --http-password xxxxpass”在 Gerrit 中设置 HTTP 密码,但没有任何效果。我还使用“gerrit xxxxuser set-account --clear-http-password”清除了 HTTP 密码,但同样没有帮助。
很明显,使用“gerrit create-account”设置的帐户中缺少某些内容或存在错误,但我不知道可能是什么,也不知道如何修复它。
(Wireshark 在端口 9080 上捕获确认 /login/ URL 的 HTTP GET 具有来自 htpasswd 文件的正确的基本身份验证标头以及用户名和密码。)
Gerrit 和 nginx 的配置文件如下:
Gerrit:
[gerrit]
basePath = /srv/git
serverId = 71ff3ca6-7f68-45a6-b700-6ca6604f184c
canonicalWebUrl = http://server2:8080/
[database]
type = postgresql
hostname = localhost
database = reviewdb
username = gerrit2
[index]
type = LUCENE
[auth]
type = HTTP
[receive]
enableSignedPush = false
[sendemail]
smtpServer = smtp.gmail.com
smtpEncryption = ssl
smtpUser = [email protected]
smtpPass = gjhfgjfgjsagjsgjh
sslVerify = false
from = Gerrit Code Review <[email protected]>
[container]
user = git
javaHome = /usr/lib/jvm/java-8-openjdk-amd64/jre
javaOptions = "-Dflogger.backend_factory=com.google.common.flogger.backend.log4j.Log4jBackendFactory#getInstance"
javaOptions = "-Dflogger.logging_context=com.google.gerrit.server.logging.LoggingContext#getInstance"
[sshd]
listenAddress = *:29418
[httpd]
listenUrl = proxy-http://localhost:9080/
[cache]
directory = cache
[plugins]
allowRemoteAdmin = true
[plugin "events-log"]
maxAge = 20
returnLimit = 10000
storeDriver = org.postgresql.Driver
storeUrl = jdbc:postgresql:gerrit-events
storeUsername = gerrit-events
urlOptions = loglevel=INFO
urlOptions = logUnclosedConnections=true
copyLocal = true
nginx的:
server {
listen 8080;
server_name server2;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
location ^~ / {
auth_basic "Gerrit User Authentication";
auth_basic_user_file /etc/nginx/auth/gerrit.htpasswd;
proxy_pass http://127.0.0.1:9080;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
}
答案1
我找到了这个问题的答案 - 在这里发布以帮助遇到同样问题的人。
事实证明,用户帐户需要一个“gerrit:”外部 ID 才能成功登录,但“gerrit create-account”CLI 命令不会自动添加这个外部 ID,并且稍后无法使用“gerrit set-account”命令添加该 ID。
我发现将 gerrit: external ID 添加到帐户的唯一方法是在 All-Users 存储库的 refs/meta/external-ids 分支上手动创建所需文件。有关如何操作的更多详细信息,请参阅这个问题但总的来说,步骤如下:
- 克隆所有用户存储库
- 获取 refs/meta/external-ids 分支并检查
- 创建一个包含 gerrit: external ID 的文件(它只是一个文本文件 - 使用其他文件之一作为模板)。文件的名称必须是新外部 ID 的 SHA,您可以使用“echo -n 'gerrit:用户名' | 沙苏姆”。
- 提交文件并推送至原点。