Mac开发-公证流程记录Notarizaiton-附带脚本

公证

macOS 中包含一项名为“门禁”的技术,旨在确保只有受信任的软件才能在 Mac 上运行,对于mac应用,我们需要进行公证才能避免App无法打开,或者是来自身份不明的开发者等等提示。
关于门禁技术 https://support.apple.com/zh-cn/HT202491


打开App的几种提示

如果您的 Mac 设置为允许安装来自 App Store 和被认可开发者的应用,则第一次启动来自被认可开发者的应用时,Mac 会询问您是否确定要打开这个应用。

经过 Apple 公证的应用表示已经通过了安全检查:
在这里插入图片描述
没有经过公证的应用会显示一个黄色警告图标:
在这里插入图片描述
或者没有签名时(例如Archive时选择Development)直接提示
在这里插入图片描述


App的配置

对于苹果官方 对您的 Mac 软件进行公证以在 macOS Catalina 中运行
的说明
在这里插入图片描述

  1. 使用Developer ID进行签名,即选择的证书类型为 Developer ID,不上架的Mac应用
  2. 使用强化版运行时 Enable hardened runtime
    在工程的Capabilities中选中即可
    在这里插入图片描述
    值得注意的是,如果你的Mac应用使用了其他的App,例如更新工具 Updater.app ,那么同样这个Updater也需要配置强化运行时。
  3. 通过第二步生出的xxxx.entitlements文件中 添加 com.apple.security.get-task-allow 值为YES

Warning!!!!:开启Enable hardened runtime会导致你的app权限获取变化,你需要重新添加app权限来防止开启摄像头等操作时在10.15上的崩溃问题 见 https://blog.csdn.net/shengpeng3344/article/details/103558765


Xcode公证流程

Xcode操作

使用Xcode 10以上版本可以公证,如果同时安装了多个Xcode,则需要切换命令行为Xcode10
sudo xcode-select -s /path/xcode10.app

使用Archive即可进行公证 选中xcode上方菜单->Product->Archive
然后弹出Organizer窗口,如果不小心关掉了,这个窗口可以通过 选中xcode上方菜单->Window->Organizer来进行打开,里面有所有的Archive记录。
在这里插入图片描述
选中你的macOS Apps

关于多 target 应用 archive 除开,可能不属于 iOS App, 也不属于 macOS App,变成了Other Items。
此时,设置主target 外其他target 的 Skip Install 为 YES 即可。

选择Distribute App,选择Developer ID方式
在这里插入图片描述
然后选择Upload,即发送给苹果进行公证,而Export则是直接导出,命令行进行公证时可以选择Export
在这里插入图片描述
这里如果需要选择自己的证书则使用手动Manually,多个证书的时候但求准确
在这里插入图片描述
选择Upload即可
在这里插入图片描述
随后弹出的界面就是让你等待公证结束,一般都很快,我几分钟就完了,公证完成后xcode会给你提示。
完成后,右下角会出现StatusReadv to distribute,即表示完成
在这里插入图片描述
点击Export Notarized App即可以导出公证后的App


确保你的App公证成功

  1. 确保你的安全性隐私设置如下
    在这里插入图片描述
    且是10.14以上的系统。
  2. 命令行输入 spctl -a -v xxxx.app
  3. 如果App被正确签名和公证,输出为:
./TrackMix.app: accepted
source=Notarized Developer ID
  1. 如果App被正确签名但未被公证,输出为:
./TrackMix.app: accepted
source=Developer ID

这里在我的10.13.6系统中无法验证是否Notarized,无论怎么验证都是步骤4,而在最新10.15的系统中验证为步骤3,所以使用低版本mac os 验证的小伙伴不要惊慌。

  1. 对于pkg包的公证权限验证要使用
    spctl -v -a --type install xxx.pkg

观看上传日志

在这里插入图片描述
选择右侧的Show status log即可查看你的上传日志,如果有必要,点击“上传失败”旁边的“感叹号三角”,查看发生的错误。

这里贴出官方文档,很详细!权威嘛!
https://help.apple.com/xcode/mac/current/#/dev88332a81e


脚本公证

关于脚本流程官网有说明 Customizing the Notarization Workflow
但由于我使用场景的差异,在Acrhive中的配置写脚本并不符合我的使用场景,虽然很方便,如下图,值得借鉴吧,不说我还不知道有这玩意,哈哈
在这里插入图片描述


打包并导出

#! /bin/bash
# Type a script or drag a script file from your workspace to insert its path.

echo "####### Webcast Archive and Notarization Script / Webcast打包公证脚本 #######"
#Webcast打包公证脚本
PRODUCT_NAME="Webcast"
#进入当前文件路径 - 请放置在Webcast工程文件路径下
CURRENT_DIR=$(dirname $0)
cd CURRENT_DIR
echo "当前脚本路径为:$CURRENT_DIR"

PROJECT_PATH="$CURRENT_DIR/$PRODUCT_NAME.xcodeproj"

if [ ! -d $PROJECT_PATH ]; then
	echo "Archive and Notarization Failed : $PROJECT_PATH not exist"
    exit 1
fi

echo "####### Webcast Archive and Notarization Script / 开始打包流程 #######"

CONFIGURATION="Release"
TARGET="Webcast"

EXPORT_PATH="$CURRENT_DIR/Export"
APP_PATH="$EXPORT_PATH/$PRODUCT_NAME.app"
ZIP_PATH="$EXPORT_PATH/$PRODUCT_NAME.zip"
ARCHIVE_PATH=$EXPORT_PATH/${TARGET}.xcarchive

rm -r "$EXPORT_PATH"
mkdir "$EXPORT_PATH"
if [ -d $EXPORT_PATH ];then
    echo "EXPORT_PATH=$EXPORT_PATH"
fi

xcodebuild archive -project "$PROJECT_PATH"  -scheme "Webcast" -configuration "$CONFIGURATION" -archivePath "$ARCHIVE_PATH" || { echo "Archive and Notarization Failed : xcodebuild archive action failed"; exit 1; }
# 关于动态库的引用关系修改问题,使用install_name_tool指令,由于在工程中附带了脚本进行处理,这里没有写

xcodebuild -exportArchive -archivePath "$ARCHIVE_PATH" -exportOptionsPlist "$CURRENT_DIR/ExportOptions.plist" -exportPath "$EXPORT_PATH"

这里使用xcodebuild进行acrhive和导出app包


ExportPlist文件设置

这里需要注意的是ExportPilist文件的设置,如果设置为upload,是会自动进行公证的。
这里设置为export
在这里插入图片描述
这里的teamID就是你的证书的标识
在这里插入图片描述
就是钥匙串中,图中红色笔的部分啦
这里给一个示例 https://github.com/shengpeng3344/Apple-Mac-Notarized-script/blob/master/ExportOptions.plist


压缩文件

1.zip

因为您不能直接将.app包上传到公证服务,所以您需要创建一个包含该应用程序的压缩存档,当使用pkg时可以不用打成zip

# 因为您不能直接将.app包上传到公证服务,所以您需要创建一个包含该应用程序的压缩存档,当使用pkg时可以忽略
ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"

2.pkg

这里涉及到packges打包pkg的流程 https://blog.csdn.net/shengpeng3344/article/details/103375025

VERSION="5.8.3"
PKGPROJ_PATH=$CURRENT_DIR/Webcast.pkgproj
# packges build command line
/usr/local/bin/packagesbuild --package-version ${VERSION} ${PKGPROJ_PATH}

FINAL_PKG="$EXPORT_PATH/${TARGET}_$VERSION.pkg"
# 需要配置你的installer证书
productsign --sign "Developer ID Installer: Yan Kang (6GHP23DFJR)" $EXPORT_PATH/${TARGET}.pkg $FINAL_PKG || { echo "Archive and Notarization Failed : pkg product sign failed"; exit 1; }
# 移除旧的,未签名的pkg文件
rm $EXPORT_PATH/${TARGET}.pkg
echo "最终打包的pkg为:$FINAL_PKG"
echo "####### Webcast Archive and Notarization Script / 完成打包流程 #######"

命令行公证

使用xcrun altool --notarize-app命令即可进行公证。

$ xcrun altool --notarize-app
               --primary-bundle-id "com.example.ote.zip"
               --username "AC_USERNAME"
               --password "@keychain:AC_PASSWORD"
               --asc-provider <ProviderShortname>
               --file OvernightTextEditor_11.6.8.zip
echo "####### Webcast Archive and Notarization Script / 开始公证流程 #######"

xcrun altool --notarize-app --primary-bundle-id "com.xxxx.xxxx" --username "appledev@xxxx.com" --password "cgki-xxxx-xxxx-amvx" --file $FINAL_PKG

请求成功后会返回一串字符 RequestUUID

gensees-iMac-2:~ gensee$ xcrun altool --notarize-app --primary-bundle-id "com.xxx.xxxx" --username "appledev@xxxx.com" --password "cgki-xxxx-jdhu-amvx" --file /Users/gensee/Documents/SVN/uniclient/webcast/osx/Export/Webcast_5.8.3.pkg 
2019-12-04 09:38:58.049 altool[50044:950440] No errors uploading '/Users/gensee/Documents/SVN/uniclient/webcast/osx/Export/Webcast_5.8.3.pkg'.
RequestUUID = b70fe4a2-689d-436d-be3e-3cf63e5276a3

错误信息

  • 上次缓存未清除
    有时候我们上传一般终止,再次进行上传时,无论如何打包,clean,都无法再次上传成功了,大部分的错误信息可以通过输出的tmp文件找出原因,所以输出到文件很有必要

    缓存问题删除此目录下的缓存文件即可
    rm "${HOME}/Library/Caches/com.apple.amp.itmstransporter/UploadTokens/*"


关于密码

注意,password 后面接的密码,并非AppleID 账号密码。需要到 https://appleid.apple.com 重生成,如下图所示
在这里插入图片描述
官方文档说明 https://support.apple.com/en-us/HT204397


查看公证结果

根据request uuid查询

xcrun altool --notarization-info b70fe4a2-689d-436d-be3e-3cf63e5276a3 --username "appledev@xxxx.com" --password "cgki-xxxx-xxxx-amvx"
结果如下

2019-12-04 10:03:13.863 altool[50277:971551] No errors getting notarization info.

   RequestUUID: b70fe4a2-689d-436d-be3e-3cf63e5276a3
          Date: 2019-12-04 01:38:58 +0000
        Status: success
    LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma123/v4/1f/b4/8a/1fb48aa6-1abe-1294-6ce1-eeae4e54d9cc/developer_log.json?accessKey=1575619393_6818351456719557549_ixcbnih6TRyFzuQBc%2B9okeORgK%2FN01NZ3bZj%2BTrLTnCaWMERm5TF%2BG0Ccet2h7TeV36UeFwBCDpk7MshcmaxJfR8cp9uEhN1S%2FxIxdd49zZ8AR0ia%2FS6NeTMTMhy2JDWFH2hR1xEpfE0p4v0lzwWjl4oIwe%2BjNvsvMrORKy9s2Q%3D
   Status Code: 0
Status Message: Package Approved

查看全部记录

使用xcrun altool --notarization-history 0来查看公证结果
xcrun altool --notarization-history 0 --username "appledev@xxxx.com" --password "cgki-xxxx-xxxx-amvx"
会以时间最新的排在最前,且默认为第一页。

gensees-iMac-2:~ gensee$ xcrun altool --notarization-history 0 --username "appledev@xxx.com" --password "cgki-xxxx-xxxx-amvx"

Notarization History - page 0

Date                      RequestUUID                          Status      Status Code Status Message   
------------------------- ------------------------------------ ----------- ----------- ---------------- 
2019-12-04 01:38:58 +0000 b70fe4a2-689d-436d-be3e-3cf63e5276a3 success     0           Package Approved 
2019-12-03 15:09:36 +0000 eda062a8-b0c4-4db3-bd29-aadd7bdaef1e in progress                              
2019-12-03 13:42:16 +0000 30d82b34-c071-41bb-a351-552cecf9f1de in progress                              
2019-12-03 13:02:24 +0000 e153878f-8ed8-4b21-9f57-a3e6131d7a1a in progress                              
2019-12-03 06:41:15 +0000 96e76982-d874-45c6-9e36-868e30fb70a6 in progress                              
2019-12-03 02:32:50 +0000 b4d742df-2bbb-454e-81ad-18c9c57d86b5 success     0           Package Approved 
2019-10-16 04:16:56 +0000 11a9ef2e-225c-49fd-a37c-73d1d00dc4d2 success     0           Package Approved 
2019-10-14 11:26:28 +0000 fc4884fa-e903-45ab-b600-f4c689b9276e success     0           Package Approved 
2019-10-14 10:47:22 +0000 57a7a114-a98d-40ce-beaf-b72945c9230e success     0           Package Approved 

Next page value: 1571050042000

给包订上公证票据

公证处会生成一个票据,告诉Gatekeeper你的应用程序已经公证处了。公证成功后,下次任何用户试图在macOS 10.14或更高版本上运行您的应用程序时,Gatekeeper会在网上找到票。这包括在公证前下载了你的应用程序的用户。

我们最好给包进行stapler,这样离线也可以使用。
xcrun stapler staple "Overnight TextEditor.app"

对于zippkg这种打包的文件,我们需要对子文件逐个进行stapler才能达到效果。

如果需要显示tiket的更多信息使用-v
xcrun stapler staple -v abc.pkg


如何定时查询状态

这里我是使用sleep方法加上while循环,来每1min获取下公证结果。

function uploadFileAndNotarized()
{
	echo "start notarized $1 ..."
	xcrun altool --notarize-app --primary-bundle-id "com.xxxx.xxxx" --username "appledev@xxxx.com" --password "cgki-xxxx-xxxx-amvx" --file $1 &> tmp
	# 从日志文件中读取UUID,并隔一段时间检查一次公证结果
	# 只有成功的格式是 RequestUUID = 
	uuid=`cat tmp | grep -Eo 'RequestUUID = [[:alnum:]]{8}-([[:alnum:]]{4}-){3}[[:alnum:]]{12}' | grep -Eo '[[:alnum:]]{8}-([[:alnum:]]{4}-){3}[[:alnum:]]{12}' | sed -n "1p"`
	# 如果上传过了,则会返回 The upload ID is 
	if [[ "$uuid" == "" ]];then
		uuid=`cat tmp | grep -Eo 'The upload ID is [[:alnum:]]{8}-([[:alnum:]]{4}-){3}[[:alnum:]]{12}' | grep -Eo '[[:alnum:]]{8}-([[:alnum:]]{4}-){3}[[:alnum:]]{12}' | sed -n "1p"`
		echo "The software asset has already been uploaded. The upload ID is $uuid"
	fi
	echo "notarization UUID is $uuid"
	# 即没有上传成功,也没有上传过,则退出
	if [[ "$uuid" == "" ]]; then
		echo "No success no uploaded, unknown error"
		cat tmp  | awk 'END {print}'
		return 1
	fi
	
	while true; do
	    echo "checking for notarization..."
	 
	    xcrun altool --notarization-info "$uuid" --username "appledev@xxxx.com" --password "cgki-xxxx-xxxx-amvx" &> tmp
	    r=`cat tmp`
	    t=`echo "$r" | grep "success"`
	    f=`echo "$r" | grep "invalid"`
	    if [[ "$t" != "" ]]; then
	        echo "notarization done!"
	        xcrun stapler staple "$1"
	        # xcrun stapler staple "Great.dmg"
	        echo "stapler done!"
	        break
	    fi
	    if [[ "$f" != "" ]]; then
	        echo "Failed : $r"
	        return 1
	    fi
	    echo "not finish yet, sleep 1min then check again..."
	    sleep 60
	done
	return 0
}

最后附上脚本,需要修改的参数有证书idpassword以及工程名等等。

脚本下载 https://github.com/shengpeng3344/Apple-Mac-Notarized-script


几种打包格式

App

对于App格式的开发包,直接压缩成zip然后进行公证即可。


pkg

  1. 对于pkg包的公证权限验证要使用
    spctl -v -a --type install xxx.pkg
  2. pkg的installer证书和app的开发ID证书不是一个账号的行不行?
    答案是可行的,和证书无关,只要经过了公证即可
  3. 公证pkg后,里面的app是否会自动公证?
    并不会,检测pkg是已经公证并签名,但是app包没有公证。但是!确是可以正常使用的,就是使用pkg不会提示警告,但是如果你将pkg解压,将获得的app通过邮件分发到其他人,那么又会提示是非公证应用了,即显示感叹号,提示:无法打开"xxxxxx",因为Apple无法检查其是否包含恶意软件
    对于这个说法苹果官方是这样说明的:

Important
If you distribute your software via a custom third-party installer, you need two rounds of notarization. First you notarize the installer’s payload (everything the installer will install). You then package the notarized (and stapled, as described in Staple the Ticket to Your Distribution) items into the installer and notarize it as you would any other executable. If you use a network installer, separately notarize both the installer and the items it downloads.

官方链接见这里
即需要经过两遍公证。


dmg

dmg的开发包不需要公证,Apple的Gatekeeper可以检测到DMG中的经过公证的.app文件,并且可以让用户正常打开App
但如果里面是pkg文件也是一样的,只要通过公证即可。


脚本下载

https://github.com/shengpeng3344/Apple-Mac-Notarized-script


参考文章
macOS 开发 - Notarization 公证你的 Developer ID
应用

Customizing the Notarization Workflow
苹果官方帮助文档

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页