It took a bit longer to get the Mac App Store version of ESEV released this cycle. Here we describe the mistakes and misunderstandings we had that led to the longer release timeline.
Apple’s application entitlements were added as far back as iOS 2.0 and Mac OS X 10.7. Apple describes an entitlement as:
a right or privilege that grants an executable particular capabilities.
This means if the application would like to read or write files, load system extensions, access certain APIs and so forth it must declare this up front in the entitlements plist file.
Entitlements are declared in the aforementioned plist, but they are also declared in the AppID you define on Apple’s developer site as part of the application signing process. They’re called “Capabilities” and not entitlements on the website. For more details on claimed vs authorized entitlements please reference Apple’s TechNote article. The AppID is combined with specific signing and distribution certificates as part of a provisioning profile. The provisioning profile is used for signing and distributing applications for different use cases like development, website download (Developer ID), App Store distribution and others.
This is where things get a little wonky. Network Extensions on macOS are implemented as System Extensions. The entitlement options for Network Extensions are detailed in Apple’s documentation.
They are:
dns-proxy
app-proxy-provider
content-filter-provider
packet-tunnel-provider
dns-proxy-systemextension
app-proxy-provider-systemextension
content-filter-provider-systemextension
packet-tunnel-provider-systemextension
dns-settings
app-push-provider
As you may note above the first four entitlements and the second set of four entitlements are duplicates of each other with the addition of a suffix -systemextension
. What was unclear to us at the start is that the same code distributed through the Mac App Store and by Developer ID requires different entitlements. This confused us as we tried to distribute the same app using different venues.
First, we generated a Developer ID
(website downloadable) signed version of the application. To do this we added the Network Extension and System Extension capabilities to the AppID on the developer webpage. Along with this change to the AppID, we created two new provisioning profiles. One for a Developer ID distributed version and one for the Mac App Store.
Next, we added the Network Extension capability in Xcode (under Signing & Capabilities
). As we mentioned in our ESEV network release post we only need the Content Filter
entitlement.
When we tried to archive for distribution we received the error message Provisioning profile doesn't match the entitlements file's value
In both the AppID (provisioning profile) and Xcode Signing & Capabilities we selected Network Extension. At this point, we were concerned about the provisioning profile cause the UI doesn’t have the same level of granularity as what we saw in Xcode. There is only one AppID checkbox for Network Extension vs five in Xcode. So we downloaded the provisioning profile from the website. Using a developer support post from Quinn we explored the contents of the provisioning profile:
nub@nubtop % security cms -D -i /Users/nub/Downloads/ESEV_Network_Developer_ID.provisionprofile
<...snip...>
<key>Entitlements</key>
<dict>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider-systemextension</string>
<string>app-proxy-provider-systemextension</string>
<string>content-filter-provider-systemextension</string>
<string>dns-proxy-systemextension</string>
<string>dns-settings</string>
</array>
<...snip...>
We tried to compare this against the entitlements plist file in Xcode. As can be seen in the screenshot below this simply showed the capability as “Content Filter”. Not super helpful.
When we chose the entitlements file via Xcode’s file browser and select Open As -> Source Code
.
We quickly see the discrepency, the Xcode version is missing the -systemextension
in the entitlement name we saw above from the provisioning profile.
Manually adding the -systemextension
allowed the archive to complete and be notarized by Apple. Why we had to manually modify the plist file didn’t make sense, but the need for the -systemextension
suffix made sense to us since the Network Extension is a System Extension…or so we thought it made sense.
Next, we tried to distribute in the Mac App Store
, but we again received the same provisioning profile entitlement match error.
This time, after a TSI support ticket to Apple on why entitlements worked for Developer ID distribution but not for Mac App Store distribution they kindly informed us that the -systemextension
is less about it being a System Extension and more about it being Developer ID distributed. So even though the code doesn’t change between the Mac App Store and the Developer ID distributions the expected entitlement name does change.
Tying this back into the start of the post. When using a Network Extension and distributing via Mac App Store
you need to use these entitlements:
dns-proxy
app-proxy-provider
content-filter-provider
packet-tunnel-provider
When distributing a Network Extension using a Developer ID
you need to use these entitlements:
dns-proxy-systemextension
app-proxy-provider-systemextension
content-filter-provider-systemextension
packet-tunnel-provider-systemextension
The final bummer is that Xcode can’t seamlessly do this for you depending on the provisioning profile selected. So to distribute the app in both places you need to manually modify the entitlements file in Xcode for each distribution.
Many thanks to Quinn "The Eskimo!"
from Apple Developer Relations for pointing out this entitlement naming subtly.
Links
- https://developer.apple.com/documentation/bundleresources/entitlements
- https://developer.apple.com/documentation/technotes/tn3125-inside-code-signing-provisioning-profiles
- https://developer.apple.com/forums/thread/685723
- https://developer.apple.com/documentation/networkextension
- https://developer.apple.com/system-extensions/
- https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_networking_networkextension