Bitbucket 觸發內網 Jenkins Build
為了保證安全性多數的持續集成系統都會部署在公司內部的局域網中,這樣如果代碼部署在 Bitbucket 等環境中就只能通過輪詢的方式來觸發 Build。那麽有沒有辦法通過 Bitbucket 的 Webhooks 功能在開發人員提交代碼時觸發 Build 呢?答案是肯定的,並且有很多種實現方式。
本文筆者將介紹一種比較簡單的實現方式來實現由 Bitbucket 的 Webhooks 觸發內網 Jenkins 中的 Build。其結構如下:
實現本方案的條件是需要在外網有一臺可以訪問的主機,通過 SSH 的端口轉發技術(準確的說是"遠程端口轉發")把外網主機監聽到的請求轉發給內網中的 Jenkins 服務器。
添加用來觸發 Build 的用戶
一般情況下我們會添加一個用戶專門用來控制自動觸發 Build。在 Manage Jenkins -> Manage Users 界面中點擊 "Create User":
輸入用戶信息並創建用戶,筆者創建的用戶名稱為 autobuilder。
配置用戶的權限
對於剛才創建的 autobuilder 用戶,只有先賦予一定的權限,它才能夠系統中的 Build。
進入 Manage Jenkins -> Configure Global Security 配置界面,在 Authorization 的配置項中選擇 "Matrix-based security",然後把 autobuilder 用戶添進來:
並賦予 Overall - Read,Job - Build,Job - Read,Job - Workspace 四種權限。
當然我們可能會使用不同的 Authorization 方式,其實只要保證賦予 autobuilder 用戶合適的權限就可以了。
打開 Build 的 job trigger 配置
必須在 Project 中進行配置才能開啟遠程觸發 Build 的功能。進入 Project 的配置界面,在 "Build Triggers" 下面選中 "Trigger builds remotely":
如上圖所示,你必須輸入一個 Authentication Token。這主要是為了唯一的標識當前的 Project 並保證一定的安全性。你可以從 https://randomkeygen.com/ 輕松的生成一個合格的 Authentication Token。
獲得觸發 Build 的 URL
萬事具備,接下來讓我們構建可以在遠程觸發 Build 的 URL。
在前面的截圖中,第二個紅框中的內容就是一個可以觸發 Build 的 URL 模板。接下來我們用 Jenkins 服務器地址替換模板中的 JENKINS_URL,用實際的 Authentication Token 替換模板中的 TOKEN_NAME。得到的 URL 為:
http://localhost:8080/jenkins/job/elephant/build?token=QTfICY6LwGvgG5jhy8EzMD6C9dEdk8fS
現在在這個 URL 還不能觸發 Build,因為還缺少認證信息。
使用 autobuilder 用戶登錄到 jenkins 服務器中,點擊右上角的用戶名稱進入用戶信息界面,然後點擊 "Configure" 進入配置界面。點擊 API Token 小節中的 "Show API Token" 按鈕:
獲得上面的認證信息後就可以拼出完整的 URL 了。
http://autobuilder:[email protected]:8080/jenkins/job/elephant/build?token=QTfICY6LwGvgG5jhy8EzMD6C9dEdk8fS
通過 curl 在 Jenkins 服務器運行的主機上觸發 Build 試試:
$ curl http://autobuilder:[email protected]:8080/job/elephant/build?token=QTfICY6LwGvgG5jhy8EzMD6C9dEdk8fS
接下來用我們準備的外網主機域名替換本地的主機名,筆者準備的外網主機域名為 xxxengine.eastasia.cloudapp.azure.com,端口號為 10055。所以用 xxxengine.eastasia.cloudapp.azure.com:10055 替換 localhost:8080,最終的 URL 為:
http://autobuilder:[email protected]re.com:10055/job/elephant/build?token=QTfICY6LwGvgG5jhy8EzMD6C9dEdk8fS
配置遠程端口轉發
遠程端口轉發是 SSH 端口轉發的一種,如果你還不熟悉 SSH 端口轉發技術,請先移步《SSH 端口轉發》。
假設我們在 Azure 上有一臺運行 Ubuntu 16.04 Server 的虛擬主機,主機的域名為 xxxengine.eastasia.cloudapp.azure.com,允許外部訪問的端口為 22 和 10055:
其中 22 端口是 SSH 服務器用來建立 SSH 連接用的,10055 端口用來監聽外部觸發 Jenkins Build 的請求。
先登錄主機 xxxengine.eastasia.cloudapp.azure.com, 在 SSH 服務器的配置文件 /etc/ssh/sshd_config 中添加一行:
GatewayPorts yes
保存並重啟 SSH 服務器。
下面我們建立一條從內網中 Jenkins 服務器到外網 xxxengine.eastasia.cloudapp.azure.com 主機的隧道。在內網中運行 Jenkins 服務器的主機上執行下面的命令:
$ ssh -fN -R 10055:localhost:8080 [email protected]
R 選項指明端口轉發的方式為遠程端口轉發,10055 為主機 xxxengine.eastasia.cloudapp.azure.com 需要監聽的端口號。localhost:8080 是 Jenkins 服務器監聽的本機端口。[email protected] 表示通過用戶 nick 建立到主機 xxxengine.eastasia.cloudapp.azure.com 的 SSH 連接。選項 fN 則讓該遠程轉發以後臺方式運行。
建立好端口轉發後讓我們再次登錄到主機 xxxengine.eastasia.cloudapp.azure.com 上,執行 ss -tunl 命令查看端口的監聽情況:
看,主機已經能夠監聽任何來源發送到 10055 端口的請求了。
配置 Bitbucket Webhooks
在 Bitbucket 中打開你的項目,選擇 "Settings -> Webhooks" 進入 Webhooks 的配置界面。添加一個新的 webhook 配置,並且把我們在前面創建的最終版的 URL 設置其 URL:
直接保存就可以了!
檢查結果
向 Bitbucket 代碼庫中提交代碼,Bitbucket 在收到代碼推送後會使用我們在 webhook 中設置的 URL 發送 http 請求。結果內網中的 Jenkins 服務器收到請求觸發一個新的 Build。
整個過程中的數據流向為:
Bitbucket 向 xxxengine.eastasia.cloudapp.azure.com 的 10055 端口發送請求; SSH 服務器監聽 10055 端口並且把接收到的請求通過 SSH 隧道發送到內網中 Jenkins 服務器上 localhost 的 8080 端口; Jenkins 服務器監聽 localhsot 的 8080 端口,並且處理收到的請求。
總結
我們在沒有對現有系統做太多改變的情況下,僅僅使用 SSH 在內網與外網之間建立了一條隧道,就實現了外網對內容 Jenkins 的訪問。
其實日常工作中還有很多類似的用例,都可以通過 SSH 建立隧道的方式簡單便捷的解決。
Bitbucket 觸發內網 Jenkins Build