"User interaction is not allowed" trying to sign an OSX app using codesign
Asked Answered
P

17

161

Our automated build is running on Jenkins. The build itself is running on slaves, with the slaves being executed via SSH.

I get an error:

00:03:25.113 [codesign-app] build/App.app: User interaction is not allowed.

I have tried every suggestion I have seen so far in other posts here:

  • Using security unlock-keychain immediately before signing to unlock the keychain.
  • Moving the signing key out into its own keychain.
  • Moving the signing key into the login keychain.
  • Moving the signing key into the system keychain.
  • Manually setting list-keychains to only the keychain which contains the key.

In all cases, I get the same error.

In an attempt to diagnose the issue, I tried running the "security unlock-keychain" command on my local terminal and found that it doesn't actually unlock the keychain - if I look in Keychain Access, the lock symbol is still there. This is the case whether I pass the password on the command-line or whether I let it prompt me for it. Unlocking the same keychain using the GUI will prompt me for the password and then unlock it. Additionally, if I run "security lock-keychain", I do see the key lock immediately after running the command. This makes me think that unlock-keychain doesn't actually work. I experience the same behaviour on Lion (which we're using for the build slaves) and Mavericks (which I'm developing on.)

Next, I tried adding -v to all the security commands:

list-keychains "-d" "system" "-s" "/Users/tester/.secret/App.keychain"
Listing keychains to see if it was added: ((
        "/Library/Keychains/System.keychain"
))
unlock-keychain "-p" "**PASSWORD**" "/Users/tester/.secret/App.keychain"
build/App.app: User interaction is not allowed.

From this, it would seem that list-keychains is what isn't working. Maybe neither work. :/

There is a similar question here. The solution is interesting - set "SessionCreate" to true in launchctl. But I'm not building on the master - my build process is started from SSH on a slave build machine. Maybe there is a command-line way to do what launchctl is doing when you run "SessionCreate"?

Prodigious answered 25/11, 2013 at 22:54 Comment(2)
How to set keychain password on circleci?Glue
@SachinKumaram sounds like a viable new question?Prodigious
P
85

Well, I guess I get to answer my own question today, because after stabbing at it over two and a half days, one of the things I tried seems to have worked. I'm just going to back away from it now and hope it keeps working.

Essentially, it looks like it comes down to -d system not actually working. So a lot of answers to other questions around here should probably be updated to reflect that.

security -v list-keychains -s "$KEYCHAIN" "$HOME/Library/Keychains/login.keychain"
security list-keychains # so we can verify that it was added if it fails again
security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
codesign --sign "$SIGNER_IDENTITY" --force --signature-size 9600 \
         --resource-rules src/AppResourceRules.plist --timestamp --verbose \
         "$APP"
Prodigious answered 26/11, 2013 at 3:45 Comment(5)
Thanks. I've been able to narrow this down. Just run the following command right before attempting to build: security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$HOME/Library/Keychains/login.keychain"Mallet
So there is no way to access codesign through ssh without actually storing the login password inside some script?Medusa
@Medusa in the example above, I only pass the keychain password, not the login password. I realise that for a lot of users, the login keychain is the only keychain, but in our case, we keep the signing keys in a separate keystore to make them easier to synchronise to build machines. But yes, a lot of this stuff seems rather inconvenient for automated builds, leading me to wonder if Apple even do automated builds.Prodigious
@Trejkaz oh okay, atleast sharing a keychain password is not as bad.Medusa
In my use case of automated remote builds, storing the keychain password to an .env file is not that bad, since the .env file already contains sensitive keys to eg. AWS and Heroku. In our case the build related code sign credentials are stored in a newly created Keychain which is then removed after the build. Then it is recreated again for the next build. However, the login keychain must still be opened, so security unlock-keychain -p pass login.keychain was the missing link here. Thanks!Kabul
R
212

I too have been fighting this. Nothing helped until I tried the suggestion on http://devnet.jetbrains.com/thread/311971. Thanks ashish agrawal!

Login your build user via the GUI and open Keychain Access. Select your signing private key, right-click, choose Get Info, change to the Access Control tab and select the "Allow all applications to access this item".

access control tab

Reductive answered 25/3, 2014 at 14:41 Comment(13)
Thanks for sharing this! This was exactly the problem I was having with a post archive script on my XCode bot.Capillaceous
You're welcome. You might also consider adding codesign to the application list at the bottom instead of allowing all applications like I did. It's already there in my screenshot, but I think originally it wasn't.Reductive
I had to unhide the /usr directory with apple.stackexchange.com/a/34872/6052 to be able to add codesign to the "Always Allow" list.Fanniefannin
just a note that in addition to this you have to do the whole security unlock-keychain stuff, tooDecoction
In addition, you might want to move your keys from login to system so they are accessible when you do remote builds on your machine.Priority
May be I'm a bit paranoid, but it should be just fine, to add "codesign" in the "Always allow access by these applications" box. I just think, there is no need to allow it to all applications, if you just need it for codesign.Zimbabwe
@Zimbabwe I agree. See my comment above.Reductive
Is there a way to do this from the command line, for automation? My CI build environment rebuilds it self on every build, so no point logging in manually..Stokeontrent
Does anyone know any way to do this from the command line? My remote build machine will not let me do this over screen sharing for security reasons.Pomcroy
If you're using El Capitan, you need to double click the password item in the keychain window in order to get to the Access Control tab.Cleanthes
I'm on El Cap and the same process as originally described worked for me. The only exception is that I added codesign to the list of applications as described on my April 14 comment.Reductive
I did this but the system is not saving it, if I look at it again, it's checked "Confirm before..." again. Any thoughts?Howell
Oddly enough, when I set the keychain access to Allow all, the next time I do a get info on it, it's set back to Confirm, even though I entered my admin username and password. : /Barkeeper
P
85

Well, I guess I get to answer my own question today, because after stabbing at it over two and a half days, one of the things I tried seems to have worked. I'm just going to back away from it now and hope it keeps working.

Essentially, it looks like it comes down to -d system not actually working. So a lot of answers to other questions around here should probably be updated to reflect that.

security -v list-keychains -s "$KEYCHAIN" "$HOME/Library/Keychains/login.keychain"
security list-keychains # so we can verify that it was added if it fails again
security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
codesign --sign "$SIGNER_IDENTITY" --force --signature-size 9600 \
         --resource-rules src/AppResourceRules.plist --timestamp --verbose \
         "$APP"
Prodigious answered 26/11, 2013 at 3:45 Comment(5)
Thanks. I've been able to narrow this down. Just run the following command right before attempting to build: security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$HOME/Library/Keychains/login.keychain"Mallet
So there is no way to access codesign through ssh without actually storing the login password inside some script?Medusa
@Medusa in the example above, I only pass the keychain password, not the login password. I realise that for a lot of users, the login keychain is the only keychain, but in our case, we keep the signing keys in a separate keystore to make them easier to synchronise to build machines. But yes, a lot of this stuff seems rather inconvenient for automated builds, leading me to wonder if Apple even do automated builds.Prodigious
@Trejkaz oh okay, atleast sharing a keychain password is not as bad.Medusa
In my use case of automated remote builds, storing the keychain password to an .env file is not that bad, since the .env file already contains sensitive keys to eg. AWS and Heroku. In our case the build related code sign credentials are stored in a newly created Keychain which is then removed after the build. Then it is recreated again for the next build. However, the login keychain must still be opened, so security unlock-keychain -p pass login.keychain was the missing link here. Thanks!Kabul
J
43

Using Security to create a Keychain for /usr/bin/codesign

Importing the certificate and having it work with codesign programmatically isn't a matter of using login or System keychains or praying to some god of codesign. You just need to have the correct permissions set. I recommend creating a new keychain specifically for codesign purposes.

These days to get codesign to not yield an errSecInternalComponent you need to get the partition list (ACLs) correct. I'll walk through the steps:

Create the Keychain

security create-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

at this point the keychain is unlocked but won't appear in Keychain Access.

Add the new Keychain to the search list

security list-keychains -s "${KEYCHAIN_NAME}" "${OLD_KEYCHAIN_NAMES[@]}"

Add the new Keychain to the list. If you don't first grab out the original list from list-keychains you'll no longer have login.keychain in your search-list.

Unlock the keychain

security unlock-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

This is redundant if you created the Keychain above, but if the Keychain already existed it is necessary.

Remove the defaults from the Keychain

security set-keychain-settings "${TESTING_KEYCHAIN}"

By not specifying any arguments this will set the auto-lock timeout to unlimited and remove auto-lock on sleep.

Import your signing certs from a .p12

security import "${DIST_CER}" -P "${CERTIFICATE_PASSWORD}" -k "${KEYCHAIN_NAME}" -T /usr/bin/codesign

Import the certs and gives codesign access through the -T option.

Set the ACL on the keychain

security set-key-partition-list -S apple-tool:,apple: -s -k "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

This is a requirement that many people miss. You can see what macOS does by using dump-keychain. Which in the case of codesigning requires apple: and apple-tool:. -s refers to signing certificates.

Where's my signing certificate?

Always a good idea to make sure you can find your certificates

security find-identity -p codesigning -v /path/to/keychain

Gitlab-Runner, Jenkins and the like

One very important thing for any CI-type runner or build system is to make sure the process is started from launchd correctly. Make sure your plist contains <SessionCreate> </true>.

Not correctly matching the the owner of the keychain with the build process and making sure a security session is created will result is all sorts of headaches. Diagnostically speaking you can introduce list-keychains and see if the output matches your expectations.

This is from the launchd.plist man-page:

SessionCreate <boolean>

This key specifies that the job should be spawned into a new security audit session rather than the default session for the context is belongs to. See auditon(2) for details.

UserName <string>

This optional key specifies the user to run the job as. This key is only applicable for services that are loaded into the privileged system domain.

GroupName <string>

This optional key specifies the group to run the job as. This key is only applicable for services that are loaded into the privileged system domain. If UserName is set and GroupName is not, then the group will be set to the primary group of the user.

Example /Library/LaunchDaemons/com.company.gitlab-runner.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.company.gitlab-runner</string>
    <key>SessionCreate</key><true/>
    <key>KeepAlive</key><true/>
    <key>Disabled</key><false/>
    <key>UserName</key>
    <string>bob</string>
    <key>GroupName</key>
    <string>staff</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/opt/gitlab-runner/bin/gitlab-runner</string>
      <string>run</string>
      <string>--working-directory</string>
      <string>/Users/bob/gitlab-runner</string>
      <string>--config</string>
      <string>/Users/bob/gitlab-runner/config.toml</string>
      <string>--service</string>
      <string>gitlab-runner</string>
      <string>--syslog</string>
    </array>
    <key>EnvironmentVariables</key>
      <dict>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>
  </dict>
</plist>

Register the runner

gitlab-runner register \
  --non-interactive \
  --tls-ca-file "{{ gitlab_runner_dir }}/certs/git.company.com.crt" \
  --config "{{ gitlab_runner_dir }}/config.toml" \
  --builds-dir "{{ gitlab_runner_dir }}/builds" \
  --url "{{ gitlab_ci }}" \
  --registration-token "{{ gitlab_token }}" \
  --name "{{ computername }}" \
  --tag-list "{{ gitlab_runner_tags }}" \
  --output-limit 16384 \
  --executor shell \
  --shell bash

Finally codesign

You can lookup the signing certificates hash using find-identity

security find-identity -p codesigning -v

Before beginning signing Xcode sets the environment variable CODESIGN_ALLOCATE to use the codesign_allocate that comes with Xcode, not in /usr/bin.

export CODESIGN_ALLOCATE="$( xcrun --find codesign_allocate )"

Codesign a framework, dylib, etc.

If you're codesigning manually, start with the frameworks and dylibs and after they are all signed, then sign the .app. Or in other words - you codesign from the bottom up.

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" "$SIGNABLE"

Codesign the app bundle

After all the other signables are signed, sign the .app itself. In theory, you could do this all in one go with --deep, however, you would still need to make sure your app has entitlements and possibly other flags.

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" "$SIGNABLE"

Flag passed to all items:

  • --timestamp=none disable timestamps

Other flags to the app signing step:

  • --entitlements /path/to/entitlements.xcent new entitlements
  • --preserve-metadata=entitlements keep current entitlements

New codesign requirement - DER encoded entitlements

Apple has recently started requiring entitlements to not be embedded only in plist form, but also in DER encoded form. If you are using an older Mac/Xcode you might encounter the error...

The code signature version is no longer supported

Jevons answered 31/8, 2018 at 12:56 Comment(7)
Dude you can definitively write an article about it, I was looking for this since 2 days. I don't know how many stuff and stackoverflow posts I read. Many thanks to you !Basilbasilar
ACL on keychain was the missing part for me. thanks for the clear explanation sir !Tito
I so wanted this to be the real trick to get this working, but I get the same errSecInternalComponent error with GitLab. Xcode 12.2. GitLab runner 13.7.0. Followed your directions to the letter, @cameron-lowell-palmer. The only solution I've found is to unlock the keychain during the build, then sign. Sad.Gemmulation
I use this on 20 different builders - so I'm curious what the issue is... Do you have SessionCreate true and the username of the gitlab-runner set correctly in LaunchD?Jevons
@Gemmulation - I even have ruby scripts that dynamically create and populate the keychains for signing during the build.Jevons
Thanks @CameronLowellPalmer. Yes I do have SessionCreate true and there is only one user on the Mac and the gitlab-runner is installed only for that user (not a system runner since they are not recommended). I do believe you have it working. I just don't know what I'm missing. I hate to pollute the comments here with this discussion, but not sure how/where else to get help on this. I worked with to GitLab support (we're premium customers) and they couldn't figure it out either. As it is, I just added keychain unlock via obfuscated password during each build so I could move on.Gemmulation
@Gemmulation the instructions on the GitLab website regarding installation are absolutely horrific. My strategy - basic install via brew as admin-user, config and run as builder-user in launchd. Do not set auto-login - that comment from GitLab is ancient. Skip the credential helper stuff, in fact, the only thing there worthwhile is my plist at the end.Jevons
E
19

None of the other answers worked for me.

What eventually saved me was this post

To sum it up, this can be caused by a default timeout of 5 minutes, that will trigger this error after a long build.

To fix:

security set-keychain-settings -t 3600 -l ~/Library/Keychains/login.keychain
Expiate answered 1/6, 2014 at 21:25 Comment(4)
On El Capitan, you can do that through the user interface, too. Just open keychain app, right click on your keychain (login, system etc.) and click on something that matches 'change settings for <your_keychain>' best.Archipenko
This always sets my System keychain access back to Confirm even after I change access. : /Barkeeper
It was helpful for me!!Steelman
I've been struggling with it for 2 days, before I found your comment, thanks!!!Underscore
Y
18

Try to call security unlock-keychain and codesign as an one-line command. This helped me. Something like:

security unlock-keychain -p <password> /Users/<user>/Library/Keychains/login.keychain && codesign --force --verify --verbose --sign "<certificate id>" <app name>
Yean answered 24/1, 2014 at 8:13 Comment(3)
That's the same as doing it on two lines. I guess the difference is that if the first command fails, it won't run the second.Prodigious
For me they are not the same. I call them via ant sshexec and each time it creates a new ssh session.Yean
You can do more than one line through a single ssh session too, if you really want. So... it's still the same, aside from the treatment of errors.Prodigious
W
12

Put your keys in the System keychain

Whiskey answered 30/7, 2015 at 15:36 Comment(6)
But it still asks username and passwordVegetarian
How to put keys in system keychain .......will copy paste from keychain access work ?Gilberto
Drag and drop @AshishKarpeWhiskey
Did Drag and drop still getting same error : === BUILD TARGET PatientPortal OF PROJECT PatientPortal WITH CONFIGURATION Debug === Check dependencies No profiles for 'com.abc.xyz360' were found: Xcode couldn't find a provisioning profile matching 'com.abc.xyz360'. Code signing is required for product type 'Application' in SDK 'iOS 10.2'Gilberto
It says you don't have a provisioning profile installed on the machine, not that you're missing the keys @AshishKarpeWhiskey
Doesn't work. And then, even if I set access to be All, the next time I check the access, it's set back to Confirm.Barkeeper
L
7

So this is the command that works. -A is to prevent Mac from asking password. Importing to system.keychain doesn't require an GUI.

sudo security import <cert.p12> -k "/Library/Keychains/System.keychain" -P <passphrase> -A

Lopeared answered 3/5, 2016 at 3:15 Comment(0)
P
3

My keychain was locked. It resisted my advances to change that fact...

Keychain Access -> Keychain First Aid -> Repair, et voilá!

Posset answered 3/10, 2014 at 11:18 Comment(0)
S
2

Unlocking the keychain is not enough. You also have to set the private key access to "Allow all apps to access this item". And to do that from command line requires reimporting the key. So to take things at a time:

Unlock the login keychain if it is locked. It shouldn't be locked though, but anyway here's how you do that:

security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "~/Library/Keychains/login.keychain"

If for some reason your build machine has the login keychain locked, and you don't want to expose that password in a script, then you should use a different keychain. You can create one on the spot and use that in the previous and the following command. To create one on the spot:

security create-keychain -p 'temporaryPassword' MyKeychain.keychain
security list-keychains -d user -s login.keychain MyKeychain.keychain

Then import your certificates and associated private keys into the login keychain using the -A parameter. Note that you don't need to sudo for all this...

security import <cert.p12> -k "~/Library/Keychains/login.keychain" -P <passphrase> -A

The -A parameter is what will make your private key to be set to "Allow all apps to access this item"

So using all these you should be able to make a script that installs the required certificate to build a release ipa and sign it without prompt. You can store the .p12 file in your repo, so any machine can build your ipa without requiring manual setup.

Sewing answered 15/11, 2016 at 17:35 Comment(0)
H
1

Apart from unlocking keychain (as mentioned in another answers), you need to allow access from all applications to Xcode authentication token in keychain:

  • Select "login" keychain
  • Select "All Items" category
  • Search for "xcode" keyword
  • Select "Allow all applications to access this item" for all Xcode tokens
  • Don't forget to add unlock keychain step (from previous answers)

Screenshot

Hajji answered 30/7, 2019 at 7:25 Comment(0)
R
0

Import your keys to System keychain. You can use this command:

sudo security import YourKey.p12 -k /Library/Keychains/System.keychain -P PasswordToYourKey -T /usr/bin/codesign
Rosalindarosalinde answered 7/1, 2016 at 1:31 Comment(0)
K
0

So I tried every answer here and something wasn't quite adding up. Finally I figured out when I rebooted my CI service, it was running under a different user than I had expected. Changing to the user that actually had access to the key in their login chain fixed everything. This may not be a common problem, but wanted to document my specific reason for this error, in case it happens to others.

Kweichow answered 16/1, 2017 at 21:21 Comment(1)
I had exactly the same problem. Thank you for your answer. :)Stale
B
-1

For me nothing worked seems have to reinstall Xcode all over again. Jenkins keeps giving the same error. You would save lot of time if you just move Xcode installation to Trash and reinstall. Ensure you run the codesign command from command line atleast once.

Even after if you get the same error try setting 'Unlock Keychain?' property within Jenkins and give path to your login.keychain under /Users/${USER}/Library/Keychains/login.keychain

I hope god be with you after that.

Bookish answered 16/9, 2014 at 12:35 Comment(0)
H
-1

In my case, this was caused by a keychain being created with a default timeout of 300s and a long xcode compile lasting more than 300s. The workaround, for me, was to invoke:

security set-keychain-settings -t <longer timeout in seconds> <keychain>

immediately after creating the temporary keychain.

Hail answered 27/10, 2015 at 9:37 Comment(0)
N
-1

I ran through all these suggestions and was still having problems using fastlane's gym in a Jenkins job. I had the certificate installed and keychain unlocked, and was able to codesign on the slave when I manually ran the codesign command on the command line.

As a workaround, if Jenkins connects to the slave using JNLP instead of SSH, you'll be able to codesign.

Nocuous answered 29/10, 2016 at 13:7 Comment(0)
U
-1

For me it happens when there is a second keychain added manually and it's locked. For some reason codesign tries to access the locked keychain and fails even though the certificates are in the login keychain (and is unlocked). Unlocking the second one solves the problem. Just doesn't make sense to me.

Urnfield answered 7/9, 2017 at 21:55 Comment(1)
It will try the first keychain that matches the Hash of the signing key. So, it is important to have it in one keychain, and that keychain is unlocked.Jevons
P
-2

After trying a number of the above solutions. I realized that one factor I had, was that I was starting the build using the ION Console. When I switched back to making the build from the Terminal app, everything worked just fine.

Paulo answered 6/2, 2015 at 2:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.