We have a mac (10.15.1) build server setup running Xcode 11 and Jenkins for CI that I want to use for notarization on release builds. However, I am unable to access the keychain item from the build server (which is started with the machine via launchd).
If I login to the mac as the jenkins user and run the same commands, everything works fine as long as I unlock the keychain. But I get a keychain error when I try to run it as part of a build job, even if I try to unlock they keychain first as part of the job:
altool[3090:62816] *** Error: The keychain returned error code: -25291. Failed to get the password for the keychain item 'blah'.
altool[3096:62956] *** Error: Use the -u option to specify the account in the keychain item 'blah'. Failed to get the password for the keychain item 'blah'.
Any tips? Jenkins seems to be able to access the syste keychain without issue, but for whatever reason I cannot move or add the password item to it; it can only seem to be in the login keychain. I really don't want to put a password in plaintext as part of the build jobl; surely there is a better way?
As far as I know,
altool
does do anything special with the keychain. I did some poking around with LLDB and, AFAICT, it’s just calling
SecItemCopyMatching
in the obvious way.
The most likely cause of this problem is the way that Jenkins is running its jobs. It’s very common for UNIX-y software to partially switch their execution context, that is, switch the traditional BSD execution context (the UIDs and GIDs, basically) but not the macOS-specific execution context (the Mach bootstrap namespace and the security context). See Technote 2083 Daemons and Agents for more background on this than is likely to be helpful.
As to what you can do about this, I think your first suggestion, using the System keychain, is likely to be the most successful. I tried this here in my office, and it seems to work.
Specifically:
On 10.15 with Xcode 11.1 installed, I used System Preferences to create
user. I made it a standard user (that is, not an admin).qnotarisation
I logged in as that user, just to make sure the account was set up correctly.
I then logged out, doing the rest of this work with the Mac’s GUI setting at the login screen.
I used SSH to log in as an admin user.
I created a small shell script to act as my daemon:
$ cat /Library/PrivilegedHelperTools/altest.sh #! /bin/sh xcrun altool --list-providers -u uuu -p @keychain:sss
.
I wrapped that in a
job:launchd
$ cat /Library/LaunchDaemons/com.example.altest.plist … <dict> <key>Label</key> <string>com.example.altest</string> <key>ProgramArguments</key> <array> <string>/Library/PrivilegedHelperTools/altest.sh</string> </array> <key>UserName</key> <string>qnotarisation</string> <key>StandardOutPath</key> <string>/Users/qnotarisation/altest-stdout.txt</string> <key>StandardErrorPath</key> <string>/Users/qnotarisation/altest-stderr.txt</string> </dict> </plist>
.
I loaded that as a
daemon:launchd
$ sudo launchctl load /Library/LaunchDaemons/com.example.altest.plist
.
I used the
tool to created a generic password in System keychain:security
$ sudo security add-generic-password -a uuu -s sss -w ppp -A /Library/Keychains/System.keychain
IMPORTANT This uses the
argument to set the ACL wide open. On a real machine, you’ll probably want to use the-A
argument.-T
I started my launchd job:
$ sudo launchctl start com.example.altest
.
After waiting a few seconds, I looked at the job’s output:
$ cat /Users/qnotarisation/altest-stderr.txt 2019-11-27 02:58:54.910 altool[1538:23135] *** Error: Failed to retrieve providers info: ( "Error Domain=ITunesConnectionOperationErrorDomain Code=-20209 \"This Apple ID has been locked for security reasons. Visit iForgot to reset your account (https://iforgot.apple.com).\" UserInfo={NSLocalizedRecoverySuggestion=This Apple ID has been locked for security reasons. Visit iForgot to reset your account (https://iforgot.apple.com)., NSLocalizedDescription=This Apple ID has been locked for security reasons. Visit iForgot to reset your account (https://iforgot.apple.com)., NSLocalizedFailureReason=App Store operation failed.}" )
.
As you can see, it found the password and attempting to contact the notary service (that failed, of course, because the account and password are completely bogus).
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
ps DTS is closed 25…29 Nov in observance of the US Thanksgiving holiday.