Missing certificates and keys in the keychain while using Jenkins/Hudson as Continuous Integration for iOS and Mac development

I have found a solution giving me access to the regular keychains for my Jenkins user.

In addition to specifying the UserName element in the plist as the accepted answer suggests, the trick to get access to the normal keychains for the user you specified in UserName is to also add a SessionCreate element with value true to the plist file - /Library/LaunchDaemons/org.jenkins-ci.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>EnvironmentVariables</key>
        <dict>
                <key>JENKINS_HOME</key>
                <string>/Users/Shared/Jenkins/Home</string>
        </dict>
        <key>GroupName</key>
        <string>wheel</string>
        <key>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>org.jenkins-ci</string>
        <key>ProgramArguments</key>
        <array>
                <string>/bin/bash</string>
                <string>/Library/Application Support/Jenkins/jenkins-runner.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>UserName</key>
        <string>jenkins</string>
        <key>SessionCreate</key>
        <true />
</dict>

Then restart the daemon and try running a job in Jenkins that calls security list-keychains - and you should no longer see System.keychain as the only entry but the regular login and any custom key chains you might have added to the list of keychains for the "jenkins" user.

I am now using codesigning certificates from a custom keychain on my Jenkins build server - I have not installed any certificates or keys in my System keychain.


After spending hours and days with this issue I found a fairly easy solution to this. It doesn't matter if you have a distinct username in your launchd configuration as stated above:

<key>UserName</key>
<string>user</string>

The missing certificates and keys have to be on the system keychain (/Library/Keychains/System.keychain). I found this after I setup a jenkins job which executes several security shell calls. The one which's interesting is security list-keychains:

+ security list-keychains
    "/Library/Keychains/System.keychain"
    "/Library/Keychains/applepushserviced.keychain"
    "/Library/Keychains/System.keychain"

That are the keychains jenkins will search the certificates and keys for so they should be there. After I moved my certs there it works. Make sure you also copy the »Apple Worldwide Developer Relations Certification Authority« certificate to the system keychain, otherwise you will see a CSSMERR_TP_NOT_TRUSTED error from codesign.

It is also possible to register more keychains with security list-keychains -s [path to additional keychains]. I haven't tried it but something like security list-keychains -s $HOME/Library/Keychains/login.keychain as a pre-build shell execution in jenkins might work.

EDIT: I've tried to add a user keychain to the search path with -s but I wasn't able to get it to work. So for now, we have to copy our certs and keys into the system keychain.

EDIT^2: Read and use joensson' solution instead of mine, he managed it to access the users keychain instead of just the system keychain.


We had the same problem with a hudson slave started as a launchdaemon on Mac OSX Lion. It worked, when we started the slave with webstart. The only difference we spotted was a different environment variable.

com.apple.java.jvmTask=WebStart

works, if we started the slave without webstart the variable was

com.apple.java.jvmTask=CommandLine.java

We found no way to influence the value upfront. I suggest you create a new node in Hudson, running on the same machine and started by webstart. For starting the slave we use the following launchdaemon configuration:

<?xml version"1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>jenkins</string>
    <key>UserName</key>
    <string>apple</string>
    <key>Program</key>
    <string>/usr/bin/javaws</string>
    <key>ProgramArguments</key>
    <array>
        <string>-verbose</string>
        <string>-wait</string>
        <string>http://<hudson-hostname>:8080/computer/<node-name>/slave-agent.jnlp</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>WorkingDirectory</key>
    <string>/Users/apple</string>
</dict>
</plist>