Jenkins - Xcode构建工作代码签名失败

时间:2013-05-14 18:49:10

标签: ios jenkins continuous-integration

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

  1. 构建步骤
  2. 我创建了一个单独的钥匙串,其中包含所需的证书和私钥,它们在Keychain Access中可见
  3. keychain命令在脚本中不会失败
  4. 安全列表 - 钥匙串将这些显示为有效的钥匙串
  5. 它的行为就像解锁命令并没有真正成功。 当我尝试从命令行通过

    运行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.
    

    非常感谢任何帮助。

12 个答案:

答案 0 :(得分:67)

我们不使用Jenkins,但我之前在构建自动化中已经看过这个。以下是我们解决问题的方法:

1)创建构建Keychain。这将包含用于代码签名的私钥/证书:

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)但是你要保存Keychain(例如:将其检入源代码控制中),确保它可由构建用户编写和执行。

当您准备构建时,请在运行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"

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

答案 1 :(得分:25)

将证书移至系统钥匙串,并引用它专门修复了问题

答案 2 :(得分:14)

在签名之前需要解锁钥匙串 “security unlock-keychain -p”

答案 3 :(得分:9)

在这个答案中,我们在不操纵登录钥匙串的情况下添加/删除您的iOS证书,也不会通过以下方式更改默认钥匙串:

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

    创建临时钥匙串。我添加了$$这是PID。这意味着我们允许通过允许同时创建多个临时密钥链来并行化脚本:

    # Create temp 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)。如果您忘记修复重新锁定超时,则构建时间超过默认重新锁定超时将触发密码提示:

    # 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}')
    
    # 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
    

答案 4 :(得分:4)

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

我所做的是在“钥匙串访问”中将签名证书私钥设置为允许所有应用程序访问此项目。< / p>

this

答案 5 :(得分:3)

我将所有证书/私钥复制到新的钥匙串(您可以右键单击这些项目,然后只需复制和粘贴)。在新的钥匙串中,右键单击每个私钥,获取信息 - &gt;访问控制并使密钥可用于所有应用程序。

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

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

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

答案 6 :(得分:3)

FWIW ......让我抛出另一个可能的原因。您可能有重复的证书,codesign无法告诉您使用哪个证书。从Jenkins slave运行此命令时,您是否看到重复的有效证书?像这样:

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

答案 7 :(得分:1)

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

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

的回答

答案 8 :(得分:1)

这对我有用:

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

这是代码签名错误,xcodebuild命令无法访问证书的私钥,因为它通过SSH运行Jenkins的slave。

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

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

希望有所帮助!

答案 10 :(得分:0)

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

答案 11 :(得分:0)

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

例如: security -v unlock-keychain -p <keychain password> $KEYCHAIN

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

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