当其他用户正常工作时,新用户使用代理 HTTP 对 Gerrit 设置进行身份验证失败

当其他用户正常工作时,新用户使用代理 HTTP 对 Gerrit 设置进行身份验证失败

我们在 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 分支上手动创建所需文件。有关如何操作的更多详细信息,请参阅这个问题但总的来说,步骤如下:

  1. 克隆所有用户存储库
  2. 获取 refs/meta/external-ids 分支并检查
  3. 创建一个包含 gerrit: external ID 的文件(它只是一个文本文件 - 使用其他文件之一作为模板)。文件的名称必须是新外部 ID 的 SHA,您可以使用“echo -n 'gerrit:用户名' | 沙苏姆”。
  4. 提交文件并推送至原点。

相关内容