【问题标题】:Jenkins - Xcode build works codesign failsJenkins - Xcode 构建工作代码设计失败
【发布时间】:2013-05-09 04:07:17
【问题描述】:

以下是我的构建脚本(不使用 xcodebuild 插件)。

  1. 构建步骤有效
  2. 我创建了一个带有所需证书和私钥的单独钥匙串,它们在钥匙串访问中可见
  3. 钥匙串命令在脚本中不会失败
  4. security list-keychains 将这些显示为有效的钥匙串

就像解锁命令没有真正成功一样。 当我尝试通过

从命令行运行 codesign
codesign -f -s "iPhone Developer: mycert" -v sample.app/ --keychain /Users/Shared/Jenkins/Library/Keychains/JenkinsCI.keychain

我明白了

CSSM_SignData returned: 000186AD
sample.app/: unknown error -2070=fffffffffffff7ea

虽然我不确定我是否正确地从命令行模拟,因为你充其量可以

sudo -u jenkins bash

xcodebuild ONLY_ACTIVE_ARCH="NO" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED="NO" -scheme "MySchemeName" CONFIGURATION_BUILD_DIR="`pwd`"
security list-keychains -s /Users/Shared/Jenkins/Library/Keychains/JenkinsCI.keychain
+ security default-keychain -d user -s /Users/Shared/Jenkins/Library/Keychains/JenkinsCI.keychain
+ security unlock-keychain -p jenkins /Users/Shared/Jenkins/Library/Keychains/JenkinsCI.keychain
+ security list-keychains
    "/Users/Shared/Jenkins/Library/Keychains/JenkinsCI.keychain"
    "/Library/Keychains/System.keychain"
+ security default-keychain
    "/Users/Shared/Jenkins/Library/Keychains/JenkinsCI.keychain"
+ codesign -f -s '$IDENTITY_GOES_HERE.' -v sample.app/
sample.app/: User interaction is not allowed.

非常感谢任何帮助。

【问题讨论】:

    标签: ios jenkins continuous-integration


    【解决方案1】:

    我们不使用 Jenkins,但我之前在我们的构建自动化中看到过这一点。以下是我们的解决方法:

    1) 创建您的构建钥匙串。这将包含用于协同签名的私钥/证书:

    security create-keychain -p [keychain_password] MyKeychain.keychain
    

    keychain_password 由您决定。稍后您将在构建过程中使用它来解锁钥匙串。

    2) 导入您的 CodeSign 身份的私钥 (*.p12):

    security import MyPrivateKey.p12 -t agg -k MyKeychain.keychain -P [p12_Password] -A
    

    这里的关键是“-A”标志。这将允许在没有警告的情况下访问钥匙串。这就是您看到“不允许用户交互”错误的原因。如果您尝试通过 Xcode UI 进行此构建,则会在此处提示您“允许访问”您的钥匙串。

    3) 但是,您要保存钥匙串(例如:将其签入源代码管理),请确保它可由您的构建用户写入和执行。

    当您准备好构建时,在运行 xcodebuild 之前添加以下内容:

    # Switch keychain
    security list-keychains -s "/path/to/MyKeyhain.keychain"
    security default-keychain -s "/path/to/MyKeychain.keychain"
    security unlock-keychain -p "[keychain_password]" "/path/to/MyKeychain.keychain"
    

    如果您在本地运行,您可能希望在构建脚本的末尾添加一些内容以切换回登录钥匙串(~/Library/Keychains/login.keychain),例如:

    # Switch back to login keychain
    security list-keychains -s "~/Library/Keychains/login.keychain"
    security default-keychain -s "~/Library/Keychains/login.keychain"
    

    试试看。我们为我们使用的每个身份创建一个单独的钥匙串(我们自己的 plus 代表客户构建)。在我们公司的案例中,我们同时拥有 AppStore 和 Enterprise 帐户。这可能会导致在进行代码设计时出现命名冲突(例如:两个帐户都解析为“iPhone Distribution: ACME Corporation”)。通过将这些身份保存在单独的钥匙串中,我们可以避免这种冲突。

    【讨论】:

    • 哇.. necro 在这个帖子上发帖.. 但很酷... 我完全理解您对 -A 标志的意思。当我们为我们的新应用程序设置 CI 时,我会试一试。谢谢:)
    • 我为此苦苦挣扎,而这正是我所需要的。谢谢贾米森。
    • 谁能帮忙解决这个问题stackoverflow.com/questions/52187300/…
    • 此修复仍然适用于 macOS Mojave (10.14.5)。谢谢@jamieson
    • KUDOS 在 2017 年为这个答案做 @Jamieson。看来问题在那个时候得到了解决。但是,我建议更新此答案并将“Stephen Quan”解决方案作为最新版本。这里的答案似乎不再起作用。 Stephen Quan现在是正确的人!两个都点赞! :-)
    【解决方案2】:

    将证书移动到系统钥匙串,并专门引用它来解决问题

    【讨论】:

    • 即使在我将签名证书复制到系统钥匙串之后,构建仍然失败并出现同样的错误,直到我主动从登录钥匙串中删除了“原始”
    • 为我工作,也是最简单的解决方案。
    • 使用 Jenkins 2.235.3 LTS 和 Mac 代理(通过 SSH 连接)和 Xcode 11.6,这是对我有用的解决方案(移动,而不是复制,从登录到系统钥匙串的证书)。
    【解决方案3】:

    在此答案中,我们添加/删除您的 iOS 证书,无需操作登录钥匙串,也无需更改默认钥匙串:

    1. 使用临时钥匙串
    2. 将临时钥匙串附加到搜索列表(不替换)
    3. 无超时解锁临时钥匙串
    4. 使用-T /usr/bin/codesign 导入您的证书
    5. 进行构建
    6. 通过删除临时钥匙串来删除证书

    创建一个临时钥匙串。我添加了$$,这是为钥匙串创建唯一名称的 PID。这允许创建多个临时钥匙串而不会发生冲突。如果我们同时运行 Jenkins 作业,这很有用。

    # Create temporary keychain
    MY_KEYCHAIN="MyKeychain-$$.keychain"
    MY_KEYCHAIN_PASSWORD="secret"
    security create-keychain -p "$MY_KEYCHAIN_PASSWORD" "$MY_KEYCHAIN"
    

    将临时钥匙串附加到搜索列表。小心使用security list-keychains -s 附加您的钥匙串,否则您将破坏在另一个线程中运行的构建:

    # Append keychain to the search list
    security list-keychains -d user -s "$MY_KEYCHAIN" $(security list-keychains -d user | sed s/\"//g)
    security list-keychains
    

    解锁临时钥匙串,没有自动重新锁定超时 (security set-keychain-settings)。如果您忘记修复重新锁定超时,构建花费的时间超过默认重新锁定超时(通常大约 30 分钟)将触发密码提示:

    # Unlock the keychain
    security set-keychain-settings "$MY_KEYCHAIN"
    security unlock-keychain -p "$MY_KEYCHAIN_PASSWORD" "$MY_KEYCHAIN"
    

    导入 iOS 证书并授予 /usr/bin/codesign 访问权限,无需密码提示。

    # Import certificate
    security import $CERT -k "$MY_KEYCHAIN" -P "$CERT_PASSWORD" -T "/usr/bin/codesign"
    

    由于临时钥匙串仅包含 1 个证书,我们可以通过编程方式派生 IOS_IDENTITY(通常需要作为构建步骤的输入)。

    # Detect the iOS identity
    IOS_IDENTITY=$(security find-identity -v -p codesigning "$MY_KEYCHAIN" | head -1 | grep '"' | sed -e 's/[^"]*"//' -e 's/".*//')
    IOS_UUID=$(security find-identity -v -p codesigning "$MY_KEYCHAIN" | head -1 | grep '"' | awk '{print $2}')
    

    security set-key-partition-list 是解锁证书的新/附加要求。

    # New requirement for MacOS 10.12
    security set-key-partition-list -S apple-tool:,apple: -s -k $MY_KEYCHAIN_PASSWORD $MY_KEYCHAIN
    

    现在开始构建:

    # Insert your custom build steps
    

    删除临时钥匙串。因为构建完成,我们不再需要钥匙串和证书。删除临时钥匙串会自动将其从搜索列表中弹出。即所有其他钥匙串都将保留。

    # Delete the temp keychain
    security list-keychains
    security delete-keychain "$MY_KEYCHAIN"
    security list-keychains
    

    【讨论】:

    • 这仍然不适用于我的詹金斯。当我在本地使用它时它工作,它在通过 SSH 在构建机器上运行时工作。通过 jenkins 在构建机器上运行时失败。
    • 我认为我的问题是由于Apple cert change
    • 是的,只需将new cert 添加到我的系统钥匙串中
    【解决方案4】:

    签名前需要解锁钥匙串 "安全解锁-钥匙串-p"

    【讨论】:

    • 正如我在下面的回答中所说,将其添加到系统工作。如果您引用上面粘贴的脚本,我确实有“security unlock-keychain -p”并且它成功地这样做了......它只是不会尊重它,直到它在 System.可能有一个不涉及使用系统的解决方案......但对于持续集成服务器,我认为这是一个可以接受的解决方案。
    • 我又遇到这个问题了,这次unlock解决了我的问题。
    • 绝对是解决方案。
    • 当我 ssh 进入盒子进行构建时,这就是解决方案。
    【解决方案5】:

    只有一件事为我解决了这个问题。

    我所做的是将钥匙串访问中签名证书私钥设置为允许所有应用程序访问此项目

    【讨论】:

    • 这是我们的修复,当 jenkins 在升级 macOS 后开始遇到 CodeSign errSecInternalComponent 错误时。谢谢!
    【解决方案6】:

    FWIW...让我抛出另一个可能的原因。您可能有重复的证书浮动,codesign 不知道该使用哪一个。当您从 Jenkins 从站运行此命令时,您是否看到重复的有效证书?像这样的:

    $ security find-identity -v -p codesigning
      1) AAAAE00066DED2FE77DF43012573AD5B6188AAAA "iPhone Developer: JOHN SMITH (XAAAAFSUSJ)"
      2) AAAAE00066DED2FE77DF43012573AD5B6188AAAA "iPhone Developer: JOHN SMITH (XAAAAFSUSJ)"
      3) BBBB5B03DB566209964247982908D3DD74D1BBBB "iPhone Distribution: Example, Inc. (TBBBBH5HUE)"
      4) BBBB5B03DB566209964247982908D3DD74D1BBBB "iPhone Distribution: Example, Inc. (TBBBBH5HUE)"
      5) BBBB5B03DB566209964247982908D3DD74D1BBBB "iPhone Distribution: Example, Inc. (TBBBBH5HUE)"
      6) AAAAE00066DED2FE77DF43012573AD5B6188AAAA "iPhone Developer: JOHN SMITH (XAAAAFSUSJ)"
      7) AAAAE00066DED2FE77DF43012573AD5B6188AAAA "iPhone Developer: JOHN SMITH (XAAAAFSUSJ)"
      8) BBBB5B03DB566209964247982908D3DD74D1BBBB "iPhone Distribution: Example, Inc. (TBBBBH5HUE)"
      8 valid identities found
    

    如果是这样,我发现执行以下操作并返回签名证书的基线集很有用:

    • 删除 Jenkins 从站(以及将运行您的构建脚本的其他 Jenkins 从站)上的所有证书。
    • 下一步:通过再次运行 $ security find-identity -v -p codesigning 来验证您是否拥有 0 identifies
    • 在应用程序的存储库中包含一个自定义MyApp.keychain,其中包含两个有效证书。请务必删除所有重复项。
    • 现在,从您的构建脚本中,在 codesign 进程从 unlock MyApp.keychain 运行之前,并将其设置为默认值。这会将这些证书公开为可用于codesign
    • 最后,再次在您的 Jenkins 从站上验证:$ security find-identity -v -p codesigning 您看到您捆绑到 MyApp.keychain 的证书,并且系统上没有其他签名身份。如果您在完成此操作后仍然看到重复项,那么您的 Jenkins 奴隶在其他地方也可以知道这些证书。

    【讨论】:

      【解决方案7】:

      我将所有证书/私钥复制到一个新的钥匙串中(您可以右键单击这些项目并简单地复制和粘贴)。在新的钥匙串中,右键单击每个私钥,获取信息 -> 访问控制,然后将密钥提供给所有应用程序。

      重要的是,钥匙串应用程序的左上角是钥匙串列表。重新排序,使新的钥匙串在列表中排在第一位。

      我发现的另一个答案给出了在构建过程中解锁此钥匙串的构建步骤:

      KEYCHAIN=/Users/<you>/Library/Keychains/codesign.keychain
      
      # the -s option adds $KEYCHAIN to the search scope, while the -d option adds $KEYCHAIN to the system domain; both are needed
      security -v list-keychains -d system -s $KEYCHAIN
      security -v unlock-keychain -p <keychain password> $KEYCHAIN
      

      【讨论】:

      • 所以我在构建过程中做了同样的步骤。但是,我没有执行您之前在帖子中提到的细粒度钥匙串步骤。对我来说问题是它运行 AS Jenkins.. 我无法登录以重新订购钥匙串。
      • 这是我需要的答案。谢谢。
      【解决方案8】:

      这对我有用:

      1. 我创建了一个新的钥匙串并将所有条目从“登录”复制到它,命名为“jenkins_ios”
      2. 将新的钥匙串设为默认值。
      3. 在 Jenkins 配置中添加了一个新的“执行 shell”步骤,它应该是代码签名之前的第一步,包含以下内容:

      KEYCHAIN=/Users/<user>/Library/Keychains/jenkins_ios.keychain
      security -v list-keychains -s $KEYCHAIN
      security -v unlock-keychain -p <password> $KEYCHAIN
      security set-keychain-settings -t 3600 -l $KEYCHAIN
      

      最后一步非常重要,因为默认解锁超时时间可能不足以让您的项目正确构建(这正是我们的项目所发生的,因为它很大,构建步骤大约需要 5-7 分钟,并且钥匙串被锁定目前它是协同设计所必需的)。

      【讨论】:

        【解决方案9】:

        这也可能是由钥匙串上的默认超时引起的。

        查看我对"User interaction is not allowed" trying to sign an OSX app using codesign的回复

        【讨论】:

        • 在这种情况下,这是一个短期运行的构建。我认为在我的情况下,问题源于 Jenkins 不是拥有桌面的真正用户。从那时起,在配置中,我们已经能够使 Jenkins 用户可以登录,并且不需要将其破解到系统钥匙串中。
        【解决方案10】:

        这是一个代码签名错误,xcodebuild 命令无法访问您证书的私钥,因为它是通过 Jenkins 的从属设备使用 SSH 运行的。

        在运行 xcodebuild 之前在 shell 脚本中运行此行以允许访问:

        security set-key-partition-list -S apple-tool:,apple: -s -k <ROOT-PASSWORD> /Users/<YOUR USER NAME>/Library/Keychains/login.keychain-db
        

        希望有帮助!

        【讨论】:

        • 请注意,在我的具体原始示例中,它不是通过具有 SSH 的从属设备运行的,它都是本地的。
        【解决方案11】:

        如果您在 CI 上遇到这个问题(在我的例子中是 GitHub Actions)。 然后在运行xcodebuild 命令之前不要忘记解锁安装证书的钥匙串。

        例如: security -v unlock-keychain -p &lt;keychain password&gt; $KEYCHAIN

        如果钥匙串被锁定,xcodebuild 命令将在尝试签署应用程序时挂起/冻结,因为它将等待输入钥匙串密码,因此这是一个 CI,而不是您自己的机器,没有办法在被要求输入密码时输入密码。

        如果您在没有代码签名的情况下构建应用程序,则无需解锁钥匙串,例如 ... CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY="" ...

        【讨论】:

          【解决方案12】:

          我从钥匙链(登录和系统)中删除了重复的钥匙,它开始工作了。我确实只有一个证书,但有很多密钥,所以我必须过滤密钥才能正确查看它们。

          【讨论】:

            猜你喜欢
            • 2012-04-06
            • 2017-11-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-24
            • 1970-01-01
            • 2021-10-10
            相关资源
            最近更新 更多