Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jenkins - Xcode build works codesign fails

Below is my build script (not using xcodebuild plugin).

  1. Build step works
  2. I have created a separate keychain with the required certs and private keys, and they are visible in Keychain Access
  3. keychain commands don't fail in the script
  4. security list-keychains shows these as valid keychains

It's acting like unlock command doesn't truly succeed. When I try to run codesign from the command line via

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

I get

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

although I'm not sure I'm emulating from the command line properly since you can at best

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.

Any help is greatly appreciated.

like image 766
mckeejm Avatar asked May 14 '13 18:05

mckeejm


4 Answers

We don't use Jenkins but I've seen this in our build automation before. Here's how we solved it:

1) Create your build Keychain. This will contain the private key/certificate used for codesigning:

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

The keychain_password is up to you. You'll use this later to unlock the keychain during the build.

2) Import the private key (*.p12) for your CodeSign identity:

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

The key here is the "-A" flag. This will allow access to the keychain without warning. This is why you're seeing the "User interaction is not allowed" error. If you were attempting this build via the Xcode UI, this is the point where it would prompt you to "Allow access" to your keychain.

3) However you're saving the Keychain (e.g.: checking it in to source control), make sure it's writeable and executable by your build user.

When you're ready to build, add the following prior to running 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"

If you're running locally, you may want to add something at the end of your build script that switches back to the login keychain (~/Library/Keychains/login.keychain), e.g.:

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

Give that a try. We create a separate Keychain for each identity we use (our own plus builds on behalf of customers). In our company's case, we have both an AppStore and Enterprise account. This can result in naming conflicts while codesigning (e.g.: both accounts resolve to "iPhone Distribution: ACME Corporation"). By keeping these identities in separate keychains we avoid this conflict.

like image 111
Jamieson Avatar answered Nov 18 '22 22:11

Jamieson


Moving the certs to the System keychain, and referencing it specifically fixed the issue

like image 39
mckeejm Avatar answered Nov 18 '22 22:11

mckeejm


In this answer, we add / remove your iOS certificate without manipulating the login keychain nor changing the default keychain by:

  1. Use a temporary keychain
  2. Append temporary keychain to the search list (not replacing)
  3. Unlock temporary keychain with no timeout
  4. Import your certificate using -T /usr/bin/codesign
  5. Do the build
  6. Delete certificate by deleting temporary keychain

Create a temporary keychain. I add $$ which is the PID to create a unique name for the keychain. This allows multiple temporary keychains to be created without clashing. This is useful, if we running concurrent Jenkins jobs.

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

Appends temporary keychain to the search list. Be careful to use security list-keychains -s to append your keychain, else, you will clobber builds running in another thread:

# 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

Unlocks temporary keychain with no automatic relocking timeout (security set-keychain-settings). If you forget to fix the relocking timeout, builds taking longer than the default relocking timeout (typically about 30 minutes) will trigger the password prompt:

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

Import iOS certificate and grants /usr/bin/codesign access without requiring a password prompt.

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

Since the temporary keychain contains only 1 certificate we can, programmatically, derive the IOS_IDENTITY (typically required as an input to build steps).

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

The security set-key-partition-list is a new/additional requirement for unlocking the certificate.

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

Do your build now:

# Insert your custom build steps

Delete temporary keychain. Because the build is done, we no longer require the keychain and the certificate. Deleting the temporary keychain will automatically pop it from the search list. i.e. all other keychains will remain.

# Delete the temp keychain
security list-keychains
security delete-keychain "$MY_KEYCHAIN"
security list-keychains
like image 18
Stephen Quan Avatar answered Nov 18 '22 21:11

Stephen Quan


Required to unlock keychain before to sign "security unlock-keychain -p"

like image 16
user2317738 Avatar answered Nov 18 '22 21:11

user2317738