Java 和 Mojave 的强化运行时
Hardened runtime for Java and Mojave
我目前在 macOS packaged and signed using pkgbuild
上分发 Java 应用程序。
最近,Apple 警告开发者:
"In an upcoming release of macOS, Gatekeeper will require Developer ID–signed software to be notarized by Apple."
阅读公证文档后,apple warns developers:
"You must enable hardened runtime for your app to be notarized by Apple."
其中详细介绍了如何在 Xcode 中启用这些设置。但是那些不是用 Xcode 开发的应用程序呢? Xamarin/Mono have some back and forth 关于他们如何解决这个问题,但到目前为止的提交似乎集中在 Mojave 检测和 C/C++ 上。 Java 应用程序或不分发任何 C/C++/Objective-C 编译代码的应用程序呢?项目如何获得 "notarized" 以便它不会被未来的 macOS 更新阻止?
可能相关:
我正在回答这个关于需要公证的 Java 项目的问题。稍作修改后,答案也适用于其他类型的项目(python、powershell、节点)。
注意:在发布这篇文章时,Apple 的公证命令允许以下程序运行,但是随着公证和安全性变得越来越普遍并且执行得越来越严格,Apple 不可避免地会将改变和改进加固要求和程序。请根据需要进行编辑、评论或重新回答。
代码签名
- 对于普通 Java 应用程序(
.pkg
或 .app
包含脚本、jar),公证应该通过。在公证期间,Apple 将 提取 .jar
并寻找原生库。如果发现任何未签名的内容,它将被拒绝。如果没有,你没关系。使用 xcrun
进行公证的说明在下面进一步说明。
对于包含对捆绑库(.dylib
、.jnilib
)的本机调用(例如 JNI)的 Java 应用程序,每个捆绑库必须使用"Application"(例如 developerID_application.cer
)证书。
- 证书,标识符和配置文件,(单击"iOS, tvOS, watchOS"下拉菜单)macOS, 开发者 ID 申请。 (也可以说 "with Kext")。
- 如果您没有此证书,则需要使用 CSR 申请一个。就我而言,我最初只有一个用于打包安装程序的证书(而不是代码签名)。此过程可能会变得棘手,特别是如果您对两个证书使用相同的私钥。如果遇到问题,请通过命令行使用
openssl
(而不是 Keychain Access
)。
获得证书后,对每个本机库进行签名 .dylib|.jnilib|.so|bin
gets tricky。一般的想法是对本机库使用 codesign
命令,以便它以您(开发人员)的身份进行签名。语法是:
xargs codesign -s "P6DMU6694X" -v dependency.dylib
... 其中 P6DMU6694X
是唯一的开发者 ID 或确切的证书公用名(都可以)。
对于 .jar
文件,这可以是 particularly cumbersome 因为每个包都需要提取、签名然后压缩备份。
公证
一旦对本机库进行签名,就必须使用 xcrun
.
发送包进行公证
xcrun altool --eval-app --primary-bundle-id <bundle id> -u <iTunes Connect Account> -f <file path>
可能看起来像这样:
xcrun altool --eval-app --primary-bundle-id com.domain.appname -u john@domain.com -f appname.pkg
系统将提示您输入 Apple Developer 密码(不是 您用来登录 Mac 的密码。 编辑: 由于双因素已被强制执行,因此您需要为此步骤创建一个 app-specific password!
几分钟后,xcrun
命令将return一个唯一ID,可用于确定公证是否被批准。
RequestUUID = a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6
- 定期检查此唯一 ID 的状态,看看它是被批准还是被拒绝。
xcrun altool --eval-info a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6 -u john@domain.com
如果被拒绝,他们不会直接告诉你原因,你必须解析JSON响应。
LogFileURL: <a href="https://osxapps-ssl.itunes.apple.com/itunes-assets/" rel="noreferrer">https://osxapps-ssl.itunes.apple.com/itunes-assets/</a>...
阅读 JSON 并更正发现的问题。 JSON 已缩小,您可能希望通过漂亮的格式化程序 运行 它。如果没有问题,您的应用程序已经过公证并且是 Ready for distribution
.
{
"logFormatVersion": 1,
"jobId": "a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6",
"status": "Accepted",
"statusSummary": "Ready for distribution",
"statusCode": 0,
"archiveFilename": "appname.pkg",
"uploadDate": "2018-10-26T05:41:12Z",
"sha256": "e2350bda66...",
"issues" null
}
装订
最后,装订构建将确保即使在网络连接不可用时包也是可信的。
(apple.com) You should also attach the ticket to your software using the stapler tool, so that future distributions include the ticket. This ensures that Gatekeeper can find the ticket even when a network connection isn’t available. To attach a ticket to your app, use the stapler tool:
xcrun stapler staple appname.pkg
运行时间
@NaderNader 提供的额外解决方案,如果将 Java 运行 时间与 .app
捆绑在一起,则需要额外的步骤将分发标记为 runtime
使用 --option=runtime
标志,其中 P6DMU6694X
是您的签名 ID:
codesign --force --deep --options=runtime -s "P6DMU6694X" /path/to/My.app
除了上述 tresf 的回答之外,如果您的应用程序是沙箱(即使不是沙箱),那么在加载 JVM 时强化的运行时将失败。要解决这个问题,您需要在签名时为您的权利添加一些密钥。必要的权利条目如下,从 TAO ZHOU 的解决方案复制而来:https://github.com/TheInfiniteKind/appbundler/issues/39
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
这是一个简单的 shell 脚本,它将在 jar 文件中对 .so、.dylib 和 .jnilib 进行代码签名
用法:codesign_jar_script.shfilename.jar
jar tf | grep '\.so\|\.dylib\|\.jnilib' > filelist.txt
IDENTITY="your_signing_identity"
echo $IDENTITY
while read f
do
jar xf $f
codesign --force -s "$IDENTITY" -v $f
jar uf $f
rm -rf $f
done < filelist.txt
我目前在 macOS packaged and signed using pkgbuild
上分发 Java 应用程序。
最近,Apple 警告开发者:
"In an upcoming release of macOS, Gatekeeper will require Developer ID–signed software to be notarized by Apple."
阅读公证文档后,apple warns developers:
"You must enable hardened runtime for your app to be notarized by Apple."
其中详细介绍了如何在 Xcode 中启用这些设置。但是那些不是用 Xcode 开发的应用程序呢? Xamarin/Mono have some back and forth 关于他们如何解决这个问题,但到目前为止的提交似乎集中在 Mojave 检测和 C/C++ 上。 Java 应用程序或不分发任何 C/C++/Objective-C 编译代码的应用程序呢?项目如何获得 "notarized" 以便它不会被未来的 macOS 更新阻止?
可能相关:
我正在回答这个关于需要公证的 Java 项目的问题。稍作修改后,答案也适用于其他类型的项目(python、powershell、节点)。
注意:在发布这篇文章时,Apple 的公证命令允许以下程序运行,但是随着公证和安全性变得越来越普遍并且执行得越来越严格,Apple 不可避免地会将改变和改进加固要求和程序。请根据需要进行编辑、评论或重新回答。
代码签名
- 对于普通 Java 应用程序(
.pkg
或.app
包含脚本、jar),公证应该通过。在公证期间,Apple 将 提取.jar
并寻找原生库。如果发现任何未签名的内容,它将被拒绝。如果没有,你没关系。使用xcrun
进行公证的说明在下面进一步说明。 对于包含对捆绑库(
.dylib
、.jnilib
)的本机调用(例如 JNI)的 Java 应用程序,每个捆绑库必须使用"Application"(例如developerID_application.cer
)证书。- 证书,标识符和配置文件,(单击"iOS, tvOS, watchOS"下拉菜单)macOS, 开发者 ID 申请。 (也可以说 "with Kext")。
- 如果您没有此证书,则需要使用 CSR 申请一个。就我而言,我最初只有一个用于打包安装程序的证书(而不是代码签名)。此过程可能会变得棘手,特别是如果您对两个证书使用相同的私钥。如果遇到问题,请通过命令行使用
openssl
(而不是Keychain Access
)。 获得证书后,对每个本机库进行签名
.dylib|.jnilib|.so|bin
gets tricky。一般的想法是对本机库使用codesign
命令,以便它以您(开发人员)的身份进行签名。语法是:xargs codesign -s "P6DMU6694X" -v dependency.dylib
... 其中
P6DMU6694X
是唯一的开发者 ID 或确切的证书公用名(都可以)。对于
.jar
文件,这可以是 particularly cumbersome 因为每个包都需要提取、签名然后压缩备份。
- 证书,标识符和配置文件,(单击"iOS, tvOS, watchOS"下拉菜单)macOS, 开发者 ID 申请。 (也可以说 "with Kext")。
公证
一旦对本机库进行签名,就必须使用
发送包进行公证xcrun
.xcrun altool --eval-app --primary-bundle-id <bundle id> -u <iTunes Connect Account> -f <file path>
可能看起来像这样:
xcrun altool --eval-app --primary-bundle-id com.domain.appname -u john@domain.com -f appname.pkg
系统将提示您输入 Apple Developer 密码(不是 您用来登录 Mac 的密码。 编辑: 由于双因素已被强制执行,因此您需要为此步骤创建一个 app-specific password!
几分钟后,
xcrun
命令将return一个唯一ID,可用于确定公证是否被批准。RequestUUID = a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6
- 定期检查此唯一 ID 的状态,看看它是被批准还是被拒绝。
xcrun altool --eval-info a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6 -u john@domain.com
如果被拒绝,他们不会直接告诉你原因,你必须解析JSON响应。
LogFileURL: <a href="https://osxapps-ssl.itunes.apple.com/itunes-assets/" rel="noreferrer">https://osxapps-ssl.itunes.apple.com/itunes-assets/</a>...
阅读 JSON 并更正发现的问题。 JSON 已缩小,您可能希望通过漂亮的格式化程序 运行 它。如果没有问题,您的应用程序已经过公证并且是
Ready for distribution
.{ "logFormatVersion": 1, "jobId": "a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6", "status": "Accepted", "statusSummary": "Ready for distribution", "statusCode": 0, "archiveFilename": "appname.pkg", "uploadDate": "2018-10-26T05:41:12Z", "sha256": "e2350bda66...", "issues" null }
装订
最后,装订构建将确保即使在网络连接不可用时包也是可信的。
(apple.com) You should also attach the ticket to your software using the stapler tool, so that future distributions include the ticket. This ensures that Gatekeeper can find the ticket even when a network connection isn’t available. To attach a ticket to your app, use the stapler tool:
xcrun stapler staple appname.pkg
运行时间
@NaderNader 提供的额外解决方案,如果将 Java 运行 时间与 .app
捆绑在一起,则需要额外的步骤将分发标记为 runtime
使用 --option=runtime
标志,其中 P6DMU6694X
是您的签名 ID:
codesign --force --deep --options=runtime -s "P6DMU6694X" /path/to/My.app
除了上述 tresf 的回答之外,如果您的应用程序是沙箱(即使不是沙箱),那么在加载 JVM 时强化的运行时将失败。要解决这个问题,您需要在签名时为您的权利添加一些密钥。必要的权利条目如下,从 TAO ZHOU 的解决方案复制而来:https://github.com/TheInfiniteKind/appbundler/issues/39
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
这是一个简单的 shell 脚本,它将在 jar 文件中对 .so、.dylib 和 .jnilib 进行代码签名
用法:codesign_jar_script.shfilename.jar
jar tf | grep '\.so\|\.dylib\|\.jnilib' > filelist.txt
IDENTITY="your_signing_identity"
echo $IDENTITY
while read f
do
jar xf $f
codesign --force -s "$IDENTITY" -v $f
jar uf $f
rm -rf $f
done < filelist.txt