xcodebuild stuck on codesign? how to disable prompt? - ios

I'm trying to get continuous integration set up, specifically for circleci with iOS. someone has done a great job of writing the details of this: http://mazyod.com/blog/2015/03/26/marry-circleci-to-hockey/
however, my xcodebuild always gets stuck, and it looks like it's waiting for codesign:
/usr/bin/codesign --force --sign...
the log shows that it has been running for over an hour. my guess is that... is this command waiting for an input or something?
if so, how do i force it to use the keychain i've created using the distribution cert/private key ?
here's what the script (add-keys.sh) looks like:
#!/bin/sh
security -v create-keychain -p $KEY_PASSWORD ios-build.keychain
security -v import ./utils/build_tools/custom_builds/apple.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
security -v import ./utils/build_tools/custom_builds/distribution.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
security -v import ./utils/build_tools/custom_builds/distribution_cert_private_key.p12 -k ~/Library/Keychains/ios-build.keychain -P $KEY_PASSWORD -T /usr/bin/codesign
security -v list-keychain -s ~/Library/Keychains/ios-build.keychain
security -v unlock-keychain -p $KEY_PASSWORD ~/Library/Keychains/ios-build.keychain
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp ./utils/build_tools/custom_builds/profile/* ~/Library/MobileDevice/Provisioning\ Profiles/
ls ~/Library/MobileDevice/Provisioning\ Profiles/
where i've stored $KEY_PASSWORD on circle ci's environment vars and is being recognized.
is it that this is causing a pop up prompt to allow user to use keychain or something? if so, am i just supposed to sudo everywhere? or how do i get rid of this?
did i not import the correct certificates or something? are they incorrectly named or something? i used the exact ones i use to build normally.

Perhaps it was re-locked after executing security unlock-keychain if your build process took a long time.
The default timeout is 300s. (You can check it with security show-keychain-info <your keychain path>.)
You can extend it like this:
# Extend the timeout to 600s
security set-keychain-settings -lut 600
FYI, it's described in man security like this:
set-keychain-settings [-hlu] [-t timeout] [keychain]
Set settings for keychain, or the default keychain if none is specified.
-l Lock keychain when the system sleeps.
-u Lock keychain after timeout interval.
-t timeout Specify timeout interval in seconds (omitting this option specifies "no timeout").

I had the same problem with Circle CI 2.0 and xcode >= 9.0.
Looks like problem in MacOS Sierra (and popup with credentials prompt).
You can fix it simply by using following command as build step:
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD circle.keychain
I've found solved issue in Circle CI discuss:
https://discuss.circleci.com/t/xcode-8-3-build-timing-out/11721/5
Good luck!

You have confused P12_PASSWORD and KEYCHAIN_PASSWORD!
Please see the original version: https://github.com/thorikawa/CircleCI-iOS-TestFlight-Sample/blob/master/scripts/add-key.sh
From there, you could see that create-keychain and unlock-keychain use KEYCHAIN_PASSWORD, import use P12_PASSWORD!
So you need store two password and use them correctly!

Related

Github action macos keychain access

I'm trying to move our iOS CI over to github actions but I'm running into some build issues . These issues (fastlane just hangs when gym runs) seem to arise when using match.
Here's the log that makes me think it's keychain related
WARN [2019-09-26 13:46:14.52]: Could not configure imported keychain item (certificate) to prevent UI permission popup when code signing
Check if you supplied the correct `keychain_password` for keychain: `/Users/runner/Library/Keychains/login.keychain-db`
security: SecKeychainItemSetAccessWithPassword: The user name or passphrase you entered is not correct.
The docs say sudo is passwordless so I assumed the same for keychain. I seem to be wrong but I can't find anything in the docs for it. Any help would be greatly appreciated.
EDIT
Lyndsey Ferguson's comment below is mostly the solution. They're approach of using create_keychain and then match I was able to just specify the keychain and it's password so I was able to avoid import_certificate
EDIT 2
Here's what I'm doing in fastlane to get around this
create_keychain(
name: "actiontest_keychain",
password: "meow",
default_keychain: true,
unlock: true,
timeout: 3600,
lock_when_sleeps: false
)
match(
type: "appstore",
readonly: is_ci,
keychain_name: "actiontest_keychain",
keychain_password: "meow"
)
Maybe it is a little late, but I think it is worth mentioning that there is a handy fastlane action setup_ci for this purpose:
Description
Setup the keychain and match to work with CI
Creates a new temporary keychain for use with match
Switches match to readonly mode to not create new profiles/cert on CI
Sets up log and test result paths to be easily collectible
Just add this to the top of your Fastfile or within a specific lane if you use CI.
Fastfile lane Example
lane :build_release do
setup_ci
sync_code_signing(
type: "appstore",
readonly: is_ci
)
build_app
end
Also make sure, your provisioning profiles and certificates within your match storage are up to date and you configured manual signing for release build. Otherwise match will maybe try to sign your app with wrong signing identities which will fail ;)
I can’t use Fastlane because I am trying to use the keychain to work with Java 14’s new jpackage tool in GitHub Actions to build and code sign a Java application native bundle, so I was excited to see Yakuhzi’s answer. It almost worked for me, but there were a couple of errors I had to sort out, which were very difficult because there were no error messages: my workflow just hung on the jpackage command, while I assume the build Mac virtual machine invisibly prompted for the keychain to be unlocked in the virtual frame buffer.
Here is the variation that worked for me. The first three steps were fine (I am passing my signing certificate and its decryption passphrase to the script as environment variables extracted from Github Action secrets, and use the same passphrase to create the build keychain):
security create-keychain -p "$IDENTITY_PASSPHRASE" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$IDENTITY_PASSPHRASE" build.keychain
But trying to run his fourth line at this point would fail with this error:
security: SecItemCopyMatching: The specified item could not be found in the keychain.
Eventually, I after studying the documentation for security set-key-partition-list I realized the first problem was that the -k argument requires the keychain password, which must have been actions in his case! So my next step was to fix line 4 to look like this:
security set-key-partition-list -S apple-tool:,apple: -s -k "$IDENTITY_PASSPHRASE" build.keychain
I was still getting the error though, so I studied the documentation some more, and experimented with the command on a spare Mac mini that didn’t have my signing identity in the login keychain. Eventually I discovered the command was trying to take an action on a signing key that did not yet exist in the keychain. So I moved my steps that import my signing key before that line, and it started to work. Here is the full section once it worked, and you can see the entire script on GitHub:
security create-keychain -p "$IDENTITY_PASSPHRASE" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$IDENTITY_PASSPHRASE" build.keychain
echo "$IDENTITY_P12_B64" > DS_ID_App.p12.txt
openssl base64 -d -in DS_ID_App.p12.txt -out DS_ID_App.p12
security import DS_ID_App.p12 -A -P "$IDENTITY_PASSPHRASE"
security set-key-partition-list -S apple-tool:,apple: -s -k "$IDENTITY_PASSPHRASE" build.keychain
This is an answer that can be accepted, but I would like to understand how the cert and private key get into the keychain.
Try this:
- name: Set up keychain
run: fastlane run create_keychain name:name_of_keychain password:chosen_password
That will create the keychain, and then when you want to use it, you can again provide the chosen_password however you have it. Probably a GITHUB_X env var?
You could try to create a new keychain and set it as default.
- name: Set up keychain
run: |
security create-keychain -p <password> build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p <password> build.keychain
security set-key-partition-list -S apple-tool:,apple: -s -k actions build.keychain

Manage keychain to codesign macOS / iOS app with xcodebuild unattended

I need to create a build of my macOS app every day at midnight. I would like it to be code signed so people can use it without jumping through hoops. I am asleep at midnight, and I'm too busy to do this manually. I would like to run xcodebuild via launch agent and get a signed application while away from the keyboard. But code signing always fails.
It fails with errors like:
No signing certificate "Mac Development" found: No "Mac Development" signing certificate matching team ID "H7V7XYVQ7D" with a private key was found.
It doesn't fail when I'm watching, which means it must have something to do with the keychain locking itself. I flailed around trying to fix this a while ago with no luck:
https://github.com/gnachman/iTerm2/commit/f4082825f3dfa52db08d660ec4821ab6c5bca3f * c
https://github.com/gnachman/iTerm2/commit/4cc902449549995d90da1856068e0f56640d55d1
https://github.com/gnachman/iTerm2/commit/b84b5739fb2e0d3f89bade68467831891d31f79f
https://github.com/gnachman/iTerm2/commit/29817cbb00d755c247c7071cfac7a6580f7b13b1
https://github.com/gnachman/iTerm2/commit/3f33828b5740a764740c98801ff2d12b21d72e7b
https://github.com/gnachman/iTerm2/commit/f4082825f3dfa52db08d660ec4821ab6c5bca3fc
But nothing works. Is this even possible?
export tempKeychain=tempKeychain
export identity="iPhone Whatever: Bob Developer(132455334)"
# create new empty keychain
security create-keychain -p "${ADMIN_PASSWORD}" "${tempKeychain}"
# add keychain to user's keychain search list so they can access it
security list-keychains -d user -s "${tempKeychain}" $(security list-keychains -d user | tr -d '"')
# removing relock timeout on keychain
security set-keychain-settings "${tempKeychain}"
# import the certs
security import foo.p12 -k "${tempKeychain}" -P "${CERT_PASSWORD}" -T "/usr/bin/codesign"
# tell os it's ok to access this identity from command line with tools shipped by apple (suppress codesign modal UI)
security set-key-partition-list -S apple-tool:,apple: -s -k "$ADMIN_PASSWORD" -D "${identity}" -t private ${tempKeychain}
# set default keychain to temp keychain
security default-keychain -d user -s ${tempKeychain}
# unlock keychain
security unlock-keychain -p ${ADMIN_PASSWORD} ${tempKeychain}
# prove we added the code signing identity to the temp keychain
security find-identity -v -p codesigning
# do some codesign stuff
# clean up temp keychain we created
security delete-keychain ${tempKeychain}
have you considered having the launchd script use ssh -o to localhost to run the commands like a CI server (e.g Jenkins) would?

Xcode Build command ask permission to access the private key from Keychain

I am trying the automate the build process of Xcode using ant scripts. I used the security import command with -A and -T to import the certificates.
Command which I used to import the certificate
security import <PATH till the certificate> -k <PATH of keychain> -t priv -P <password> -T <codeSigning Path> -T <Xcode.app Path> -A
But still when I run the xcodeBuild command to archive the build, it pops up a pop which asks for the permission to access the key chain
ask for the permission to access the key chain
Please post as soon as you see this post.
I've had this issue as well. It seems Mac won't let anything automatically access your keychain. Best solution was to check the "Do this every time" box in the popup to prevent it bothering you again
It's Working fine
If its default login keychain the above command will work.
If you have created the login keychain then some times code sign will ask for permission.Solution for this restore your login keychain to default version by taking a backup of all the certificates from the login keychain.

xcodebuild stuck at codesign step when being run in Travis CI

I'm trying to get an iOS archive build to work on Travis CI, after having setup certs and private keys for signing without issues. All goes well until the point where signing occurs, at which point the build gets stuck, until travis CI kills it after timeout:
...
/usr/bin/codesign --force --sign 15E2916907037CFB777FC5F494A6CA252EF0895C --preserve-metadata=identifier,entitlements "/Users/travis/build/RestComm/restcomm-ios-sdk/build/Build/Intermediates/ArchiveIntermediates/restcomm-olympus/InstallationBuildProductsLocation/Applications/restcomm-olympus.app/Frameworks/sofiasip.framework"
No output has been received in the last 10m0s, this potentially indicates a stalled build or something wrong with the build itself
At first I thought it was issue described here, so I added the -A flag in my 'security import ...' commands but to no avail.
Any hints?
Some more details:
I create a new keychain where I add Apple's cert, together with my development & distribution certs and private keys
I set that keychain as default and unlock it prior to any build action
Tried to use travis_wait to allow the codesign step to run for more than 10 minutes just in case, but still after 40 minutes it continued to be stuck. It's like it's waiting for some user input (in the UI maybe) that never arrives?
Thanks in advance,
Antonis
I solved same problem by following steps that is described here.
https://github.com/travis-ci/travis-ci/issues/6791#issuecomment-261215038
a) change argument for all your security imports to keychain from -T to -A
security import ./scripts/certs/dist.cer -k ~/Library/Keychains/ios-build.keychain -A
b) after all imports execute command set-key-partition-list
security set-key-partition-list -S apple-tool:,apple: -s -k <keychainPass> <keychainName>

Jenkins - Xcode build works codesign fails

Below is my build script (not using xcodebuild plugin).
Build step works
I have created a separate keychain with the required certs and private keys, and they are visible in Keychain Access
keychain commands don't fail in the script
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.
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.
Moving the certs to the System keychain, and referencing it specifically fixed the issue
In this answer, we add / remove your iOS certificate without manipulating the login keychain nor changing the default keychain by:
Use a temporary keychain
Append temporary keychain to the search list (not replacing)
Unlock temporary keychain with no timeout
Import your certificate using -T /usr/bin/codesign
Do the build
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
Required to unlock keychain before to sign
"security unlock-keychain -p"
Only one thing solved this problem for me.
What I did is setting the Private Key of the Signing Certificate in the Keychain Access to Allow all applications to access this item.
FWIW... let me throw out another possible reason for this. You may have duplicate certificates floating around and codesign can't tell which one to use. When you run this command from your Jenkins slave do you see duplicate, valid certificates? Something like this:
$ 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
If so, I have found it useful to do the following and get back to a baseline set of signing certificates:
Delete all the certificates on the Jenkins slave (and other Jenkins slaves that will be running your build script).
Next: verify, you have 0 identifies by running $ security find-identity -v -p codesigning again.
Within your application's repository include a custom MyApp.keychain with the two valid certificates in it. Be sure to remove any duplicates.
Now, from your build script and before the codesign process runs from unlock MyApp.keychain and set it as the default. This exposes those certificates as available for codesign.
Finally, verify on your Jenkins slave again: $ security find-identity -v -p codesigning that you see only the certificates you bundled into MyApp.keychain and that there are no other signing identities on the system. If you still see duplicates after having done this you have other places where your Jenkins slave is being made aware of these certificates.
I copied all the certs/private keys to a new keychain (you can right-click on the items and simply copy and paste). In the new keychain, right-click on each private key, Get Info -> Access Control and make the keys available to all apps.
Importantly, in the upper left of the Keychain app is the list of keychains. Re-order them so that the new keychain is first in the list.
Another answer I found gave the build step to unlock this keychain during the build:
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
Here what worked for me:
I created a new keychain and copied all entries from "login" to it, named it "jenkins_ios"
Made new keychain default.
Added a new "Execute shell" step in Jenkins config, it should be the first step beforecode signing, containing the following:
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
Last step is really important, as default unlock timeout may not be enough long for your project to build properly (exactly this happened with our project, as it is huge and build step took about 5-7 minutes, and keychain became locked at the moment it was required for codesign).
This might also be caused by a default timeout on the keychain.
Check out my answer to "User interaction is not allowed" trying to sign an OSX app using codesign
That's a code signing error, the xcodebuild command can't access your certificate's private key since it's running through Jenkins' slave with SSH.
Run this line in your shell script before you run the xcodebuild in order to allow access:
security set-key-partition-list -S apple-tool:,apple: -s -k <ROOT-PASSWORD> /Users/<YOUR USER NAME>/Library/Keychains/login.keychain-db
Hope that helps!
If you face this issue on a CI (GitHub Actions in my case).
Then don't forget to unlock the keychain where your certificates are installed before you run the xcodebuild command.
For example:
security -v unlock-keychain -p <keychain password> $KEYCHAIN
If the keychain is locked the xcodebuild command will hang/freeze when trying to sign the app because it will be waiting for the keychain password to be entered and hence this is a CI and not your own machine there is no way to enter the password when you are asked for it.
You don't need to unlock the keychain if you build the app without code signing e.g ... CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY="" ...
I removed duplicate keys from the key chains (login and system) and it started working. I did only have one certificate but many keys so I had to filter on keys to see them properly.

Resources