Per-device exemptions using flag files

Setting and removing flag files can be a quick, reliable way to identify Macs that should be included (or exempted) from certain actions.

Per-device exemptions using flag files

There are plenty of ways to exempt policies or devices from certain actions. Previously, I detailed a way to set up your MacManage configuration to allow individual policies to opt out of displaying an installer. This time around, we'll look at a more universal method you can use to flag individual computers, or groups of computers, from being targeted by a script or installer.

Flag files

No matter which MDM platform you use (most of my work is in Addigy, with some history in JAMF, and familiarity with Meraki), you should be able to set up condition scripts for your software installers. You're probably already familiar with some of the most common types of conditions - does the Mac have a compatible operating system, is the version of the software you're about to install newer than what the computer already has, etc. Similar to checking for an existing version of an app, you could also set up a script to look for a specific file - if that file is found (or not found, at your discretion), the installer can bail out.

I refer to these files as "flag files" - our goal is to flag ceratin Macs to either be explicitly targeted for (or exempt from) specific actions. You could use flag files to:

  • Flag a Mac that has available software updates
  • Flag a Mac that should be allowed to read and write to external drives
  • Flag a Mac that hasn't enrolled in MDM
  • Flag a Mac that has Find My Mac enabled

You can push flag files to Macs by hand, or have them written by recurring maintenance items. Either way, their anatomy can be incredibly simple, as their contents can have as much, or little, information as you please.

To explore this, here's how I recently set up a flag file system for a client who was transitioning to a new endpoint protection software (it's passé to call it "antivirus"), and one Mac needed to retain the older app.

1 – Write the flag file

To create a basic flag file, we're just going to touch it - this will create a blank/empty file at the location we specify. Since I just need to know if the flag file is there or not, this isn't as complex as creating a file and echoing text into it:

touch /Library/Addigy/ntiva/data/noCrowdstrike.dat
Using touch to create a flag file

The touch command is wonderfully simple, and in this workflow, we don't need to stress about updating its permissions, the file just needs to exist. In the above example, I've placed the flag file in a directory that will be automatically deleted when the device un-enrolls from management, just to keep things nice and tidy during off-boardings.

2 – Bailout if the flag file is found

Once the flag is planted, you'll need to append your condition script with a check to look for the flag file. If detected, you can bail out before any other checks are run, making sure that any recurring actions taken by your MDM have minimal overhead on the managed Mac. Even though these tasks are already lightweight, I'm a big fan of designing your code to be as considerate as possible.

# Bailout if flag file detected

FLAG="/Library/Addigy/ntiva/data/noCrowdstrike.dat"
if [[ -f "$FLAG" ]]; then
    echo "Flag detected, bailout"
    exit 1
  else
    echo "Flag not found, continue"
fi
Sample flag file detector for a condition script

3 – Deploying flags

Simple, no? Get creative with how you deploy flags and you'll find them working in many situations:

  • If you need to target a single Mac, you can just run your flag deployment script and you're done.
  • If you need to target static groups of Macs, make a flag generator script and assign it to an entire policy.
  • If you need to target Macs meeting certain criteria, take your flag generator script and assign it to a Smart Group (or Flex Policy, whatever your platform calls it) that has membership criteria (certain versions of macOS, certain apps found, disk usage thresholds reached, and so on).
  • Embed flag generators into your custom facts or extension attributes - if the output of the fact/attribute falls within certain criteria, a flag file can be created. The next time the fact/attribute runs, if the return is outside those criteria, clear the flag.

One best practice I'd always recommend would be to build both a flag generator script, and a flag remover script, so you have a fast, easy way to clear a flag once you've planted it. Future you will be grateful.

4 – Summary

# Flag Generator
FLAG="/Library/Addigy/ntiva/data/noCrowdstrike.dat"

if [[ -f "$FLAG" ]]; then
    echo "Flag detected, no action required"
  else
    echo "Flag not found, creating"
    touch "$FLAG"
fi
Sample Flag Generator
# Flag Remover
FLAG="/Library/Addigy/ntiva/data/noCrowdstrike.dat"

if [[ -f "$FLAG" ]]; then
    echo "Flag detected, deleting
    rm "$FLAG"
  else
    echo "Flag not found"
fi
Sample Flag Remover
# Bailout if flag file detected

FLAG="/Library/Addigy/ntiva/data/noCrowdstrike.dat"
if [[ -f "$FLAG" ]]; then
    echo "Flag detected, bailout"
    exit 1
  else
    echo "Flag not found, continue"
fi
Sample Flag Checker for your condition scripts