谷歌认证用于 Gerrit 和 Jenkins

16
Jenkins和Gerrit都有OpenID 2.0插件,但是这个API已经被Google于2014年5月19日弃用(https://developers.google.com/accounts/docs/OpenID),因此新的安装无法使用,现有的安装必须迁移到OAuth2.0(OpendID连接)。如果尝试使用OpenID 2.0,则会收到错误消息“错误400:OpenID auth请求包含未注册的域”。
Gerrit团队知道这个问题,但目前还没有解决方案:https://code.google.com/p/gerrit/issues/detail?id=2677 不确定Jenkins是否有类似的问题。

1
为了符合问答网站的期望,这里应该有一个问题。也许这会帮助我理解你的回答包含了什么。 - mabraham
3个回答

12
更新 2014/11/05: 如果您是第一次来到这里,请继续向下阅读。感谢hans-zandbelt的反馈。更新版本已经将其纳入考虑并使用了建议的改进,仅使用mod_rewrite将gerrit注销url重定向到正确的位置。另请注意,与其仅使用电子邮件的非域部分不同,电子邮件现在未经修改就被使用。这意味着,如果您已经有一个现有的设置,则需要更改用户名映射。

对于Jenkins,请执行以下操作:

  • 将 ${jenkins_home}/users/youruser 移动到 ${jenkins_home}/users/youruser@yourdomain
  • 打开 ${jenkins_home}/config.xml,搜索“youruser”,并将其替换为 youruser@yourdomain

对于Gerrit:

要么在机器本身上(将GERRIT_HOME更改为您的机器上的位置):

  • 使用以下两种方法之一打开sql数据库:

    1. [推荐] 通过ssh可用的gerrit命令:

      ssh  gerrit.revault.ch gerrit  gsql
      
    2. 在机器本身上执行OR操作(将GERRIT_HOME更改为其在您的机器上的位置):

    3. export GERRIT_HOME=/var/gerrit_home
      pushd ${GERRIT_HOME}
      java -cp $(find . -name "h2*.jar") org.h2.tools.Shell -url "jdbc:h2:file:${GERRIT_HOME}/db/ReviewDB;IFEXISTS=TRUE"
      
  • 展示外部资源

  • select * from ACCOUNT_EXTERNAL_IDS;
    
  • 外部ID将您的帐户映射到不同的用户名、电子邮件地址等。

  • 以username:为前缀的ID,例如username:test@example.com是用于SSH/Git登录名的
  • 以gerrit:为前缀的ID,例如gerrit:test@example.com用于Web界面
  • 对于给定的account_id,您可以使用SQL添加现有用户的新映射,例如:

  • insert into ACCOUNT_EXTERNAL_IDS values(1000032, NULL,NULL, 'username:test@example.com');
    insert into ACCOUNT_EXTERNAL_IDS values(1000032, NULL,NULL, 'gerrit:test@example.com');
    


解决方案

您可以使用Apache作为反向代理来处理身份验证:

Gerrit

假设您已经安装了Gerrit并且它正在侦听地址10.10.10.10:8080。 您需要配置Gerrit使用基本身份验证,在您的 ${gerrit_installation}/etc/gerrit.config 中,[auth] 部分应如下所示:

[gerrit]
        basePath = git
        canonicalWebUrl = http://gerrit.example.com
[database]
        type = h2
        database = db/ReviewDB
[index]
        type = LUCENE
[auth]
        type = HTTP
        emailFormat = {0}@example.com
        httpHeader =  X-Forwarded-User
[sendemail]
        smtpServer = localhost
[container]
        user = gerrit
        javaHome = /usr/lib/jvm/java-8-oracle/jre
[sshd]
        listenAddress = 10.10.10.10:2222
[httpd]
        listenUrl = http://10.10.10.10:8080/
[cache]
        directory = cache

用户名将在标题X-Forwarded-User中。这就是Apache将用户名转发给Gerrit的方式。

在Apache上,我们将使用支持oauth2的mod_auth_openidc。有关更多信息和示例文档,请参见https://github.com/pingidentity/mod_auth_openidc。在最近的Ubuntu上,安装看起来像这样:

sudo aptitude install libjansson-dev apache2 apache2-dev libcurl4-openssl-dev build-essential autoconf libhiredis-dev

git clone https://github.com/pingidentity/mod_auth_openidc.git
cd mod_auth_openidc
./autogen.sh 
./configure
make
sudo make install

sudo a2enmod auth_openidc
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo a2enmod rewrite

您需要添加一个站点配置,例如下面的gerrit.conf(您可能还需要TLS),并将其激活到/etc/apache2/sites-available中:

sudo a2ensite gerrit.conf

/etc/apache2/sites-available/gerrit.conf文件的内容如下:

<VirtualHost *:80>
ServerName gerrit.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

OIDCProviderMetadataURL https://accounts.google.com/.well-known/openid-configuration
OIDCClientID <from api console>
OIDCClientSecret <from api console>

OIDCScope "openid email profile"
OIDCRedirectURI http://gerrit.example.com/oauth2callback
OIDCCryptoPassphrase <generate long random passphrase here, no sure if used>

OIDCSessionInactivityTimeout 600

OIDCCookiePath /

OIDCAuthRequestParams hd=example.com
OIDCRemoteUserClaim email
OIDCAuthNHeader X-Forwarded-User

RewriteEngine On
#LogLevel alert rewrite:trace2
RewriteRule ^/logout$ /oauth2callback?logout=http://gerrit.example.com/ [R]

ProxyPass /  http://gerrit.example.com:8080/ nocanon
ProxyPassReverse / http://gerrit.example.com:8080/
ProxyRequests     Off
AllowEncodedSlashes NoDecode


<Proxy http://gerrit.example.com:8080/*>
# add rewrites here if necessary
</Proxy>

<Location />
   AuthType openid-connect
   Require claim hd:example.com
   Require valid-user
</Location>

</VirtualHost>

要获取参数OIDCClientID和OIDCClientSecret,请前往https://console.developers.google.com/project中的API控制台。如果您还没有项目,请先创建一个项目。例如:example-it-authentication

Developer Console projects

在项目上转到API和身份验证:

  • 在API下激活Google+ API。Developer Console enabled APIs
  • 在凭据下,OAuth创建新的客户端ID。 Developer Console create credentials
  • 在您的Apache配置文件(例如gerrit.conf)中填写OIDCClientID和OIDCClientSecret。 Developer Console credentials
  • 在同意屏幕下填写电子邮件和产品名称(如果您不这样做,您将收到错误消息)

service apache2 restart

你完成了!

Jenkins

假设您已经安装了Jenkins并且正在侦听10.10.10.11:8080。

对于Jenkins,配置几乎相同。您需要安装并激活反向代理身份验证插件http://wiki.jenkins-ci.org/display/JENKINS/Reverse+Proxy+Auth+Plugin。 在配置全局安全性下,选中“通过反向代理的HTTP标头”单选按钮。 Jenkins activating security

默认值对应于以下配置。 您需要在API控制台https://console.developers.google.com/project中创建与jenkins主机名匹配的凭据。像以前一样报告给您的配置文件(例如:jenkins.conf)。就这些了。

<VirtualHost *:80>
ServerName jenkins.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

OIDCProviderMetadataURL https://accounts.google.com/.well-known/openid-configuration
OIDCClientID <from api console>
OIDCClientSecret <from api console>

OIDCScope "openid email profile"
OIDCRedirectURI http://jenkins.example.com/oauth2callback
OIDCCryptoPassphrase <generate long random passphrase here, no sure if used>

OIDCSessionInactivityTimeout 600

OIDCCookiePath /

OIDCAuthRequestParams hd=example.com
OIDCRemoteUserClaim email
OIDCAuthNHeader X-Forwarded-User

ProxyPass /  http://jenkins.example.com:8080/ nocanon
ProxyPassReverse / http://jenkins.example.com:8080/
ProxyRequests     Off
AllowEncodedSlashes NoDecode

<Proxy http://jenkins.example.com:8080/*>
# add rewrites here if necessary
</Proxy>

<Location />
   AuthType openid-connect
   Require claim hd:example.com
   Require valid-user
</Location>

<Location ~ "^/(cli|jnlpJars|subversion|whoAmI|computer/[^/]+/slave-agent.jnlp|tcpSlaveAgentListener)">
 Satisfy Any
 Allow from all 
</Location>

</VirtualHost>

目前mod_auth_openidc似乎不支持组。如果您需要组,可以安装存储它们的LDAP(但这可能不是您想要的,因为您正在使用Google身份验证),或者等待mod_auth_openidc支持。


我不确定这里解决了问题的哪个方面。Apache可以进行新式身份验证,因此Gerrit被告知要询问它而不是Google获取详细信息? - mabraham
如果您安装了Gerrit(新域),则无法使用内置的OpenID插件通过Google进行身份验证。 Google已弃用该API,并不允许您注册新域。本文展示了一种解决方法,直到Gerrit支持OAuth2.0(OpenID连接)成为标准功能为止。 - revau.lt
非常出色的回答,谢谢您。不过我有一个问题,关于Jenkins中的设置。如果我有一个名为admin.olly.com的域管理员,并将oauth放在整个域周围,以便在没有它的情况下无法访问admin.olly.com/jenkins,那么我还需要进行Jenkins安全设置吗?这又会添加什么额外的内容呢?谢谢! - Olly W
很好的答案,但我似乎无法使用选项1或2进入H2数据库。它显示以下内容:“未识别的选项:-url”。 - JAM
这个解决方案在我从Google的OAuth迁移到OpenID Connect时对我起了作用,但是我发现新用户可以访问用户界面。Gerrit日志报错说用户名无效(电子邮件地址包含@字符,而Gerrit不接受):Cannot assign user name xxx@abc.com to account 73; name does not conform。解决方案是在Apache配置中设置OIDCRemoteUserClaim email ^(.*)@。值的第二部分是一个正则表达式,只返回电子邮件的名称部分。之后,我必须为没有域的现有用户在account_external_ids中创建新条目。 - kresho
显示剩余4条评论

3
Google的OpenID 2.0已被OpenID Connect取代。Apache模块mod_auth_openidc实现了OpenID Connect,因此可以在反向代理中使用,以像revau.lt所描述的方式作为Gerrit/Jenkins的前端。
然而,请注意,除非您使用以下两个配置设置将登录限制为特定域名,否则依赖电子邮件地址的非域部分作为唯一标识符是不安全的:
OIDCAuthRequestParams hd=example.com

要跳过谷歌账户选择屏幕,并在<Location>部分中执行以下操作:
Require claim hd:example.com

为了限制访问权限只允许来自example.com谷歌域的用户,如果您的应用程序对任何谷歌账户开放,则不应使用电子邮件前缀作为主要标识符,因为有可能出现不同域中的用户具有相同的用户前缀而产生冲突。

这就是为什么最好依赖于完整的电子邮件地址,例如:

OIDCRemoteUserClaim email

或者是 Google 在 sub 声明中使用的(不透明)主标识符,例如:

OIDCRemoteUserClaim sub

此外,您可以直接使用以下方法,而无需将声明重写为头部:
OIDCAuthNHeader X-Forwarded-User

从OpenID 2.0迁移到OpenID Connect(保留OpenID 2.0用户标识符)是可能的,具体方法可以参考这里这里的描述。因此,您需要使用以下内容:
OIDCAuthRequestParams openid.realm=<urlencoded-realm-value>
OIDCRemoteUserClaim openid_id

想要全面了解配置基础知识,请参考以下链接:https://github.com/pingidentity/mod_auth_openidc/blob/master/auth_openidc.conf


非常感谢您。我猜我没有深入阅读文档。您的建议已经融入了我的答案中。 - revau.lt
您的设置似乎仅使用来自单个域的用户,如果是这种情况,出于安全原因,我强烈建议使用OIDCRequestParams和Require声明设置。 - Hans Z.
你的设置假定 Google 邮件前缀实际上与 Jenkins 中的用户名相同,这是在创建 Google 用户帐户时需要强制执行的事情,人们需要意识到这一点;另一种映射方法是在 mod_auth_openidc 设置 OIDCAuthNHeader 后重新编写它,而不是翻译数据库中的所有用户标识符。 - Hans Z.

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接