背景

在知乎上收到一个付费咨询(https://www.zhihu.com/consult/conversation/1413515497665662976/archive),他已经在自己部署好的 GitLab 实例上集成了 Keycloak 登录,想更进一步,在用户选择 keycloak 登录 GitLab 后,其身份信息也自动带过去。

这个功能其实正好是 GitLab 近期实现的 SAML Group Sync 功能,不过只对 GitLab 托管的部分客户开放。这位咨询者搭建的是自托管 GtiLab 企业版,目前的版本不支持这个功能。不过,为了重现这位咨询者碰到的实际问题,我也搭建了一个自托管的 GitLab 企业版,进行了 Keycloak 登录集成,过程好挺有趣的,因此记录下来。

效果展示

录了一个视频,展示了如何通过薅 GitHub CodeSpace 羊毛的方式启动了一个 GitLab 企业版实例,然后点击 Keycloak 登录,重用了自己开发的关注微信公众号即登录的方式,成功登录 GitLab。

https://www.zhihu.com/zvideo/1416018136143802369

步骤详解

部署 Keycloak


Keycloak 是一个开源的认证授权系统,基于 Java 开发。部署方式有多种,详见《基于 keycloak 的关注公众号即登录功能的设计与实现》中 5.1 的介绍。我按照其中介绍的部署到 Heroku 的方式,部署了一个实例:https://keycloak.jiwai.win/,部署到 Heroku 的优势是简单、免费。

部署 GitLab


GitLab 官网介绍了多种部署方式,但是对于我的演示目的,各有优劣:

SaaS 部署到云(Google、AWS,Azure)上虚拟服务器上 部署到云提供的 Kubernetes 集群 本地部署
好处 最简单

能外网访问 ​

我最想采用的方式 | 能外网访问 | 能外网访问 | 部署简单 ​

免费 | | 坏处 | 要钱! ​

没有超级管理员权限 | 要钱! ​

配置工作量大 | 要钱! ​

配置工作量大 | 配置外网访问复杂 ​

耗本地机器资源 |

基于一定要免费的原则,似乎只能本地部署。本地部署最简单的方式就是 docker-compose 启动,但是这样会有个问题,就是现在的浏览器(Chrome、Safari 等)都打不开页面,原因是 GitLab 实例的自签发证书不被信任!要设置信任特别复杂,再加上需要 Keycloak 回调 GitLab 实例,部署在本地有诸多不便。 ​

但是本地使用 docker-compose 启动 GitLab 实例的方式实在是太香了,有没有办法把本地 docker-compose 部署的方式移植到线上呢?想到这里,我把目光投向了 GitHub 的 CodeSpace,CodeSpace 在我炯炯有神的坚毅的不薅羊毛到底绝不罢休的眼神中瑟瑟发抖。 ​

docker-compose

首先,我按照官网的知道说明,创建了 docker-compose.yml 文件,并将它提交到了 GitHub 代码仓库:https://github.com/Jeff-Tian/gitlab 。然后打开 GitHub 仓库主页,按下了句点键,GitHub 切换进入了网页编辑器界面:https://github.dev/Jeff-Tian/gitlab。熟悉的 VsCode 编辑器出现了,就凭这,足以回答知乎上的这个问题了:《Visual Studio Code 可以翻盘成功主要是因为什么?》。 ​

VsCode 网页编辑器

接着,我打开 Terminal,想运行 docker-compose up -d 以像在本地启动 GitLab 实例一样在网页编辑器中启动 GitLab,看到了 Terminal 不被支持,但是不要慌,点击“继续”按钮就打开了 CodeSpace。(当然,后来知道了可以直接输入 https://github.com/codespaces 打开已经新建过的项目,而不用每次重新创建) ​

image.png

点击“继续”按钮后,就来到了 CodeSpace,仍然是熟悉的 VsCode 编辑器。但是这里的 Terminal 可以使用。运行 docker-compose up -d 。 ​

image.png

实例启动后,就可以在网页端打开了,记住 docker-compose.yml 中配置了 8929 这个端口。按下 Cmd+Shift+P 键,选择 docker 容器插件提供的在浏览器打开功能,依次选择应用,端口: ​

image.png

image.png

image.png

image.png

这样就在新窗口中打开了: https://jeff-tian-gitlab-wq766wrh9r57-8929.githubpreview.dev/users/sign_in

image.png

GitLab 实例就这样部署好了,而且连 https 以及证书,都被 CodeSpace 搞定了,外网也可以访问! ​

image.png

配置 KeyCloak

接下来,需要在 Keycloak 中配置 GitLab 客户端,因为我们的目的是在 GitLab 中启用 Keycloak 登录,那么 Keycloak 就是一个 IDP 了,而 GitLab 是其一个 OAuth 2 客户端应用。要将 Keycloak 当作 IDP,一般有两种形式,OIDC 形式和 SAML 形式。 ​

使用 OIDC 的形式集成,有两篇文章做过详细的介绍: ​

如果对这种集成方式感兴趣,可以详细参考。这里准备采用 SAML 方式集成,以便补充这种集成方式的实战。实际上,网上已经有一些 GitLab 和 Keycloak 采用 SAML 集成的文章了,但是采用了非常复杂的方法,因此整篇文章都在讲集成细节。这里采用了一个简单的方式,只需要一小节介绍即可。 ​

导出 GitLab 的 SAML 元数据 xml 定义

对于支持 SAML 集成的应用,可以访问其 /users/auth/saml/metadata 获得其 SAML 源数据信息。将其保存到本地: ​

image.png

在 Keycloak 中导入 GitLab 的 SAML 元信息

image.png

在 Keycloak 中添加 GitLab 客户端的 email 映射

你可以添加更多的映射,以便把 Keycloak 中的用户信息映射到 GitLab 系统。但是只有 email 是必须的。 ​

image.png

配置 GitLab

现在,Keycloak 中已经有了我们新部署的 GitLab 实例信息,现在需要配置 GitLab,让它知道我们部署好的 Keycloak 实例信息。 ​

首先,需要记下 Keycloak 应用对应的 Realm 的 url,以及拷贝一下它的证书信息: ​

image.png

然后,回到 CodeSpaces,进入到 GitLab docker 镜像里: ​

image.png

在 shell 里,进入到 /etc/gitlab 目录,输入 vi gitlab.rb 命令,贴入一段 Keycloak 相关的配置: ​

image.png 配置的文本内容如下,注意替换相关 url 和具体证书内容。 ​

ruby gitlabrails[omniauthenabled] = true gitlabrails[omniauthallowsinglesign_on] = [saml]

gitlabrails[omniauthautosigninwithprovider] = saml

gitlabrails[omniauthblockautocreated_users] = false

gitlabrails[omniauthautolinkldap_user] = false

gitlabrails[omniauthautolinksamluser] = true gitlabrails[omniauth_providers] = [ { name: saml, args: { assertionconsumerserviceurl: https://jeff-tian-gitlab-wq766wrh9r57-8929.githubpreview.dev/users/auth/saml/callback, idpcert: -----BEGIN CERTIFICATE----- n MIIC...WWDcIuuyzUn -----END CERTIFICATE----- n, idpssotargeturl: https://keycloak.jiwai.win/auth/realms/UniHeart/protocol/saml/clients/jeff-tian-gitlab-wq766wrh9r57-8929.githubpreview.dev, issuer: jeff-tian-gitlab-wq766wrh9r57-8929.githubpreview.dev, nameidentifier_format: urn:oasis:names:tc:SAML:2.0:nameid-format:persistent }, label: KEYCLOAK 登录 } ]

image.png

小提示:这里是在网页中操作 vi,进入编辑模式后,要退出到普通模式,不能采用一般的 Esc 或者 Ctrl + [ 键,因为这只会让浏览器编辑器失去焦点。这应该是 VsCode 网页编辑器可以进一步优化的点,目前绕过这个问题的方式是,Ctrl + C ,退出插入模式的同事,不失去焦点。

输入 :wq 保存并退出配置文件,然后重启 GitLab:gitlab-ctl reconfigure

重新打开 GitLab,就会看到登录框下多了一个 “Keycloak 登录” 选项:

image.png

体验


如展示小节的视频展示,登录成功后可以对比一下用户资料,匹配!

image.png

image.png

总结


通过薅 CodeSpace 羊毛的方式,部署了 GitLab 企业版实例,并通过配置的方式,对接 Keycloak 登录。

后期工作

目前通过 Docker-compose,使用了 GitLab 官方镜像,在对接 Keycloak 时还有些手动步骤。后面可以把配置好的 GitLab 打包成自定义镜像,以实现 0 配置对接。