Mac APP 公正,蘋(píng)果公正, Apple Notarization

Notarize a Command Line Tool

經(jīng)過(guò)初淺的Google 翻譯:

macOS 10.15 Catalina 要求 應(yīng)用程序和工具 需要經(jīng)過(guò)公證。

Developer ID Certificates

要在App Store之外分發(fā)二進(jìn)制文件(應(yīng)用程序和命令行工具),您需要“開(kāi)發(fā)者ID應(yīng)用程序”證書(shū)。要簽署安裝程序包以在Mac App Store之外分發(fā),您需要提供“開(kāi)發(fā)人員ID安裝程序”證書(shū)。

如果尚未創(chuàng)建它們,則可以在XcodeDeveloper Portal中進(jìn)行。如果您已經(jīng)擁有證書(shū),但在另一臺(tái)Mac上,則需要導(dǎo)出它們,然后在新Mac上重新導(dǎo)入它們。創(chuàng)建新證書(shū)可能會(huì)使現(xiàn)有證書(shū)無(wú)效! 所以要當(dāng)心。

在工作計(jì)算機(jī)上創(chuàng)建或?qū)胱C書(shū)后,您可以使用以下方法在終端中驗(yàn)證證書(shū)的存在:

$ security find-identity -p basic -v

此命令將列出此Mac上的所有可用證書(shū)。檢查您是否可以看到“開(kāi)發(fā)人員ID應(yīng)用程序”和“開(kāi)發(fā)人員ID安裝程序”證書(shū)。如果您是多個(gè)團(tuán)隊(duì)的成員,則每個(gè)團(tuán)隊(duì)可能會(huì)看到多個(gè)證書(shū)。

您以后可以通過(guò)長(zhǎng)十六進(jìn)制數(shù)字或描述性名稱(chēng)來(lái)標(biāo)識(shí)證書(shū)(或“身份”),例如 "Developer ID Installer: Armin Briegel (ABCD123456)"

名稱(chēng)末尾的十個(gè)字符代碼是您的開(kāi)發(fā)人員團(tuán)隊(duì)ID。記下它。如果您是多個(gè)開(kāi)發(fā)人員團(tuán)隊(duì)的成員,則可以擁有多個(gè)開(kāi)發(fā)人員ID證書(shū),團(tuán)隊(duì)ID將幫助您區(qū)分它們。

您的開(kāi)發(fā)者帳戶(hù)的應(yīng)用專(zhuān)用密碼

Apple要求使用兩因素身份驗(yàn)證保護(hù)開(kāi)發(fā)者帳戶(hù)。要允許需要身份驗(yàn)證的自動(dòng)化工作流,您可以創(chuàng)建應(yīng)用程序特定的密碼。

在Apple ID門(mén)戶(hù)中為您的開(kāi)發(fā)人員帳戶(hù)創(chuàng)建一個(gè)新的應(yīng)用程序?qū)S妹艽a。

創(chuàng)建密碼時(shí),只會(huì)顯示密碼。立即在您的鑰匙串中使用以下字段創(chuàng)建“新密碼項(xiàng)”:

  • 鑰匙扣物品名稱(chēng): Developer-altool
  • 帳戶(hù)名稱(chēng):您的開(kāi)發(fā)者帳戶(hù)電子郵件
  • 密碼:您剛創(chuàng)建的應(yīng)用專(zhuān)用密碼

這將創(chuàng)建一個(gè)開(kāi)發(fā)人員專(zhuān)用的密碼項(xiàng)目,我們可以從工具中安全地訪問(wèn)該項(xiàng)目。

如果需要,您還可以將應(yīng)用程序特定的密碼存儲(chǔ)在其他密碼管理器中,但是Xcode工具具有使用“鑰匙串”的特殊選項(xiàng)。

啟用強(qiáng)化運(yùn)行時(shí)

啟用“ Hardened Runtime”將以某種方式編譯二進(jìn)制文件,從而使外部進(jìn)程更難以注入代碼。從2020年1月開(kāi)始,這是成功進(jìn)行公證的要求。

  1. 在更改簽名選項(xiàng)的視圖中,單擊上方選項(xiàng)卡行中的“構(gòu)建設(shè)置”
  2. 單擊“全部”以顯示所有可用設(shè)置
  3. 在搜索字段中輸入“ enable hardened”,這將顯示“ Enable Hardened Runtime”設(shè)置
  4. 將項(xiàng)目列(藍(lán)色圖標(biāo))中的值設(shè)置為 YES
啟用強(qiáng)化運(yùn)行時(shí)

建立pkg

命令行工具可以簽名,但不能直接公證。但是,您可以對(duì)包含命令行工具的zip,dmg或pkg文件進(jìn)行公證。同樣,當(dāng)您的工具帶有正確的安裝包時(shí),對(duì)于用戶(hù)和管理員來(lái)說(shuō),安裝起來(lái)也容易得多。

我們可以使用pkgroot目錄作為有效負(fù)載來(lái)構(gòu)建安裝程序包:

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

為了清楚起見(jiàn),我將命令分為多行,您可以在一行中輸入該命令,而無(wú)需使用行尾反斜杠\。您想用數(shù)據(jù)替換標(biāo)識(shí)符,版本和簽名證書(shū)的值。

對(duì)安裝程序包進(jìn)行公證

Xcode有一個(gè)命令行工具altool,您可以使用該工具上載工具以進(jìn)行公證:

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

這username是您的開(kāi)發(fā)者帳戶(hù)電子郵件。

該asc-provider是你的十位數(shù)組ID。如果您只是單個(gè)團(tuán)隊(duì)的成員,則無(wú)需提供此信息。

密碼使用一個(gè)特殊的@keychain:關(guān)鍵字,該關(guān)鍵字告訴altool您從名為的鑰匙串項(xiàng)中獲取應(yīng)用程序?qū)S玫拿艽aDeveloper-altool。(還記得我們之前創(chuàng)建的嗎?)

這需要一段時(shí)間。當(dāng)命令成功將pkg上傳到Apple的公證服務(wù)器時(shí),它將返回RequestUUID。您的公證請(qǐng)求將被排隊(duì),并最終得到處理。您可以使用以下方法檢查請(qǐng)求的狀態(tài):

xcrun altool --notarization-info "Your-Request-UUID" \
             --username "username@example.com" \                                    
             --password "@keychain:Developer-altool"

該過(guò)程完成后,Apple還將向您的開(kāi)發(fā)人員帳戶(hù)發(fā)送電子郵件。我的經(jīng)驗(yàn)很少會(huì)花費(fèi)一兩分鐘以上的時(shí)間。(在中歐時(shí)區(qū)可能是一個(gè)優(yōu)勢(shì))。該過(guò)程完成后,您可以運(yùn)行上面的notarization-info命令以獲取一些詳細(xì)信息。該信息將包含一個(gè)包含更多信息的鏈接,當(dāng)您的請(qǐng)求被拒絕時(shí),該鏈接將非常有用。

請(qǐng)注意,信息鏈接會(huì)在24小時(shí)左右后失效。您應(yīng)該復(fù)制任何您想要保留的信息。

驗(yàn)證成功后的郵件


驗(yàn)證成功后的郵件

完成流程

除了確認(rèn)或拒絕您的請(qǐng)求外,您不會(huì)從Apple得到任何回報(bào)。Mac下載您的安裝程序包并驗(yàn)證其公證狀態(tài)時(shí),它將與Apple的公證服務(wù)器聯(lián)系,他們將確認(rèn)或拒絕該狀態(tài)。

如果Mac當(dāng)前處于脫機(jī)狀態(tài),或者位于阻止訪問(wèn)Apple服務(wù)器的代理或防火墻之后,則它無(wú)法驗(yàn)證您的pkg文件是否已經(jīng)過(guò)公證。

但是,您可以將公證單“裝訂”到pkg文件,因此客戶(hù)端不需要連接到服務(wù)器:

xcrun stapler staple build/hello-1.0.pkg

您還可以stapler用來(lái)驗(yàn)證過(guò)程是否順利:

xcrun stapler validate build/hello-1.0.pkg

但由于stapler取決于要安裝的開(kāi)發(fā)人員工具,因此通常應(yīng)首選spctl檢查公證:

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

流程自動(dòng)化

顯然,我構(gòu)建了一個(gè)腳本來(lái)自動(dòng)化所有這些。將以下腳本放在項(xiàng)目文件夾的根目錄中,使用您的信息在腳本的開(kāi)頭(第20-38行)修改變量,然后運(yùn)行它。

該腳本將構(gòu)建該工具,創(chuàng)建一個(gè)已簽名的pkg,將其上傳以進(jìn)行公證,等待結(jié)果,然后裝訂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="user@example.com"

# 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)向我展示了這一點(diǎn)甚至是可能的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容