Menu Close

Hacking Falcon Sensor Grouping Tags

Leverage MDM-delivered Configuration Profiles and a custom Bash script for dynamic, yet consistent Sensor Grouping Tags in CrowdStrike Falcon

Update: 17-May-2023

CrowdStrike customers should login to the Support portal and view this article before attempting to implement this approach.

You’re also invited to up-vote Idea No. 8109: Allow Changing of Sensor Tags

Background

As we’ve considered deploying CrowdStrike Falcon on macOS, we’ve wanted to leverage Sensor Grouping Tags in a way which was dynamic, yet consistent across our fleet.

However, learning about any new software product also includes learning about its limitations.

Yet another job for system engineers.

The Goal

Server-side

We wanted to distribute one server-wide “CrowdStrike Falcon” Configuration Profile which included all the critical payloads:

  • Content Filter
  • Privacy Preferences Policy Control
  • System Extensions
“CrowdStrike Falcon” Configuration Profile with multiple, critical payloads

Then, a second, Site-specific Configuration Profile would immutably set the Customer ID (ccid) and the Sensor Grouping Tags (groupingTags):

  • Application & Custom Settings
    • com.crowdstrike.falcon domain
      • Customer ID (i.e., ccid)
      • Sensor Grouping Tags (i.e., groupingTags)
Site-specific Configuration Profile with Customer ID and Sensor Grouping Tags only

Client-side

On the Mac, while these two independent Configuration Profiles are both displayed in System Settings > Privacy & Security > Profiles

System Settings > Privacy & Security > Profiles

… In the /Library/Managed Preferences/ directory, there is a single com.crowdstrike.falcon.plist with the Application & Custom Settings from the Site-specific Configuration Profile:

The Rub

Normally, at this point, you’re done.

When you re-assign a Computer Record to a different Site in Jamf Pro, the old Site-specific Configuration Profile is automatically swapped out for the new Site-specific Configuration Profile. The software vendor detects this change and honors the new setting, which is then reflected in the vendor’s console.

A special thanks to CrowdStrike representatives for confirming with CrowdStrike engineering that — as of this writing — the com.crowdstrike.falcon.plist is consulted only once: during initial installation.

Any changes to Falcon Sensor Grouping Tags after initial installation require leveraging falconctl.

Idea No. 9326

Current CrowdStrike customers are invited to up-vote Idea No. 9326 (US-1 | US-2):

macOS falconctl should read com.crowdstrike.falcon.plist every time it loads

The CLI

To assign tags to a host, you’ll use the falconctl command-line interface with the grouping-tags command, which offers the following three options:

  • get
  • set
  • clear

Tag changes take effect the next time the Falcon sensor — or the Mac — restarts. To restart the Falcon sensor immediately, you can again leverage the falconctl binary with the following options, in the order listed:

  1. unload
  2. load

Another Rub

While any user account with local administrative privileges can leverage the falconctl binary to set — or even cleargrouping-tags, a Maintenance Token (about which I’m currently unqualified to discuss in greater detail) is required to unload the Falcon sensor.

Don’t know your Mac’s unique Maintenance Token? No problem, just make whatever grouping-tags change you like and restart.

So much for immutable Configuration Profile settings.

The Script

After better understanding the current state of grouping-tags, I was blessed with some heavenly inspiration to develop a fourth grouping-tags option: reset

grouping-tags reset

  1. Distribute both Configuration Profiles according to the original design
  2. Use defaults read to determine the MDM-specified grouping-tags settings
  3. Leverage falconctl grouping-tags set to update the Falcon Sensor Grouping Tags
  4. Wait for the Mac to restart

Note: The current — at least self-perceived — restrictions / limitations for using Maintenance Tokens has lead me to comment-out the restartCrowdStrikeFalcon function (i.e., unload / load); perhaps you’ll be able to leverage it in your environment.

Configuration

After having followed CrowdStrike’s latest deployment documentation for Configuration Profiles (and using the above examples), complete the following steps to reset Falcon Sensor grouping-tags to your MDM-defined settings.

A. Add the CrowdStrike Falcon Tags script to your Jamf Pro server
  1. Add the CrowdStrike Falcon Tags script to your Jamf Pro server
  2. Specify the following for Options > Parameter Labels
    • Parameter 4: Script Log Location
    • Parameter 5: Maintenance Token
    • Parameter 6: Mode [ get | set | clear | reset (default) ]
    • Parameter 7: Tags
  3. Click Save
#!/bin/bash
####################################################################################################
#
# ABOUT
#
#   CrowdStrike Falcon Tags
#       - See: https://snelson.us/2023/01/grouping-tag-hacks/
#
#   Inspired by:
#       - Phillip Boushy
#       - https://macadmins.slack.com/archives/CA9SU2FSS/p1617295375480700?thread_ts=1617196227.417300&cid=CA9SU2FSS
#
####################################################################################################
#
# HISTORY
#
#   Version 0.0.1, 19-Jan-2023, Dan K. Snelson (@dan-snelson)
#   - Original version
#
#   Version 0.0.2, 22-Jan-2023, Dan K. Snelson (@dan-snelson)
#   - Changed exit status when 'groupingTags' not found in com.crowdstrike.falcon.plist
#
#   Version 0.0.3, 27-Jan-2023, Dan K. Snelson (@dan-snelson)
#   - Changed exit status when 'groupingTags' not found in com.crowdstrike.falcon.plist
#
#   Version 0.0.4, 31-Jan-2023, Dan K. Snelson (@dan-snelson)
#   - Added Palo Alto Networks GlobalProtect HIP-compatibility
#
####################################################################################################


####################################################################################################
#
# Pre-flight Checks
#
####################################################################################################

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Confirm script is running as root
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

if [[ $(id -u) -ne 0 ]]; then
    echo "This script must be run as root; exiting."
    exit 1
fi



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Confirm CrowdStrike Falcon is installed
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

if [[ -d "/Applications/Falcon.app" ]]; then
    echo "CrowdStrike Falcon installed; proceeding …"
else
    echo "CrowdStrike Falcon NOT found; exiting."
    exit #1
fi



####################################################################################################
#
# Variables
#
####################################################################################################

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Script Version and Jamf Pro Script Parameters
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

scriptVersion="0.0.4"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin/
falconBinary="/Applications/Falcon.app/Contents/Resources/falconctl"
scriptLog="${4:-"/var/log/com.company.log"}"
plist="/Library/Preferences/com.crowdstrike.falcon.plist"
maintenanceToken="${5:-"J8E6N7N5Y3J0E9N9NYJ8E6N7N5Y3J0E9N9NY"}"   # [ CrowdStrike Maintenance Token ]
mode="${6:-"reset"}"                                              # [ get | set | clear | reset (default) ]
tags="${7:-"Server,Lane,Site"}"                                   # [ Server,Lane,Site (default) ]
exitCode="0"



####################################################################################################
#
# Functions
#
####################################################################################################

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Client-side Script Logging
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function updateScriptLog() {
    echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}"
}



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Get CrowdStrike Falcon Tags
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function getCrowdStrikeFalconTags() {

    # updateScriptLog "# Get CrowdStrike Falcon Tags:"

    currentTags=$("${falconBinary}" grouping-tags get | sed 's/.*: //')

    if [[ "${currentTags}" == *" "* ]]; then
        currentTags=""
    fi

    updateScriptLog "# Current Tags: ${currentTags}"

}



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Set CrowdStrike Falcon Tags
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function setCrowdStrikeFalconTags() {

    updateScriptLog "# Set CrowdStrike Falcon Tags"
    if [[ -n "${tags}" ]]; then
        updateScriptLog "• New Tags: ${tags}"
        "${falconBinary}" grouping-tags set "$tags" | tee -a "${scriptLog}"
    else
        updateScriptLog "• Tags [Parameter 7] is blank; nothing to set"
        exitCode="1"
    fi

}


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Clear CrowdStrike Falcon Tags
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function clearCrowdStrikeFalconTags() {

    updateScriptLog "# Clear CrowdStrike Falcon Tags"
    "${falconBinary}" grouping-tags clear | sed 's/.*: //' | tee -a "${scriptLog}"

}



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Reset CrowdStrike Falcon Tags
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function resetCrowdStrikeFalconTags() {

    updateScriptLog "# Reset CrowdStrike Falcon Tags"

    if [[ -f "/Library/Managed Preferences/com.crowdstrike.falcon.plist" ]]; then
        tags=$( defaults read /Library/Managed\ Preferences/com.crowdstrike.falcon.plist groupingTags 2>&1 )
    else
        updateScriptLog "• com.crowdstrike.falcon.plist NOT found; exiting"
        exitCode="0" #1
    fi

    if [[ ${tags} == *"does not exist"* ]]; then
        updateScriptLog "• 'groupingTags' not found in com.crowdstrike.falcon.plist; exiting with warning"
        exitCode="0"
    else
        updateScriptLog "• Resetting Tags: ${tags}"
        "${falconBinary}" grouping-tags set "$tags" | tee -a "${scriptLog}"
    fi

}



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Restart CrowdStrike Falcon
# shellcheck disable=SC2317
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

function restartCrowdStrikeFalcon() {

    updateScriptLog "# Restarting CrowdStrike Falcon"

    if [[ -z "${1}" ]]; then

        updateScriptLog "• Unloading CrowdStrike Falcon sensor (sans Maintenance Token) …"
        "${falconBinary}" unload | tee -a "${scriptLog}"

    else

        updateScriptLog "• Unloading CrowdStrike Falcon sensor …"
        unloadCommand=$( expect <<EOF
spawn sudo "${falconBinary}" unload --maintenance-token
expect "Token:"
send "${1}\r"
expect "*#*"
EOF
)

        # updateScriptLog "unloadCommand: ${unloadCommand}"

        if [[ ${unloadCommand} == *"Error"* ]]; then
            updateScriptLog "• Result: $(echo "${unloadCommand}" | tail -n1)"
            exitCode="1"
        else
            updateScriptLog "• Result: $(echo "${unloadCommand}" | tail -n1)"
            updateScriptLog "• Loading CrowdStrike Falcon sensor …"
            "${falconBinary}" load | tee -a "${scriptLog}"
        fi

    fi

}



####################################################################################################
#
# Program
#
####################################################################################################

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Client-side Logging
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

if [[ ! -f "${scriptLog}" ]]; then
    touch "${scriptLog}"
    updateScriptLog "*** Created log file via script ***"
fi



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Logging preamble
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

updateScriptLog "\n\n###\n# CrowdStrike Falcon Tags (${scriptVersion})\n###\n"



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Palo Alto Networks GlobalProtect HIP-compatibility 
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

updateScriptLog "\n\n# # #\n# Palo Alto Networks GlobalProtect HIP-compatibility\n# # #\n"

if [[ -f "/Library/Managed Preferences/com.crowdstrike.falcon.plist" ]]; then
    updateScriptLog "Creating hard link of 'com.crowdstrike.falcon.plist' …"
    ln -v "/Library/Managed Preferences/com.crowdstrike.falcon.plist" "${plist}" | tee -a "${scriptLog}"
else
    updateScriptLog "• com.crowdstrike.falcon.plist NOT found; exiting with error"
    exitCode="1"
fi



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Execute specified mode option
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

updateScriptLog "\n\n# # #\n# Executing specified mode option: '${mode}'\n# # #\n"

case ${mode} in

    "get" )
        getCrowdStrikeFalconTags
        ;;

    "set" )
        getCrowdStrikeFalconTags
        setCrowdStrikeFalconTags
        getCrowdStrikeFalconTags
        # restartCrowdStrikeFalcon "${maintenanceToken}"
        ;;

    "clear" )
        getCrowdStrikeFalconTags
        clearCrowdStrikeFalconTags
        getCrowdStrikeFalconTags
        # restartCrowdStrikeFalcon "${maintenanceToken}"
        ;;

    "reset" )
        getCrowdStrikeFalconTags
        resetCrowdStrikeFalconTags
        getCrowdStrikeFalconTags
        # restartCrowdStrikeFalcon "${maintenanceToken}"
        ;;

    * )
        updateScriptLog "• Catch-all: ${mode}; exiting with error"
        exitCode="1"
        ;;

esac



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Exit
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

updateScriptLog "Exit Code: ${exitCode}"

exit "${exitCode}"
B. Modify a Jamf Pro Policy to include the CrowdStrike Falcon Tags script

For the time being, we elected to add the CrowdStrike Falcon Tags script to our daily Update Inventory policy.

  1. Edit your daily Update Inventory policy
  2. Select the Scripts payload and add the CrowdStrike Falcon Tags script
  3. Specify the Parameter Values
    • Script Log Location: /var/log/com.company.log
    • Maintenance Token: See your CrowdStrike console (not required when using reset)
    • Mode:
      • get Reads the current grouping-tags
      • set Updates the grouping-tags as specified in Tags [Parameter 7]
      • clear Clears all grouping-tags
      • reset Reads and sets grouping-tags from com.crowdstrike.falcon.plist
    • Tags: Division,Lane,Site (not required when using reset)
  4. Click Save

Bonus Hack

Palo Alto Networks GlobalProtect HIP-compatibility

Since CrowdStrike Falcon currently does not write its preferences file to the standard /Library/Preferences/ directory, the script also creates a hard link of /Library/Managed Preferences/com.crowdstrike.falcon.plist as /Library/Preferences/com.crowdstrike.falcon.plist so Palo Alto Networks GlobalProtect can read the value of ccid for HIP-compatibility.

Posted in CrowdStrike Falcon, Jamf Pro, Scripts, Tips & Tricks

Related Posts