This is a continuation of my own old post that became inactive to regain traction. I am trying to resolve issues that arise when distributing a macOS app with a SysExt Network Extension (Packet Tunnel) outside the App Store using a Developer ID Certificate.
To directly distribute the app, I start with exporting the .app via Archive in Xcode. After that, I create a new Developer ID provisioning profile for both the app and sysext and replace the embedded ones in the .app package.
After I have replaced the provisioning profiles and the have the entitlements files ready, I start signing the frameworks, sysext and parent app.
codesign --force --options runtime --timestamp --sign "Developer ID Application: <name>"<app>.app/Contents/Library/SystemExtensions/<sysext>.systemextension/Contents/Frameworks/<fw>.framework/Versions/A/<fw>
codesign --force --options runtime --timestamp --sign "Developer ID Application: <name>" <app>.app/Contents/Frameworks/<fw>.framework/
codesign --force --options runtime --entitlements dist-vpn.entitlements --timestamp --sign "Developer ID Application: <name>" <app>.app/Contents/Library/SystemExtensions/<sysext>.systemextension/Contents/MacOS/<sysext>
codesign --force --options runtime --entitlements dist.entitlements --timestamp --sign "Developer ID Application: <name>" <app>.app
After validation is successful with
codesign --verify --deep --strict --verbose=4 <app>.app
I zip the package, notarize and staple it
ditto -c -k --keepParent "<app>.app" "<app>..zip"
xcrun notarytool submit <app>.zip --keychain-profile “”<credents> --wait
xcrun stapler staple <app>.app
After that I finish creating signed and notarized .dmg/.pkg.
hdiutil create -volname “<app>” -srcfolder “<app>.app/" -ov -format UDZO ./<app>.dmg
codesign --force --sign "Developer ID Application: <name>" <app>.dmg
xcrun notarytool submit <app>.dmg --keychain-profile "<credentials>" --wait
xcrun stapler staple <app>.dmg
Then when I move the .dmg to a clean system, open the .dmg, move the .app to the Applications folder, the attempt to run it fails with “The application “<app>” can’t be opened.”. When I look into the console, the gatekeeper disallows the launch job with the message:
86127 debug ProvisioningProfiles taskgated-helper ConfigurationProfiles entitlements: {
"com.apple.developer.networking.networkextension" = (
"packet-tunnel-provider-systemextension"
);
"com.apple.developer.system-extension.install" = 1;
"com.apple.developer.team-identifier" = <teamid>;
"keychain-access-groups" = (
“<teamid>.<app>.AppGroup"
);
} com.apple.ManagedClient
<app>: Unsatisfied entitlements: com.apple.developer.networking.networkextension, keychain-access-groups, com.apple.developer.system-extension.install, com.apple.developer.team-identifier
LAUNCH: Runningboard launch of <app> <private> returned RBSRequestErrorFailed, error Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x600001a25830 {Error Domain=NSPOSIXErrorDomain Code=153 "Unknown error: 153" UserInfo={NSLocalizedDescription=Launchd job spawn failed}}}, so returning -10810
I went through all possible formats (macOS-Style and iOS-Style App Group IDs) and combinations of appgroups according to the post “App Groups: macOS vs iOS: Working Towards Harmony”. But none of those work for me. The weird part is that when I try the same steps on different developer account, I am able to get the app running. What can be wrong?
Sorry I dropped the ball on your earlier thread. I wasn’t notified of your update. Still, it looks like you’ve made some progress since then, which is good.
The immediate cause of the error is that your app is using restricted entitlements that aren’t authorised by a provisioning profile. However, that just leads to the next question: Why isn’t the profile that you’ve embedded effective?
There’s a trivially correct answer to that, but it’s not the full story. Your app is missing the App ID entitlement (com.apple.application-identifier
). As explained in TN3125 Inside Code Signing: Provisioning Profiles, that entitlement is used to tie your app to its profile, so the absence of that is something you need to fix.
But, that’s not the full story because macOS 12 and later will assume that the profile embedded in the app is the right profile for that app. So the missing App ID entitlement typically only bites folks when they go to test their apps on macOS 11 or earlier.
And that brings me to this:
The weird part is that when I try the same steps on different developer account, I am able to get the app running.
This doesn’t make sense to me. Imagine if you’d correctly applied the App ID entitlement. Then the App ID of each of your code items would be registered to a specific team. That App ID embeds the bundle ID, so the bundle ID is also effectively registered to that team. If you take an app from team A and try to re-sign it as team B, that’s not going to work without you changing the bundle ID along the way. Specifically:
-
For the app to connect to its profile, it needs to be signed with the App ID entitlement.
-
The value of that App ID entitlement must match the value in the profile.
-
The profile ties together a bunch of things, including the App ID and the authorised certificates.
-
But it’s impossible to create a profile for team B that authorises an App ID that’s registered team A. The Developer website won’t let you do that, and for good reason: The clear ownership of App IDs is a foundation of Apple’s code signing security model.
The only way to achieve your goal is to change the bundle ID, which changes the App ID, which you can register to team B, and from there generate a valid profile.
This was exactly the issue I was trying to explain in your earlier thread.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"