Manipulating the System Policy Database with Configuration Profiles, Part 2

You’re going to want to read Part 1 of this piece first. It covered managing the installation of packages that are not notarized. This section of the article covers the operational limits of doing the same thing for applications, using the operation:execute verb. There are several caveats to all of this that may make this procedure non-viable. But, there’s also a way to make it work, so here we are.

The Mechanism

Last time, we got a package installer whitelisted. That’s a simple operation: whitelist the certificate of the installer with the right Requirements payload, and the installer package will pass through quarantine checks unobstructed.

But what about a non-notarized application?

There are some software manufacturers who have challenging installers (which is to say: non-pkg, app-based installers) that require a different sort of whitelisting. In this example, we’re going to be reviewing the Cisco Webex Add-in. The installer is an application, intended to be run by a user. It’s a signed application, thankfully, and that gives us everything we need to build a whitelist to recover from the lack of a notarization process.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadDescription</key>
            <string>Configures Gatekeeper to accept developer certificate</string>
            <key>PayloadDisplayName</key>
            <string>System Policy Rule</string>
            <key>PayloadIdentifier</key>
            <string>com.apple.systempolicy.rule.5B8D7EE6-199A-48BC-B317-F223FB036552</string>
            <key>PayloadType</key>
            <string>com.apple.systempolicy.rule</string>
            <key>PayloadUUID</key>
            <string>5B8D7EE6-199A-48BC-B317-F223FB036552</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>Requirement</key>
            <string>anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = DE8Y96K9QP</string>
            <key>OperationType</key>
            <string>operation:execute</string>
            <key>Priority</key>
            <real>100.0</real>
            <key>Comment</key>
            <string>Test configuration 5 - OperationType: operation:execute</string>
        </dict>
    </array>
    <key>PayloadDisplayName</key>
    <string>Gatekeeper Config</string>
    <key>PayloadIdentifier</key>
    <string>com.example.156ED537-CB5E-4AC9-80D6-376234F2DF60</string>
    <key>PayloadOrganization</key>
    <string>Example</string>
    <key>PayloadScope</key>
    <string>System</string>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadUUID</key>
    <string>156ED537-CB5E-4AC9-80D6-376234F2DF60</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>
</plist>

The Requirement payload in this this profile might look familiar. The identifier and certificate language looks a lot like the Privacy Preferences Policy Control payload that was introduced with macOS 10.14 Mojave. Much as you would with with one of those payloads, deriving the contents is as simple as interrogating the application with codesign:

codesign -dr - /path/to/Application.app

This will return what you need to embed:

identifier "com.cisco.webex.Cisco-WebEx-Add-On" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = DE8Y96K9QP

Once again, this is adding entries to the /var/db/SystemPolicy database, which Gatekeeper uses at inspection time to determine whether or not something passes. This is your pass past the security desk.

There Are Big Caveats

Okay, here’s where it gets less ideal.

There is only one road to a successful deployment.

This profile cannot be installed before macOS 10.15 Catalina is installed. Not because the profile can’t be interpreted by Mojave – it can – but because the installation process for macOS 10.15 might reset the SystemPolicy database.

And, because profiles are only ever interpreted at the time of install, you now have a profile that is installed on the machine, but no longer in the database that Gatekeeper uses.

One such failed case is here.

Once the profile’s installed, it’s installed, and it can’t or won’t be reinterpreted by the System. This is a huge flaw in the configuration profiles system overall, and we’ve seen it come back to bite us in the behind each of the last two revisions of the OS, with no revision in the system. The lack of defined-state management with configuration profiles, coupled with management-via-UDP profile delivery, means that we’re kinda stuck.

So, let’s talk about how this can go poorly.

Some MDMs have a method for reinstalling certain types of profiles after an operating system upgrade to make sure that profiles get reinterpreted, but none of those mechanisms are foolproof. There’s almost always a little lag between those mechanisms hitting and the upgrade completing.

What happens then?

Well, if the application is launched, and it won’t pass the Quarantine check, then the file gets marked as a failed application, and that file is, for all intents and purposes, blackballed.

Normally, that would mean the only recourse at that time is to uninstall and reinstall the application. If you have a good uninstall script, this could be a solution. There are some applications that aren’t such good citizens about containerization and slop their resources all over your filesystem.

But here’s the rub, even if you do catch all the resources, now you’re in an exorcism situation. There are some applications that just won’t be bypassed this way. I was able to get this working, but a colleague with another MDM has not been successful as of press time in making this work 100% of the time.

Well, That’s Bad. Now What?

Well, for starters, if you can, deploy these tools with other means. Remember that passing these checks are a lot like getting pass the security desk. Tools like the Jamf binary and root agents like Munki can build an Employees Entrance for key personnel. Installing with these tools bypasses the Quarantine process, which means notarization checks won’t apply.

If you’re expecting for users to directly download and manually install software that isn’t signed and notarized, you’re going to need to either have a robust help desk that can handle the volume, you’ll need to put pressure on your software vendor to do the responsible thing and fix their installer or fix their deployment mechanism(1).

Whitelisting is going to be a game of whackamole. If you have to play it, you’re going to need to plan for two things:

  1. Deliver your profiles with an MDM that can rapidly re-deliver the necessary profiles after a major version upgrade.
  2. Consider delivering your major version upgrade along-side a pre-install script that scrubs out packages that aren’t properly notarized.

Whatever you do, this is a use-case you will need to prepare your service desk for.

1.