Fastlane证书管理(二):match

作者: wangzzzzz | 来源:发表于2018-04-23 16:49 被阅读828次

    1. 前言

    match这个Tool的作用可以分为两步

    1. 获取合适的cert和profile
    2. 将获取的cert和profile安装到本机

    其简单流程如下图所示


    • 首先,从: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不会生效。

    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账号中创建新的。

    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的详细执行流程


    3. 获取profile

    下图是获取profile的详细执行流程


    相关文章

      网友评论

        本文标题:Fastlane证书管理(二):match

        本文链接:https://www.haomeiwen.com/subject/eymflftx.html