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

Answered by EdwardD20 in 749782022

@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**...; }

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?

Accepted Answer

@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

# 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"

@eskimo - Did I lose you? :(

Did I lose you?

Nope, I’ve just been somewhat out of the office.

You no longer receive an email notification from Apple

Right. I confirmed with the notary team that this is expected. And I did that soon enough that I was able to add this tidbit to TN3147 Migrating to the latest notarization tool.

Strange.

Yeah, this is a recent, and annoying, bug in DevForums.

# Builds with **Apple Development**, not **Developer ID Application**

You’re creating two builds there:

  • The one in the Xcode archive

  • The one exported from the Xcode archive

I’d expect the first to be Apple Development signed and the second Developer ID signed. Presumably you’re seeing both as Apple Development signed?

Share and Enjoy

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

Just to clarify:

Just to clarify:

How did you generate that screen shot?

Share and Enjoy

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

I guess this ends as an unsolved (undoable?) issue. :(

Did you miss my last post?

Yes. If you reply in comments, I’m not notified. See tip 5 in Quinn’s Top Ten DevForums Tips.

I exported the Archive, did a Show Package Contents on the .app, opened Contents, then did a quick view on embedded.provisionprofile.

OK. That Quick Look functionality is cool but, if you want to see the real info, it’s best to dump profiles using the command line. TN3125 Inside Code Signing: Provisioning Profiles shows how.

Anyway, with regards that screen shot, I’m confused by your confusion (-: The item you labelled “My Developer ID code” is your App ID. This consists of your App ID prefix, 7WNRPT262U [1], and your bundle ID, com.heat.Meteorologist. It’s best if your App ID prefix matches your Team ID. That’s the case here, which is good.

The item you labelled “Not my Developer ID” is a list of Apple Development certificates. These are, indeed, not your Developer ID certificates. Those should start with Developer ID Application.

When you said “I exported the Archive”, how did you export it? From the command line? Or from the Xcode organiser?

Share and Enjoy

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

[1] I had to type that in my hand. If you dump the profile using the command line, you can then copy snippets as text, which makes everyone’s life easier.

Thank you for the DevForums tip.

I shared the entire script I'm using. All being done via the command line.

@eskimo - Did I not reply correctly?

Did I not reply correctly?

I think you need more help than I have time for here on DevForums. I recommend that you open a DTS tech support incident so that I can allocate the time to investigate your issue in more depth.

If you do open a TSI, make sure to reference this thread for context.

Share and Enjoy

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

I opened a TSI which allowed more time and effort into finding the solution and it turned out to be very simple. In my ExportOptions.plist file, I needed:

	&lt;key>method&lt;&#x2F;key>
	&lt;string>developer-id&lt;&#x2F;string>
Hardened Runtime for distribution outside the Mac App store
 
 
Q