Sierra 中的安全/协同设计:钥匙串忽略访问控制设置和 UI-提示权限
security / codesign in Sierra: Keychain ignores access control settings and UI-prompts for permission
从 macOS Sierra 开始,如果没有 usr/bin/codesign UI,我无法再将代码签名身份导入到带有 /usr/bin/security 的钥匙串中 - 使用此身份时提示访问。这会破坏构建服务器的打包脚本。似乎没有解决方法。这会影响自定义创建的钥匙串,也会影响 login.keychain.
重现步骤:
在终端中执行以下命令(需要签名身份才能导入):
security create-keychain -p test buildagent.keychain
security unlock-keychain -p test buildagent.keychain
security list-keychains -d user -s buildagent.keychain
security default-keychain -s buildagent.keychain
security import identity.p12 -k buildagent.keychain -P password -T /usr/bin/codesign
codesign -vfs '$IDENTITY' '${PRODUCT}' --keychain 'buildagent.keychain'
结果:macOS 显示 UI-提示请求访问之前导入的私钥的权限。
我尝试了很多变通方法,但似乎没有任何效果:
- 指定钥匙串名称时使用新的 .keychain-db 扩展名
- 使用 login.keychain 而不是自定义
- 使用 -A 导入 p12('允许任何应用程序访问
导入密钥')
- 分别导入证书和密钥(正在提取
从之前的 p12 使用 openssl pkcs12)
导入身份确实有效,在钥匙串访问应用程序中显示钥匙串的内容时,我可以看到证书和密钥。私钥的访问控制设置也已正确配置(具有所需的代码设计例外规则)。
如何避免来自 Sierra 的 UI 提示?
您需要使用的命令如下:
security set-key-partition-list -S apple-tool:,apple: -s -k keychainPass keychainName
请记住,此命令行工具的工作方式类似于列表钥匙串的修改方式。 如果您使用单个值执行 set-key-partition-list,它将覆盖证书中的所有 partitionID。它不会验证传递的值。
此命令的作用是为可以为特定钥匙串签名 (-s) 的密钥设置 PartitionID(-S 之后的项目,以逗号分隔)。
允许代码签名的实际 partitionID 是 apple:
.
我不知道 apple-tool:
在做什么,因为它没有记录在案,但在使用 security import
导入密钥后它就在那里,所以我保留它以避免破坏那些复制粘贴命令。
此更改是在 Mac OS Sierra 中引入的,但没有记录(或者至少我找不到文档)。截至 10 月 16 日,安全手册页仍未列出此命令。
有关详细信息,您可以参考此错误报告 - http://www.openradar.me/28524119
对于使用 Travis 或其他 CI 遇到此问题的用户,您必须在应用程序 ID 列表中添加 codesign
。
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k keychainPass keychainName
P.S:
我正在使用 keychainName.keychain(添加 .keychain
)
来自 的命令只为我解锁了钥匙串,但我仍然有 UI 提示询问当前应用程序是否可以使用该密钥。
我这样阻止了提示:
转到钥匙串访问中的钥匙串,双击那里的所有钥匙,然后在“访问控制”选项卡中,选中'Allow all applications to access this item'。
然后我能够将新的钥匙串文件上传到我的 Jenkins 构建服务器,并在其中由 Keychains and Provisioning Profiles Plugin 解锁。构建现在成功签名。
出于某种原因,security set-key-partition-list
对我不起作用。
我在钥匙串中导入证书时使用-A选项解决了这个问题:
security import ${P12_FILE} -k ${KEYCHAIN_PATH} -P ${P12_PASSWORD} -A
以后就不用security set-key-partition-list
了。
此选项允许任何应用程序在没有警告的情况下访问导入的密钥。因此,它可以防止提示出现。请注意,它是不安全的,因为密钥不受保护,但根据您的构建上下文,它可能会有所帮助。
此外,必须将钥匙串添加到搜索列表中:
security list-keychains -s ${KEYCHAIN_PATH}
那么钥匙串应该被解锁了。否则将显示询问钥匙串密码的提示:
security unlock-keychain -p ${KEYCHAIN_PASSWORD} ${KEYCHAIN_PATH}
最终应该禁用自动锁定超时。这是为了防止构建时间很长并且钥匙串自行重新锁定:
security set-keychain-settings ${KEYCHAIN_PATH}
在尝试了许多不同的解决方案后,对我有用的只是更改我的钥匙串的密码。
- Finder > 前往 > 实用程序
- 打开钥匙串访问实用程序。
- 不确定我是否需要执行此步骤:在钥匙串访问实用程序的左侧栏中,单击我的证书。查看钥匙串列以确认您的苹果开发者证书在哪个钥匙串中。在我的例子中,它在 "login" 钥匙串中。
- 更改上一步中钥匙串的密码。您可能想尝试锁定它然后解锁它(如果已锁定)。您可以通过单击相关的钥匙串("login",在我的例子中)来更改密码,然后从钥匙串访问实用程序的编辑菜单中选择 "Change Password..."。
- 下次我 运行 Xcode 中的存档步骤(在“产品”菜单中)最终提示我输入钥匙串密码,我输入了 "login" 钥匙串的密码.然后它起作用了。完成后,我看到一个存档屏幕,其中列出了我的应用程序。
我花了几天时间寻找解决方案。这没有帮助
security import ${P12_FILE} -k ${KEYCHAIN_PATH} -P ${P12_PASSWORD} -A
但是当我明确列出应用程序时 - 它有效(至少在 Catalina 上)!
security import ${P12_FILE} -k ${KEYCHAIN_PATH} -P ${P12_PASSWORD} -T /usr/bin/codesign -T /usr/bin/productsign
仅次于使用
security set-key-partition-list -S apple-tool:,apple: -s -k keychainPass keychainName
我还必须将我的钥匙串设置更改为 "no timeout"
使用
security set-keychain-settings keychainName
上面的 None 有效,但我怀疑它确实适用于空钥匙串。问题在于,如果私钥已经存在于钥匙串中,那么 pkcs12 导入语句的访问控制修饰符 -A
和 -T
将不起作用。现有密钥的访问列表未被覆盖。
将新证书导入 CI 服务器的钥匙串时,我们使用以下脚本来确保导入成功并且代码签名在访问控制列表中:
#!/bin/zsh
KC_FILE=keychain-path
KC_PASSWORD=keychain-password
P12_STORE=pkcs12-path
P12_PASSWORD=pkcs12-password
security unlock-keychain -p $KC_PASSWORD $KC_FILE
CERT_SHA1=`openssl pkcs12 -in $P12_STORE -nodes -passin pass:"$P12_PASSWORD" 2> /dev/null |openssl x509 -noout -fingerprint | grep Fingerprint | sed '/Fingerprint/s/^.*=//;s/://g'`
security delete-identity -Z $CERT_SHA1 $KC_FILE
security import $P12_STORE -t cert -f pkcs12 -P "$P12_PASSWORD" -T /usr/bin/codesign -k $KC_FILE
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KC_PASSWORD $KC_FILE
从 macOS Sierra 开始,如果没有 usr/bin/codesign UI,我无法再将代码签名身份导入到带有 /usr/bin/security 的钥匙串中 - 使用此身份时提示访问。这会破坏构建服务器的打包脚本。似乎没有解决方法。这会影响自定义创建的钥匙串,也会影响 login.keychain.
重现步骤: 在终端中执行以下命令(需要签名身份才能导入):
security create-keychain -p test buildagent.keychain
security unlock-keychain -p test buildagent.keychain
security list-keychains -d user -s buildagent.keychain
security default-keychain -s buildagent.keychain
security import identity.p12 -k buildagent.keychain -P password -T /usr/bin/codesign
codesign -vfs '$IDENTITY' '${PRODUCT}' --keychain 'buildagent.keychain'
结果:macOS 显示 UI-提示请求访问之前导入的私钥的权限。
我尝试了很多变通方法,但似乎没有任何效果:
- 指定钥匙串名称时使用新的 .keychain-db 扩展名
- 使用 login.keychain 而不是自定义
- 使用 -A 导入 p12('允许任何应用程序访问 导入密钥')
- 分别导入证书和密钥(正在提取 从之前的 p12 使用 openssl pkcs12)
导入身份确实有效,在钥匙串访问应用程序中显示钥匙串的内容时,我可以看到证书和密钥。私钥的访问控制设置也已正确配置(具有所需的代码设计例外规则)。
如何避免来自 Sierra 的 UI 提示?
您需要使用的命令如下:
security set-key-partition-list -S apple-tool:,apple: -s -k keychainPass keychainName
请记住,此命令行工具的工作方式类似于列表钥匙串的修改方式。 如果您使用单个值执行 set-key-partition-list,它将覆盖证书中的所有 partitionID。它不会验证传递的值。
此命令的作用是为可以为特定钥匙串签名 (-s) 的密钥设置 PartitionID(-S 之后的项目,以逗号分隔)。
允许代码签名的实际 partitionID 是 apple:
.
我不知道 apple-tool:
在做什么,因为它没有记录在案,但在使用 security import
导入密钥后它就在那里,所以我保留它以避免破坏那些复制粘贴命令。
此更改是在 Mac OS Sierra 中引入的,但没有记录(或者至少我找不到文档)。截至 10 月 16 日,安全手册页仍未列出此命令。
有关详细信息,您可以参考此错误报告 - http://www.openradar.me/28524119
对于使用 Travis 或其他 CI 遇到此问题的用户,您必须在应用程序 ID 列表中添加 codesign
。
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k keychainPass keychainName
P.S:
我正在使用 keychainName.keychain(添加 .keychain
)
来自
我这样阻止了提示:
转到钥匙串访问中的钥匙串,双击那里的所有钥匙,然后在“访问控制”选项卡中,选中'Allow all applications to access this item'。
然后我能够将新的钥匙串文件上传到我的 Jenkins 构建服务器,并在其中由 Keychains and Provisioning Profiles Plugin 解锁。构建现在成功签名。
出于某种原因,security set-key-partition-list
对我不起作用。
我在钥匙串中导入证书时使用-A选项解决了这个问题:
security import ${P12_FILE} -k ${KEYCHAIN_PATH} -P ${P12_PASSWORD} -A
以后就不用security set-key-partition-list
了。
此选项允许任何应用程序在没有警告的情况下访问导入的密钥。因此,它可以防止提示出现。请注意,它是不安全的,因为密钥不受保护,但根据您的构建上下文,它可能会有所帮助。
此外,必须将钥匙串添加到搜索列表中:
security list-keychains -s ${KEYCHAIN_PATH}
那么钥匙串应该被解锁了。否则将显示询问钥匙串密码的提示:
security unlock-keychain -p ${KEYCHAIN_PASSWORD} ${KEYCHAIN_PATH}
最终应该禁用自动锁定超时。这是为了防止构建时间很长并且钥匙串自行重新锁定:
security set-keychain-settings ${KEYCHAIN_PATH}
在尝试了许多不同的解决方案后,对我有用的只是更改我的钥匙串的密码。
- Finder > 前往 > 实用程序
- 打开钥匙串访问实用程序。
- 不确定我是否需要执行此步骤:在钥匙串访问实用程序的左侧栏中,单击我的证书。查看钥匙串列以确认您的苹果开发者证书在哪个钥匙串中。在我的例子中,它在 "login" 钥匙串中。
- 更改上一步中钥匙串的密码。您可能想尝试锁定它然后解锁它(如果已锁定)。您可以通过单击相关的钥匙串("login",在我的例子中)来更改密码,然后从钥匙串访问实用程序的编辑菜单中选择 "Change Password..."。
- 下次我 运行 Xcode 中的存档步骤(在“产品”菜单中)最终提示我输入钥匙串密码,我输入了 "login" 钥匙串的密码.然后它起作用了。完成后,我看到一个存档屏幕,其中列出了我的应用程序。
我花了几天时间寻找解决方案。这没有帮助
security import ${P12_FILE} -k ${KEYCHAIN_PATH} -P ${P12_PASSWORD} -A
但是当我明确列出应用程序时 - 它有效(至少在 Catalina 上)!
security import ${P12_FILE} -k ${KEYCHAIN_PATH} -P ${P12_PASSWORD} -T /usr/bin/codesign -T /usr/bin/productsign
仅次于使用
security set-key-partition-list -S apple-tool:,apple: -s -k keychainPass keychainName
我还必须将我的钥匙串设置更改为 "no timeout"
使用security set-keychain-settings keychainName
None 有效,但我怀疑它确实适用于空钥匙串。问题在于,如果私钥已经存在于钥匙串中,那么 pkcs12 导入语句的访问控制修饰符 -A
和 -T
将不起作用。现有密钥的访问列表未被覆盖。
将新证书导入 CI 服务器的钥匙串时,我们使用以下脚本来确保导入成功并且代码签名在访问控制列表中:
#!/bin/zsh
KC_FILE=keychain-path
KC_PASSWORD=keychain-password
P12_STORE=pkcs12-path
P12_PASSWORD=pkcs12-password
security unlock-keychain -p $KC_PASSWORD $KC_FILE
CERT_SHA1=`openssl pkcs12 -in $P12_STORE -nodes -passin pass:"$P12_PASSWORD" 2> /dev/null |openssl x509 -noout -fingerprint | grep Fingerprint | sed '/Fingerprint/s/^.*=//;s/://g'`
security delete-identity -Z $CERT_SHA1 $KC_FILE
security import $P12_STORE -t cert -f pkcs12 -P "$P12_PASSWORD" -T /usr/bin/codesign -k $KC_FILE
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KC_PASSWORD $KC_FILE