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
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
)
- Customer ID (i.e.,
Client-side
On the Mac, while these two independent Configuration Profiles are both displayed in 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 readcom.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:
unload
load
Another Rub
While any user account with local administrative privileges can leverage the falconctl
binary to set
— or even clear
— grouping-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
- Distribute both Configuration Profiles according to the original design
- Use
defaults read
to determine the MDM-specifiedgrouping-tags
settings - Leverage
falconctl grouping-tags set
to update the Falcon Sensor Grouping Tags - 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
- Add the CrowdStrike Falcon Tags script to your Jamf Pro server
- 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
- Parameter 4:
- 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.
- Edit your daily Update Inventory policy
- Select the Scripts payload and add the CrowdStrike Falcon Tags script
- 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 currentgrouping-tags
set
Updates thegrouping-tags
as specified in Tags [Parameter 7]clear
Clears allgrouping-tags
reset
Reads and setsgrouping-tags
fromcom.crowdstrike.falcon.plist
- Tags:
Division,Lane,Site
(not required when usingreset
)
- Script Log Location:
- 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.