When debugging code signing problems it’s better to look at the built binary rather than your source code. That is, rather than look at MyApp.entitlements, which is source code, look at the entitlements actually baked into the app’s code signature:
% codesign -d --entitlements - /path/to/MyApp.app
Likewise for the Info.plist:
% plutil -p /path/to/MyApp.app/Contents/Info.plist
And the provisioning profile:
% security cms -D -i MyApp.app/Contents/embedded.provisionprofile | plutil -p -
In terms of how you get this to build, here’s what I’d did:
-
Open the project in Xcode.
-
For both targets, in the Signing & Capabilities editor, set the Team popup to your team.
-
In the Extension target, remove the Endpoint Security capability.
-
Build the app.
This produces an app like this:
% codesign -d -vvv --entitlements - SampleEndpointApp.app
…
Authority=Apple Development: Quinn Quinn (7XFU7D52S4)
…
[Dict]
[Key] com.apple.application-identifier
[Value]
[String] SKMME9E2Y8.com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8
[Key] com.apple.developer.system-extension.install
[Value]
[Bool] true
…
% plutil -p SampleEndpointApp.app/Contents/Info.plist
{
… nothing special here …
}
% security cms -D -i SampleEndpointApp.app/Contents/embedded.provisionprofile | plutil -p -
{
…
"Entitlements" => {
"com.apple.application-identifier" => "SKMME9E2Y8.com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8"
"com.apple.developer.system-extension.install" => 1
"com.apple.developer.team-identifier" => "SKMME9E2Y8"
"keychain-access-groups" => [
0 => "SKMME9E2Y8.*"
]
}
…
}
And an extension like this:
% codesign -d -vvv --entitlements - SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension
…
Authority=Apple Development: Quinn Quinn (7XFU7D52S4)
…
[Dict]
[Key] com.apple.security.get-task-allow
[Value]
[Bool] true
% plutil -p SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension/Contents/Info.plist
{
… standard stuff elided …
"NSSystemExtensionUsageDescription" => ""
}
% ls -lh SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension/Contents/embedded.provisionprofile
ls: SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension/Contents/embedded.provisionprofile: No such file or directory
Note that there’s no provisioning profile because the sysex doesn’t claim any restricted entitlements (com.apple.security.get-task-allow is unrestricted). Of course that’s the problem you’re trying to solve!
To fix this, you need to re-sign the extension and then re-sign the app. Let’s start with the extension.
% codesign -d --entitlements tmp.entitlements --xml SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension
Executable=/Users/quinn/Library/Developer/Xcode/DerivedData/SampleEndpointApp-ayhxblzmgtjjygbuxmwgcsgnoifh/Build/Products/Debug/SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension/Contents/MacOS/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension
% plutil -p tmp.entitlements
{
"com.apple.security.get-task-allow" => 1
}
% /usr/libexec/PlistBuddy -c "Add :com.apple.developer.endpoint-security.client bool true" tmp.entitlements
% plutil -p tmp.entitlements
{
"com.apple.developer.endpoint-security.client" => 1
"com.apple.security.get-task-allow" => 1
}
% codesign -s "Apple Development: Quinn Quinn (7XFU7D52S4)" -f --preserve-metadata=identifier,flags,runtime --entitlements tmp.entitlements SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension
SampleEndpointApp.app/Contents/Library/SystemExtensions/com.example.apple-samplecode.SampleEndpointAppSKMME9E2Y8.Extension.systemextension: replacing existing signature
And now the app:
% codesign -s "Apple Development: Quinn Quinn (7XFU7D52S4)" -f --preserve-metadata=identifier,entitlements,flags,runtime SampleEndpointApp.app
SampleEndpointApp.app: replacing existing signature
Now, I don’t have time to do a full end-to-end test of this stuff today. However, the above should get you an app that’s signed the same way as the app I used when doing the test in this post, which I’d expect to work.
Finally, a word of warning about this:
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
The sample does not require you to disable these hardened runtime security enhancements and I strongly encourage you not to do that. This is important for two reasons:
-
Historically, the system required that ES clients have the hardened runtime fully enabled. If you used these entitlements it would reject your ES client. I believe that we’ve relaxed many of these restrictions, but I still recommend that you avoid these entitlements, especially as the sample app doesn’t need them.
-
The library validation entitlement is a common source of Gatekeeper problems. You can get around those [1] but, again, it’s better to just avoid this entitlement entirely.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] See Resolving Gatekeeper Problems Caused by Dangling Load Command Paths.