Mac APP 公正,苹果公正, Apple Notarization

Notarize a Command Line Tool

经过初浅的Google 翻译:

macOS 10.15 Catalina 要求 应用程序和工具 需要经过公证。

Developer ID Certificates

要在App Store之外分发二进制文件(应用程序和命令行工具),您需要“开发者ID应用程序”证书。要签署安装程序包以在Mac App Store之外分发,您需要提供“开发人员ID安装程序”证书。

如果尚未创建它们,则可以在Xcode或Developer Portal中进行。如果您已经拥有证书,但在另一台Mac上,则需要导出它们,然后在新Mac上重新导入它们。创建新证书可能会使现有证书无效! 所以要当心。

在工作计算机上创建或导入证书后,您可以使用以下方法在终端中验证证书的存在:

$ security find-identity -p basic -v

此命令将列出此Mac上的所有可用证书。检查您是否可以看到“开发人员ID应用程序”和“开发人员ID安装程序”证书。如果您是多个团队的成员,则每个团队可能会看到多个证书。

您以后可以通过长十六进制数字或描述性名称来标识证书(或“身份”),例如 "Developer ID Installer: Armin Briegel (ABCD123456)"

名称末尾的十个字符代码是您的开发人员团队ID。记下它。如果您是多个开发人员团队的成员,则可以拥有多个开发人员ID证书,团队ID将帮助您区分它们。

您的开发者帐户的应用专用密码

Apple要求使用两因素身份验证保护开发者帐户。要允许需要身份验证的自动化工作流,您可以创建应用程序特定的密码。

在Apple ID门户中为您的开发人员帐户创建一个新的应用程序专用密码。

  • Apple支持:使用应用专用密码

创建密码时,只会显示密码。立即在您的钥匙串中使用以下字段创建“新密码项”:

  • 钥匙扣物品名称: Developer-altool
  • 帐户名称:您的开发者帐户电子邮件
  • 密码:您刚创建的应用专用密码

这将创建一个开发人员专用的密码项目,我们可以从工具中安全地访问该项目。

如果需要,您还可以将应用程序特定的密码存储在其他密码管理器中,但是Xcode工具具有使用“钥匙串”的特殊选项。

启用强化运行时

启用“ Hardened Runtime”将以某种方式编译二进制文件,从而使外部进程更难以注入代码。从2020年1月开始,这是成功进行公证的要求。

  1. 在更改签名选项的视图中,单击上方选项卡行中的“构建设置”
  2. 单击“全部”以显示所有可用设置
  3. 在搜索字段中输入“ enable hardened”,这将显示“ Enable Hardened Runtime”设置
  4. 将项目列(蓝色图标)中的值设置为 YES
启用强化运行时

建立pkg

命令行工具可以签名,但不能直接公证。但是,您可以对包含命令行工具的zip,dmg或pkg文件进行公证。同样,当您的工具带有正确的安装包时,对于用户和管理员来说,安装起来也容易得多。

我们可以使用pkgroot目录作为有效负载来构建安装程序包:

pkgbuild --root build/pkgroot \
           --identifier "com.example.hello" \
           --version "1.0" \
           --install-location "/" \
           --sign "Developer ID Installer: Armin Briegel (ABCD123456)" \
           build/hello-1.0.pkg

为了清楚起见,我将命令分为多行,您可以在一行中输入该命令,而无需使用行尾反斜杠\。您想用数据替换标识符,版本和签名证书的值。

对安装程序包进行公证

Xcode有一个命令行工具altool,您可以使用该工具上载工具以进行公证:

xcrun altool --notarize-app \
             --primary-bundle-id "com.example.com" \
             --username "[email protected]" \
             --password "@keychain:Developer-altool" \
             --asc-provider "ABCD123456" \
             --file "build/hello-1.0.pkg"

这username是您的开发者帐户电子邮件。

该asc-provider是你的十位数组ID。如果您只是单个团队的成员,则无需提供此信息。

密码使用一个特殊的@keychain:关键字,该关键字告诉altool您从名为的钥匙串项中获取应用程序专用的密码Developer-altool。(还记得我们之前创建的吗?)

这需要一段时间。当命令成功将pkg上传到Apple的公证服务器时,它将返回RequestUUID。您的公证请求将被排队,并最终得到处理。您可以使用以下方法检查请求的状态:

xcrun altool --notarization-info "Your-Request-UUID" \
             --username "[email protected]" \                                    
             --password "@keychain:Developer-altool"

该过程完成后,Apple还将向您的开发人员帐户发送电子邮件。我的经验很少会花费一两分钟以上的时间。(在中欧时区可能是一个优势)。该过程完成后,您可以运行上面的notarization-info命令以获取一些详细信息。该信息将包含一个包含更多信息的链接,当您的请求被拒绝时,该链接将非常有用。

请注意,信息链接会在24小时左右后失效。您应该复制任何您想要保留的信息。

验证成功后的邮件


验证成功后的邮件

完成流程

除了确认或拒绝您的请求外,您不会从Apple得到任何回报。Mac下载您的安装程序包并验证其公证状态时,它将与Apple的公证服务器联系,他们将确认或拒绝该状态。

如果Mac当前处于脱机状态,或者位于阻止访问Apple服务器的代理或防火墙之后,则它无法验证您的pkg文件是否已经过公证。

但是,您可以将公证单“装订”到pkg文件,因此客户端不需要连接到服务器:

xcrun stapler staple build/hello-1.0.pkg

您还可以stapler用来验证过程是否顺利:

xcrun stapler validate build/hello-1.0.pkg

但由于stapler取决于要安装的开发人员工具,因此通常应首选spctl检查公证:

spctl --assess -vvv --type install build/hello-1.0.pkg

流程自动化

显然,我构建了一个脚本来自动化所有这些。将以下脚本放在项目文件夹的根目录中,使用您的信息在脚本的开头(第20-38行)修改变量,然后运行它。

该脚本将构建该工具,创建一个已签名的pkg,将其上传以进行公证,等待结果,然后装订pkg。

#!/bin/zsh

# pkgAndNotarize.sh

# 2019 - Armin Briegel - Scripting OS X

# place a copy of this script in in the project folder
# when run it will build for installation,
# create a pkg from the product,
# upload the pkg for notarization and monitor the notarization status

# before you can run this script:
# - set release signing of the tool to 'Developer ID Application'
# - enable the hardened run-time
# - change the 'Installation Build Products Location' to `$SRCROOT/build/pkgroot`
# 
# you want to add the `build` subdirectory to gitignore


# put your dev account information into these variables

# the email address of your developer account
dev_account="[email protected]"

# the name of your Developer ID installer certificate
signature="Developer ID Installer: First Last (ABCD123456)"

# the 10-digit team id
dev_team="ABCD123456"

# the label of the keychain item which contains an app-specific password
dev_keychain_label="Developer-altool"


# put your project's information into these variables
version="1.0"
identifier="com.example.hello"
productname="Hello"


# code starts here

projectdir=$(dirname $0)

builddir="$projectdir/build"
pkgroot="$builddir/pkgroot"


# functions
requeststatus() { # $1: requestUUID
    requestUUID=${1?:"need a request UUID"}
    req_status=$(xcrun altool --notarization-info "$requestUUID" \
                              --username "$dev_account" \
                              --password "@keychain:$dev_keychain_label" 2>&1 \
                 | awk -F ': ' '/Status:/ { print $2; }' )
    echo "$req_status"
}

notarizefile() { # $1: path to file to notarize, $2: identifier
    filepath=${1:?"need a filepath"}
    identifier=${2:?"need an identifier"}
    
    # upload file
    echo "## uploading $filepath for notarization"
    requestUUID=$(xcrun altool --notarize-app \
                               --primary-bundle-id "$identifier" \
                               --username "$dev_account" \
                               --password "@keychain:$dev_keychain_label" \
                               --asc-provider "$dev_team" \
                               --file "$filepath" 2>&1 \
                  | awk '/RequestUUID/ { print $NF; }')
                               
    echo "Notarization RequestUUID: $requestUUID"
    
    if [[ $requestUUID == "" ]]; then 
        echo "could not upload for notarization"
        exit 1
    fi
        
    # wait for status to be not "in progress" any more
    request_status="in progress"
    while [[ "$request_status" == "in progress" ]]; do
        echo -n "waiting... "
        sleep 10
        request_status=$(requeststatus "$requestUUID")
        echo "$request_status"
    done
    
    # print status information
    xcrun altool --notarization-info "$requestUUID" \
                 --username "$dev_account" \
                 --password "@keychain:$dev_keychain_label"
    echo 
    
    if [[ $request_status != "success" ]]; then
        echo "## could not notarize $filepath"
        exit 1
    fi
    
}


# build clean install

echo "## building with Xcode"
xcodebuild clean install -quiet


# check if pkgroot exists where we expect it
if [[ ! -d $pkgroot ]]; then
    echo "couldn't find pkgroot $pkgroot"
    exit 1
fi

## build the pkg

pkgpath="$builddir/$productname-$version.pkg"

echo "## building pkg: $pkgpath"

pkgbuild --root "$pkgroot" \
         --version "$version" \
         --identifier "$identifier" \
         --sign "$signature" \
         "$pkgpath"

# upload for notarization
notarizefile "$pkgpath" "$identifier"

# staple result
echo "## Stapling $pkgpath"
xcrun stapler staple "$pkgpath"

echo '## Done!'

# show the pkg in Finder
open -R "$pkgpath"

exit 0

链接和视频

这些链接和视频,特别是霍华德·奥克利(Howard Oakley)的帖子以及汤姆·布里奇(Tom Bridge)的PSU演示文稿,都非常有用。也要感谢同事阿诺德(Arnold)向我展示了这一点甚至是可能的

  • 霍华德·奥克利(Howard Oakley):为Catalina构建和交付命令工具
  • 汤姆·布里奇(Tom Bridge):PSU会议讨论与跟进
  • Apple支持:为macOS Catalina公证Mac软件
  • Apple支持:使用应用专用密码
  • Apple Developer:分发前对您的应用程序进行公证
  • WWDC 2019:关于公证的一切
  • WWDC 2019:macOS安全性方面的进步
  • Apple Developer:解决常见的公证问题
  • Apple Developer: Customizing the Notarization Workflow

你可能感兴趣的:(Mac APP 公正,苹果公正, Apple Notarization)