5

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:

But nothing works. Is this even possible?

ablarg
  • 2,400
  • 1
  • 24
  • 32
George
  • 4,189
  • 2
  • 24
  • 23

1 Answers1

12
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?

ablarg
  • 2,400
  • 1
  • 24
  • 32
  • I'll try this tonight. What would be the benefit of doing it through ssh? – George Sep 13 '19 at 05:36
  • I think you might be running into the fact that your launchctl session is not a proper login session, and therefore probably is not using the keychain you think it is (hence my printing out of available keychains) When we run this via Jenkins CI, we use an ssh connection and we don't have this issue. The ssh -o operation will hopefully give you a shell with the correct user context (which launchd does not have). – ablarg Sep 13 '19 at 17:50
  • It works! The only issue was that I woke to an alert saying my keychain didn't exist. I think this happened because I deleted tempKeychain using `rm` after I was done with it. – George Sep 14 '19 at 05:17
  • You should probably use security delete keychain instead of rm so you don't pollute Keychain App with empty keychain refs. – ablarg Sep 14 '19 at 18:11
  • I'll give that a try. Thanks for your help. I don't think I would every have figured this out on my own. – George Sep 15 '19 at 00:42
  • @ablarg thanks for the ssh tip. You can set SessionCreate in your launchd daemon file instead and then the keychain seems to be accessible - see https://stackoverflow.com/questions/47582989/launchd-not-able-to-access-mac-os-keychains . But I'm still not allowed to access spctl (GateKeeper). – Hamish Moffatt Aug 10 '22 at 06:17