在自托管 GitLab 實(shí)例中集成 Keycloak 登錄
背景
在知乎上收到一個(gè)付費(fèi)咨詢(https://www.zhihu.com/consult/conversation/1413515497665662976/archive),他已經(jīng)在自己部署好的 GitLab 實(shí)例上集成了 Keycloak 登錄,想更進(jìn)一步,在用戶選擇 keycloak 登錄 GitLab 后,其身份信息也自動(dòng)帶過去。
這個(gè)功能其實(shí)正好是 GitLab 近期實(shí)現(xiàn)的 SAML Group Sync 功能,不過只對(duì) GitLab 托管的部分客戶開放。這位咨詢者搭建的是自托管 GtiLab 企業(yè)版,目前的版本不支持這個(gè)功能。不過,為了重現(xiàn)這位咨詢者碰到的實(shí)際問題,我也搭建了一個(gè)自托管的 GitLab 企業(yè)版,進(jìn)行了 Keycloak 登錄集成,過程還挺有趣的,因此記錄下來。
效果展示
錄了一個(gè)視頻,展示了如何通過薅 GitHub CodeSpace 羊毛的方式啟動(dòng)了一個(gè) GitLab 企業(yè)版實(shí)例,然后點(diǎn)擊 Keycloak 登錄,重用了自己開發(fā)的關(guān)注微信公眾號(hào)即登錄的方式,成功登錄 GitLab。
https://www.zhihu.com/zvideo/1416018136143802369
步驟詳解
部署 Keycloak
Keycloak 是一個(gè)開源的認(rèn)證授權(quán)系統(tǒng),基于 Java 開發(fā)。部署方式有多種,詳見《基于 keycloak 的關(guān)注公眾號(hào)即登錄功能的設(shè)計(jì)與實(shí)現(xiàn)》中 5.1 的介紹。我按照其中介紹的部署到 Heroku 的方式,部署了一個(gè)實(shí)例:https://keycloak.jiwai.win/,部署到 Heroku 的優(yōu)勢(shì)是簡單、免費(fèi)。
部署 GitLab
GitLab 官網(wǎng)介紹了多種部署方式,但是對(duì)于我的演示目的,各有優(yōu)劣:
SaaS | 部署到云(Google、AWS,Azure)上虛擬服務(wù)器上 | 部署到云提供的 Kubernetes 集群 | 本地部署 | |
好處 | 最簡單 能外網(wǎng)訪問 我最想采用的方式 | 能外網(wǎng)訪問 | 能外網(wǎng)訪問 | 部署簡單 免費(fèi) |
壞處 | 要錢! 沒有超級(jí)管理員權(quán)限 | 要錢! 配置工作量大 | 要錢! 配置工作量大 | 配置外網(wǎng)訪問復(fù)雜 耗本地機(jī)器資源 |
基于一定要免費(fèi)的原則,似乎只能本地部署。本地部署最簡單的方式就是 docker-compose 啟動(dòng),但是這樣會(huì)有個(gè)問題,就是現(xiàn)在的瀏覽器(Chrome、Safari 等)都打不開頁面,原因是 GitLab 實(shí)例的自簽發(fā)證書不被信任!要設(shè)置信任特別復(fù)雜,再加上需要 Keycloak 回調(diào) GitLab 實(shí)例,部署在本地有諸多不便。
但是本地使用 docker-compose 啟動(dòng) GitLab 實(shí)例的方式實(shí)在是太香了,有沒有辦法把本地 docker-compose 部署的方式移植到線上呢?想到這里,我把目光投向了 GitHub 的 CodeSpace,CodeSpace 在我炯炯有神的堅(jiān)毅的不薅羊毛到底絕不罷休的眼神中瑟瑟發(fā)抖。
docker-compose
首先,我按照官網(wǎng)的知道說明,創(chuàng)建了 docker-compose.yml 文件,并將它提交到了 GitHub 代碼倉庫:https://github.com/Jeff-Tian/gitlab 。然后打開 GitHub 倉庫主頁,按下了句點(diǎn)鍵,GitHub 切換進(jìn)入了網(wǎng)頁編輯器界面:https://github.dev/Jeff-Tian/gitlab。熟悉的 VsCode 編輯器出現(xiàn)了,就憑這,足以回答知乎上的這個(gè)問題了:《Visual Studio Code 可以翻盤成功主要是因?yàn)槭裁矗?/span>》。
VsCode 網(wǎng)頁編輯器
接著,我打開 Terminal,想運(yùn)行 docker-compose up -d 以像在本地啟動(dòng) GitLab 實(shí)例一樣在網(wǎng)頁編輯器中啟動(dòng) GitLab,看到了 Terminal 不被支持,但是不要慌,點(diǎn)擊“繼續(xù)”按鈕就打開了 CodeSpace。(當(dāng)然,后來知道了可以直接輸入 https://github.com/codespaces 打開已經(jīng)新建過的項(xiàng)目,而不用每次重新創(chuàng)建)

點(diǎn)擊“繼續(xù)”按鈕后,就來到了 CodeSpace,仍然是熟悉的 VsCode 編輯器。但是這里的 Terminal 可以使用。運(yùn)行 docker-compose up -d 。

實(shí)例啟動(dòng)后,就可以在網(wǎng)頁端打開了,記住 docker-compose.yml 中配置了 8929 這個(gè)端口。按下 Cmd+Shift+P 鍵,選擇 docker 容器插件提供的在瀏覽器打開功能,依次選擇應(yīng)用,端口:




這樣就在新窗口中打開了:https://jeff-tian-gitlab-wq766wrh9r57-8929.githubpreview.dev/users/sign_in

GitLab 實(shí)例就這樣部署好了,而且連 https 以及證書,都被 CodeSpace 搞定了,外網(wǎng)也可以訪問!

配置 KeyCloak
接下來,需要在 Keycloak 中配置 GitLab 客戶端,因?yàn)槲覀兊哪康氖窃?GitLab 中啟用 Keycloak 登錄,那么 Keycloak 就是一個(gè) IDP 了,而 GitLab 是其一個(gè) OAuth 2 客戶端應(yīng)用。要將 Keycloak 當(dāng)作 IDP,一般有兩種形式,OIDC 形式和 SAML 形式。
使用 OIDC 的形式集成,有兩篇文章做過詳細(xì)的介紹:
如果對(duì)這種集成方式感興趣,可以詳細(xì)參考。這里準(zhǔn)備采用 SAML 方式集成,以便補(bǔ)充這種集成方式的實(shí)戰(zhàn)。實(shí)際上,網(wǎng)上已經(jīng)有一些 GitLab 和 Keycloak 采用 SAML 集成的文章了,但是采用了非常復(fù)雜的方法,因此整篇文章都在講集成細(xì)節(jié)。這里采用了一個(gè)簡單的方式,只需要一小節(jié)介紹即可。
導(dǎo)出 GitLab 的 SAML 元數(shù)據(jù) xml 定義
對(duì)于支持 SAML 集成的應(yīng)用,可以訪問其 /users/auth/saml/metadata 獲得其 SAML 源數(shù)據(jù)信息。將其保存到本地:

在 Keycloak 中導(dǎo)入 GitLab 的 SAML 元信息

在 Keycloak 中添加 GitLab 客戶端的 email 映射
你可以添加更多的映射,以便把 Keycloak 中的用戶信息映射到 GitLab 系統(tǒng)。但是只有 email 是必須的。

配置 GitLab
現(xiàn)在,Keycloak 中已經(jīng)有了我們新部署的 GitLab 實(shí)例信息,現(xiàn)在需要配置 GitLab,讓它知道我們部署好的 Keycloak 實(shí)例信息。
首先,需要記下 Keycloak 應(yīng)用對(duì)應(yīng)的 Realm 的 url,以及拷貝一下它的證書信息:

然后,回到 CodeSpaces,進(jìn)入到 GitLab docker 鏡像里:

在 shell 里,進(jìn)入到 /etc/gitlab 目錄,輸入 vi gitlab.rb 命令,貼入一段 Keycloak 相關(guān)的配置:

配置的文本內(nèi)容如下,注意替換相關(guān) url 和具體證書內(nèi)容。
gitlab_rails['omniauth_enabled'] = truegitlab_rails['omniauth_allow_single_sign_on'] = ['saml']# gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'saml'gitlab_rails['omniauth_block_auto_created_users'] = false# gitlab_rails['omniauth_auto_link_ldap_user'] = falsegitlab_rails['omniauth_auto_link_saml_user'] = truegitlab_rails['omniauth_providers'] = [{name: 'saml',args: {assertion_consumer_service_url: 'https://jeff-tian-gitlab-wq766wrh9r57-8929.githubpreview.dev/users/auth/saml/callback',idp_cert: " -----BEGIN CERTIFICATE-----\n MIIC...WWDcIuuyzU\n -----END CERTIFICATE----- \n",idp_sso_target_url: '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',name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'},label: 'KEYCLOAK 登錄'}]

小提示:這里是在網(wǎng)頁中操作 vi,進(jìn)入編輯模式后,要退出到普通模式,不能采用一般的 Esc 或者 Ctrl + [ 鍵,因?yàn)檫@只會(huì)讓瀏覽器編輯器失去焦點(diǎn)。這應(yīng)該是 VsCode 網(wǎng)頁編輯器可以進(jìn)一步優(yōu)化的點(diǎn),目前繞過這個(gè)問題的方式是,Ctrl + C ,退出插入模式的同時(shí),不失去焦點(diǎn)。
輸入 :wq 保存并退出配置文件,然后重啟 GitLab:gitlab-ctl reconfigure。
重新打開 GitLab,就會(huì)看到登錄框下多了一個(gè) “Keycloak 登錄” 選項(xiàng):

體驗(yàn)
如展示小節(jié)的視頻展示,登錄成功后可以對(duì)比一下用戶資料,匹配!


總結(jié)
通過薅 CodeSpace 羊毛的方式,部署了 GitLab 企業(yè)版實(shí)例,并通過配置的方式,對(duì)接 Keycloak 登錄。
后期工作
目前通過 Docker-compose,使用了 GitLab 官方鏡像,在對(duì)接 Keycloak 時(shí)還有些手動(dòng)步驟。后面可以把配置好的 GitLab 打包成自定義鏡像,以實(shí)現(xiàn) 0 配置對(duì)接。
