Pre-approving network extension VPN permission with MDM

I have a macOS app with Network Extension. It requests VPN permission with the code like this:

self.tunnelManager = [NETunnelProviderManager new];
NETunnelProviderProtocol *protocol = [NETunnelProviderProtocol new];
protocol.providerBundleIdentifier = @"com.myapp.macos.tunnelprovider";
self.tunnelManager.protocolConfiguration = protocol;
[self.tunnelManager setOnDemandRules:nil];
[self.tunnelManager setOnDemandEnabled:NO];
[self.tunnelManager setEnabled:YES];
[self.tunnelManager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable saveError) {}];

A lot of my app users are businesses and they would like to have pre-install VPN config. We currently do it like this:

<array>
    <dict>
        <key>PayloadDisplayName</key>
        <string>MyAppName</string>
        <key>PayloadType</key>
        <string>com.apple.vpn.managed</string>
        <key>UserDefinedName</key>
        <string>MyAppName</string>
        <key>VPN</key>
        <dict>
            <key>AuthenticationMethod</key>
            <string>Password</string>
            <key>ProviderBundleIdentifier</key>
            <string>com.myapp.macos.tunnelprovider</string>
            <key>ProviderDesignatedRequirement</key>
            <string>anchor apple generic and identifier "com.myapp.macos.tunnelprovider" and (certificate leaf[field.1.2.3] /* exists */ or certificate 1[field.1.2.3] /* exists */ and certificate leaf[field.1.2.3] /* exists */ and certificate leaf[subject.OU] = "123")</string>
            <key>RemoteAddress</key>
            <string/>
        </dict>
        <key>VPNSubType</key>
        <string>com.myapp.macos</string>
        <key>VPNType</key>
        <string>VPN</string>
    </dict>
</array>

Now, if the users installs my app first and allows the VPN permission, then MDM will set the profile above to the user, the user will end up with two VPN profiles in settings. They will be called "My App" and "My App 1"

At first we thought it's harmless, but users with two VPN profiles sometimes have app update issues, where after update the newer version of client fails to communicate with the older version of tunnel, it cannot even tell it to quit. The tunnel must be force-quit by the user in this case.

We suspect two profiles to be the reason for that. Is there a way to make sure duplicate VPN profiles do not happen?

Answered by DTS Engineer in 809029022

Are you looking to to this from your app? Or from MDM?

From your app, you can call the [loadAllFromPreferences(completionHandler:) method][ref], which will return configurations that you created yourself and those from any configuration profiles you have installed.

For the MDM case, that’s not really my field, but I don’t think that configurations created by your app get reflected to MDM.

Share and Enjoy

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

Accepted Answer

Are you looking to to this from your app? Or from MDM?

From your app, you can call the [loadAllFromPreferences(completionHandler:) method][ref], which will return configurations that you created yourself and those from any configuration profiles you have installed.

For the MDM case, that’s not really my field, but I don’t think that configurations created by your app get reflected to MDM.

Share and Enjoy

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

I missed the part where after loadAllFromPreferences you can check which one is connected, and re-connect to that.. This fixes my bug

In pkg preinstall and postinstall we also now quit app and stray running tunnel if any + remove duplicate profiles

Pre-approving network extension VPN permission with MDM
 
 
Q