Hardened Runtime for distribution outside the Mac App store

I am working on an open source weather app for distribution outside the Mac App store: https://sourceforge.net/projects/heat-meteo

The project builds and runs fine in Xcode.

The batch build script was using ALTOOL which can’t/shouldn’t be used anymore. I am trying to set it up for notarytool.

This is what I think is now happening.

Again, all works fine in the Xcode debugger.

In Xcode, the build is setup with Automatically manage signing for both Debug and Release. They are using my Apple Development account, 4V7….

What I have read if that if I want to distribute outside of the Mac App store, it must be signed with my Developer ID Application, 7VN….

I tried to do an xcodebuild then codesign to switch from 4V7 to 7VN. That actually worked. codesign -dv --verbose=4 <app> shows the correct account. However when I do that, codesign --display --verbose <app> shows I lost the hardened runtime and then notarytool fails because hardened runtime isn’t set. The hardened runtime flag IS set before the codesign command.

I can physically turn off Automatically manage signing in Xcode for Release, but how to I select my Developer ID Application account? It does not appear to be a choice.

If it matters, the application needs both WeatherKit and Location entitlements and they are set to YES in the entitlements file.

I’m guessing, and this pure guessing, I need to adjust something in https://developer.apple.com/account but I don’t know what.

Thanks in advance.

Ed

Accepted Reply

@eskimo - how should should the Xcode archive take to process? It's ben over 24 hours with no feedback.

I also experimented with xcodebuild options for archive (-exportArchive -exportPath ./Build/Release -archivePath ./Build/Archive -exportOptionsPlist exportOptions.plist) and I get this message: error: archive at path '/Users/ed/Documents/Xcode-Projects/meteorologist/trunk/Build/Archive' is malformed

If it matters, my exportOptions.plist file looks like this: { destination = export; signingCertificate = "Developer ID Application"; signingStyle = automatic; teamID = 7**...; }

Replies

If your app builds with Xcode then I recommend that you distribute from an Xcode archive. I go into this in great detail in Creating Distribution-Signed Code for Mac.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I've read your article (before) and I'll admit I can't follow it. I'll go back and try again.

That said, how can make this work with xcodebuild?

@eskimo - how should should the Xcode archive take to process? It's ben over 24 hours with no feedback.

I also experimented with xcodebuild options for archive (-exportArchive -exportPath ./Build/Release -archivePath ./Build/Archive -exportOptionsPlist exportOptions.plist) and I get this message: error: archive at path '/Users/ed/Documents/Xcode-Projects/meteorologist/trunk/Build/Archive' is malformed

If it matters, my exportOptions.plist file looks like this: { destination = export; signingCertificate = "Developer ID Application"; signingStyle = automatic; teamID = 7**...; }

Progress on a minuscule front. I didn't realize the archive action was separate from the -exportArchive option. Once I split them into 2 xcodebuild commands I was able to create an archive.

Along the way I discovered that with the archive action, -archivePath is the name of the archive, not the path as the name implies. However with the -exportArchive option, -archivePath is the path as the name implies.

Moving past that, my xcodebuild -exportArchive option now throws the following error:

Error Domain=IDEFoundationErrorDomain Code=1 "exportOptionsPlist error for key "method": expected one of {}, but found development" UserInfo={NSLocalizedDescription=exportOptionsPlist error for key "method": expected one of {}, but found development}

The gotcha is that I don't have the "method" key in my plist file. According to xcodebuild -help, that is a default value.

{
 destination = export;
 signingCertificate = "Developer ID Application";
 signingStyle = automatic;
 teamID = 7**...;
}

The trick to debug problems like this is to divide the process into steps and then try different steps with Xcode and the various command-line tools. The three basic steps are:

  1. Build an archive.

  2. Export the archive as a Developer ID-signed product.

  3. Submit that produce for notarising.

To start, do all three with Xcode:

  1. To build the archive, choose Product > Archive.

  2. To export and notarise the archive, select it in the Xcode organiser and click Distribute App then follow the Developer ID > Upload workflow.

Does that work?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I did the second part. In Xcode, Product > Archive, select the new archive, click on Distribute App, selected Developer ID, Upload, Automatically Manage Signing, wait, then click on Upload.

Message says "Uploaded "Meteorologist" to Apple notary service. You will receive a notification when your app is ready for distribution."

I've done this 3 times now and never received any messages from Apple.

Ah, another big change from ALTOOL. You no longer receive an email notification from Apple (like I've been waiting for). The message the Xcode window quietly changes and allows you to click the Export button.

Still no progress on getting xcodebuild working in my batch build script.

xcodebuild

Doing my best to follow here: https://developer.apple.com/forums/thread/701514

First, I did these two steps:

xcodebuild -project Meteorologist.xcodeproj -scheme Meteorologist -configuration Release -derivedDataPath .&#x2F;Build -allowProvisioningUpdates --options=runtime clean archive -archivePath .&#x2F;Build&#x2F;Archive.xcarchive
xcodebuild -exportArchive -archivePath .&#x2F;Build&#x2F;Archive.xcarchive  -exportOptionsPlist exportOptions.plist -exportPath .&#x2F;Build&#x2F;Release

I then get to this step:

security find-identity -p codesigning -v

which yields:

  1) 1135D8B42869FDE86A1AC385DAE5D8193FF9FAB7 "Apple Development: Edward Danley (4..)" (CSSMERR_TP_CERT_REVOKED)
  2) 6BD49D05978A4EB8ED7AC2E80685D346F4631D3A "Apple Development: Edward Danley (4..)"
  3) A6BED0BFC51147B1D08CF9C38E568B58546928D0 "Developer ID Application: Edward Danley (7..)"
  4) 0C34E70124438F42668E9E3097E888B0E0390A8C "Developer ID Application: Edward Danley (7..)"

When I get to:

codesign -s "Developer ID Application: Edward Danley" .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app

I receive:

Developer ID Application: Edward Danley (7..): ambiguous (matches "Developer ID Application: Edward Danley (7..)" and "Developer ID Application: Edward Danley (7..)" in &#x2F;Users&#x2F;ed&#x2F;Library&#x2F;Keychains&#x2F;login.keychain-db)

How do I clean up my certificates? You have another article here: https://developer.apple.com/forums/thread/674115 I was following the article you referenced here: https://help.apple.com/xcode/mac/11.4/index.html?localePath=en.lproj#/dev8a2822e0b and all I managed to do was end up with 3 copies of Developer ID :(

Ed

If you can notarise from the Xcode organiser, you can get Xcode to generate your ExportOptions.plist for you. Do a new Product > Archive and then follow the Distribute App > Developer ID > Export workflow. That’ll create a directory containing the app and various log files, include an ExportOptions.plist file. Grab that and compare it the one you’re passing to the -exportArchive command.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I'm building via a sh script. Using Xcode GUI is not what I'm shooting for.

I have found that I can sign using the key:

codesign -s "A6BED0BFC51147B1D08CF9C38E568B58546928D0" --timestamp -f -o runtime .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app

That gets me around the ambiguous match.

Before the codesign, /Build/Release/Meteorologist.app runs fine (albeit with Apple Developer).

After the codesign, the app launches but immediately says:

Location services are denied.

This is covered in the existing entitlements.

I found that I can ensure the entitlement is added/replaced as part of codesign by adding --entitlements:

codesign -s "A6BED0BFC51147B1D08CF9C38E568B58546928D0" --timestamp --entitlements .&#x2F;Meteorologist&#x2F;Meteorologist.entitlements -f -o runtime .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app

But then I get the message:

The application "Meteorologist can&#039;t be opened.

Looking around in the Console, I see this:

mac_vnode_check_signature: &#x2F;Users&#x2F;ed&#x2F;Documents&#x2F;Xcode-Projects&#x2F;meteorologist&#x2F;trunk&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app&#x2F;Contents&#x2F;MacOS&#x2F;Meteorologist: code signature validation failed fatally: When validating &#x2F;Users&#x2F;ed&#x2F;Documents&#x2F;Xcode-Projects&#x2F;meteorologist&#x2F;trunk&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app&#x2F;Contents&#x2F;MacOS&#x2F;Meteorologist:
  Code has restricted entitlements, but the validation of its code signature failed.
Unsatisfied Entitlements: com.apple.developer.weatherkit

While makes me think I'm back to square 1, except that when I use the Xcode GUI, it does work.

If I open the invalid .app (after the codesign), in Contents/info.plist, I see the entitlements saying 7... (my Developer ID) but the certificates all say Apple Development (4...)

Is that what's wrong?

I'm building via a sh script. Using Xcode GUI is not what I'm shooting for.

Right. My point is that, rather than craft your own export options property list by hand, you can get Xcode to generate it for you and then, if necessary, tweak it from there.

You seem to be heading down a path where you manually re-sign your app from the command line. That’s quite possible to do, but it should be unnecessary if your app builds from an Xcode project. For apps based on an Xcode project, you can use xcodebuild -exportArchive to export it in same way you’d get if you chose the Xcode organiser > Distribute App > Developer ID > Export workflow.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you. I did not understand that. Let me see what I can do, unless you have some sample code you can get me started.

Ed

  • As it turns out, I am using an exportOptionsPlist file and it has my Developer ID TeamID in it. It is the Certificates section that is still showing Apple Development. I don''t see an option in exportOptionsPlist for the Certificate.

    I can post my script if that would help.

Add a Comment
# Developer email address
dev_account=$(cat ~&#x2F;.altoolid)
# App-specific password
dev_passwd=$(cat ~&#x2F;.altoolpw)
# Team ID 7**.....
dev_teamid=$(cat ~&#x2F;.altooltm)
# Developer ID Application: First Last or SHA value via security find-identity -p codesigning -v
dev_codesign=$(cat ~&#x2F;.altoolcs)

xcrun notarytool store-credentials --apple-id "$dev_account" --team-id="$dev_teamid" --password "$dev_passwd" notary-scriptingosx

# xcodebuild -help

echo "{" > exportOptions.plist
echo "\tdestination = export;" >> exportOptions.plist
echo "\tsigningCertificate = \"Developer ID Application\";" >> exportOptions.plist
echo "\tsigningStyle = automatic;" >> exportOptions.plist
echo "\tteamID = ${dev_teamid};" >> exportOptions.plist
echo "}" >> exportOptions.plist

# Builds with **Apple Development**, not **Developer ID Application**
#
xcodebuild -project Meteorologist.xcodeproj -scheme Meteorologist -configuration Release -derivedDataPath .&#x2F;Build -allowProvisioningUpdates --options=runtime clean archive -archivePath .&#x2F;Build&#x2F;Archive.xcarchive
xcodebuild -exportArchive -archivePath .&#x2F;Build&#x2F;Archive.xcarchive  -exportOptionsPlist exportOptions.plist -exportPath .&#x2F;Build&#x2F;Release

# Display signing, look for runtime and Developer ID
#codesign -dv --verbose=4 .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app

#security find-identity -p codesigning -v

# Display entitlements
#codesign -d --entitlements - --xml .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app | plutil -convert xml1 -o - -

# Create a ZIP archive suitable for notarization.
&#x2F;usr&#x2F;bin&#x2F;ditto -c -k --keepParent .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.zip

# notarize
xcrun notarytool submit .&#x2F;Build&#x2F;Release&#x2F;Meteorologist.zip --wait --keychain-profile "notary-scriptingosx"  > xcodebuild.log
uuid=$(grep -m 1 -w "id:"  xcodebuild.log | awk &#039;{print $2}&#039;)
echo "UUID=${uuid}"
rm xcodebuild.log

# Show results...needs uuid from above

xcrun stapler staple ".&#x2F;Build&#x2F;Release&#x2F;Meteorologist.app"
  • Oddity. If I'm not signed in I see &#x2F;. If I'm signed in I see a forward slash ( / ). Strange.

Add a Comment