Fastlane證書管理(二):match

wangzzzzz發表於2018-06-12

1. 前言

match這個Tool的作用可以分為兩步

  1. 獲取合適的cert和profile
  2. 將獲取的cert和profile安裝到本機

其簡單流程如下圖所示

Fastlane證書管理(二):match

  • 首先,從:git_url指定的git倉庫中獲取cert和profile,如果沒有,則從AppleID賬號中獲取。 當從AppleID賬號中獲取cert時,即使你的AppleID賬號中有建立好的簽名證書,match也只會嘗試去建立一個新的的簽名證書,如果你的AppleID賬號中籤名證書的數目已達到了2個,則會建立失敗,然後match異常退出; 當從AppleID賬號中獲取profile時,會強制建立一個新的來使用。具體過程可檢視上一節cert和sigh
  • match的最終目的就是把cert和profile安裝到本機 cert被匯入到鑰匙鏈中 profile被安裝到xcode中

2. 內部流程

macth特別適合在一個團隊裡面使用,在使用match時,一般會先使用match建立一套可使用的cert和profile上傳到git倉庫中,然後共享這個git倉庫給團隊的其他成員,這樣就可以一次建立,多次使用了。另外,macth提供了一個只讀模式,可以防止你修改AppleID賬號中或git倉庫中的cert和profile。

2.1. 只讀模式

:readonly的值是true時,match不會訪問AppleID賬號,只會從git倉庫獲取cert和profile,並且不會修改git倉庫。在只讀模式中,:force必須是false,否則,程式異常退出。在只讀模式中,:force_for_new_devices不會生效。

Fastlane證書管理(二):match

  1. 從倉庫克隆cert和profile 通過:git_url指定git倉庫的地址,預設情況是克隆master分支,可通過:git_branch指定分支。如果在同一個倉庫中管理多個team,可使用不同的分支來儲存不同的team。 克隆完畢之後,整個庫會被儲存在一個臨時地址中,庫的檔案結構如下圖所示
-certs
  -enterprise
    -#{cert_id}.cer
    -#{cert_id}.p12

  -development
    -#{cert_id}.cer
    -#{cert_id}.p12

  -distribution
    -#{cert_id}.cer
    -#{cert_id}.p12

-profiles
  -enterprise
    -InHouse_#{bundleID}.mobileprovision

  -appstore
    -AppStore_#{bundleID}.mobileprovision

  -adhoc
    -AdHoc_#{bundleID}.mobileprovision

  -development
    -Development_#{bundleID}.mobileprovision
複製程式碼

上述檔案結構列出了certs/profiles/目錄中所有可能的子目錄,具體使用哪個子目錄,則是由:type指定,比如在使用企業賬號時,且:type等於enterprise,則certs目錄下會有一個enterprise子資料夾。 cert和profile檔案的命名必須按照上述格式,否則match會識別不出來。

:type與子目錄名對照表

type certs/下子目錄名 profiles/下子目錄名
enterprise enterprise enterprise
appstore distribution appstore
adhoc distribution adhoc
development development development

倉庫中儲存的cert和profile檔案都被OpenSSL加密過,所以克隆下來之後的第一件事就是解密,這時match需要一個密碼用來解密,可以通過環境變數MATCH_PASSWORD來指定,如果沒有指定,則match會嘗試去鑰匙鏈的密碼列表中尋找名稱為match_#{:git_url}的鑰匙串項,如果仍然沒有,則需要使用者手動輸入。在CI環境中,最好事先使用環境變數MATCH_PASSWORD設定好。

match使用類似下列終端命令的程式碼來加解密

#加密
openssl aes-256-cbc -k "<password>" -in "<fileYouWantToEncryptPath>" -out "<encryptedFilePath>" -a -e
#解密
openssl aes-256-cbc -k "<password>" -in "<fileYouWantToDecryptPath>" -out "<decryptedFilePath>" -a -d
複製程式碼

如果cert和profile已建立好,可以使用上述命令加密下載的cert和profile,然後上傳到git倉庫。

  1. 獲取bundleIDs 通過:app_identifier來指定bundleID,如果有多個bundleID,可以通過逗號分隔。 git倉庫的同一個分支中,可以存放多個app的profile,因為profile檔名中帶有bundleID,所以可以通過檔名來區分不同的app的profile。

  2. 從倉庫獲取cert 首先,根據:type指定的型別,假設其值為enterprise,則match遍歷倉庫的/certs/enterprise/目錄下的所有檔案,將檔名符合*.cer格式的最後一個當做簽名證書,將檔名符合*.p12格式的最後一個當做其對應私鑰。 3.1 如果簽名證書和其私鑰都存在,則將簽名證書的檔名去掉副檔名,剩餘部分作為此證書的id。 3.2 如果簽名證書或其私鑰不存在,則異常退出。 (其詳細流程可檢視本文的第3小節)

  3. 安裝證書到鑰匙鏈 match使用如下命令將[步驟3]中獲取的證書和其私鑰分別安裝到鑰匙鏈中

# certificate_path 表示要匯入證書的路徑
# keychain_path 表示鑰匙鏈的路徑,一般是`~/Library/Keychains/login.keychain-db`
# certificate_password 表示證書的密碼,預設是空字串,通過`cert`建立的證書的密碼為空
# -T usr/bin/codesign 表示使用`usr/bin/codesign`訪問這個證書的時候不需要授權,也就是不需要輸入鑰匙鏈的密碼,使用xcodebuild打包app的使用會使用這個命令
security import certificate_path -k keychain_path -P certificate_password -T /usr/bin/codesign -T /usr/bin/security
複製程式碼
  1. 從倉庫獲取profile 和[步驟3]類似,首先,根據:type指定的型別,假設其值為enterprise,則match遍歷倉庫的/profiles/enterprise/目錄下的所有檔案,將檔名符合InHouse_#{bundleID}.mobileprovision格式的最後一個作為要使用的profile。 5.1 profile存在,則執行[步驟6] 5.2 profile不存在,則異常退出。 (其詳細流程可檢視本文的第4小節)

  2. 安裝profile到xcode 將[步驟5]中獲取的profile檔案複製到~/Library/MobileDevice/Provisioning Profiles/目錄下,檔名為#{uuid}.mobileprovision,其中uuid是profile的uuid

  3. 然後正常退出

注意,在獲取cert和其私鑰時,match只是粗略的通過副檔名來做篩選,並沒有驗證證書和其私鑰是否是一一對應的,所以不要把兩套cert放在同一個子目錄下。同理,在獲取profile時,也沒有驗證cert和profile中關聯的cert是否是同一個簽名證書。所以可能出現一種情況,macth執行成功,但是app打包不成功。當然,如果你沒有手動修改git倉庫,只通過match來建立和更新,則不會出現這種情況。

2.2 非只讀模式

:readonly的值是false時,如果git倉庫中沒有找到可用的cert和profile,則match會從AppleID賬號中建立新的。

Fastlane證書管理(二):match

  1. 從倉庫克隆cert和profile

  2. 登入AppleID和選擇teamID

  3. 檢測type 當:type的值是enterprise,但你使用的AppleID賬號不是一個企業賬號時,異常退出。

  4. 獲取bundleIDs

  5. 檢測bundleIDs的可用性 遍歷bundleIDs,如果在AppleID賬號中不存在對應App ID,則異常退出,只要有一個不存在就會異常退出。

  6. 獲取cert 首先嚐試從git倉庫獲取cert,其具體流程和[2.1節的步驟3]完全一樣,如果git倉庫中沒有,則嘗試從AppleID賬號中建立一個新的簽名證書。 為了實現建立新的證書這一功能,match呼叫了cert這個Tool,並設定cert:force引數的值為true來強制建立,而不管本地鑰匙鏈中是否存在cert。如果建立成功,則下載建立的cert和其對應私鑰到git倉庫的子目錄certs/cert_type中。 (呼叫cert的詳細流程可檢視cert和sigh,本步驟的詳細流程可檢視本文的第3小節)

  7. 安裝cert到鑰匙鏈

  8. 檢測cert可用性 檢測在[步驟6]中獲取的cert是否存在於AppleID賬號中,具體而言就是比較cert和AppleID賬號中獲取的cert的唯一識別符號是否一致。 從步驟6可知,有兩個途徑獲取cert,git倉庫和AppleID賬號。從AppID賬號中下載的cert肯定是沒問題的,這一步主要是驗證從git倉庫中得到的cert的唯一識別符號的可用性。上文中有提到,在git倉庫中獲取的cert的唯一識別符號就是這個cert去掉了副檔名之後的檔名。

  9. 獲取profile 和[步驟6]類似,首先嚐試從git倉庫獲取profile,如果git倉庫中沒有,則嘗試從AppleID賬號中建立一個新的profile。 假設:type的值為enterprise,從git倉庫中獲取profile的具體流程是,遍歷倉庫中/profiles/enterprise/目錄下的所有檔名符合InHouse_#{bundleID}.mobileprovision格式的profile檔案,如果這個profile存在於AppleID賬號中,則返回這個profile。 為了實現建立新的profile這一功能,match呼叫了sigh這個Tool,並設定sigh:force引數的值為true來強制建立,而不管AppleID賬號中是否已存在profile。同時,也指定了sigh:cert_id引數的值為[步驟6]中獲取的cert的唯一識別符號。 (呼叫sigh的詳細流程可檢視cert和sigh,本步驟的詳細流程可檢視本文的第4小節)

  10. 安裝profile到xcode

  11. 提交cert和profile到倉庫 如果在[步驟6]建立了新的cert或在[步驟9]中建立新的profile,則需要將這些新建立的檔案新增到倉庫,並推送的遠端倉庫中。

3. 獲取cert

下圖是獲取cert的詳細執行流程

Fastlane證書管理(二):match

4. 獲取profile

下圖是獲取profile的詳細執行流程

Fastlane證書管理(二):match

相關文章