Jenkins Mac Slave 的 Keychain 配置方法
1 動機
最近在給 Mac 系統做 Jenkins 的持續整合,需要用 Mac 編譯、打包一個 ios app,中間碰到很多問題,試了很久才解決,在此記錄一下。
其中最關鍵的問題是 Mac 系統的 Keychain 導致的問題。因為我之前沒有怎麼接觸過 Mac,所以完全不瞭解什麼是 Keychain。其實很簡單,從 wikipedia 上查一下就明白了,基本就是一個密碼、證書等安全資訊的統一管理軟體,跟 Linux 下的 Gnome Keyring 是很類似的。
2 步驟
理解了這一點之後,很多問題就都很好解決了(注意!建議繼續閱讀之前,一定要先閱讀 wikipedia 上的 keychain 條目 ,否則可能很難理解下面的內容):
-
一定要先用圖形介面的 xcode 編譯驗證一遍
在這一步,需要先通過 xcode 的
Preferrences...
->Accounts
對話方塊標籤頁裡新增開發所使用的 Apple ID,然後執行下載 Manual Profiles、管理並下載開發證書等操作。這些操作最後會把開發賬號的安全證書資訊新增到當前的 Keychain 裡。
-
在圖形介面的命令列上用 xcodebuild 再編譯驗證一遍
在這一步,編譯打包的過程中,如果用到了 codesign 的話,系統會彈出一個對話方塊讓你輸入密碼並問你是否允許/永遠允許,這裡一定要選永遠允許。
這裡需要輸入的是當前預設的 keychain 密碼。因為預設使用的是 login 的 keychain,而 login keychain 的密碼預設就是使用者登入的密碼,所以這裡只需要輸入使用者登入的密碼即可。
-
通過 ssh 遠端連線到 Mac 系統上,再在 ssh 的終端上通過 xcodebuild 命令進行編譯,這裡編譯會報證書、安全相關的錯誤,上網查一下就能查到問題原因及解決方案。原因是 ssh 登入上去之後,keychain 沒有被解鎖;解決方案是用
security unlock-keychain
命令將證書解鎖。解鎖過程中需要輸入 keychain 的密碼(預設是 login keychain,login keychain 的密碼預設是使用者的登入密碼)。注意如果 2 和 3 的順序弄錯,沒有執行過步驟 2 直接執行步驟 3 的話,即使解鎖了 keychain,也會繼續報另一個安全證書相關的錯誤,並且從網上很難查到相關的資訊。其原因是 ssh 登入的終端,不會像圖形登入的終端那樣,彈出一個對話方塊給你選擇“永遠允許”,而是直接報一個晦澀難懂的錯誤就退出了。所以先執行步驟 2 非常重要!因為選了“永遠允許”,所以在 ssh 遠端終端裡用到安全證書時也被允許了,不會因為證書訪問被拒絕而出錯。
(我在這一點上浪費了很多時間
,一開始就用 ssh 登入去編,怎麼也編不過,網上說要解鎖 keychain,解鎖了也還是編不過,後來好不容易想起來在圖形的終端上先試一下。。。)
做完這一步之後,因為通過 ssh 已經可以編譯,所以把 Mac 用 ssh 的方式新增到 Jenkins 上,編譯也是沒有問題的。唯一剩下的問題就是我們不應該在 Jenkins 任務裡用 Mac 使用者登入的密碼去解鎖 Keychain,所以我們需要換一個新的keychain及其配套密碼(這個密碼不同於 Mac 使用者登入密碼,並且安全上的重要程度也相應更低一些——萬一洩露的話造成的危害遠遠不如 Mac 登入密碼洩露造成的危害)。
- 更換 keychain 的方法
- 在 keychain 應用裡新增一個新的 keychain(過程中需要輸入新的 keychain 密碼,之後就用這個新密碼來解鎖這個新 keychain)。
-
臨時把這個新 keychain 設為預設 keychain,把上面的 1、2、3 幾個步驟重新執行一遍,其中執行 1 之前,可能需要在 xcode 裡先刪除已有的 Apple ID 再重新新增。
因為把新的 keychain 設成了預設,所有安全證書相關的操作就都會使用這個新 keychain。
所以重做了這幾個步驟之後,編譯相關的安全證書資訊被新增到了這個新的 keychain 裡。之後我們就可以用這個新 keychain 來進行 ios 專案的編譯、打包、簽名了。
- 操作完成後,記得把系統預設 keychain 設定回原來的 login.keychain。
- 在 Jenkins 任務裡通過在編譯指令碼開始位置新增
security default-keychain ...
、security unlock-keychain ...
等命令,設定編譯任務預設 keychain 為上述新 keychain 並將其解鎖,這樣編譯打包簽名就不會因為證書問題而出錯了。
3 其他問題
注意在上面配置完成之後,當前的 Mac 使用者就無法登入之後直接使用 xcode 進行編譯了。因為預設的 login.keychain 裡沒有 ios 開發所需的賬號安全證書(新增新 keychain 時被刪掉了)。
這個問題不算很嚴重,因為作為 Jenkins 整合的 Mac 伺服器,平時不會有使用者圖形登入上去執行編譯操作。如果真的需要解決這個問題的話,以下是可能的兩種方案:
- 研究一下怎麼把 xcode 的 apple id account 同時新增到兩個 keychain 裡
- 利用 Mac 的多使用者特性,建立一個專門的 Jenkins 賬號和一個工程師登入賬號