Check for existence of a kernel extension?

hendersond
New Contributor III

We have a number of applications that install kernel extensions. I was told by Jamf support that the kernel extension needs to be installed via a config profile BEFORE the policy that installs the application runs. There are two ways to do this:

  1. Create a separate config profile for each kernel extension. Scope the policy that installs the app associated with this extension to check for the existence of this config profile before it runs. This will work but is cumbersome if a bunch of kernel extensions need to be loaded
  2. Use an extension attribute to somehow check for the existence of a particular kernel extension. If it exists, then run the policy to install the app

Does anyone know how to check for the existence of a kernel extension?

21 REPLIES 21

Hugonaut
Valued Contributor

in terminal run

sudo sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy

then you will be in the sqlite3 db and prompted with

sqlite> vs Computer:!Username$:

then once in the database run

SELECT * FROM kext_policy;

this will populated all your installed kexts

________________
Looking for a Jamf Managed Service Provider? Look no further than Rocketman

hendersond
New Contributor III

I do know how to get a list of kernel extensions via the command line. How can I make an extension attribute that check for the existence of a particular one so I can use the extension attribute to trigger the install of the app via a policy?

tdclark
Contributor

I can't remember where I found this script, (so I apologize to the genius author who wrote it) but it does a nice job of creating a CSV file that you can use to create a Config Profile with all the KEXT's you want to allow.

#!/bin/sh
# Gather list of User Approved Kernel Extensions. 20180313 DM

folder=/Library/COMPANY/SearchResults
file=checkKEXTs.csv

# Create folder
/bin/mkdir -p ${folder}
/usr/sbin/chown root:admin ${folder}
/bin/chmod 755 ${folder}

/usr/bin/sqlite3 -csv /var/db/SystemPolicyConfiguration/KextPolicy "select team_id,bundle_id from kext_policy" > ${folder}/${file}

exit 0

sshort
Valued Contributor
I do know how to get a list of kernel extensions via the command line. How can I make an extension attribute that check for the existence of a particular one so I can use the extension attribute to trigger the install of the app via a policy?

@hendersond This seems a bit backwards, the kext profile should be in place before an app is launched for the first time, otherwise a user is going to get a prompt. So in this scenario it sounds like you're using an extension attribute to search for the kernel extension of an app that is not yet present, and then based off the result, install the app??

Unless your org has a strict policy to only allow whitelisted kexts on Macs that need X app installed, I would just create a profile of the "core" apps that your org uses, and then push to all your devices. A whitelisted kext doesn't care if the app is already installed or not when you install the profile.

scottb
Valued Contributor III
Unless your org has a strict policy to only allow whitelisted kexts on Macs that need X app installed, I would just create a profile of the "core" apps that your org uses, and then push to all your devices. A whitelisted kext doesn't care if the app is already installed or not when you install the profile.

That ^

hendersond
New Contributor III

I am think I am confused about the order of operations here. We have an Application that we want to install on ever Mac called vCastSender. I installed it manually on my Mac and was hit with the message to go to the Security System Preference to approve the kernel extension which I did.

I now want to use Jamf to install this. I have a config profile with the kernel extension and a policy that installs the app. I was told that the config profile had to be installed before the Application or the kernel extension would not be installed correctly. I could link the install of the Application to the existence of the config profile. This would work with one downside. I would need a separate config profile for each kernel extension I wanted to load. Why is that?

Let's say I had config profile that allows one kernel extension and I linked that to loading of the App. The config profile loads first then the Application and everything works fine. I then want to install a second Application that also loads a kernel extension. If I add this kernel extension to the existing config profile it might not work. The Application gets installed before the updated config profile gets pushed out and the kernel extension never gets loaded

sdagley
Honored Contributor II

@hendersond To avoid the problem you describe I think you'll find the consensus for enabling kernel extensions via Config Profile is to create one Profile containing every kext used in your organization and targeting any Mac running 10.13.4 or newer for it. Don't deploy the Profile to older OS versions as it'll deploy but not be processed, and if you then upgrade the OS on that Mac it doesn't automatically re-install.

hendersond
New Contributor III

But what happens when we have a new piece of software that we need to deploy through a policy to install an application and it needs a kernel extension?
- We add the kernel extension to the one config profile that has all the kernel extensions
- We make a policy to deploy the application

If the Mac gets the policy BEFORE getting the new config profile, the application will not install successfully since the kernel extension was not allowed at the time the policy ran.

JustDeWon
Contributor III

@hendersond there is really no way around this.. It's a simple, don't push out a policy unless the profile is installed on the machine. What you could do is create an Extension Attribute searching for a specific profile, then create a smart group based off the EA. From there you would create a policy scoped to that Smart Group. So however many Config profiles, you need to create the EA for them. As an example of one..

#!/bin/sh

profiles=$(profiles -C -v | grep attribute | awk '/name/{$1=$2=$3=""; print $0}' | grep "name of Profile")

if [[ ! -z "$profiles" ]]; then
    echo "<result>$profiles</result>"
else
    echo "<result>Not Installed</result>"
fi

exit 0

mm2270
Legendary Contributor II

I agree that creating Smart Groups for machines that have the specific profiles already installed may be a good approach to know which systems can have the software installed.
However, Configuration Profiles are standard Smart Group criteria items these days, so there shouldn't be a need for an Extension Attribute for each one.
When in Criteria, click on Show Advanced Criteria and look for "Profile Name" From there, you will be able to choose a name from a list by clicking the ellipses button and choosing one. Or you can enter your own if needed.

595509bebe554d818dc415687d239eda

With this approach, you can be reasonably sure that whatever KEXT approval profile is needed before the software is installed is there.
I say reasonably, because inventory information for devices is only as good as the last collected inventory for any given system. There's always a remote possibility that a profile may become unscoped/removed at some point, but the inventory won't reflect that right away. It's a minor possibility though, so not something to really be concerned about.

JustDeWon
Contributor III

@mm2270 .. lol, I'm so stuck with the old "Casper" way of Smart Groups needing custom EA's, I keep forgetting that they've been updated. Good to know there is now a Profiles one..

mm2270
Legendary Contributor II

@JustDeWon No worries! 🙂 I totally get it. If I hadn't been forced to start over with a fresh Jamf Pro instance when I changed positions/roles a few months ago, I might still have a lot of crusty stuff and old EAs and other workarounds that I created a long time ago when they were necessary, but are now no longer useful.
Not that I can complain. Those "workarounds" served us well until they officially made it into the product. 🙂

hendersond
New Contributor III

Thanks everyone for your help, learned something new today. I am now ready to push out this new Application

hendersond
New Contributor III

I spoke too soon, I think the Smartgroup that looks for a config profile also will not work. Back to my example
1. I create a config profile and it contains one kernel extension
2. I create a policy to install an application that also installs the kernel extension
3. I create a Smartgroup that looks for the existence of the config profile
4. I use this Smartgroup as the scope to install the application

The above method will ensure that the config profile that allows the kernel extension is installed BEFORE the application is installed

Now I have a second application that needs to be installed and it also has a kernel extension
1. I add the kernel extension to the existing config profile that already contains one kernel extension
2. I create a policy to install this application
3. I use the Smartgroup already created to scope this new application

The problem is the computers I am trying to install this new application on already have the config profile. This might be the version of the config profile previously installed that allows just one kernel extension or they may have received the updated profile with both kernel extensions. If the policy that installs the application runs BEFORE a machine gets the updated config profile, the application will not install properly.

Is there any way to check using a Smartgroup that a computer not only has the config profile but the config profile contains a particular kernel extension?

JustDeWon
Contributor III

@hendersond ,

Edit: Make sure you are deploying to All on the config profile change. That could by itself be the issue. Instead of new users. So any new policies you scope to that SmartGroup, they will have the updated config profile.

Completely misread what you stated at first.

sdagley
Honored Contributor II

@hendersond How fast are you at creating new policies to deploy applications? When you create/change a Computer Level Configuration Profile your JSS will send a message via APNS to all Macs scoped by the profile (unless you select new only in the prompt asking if you want it installed to machines currently in scope + new or just new) that they need to download the new profile and install it. Every Mac that's online, and can reach your JSS, should have done that in a few minutes and well before you're likely to finish creating a new policy from scratch.

hendersond
New Contributor III

I have a lot of Macs and when editing this config profile I do send it to all of them. Are we sure they will all get this new config profile BEFORE the application is installed via a policy. If I am not 100% sure this will happen I will end up creating a separate config profile for each app that also installs a kernel extension

sdagley
Honored Contributor II

@hendersond I'd recommend you create a Computer Level configuration profile with an innocuous payload, say a dummy Privacy Preferences Policy Control, scoped to all your Macs then watch the Completed, Pending, and Failed stats on the Configuration Profiles screen to get a feel for how rapidly it deploys. That's not a live update page so you'll need to reload periodically.

JustDeWon
Contributor III

To be totally honest. If you're going to continue updating the Config Profile and expect the result to be 100% accurate. Your best bet is to create a config profile for each application.

This is also good for "troubleshooting", as you know what would be the culprit if any issues arises. That way you can actually view the status as @sdagley pointed out.

tcandela
Valued Contributor

@hendersond how did you get the policy to also install the config profile?

i have a seperate config profile with the applications TeamIdentifier
and i have a seperate policy that installs the application

the policy is a self service policy

Thelunes
New Contributor

@hendersond In case anyone is still wondering how to take @Hugonaut 's suggestion to create an extension attribute:

#!/bin/bash

sudo sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy <<EOF
SELECT * FROM kext_policy;
EOF