(Hopefully) automate the remediation of sideways Falcon installations

Background
During the initial phases of our CrowdStrike Falcon pilot, we discovered a surprising number of sideways installations which were reporting the seemingly dreaded: Error while accessing Falcon service.
As we developed a “kickstart” script to (hopefully) automate the remediation, we’d occasionally observe the following error:
falconBinary="/Applications/Falcon.app/Contents/Resources/falconctl"
$falconBinary stats agent_info | awk '/Sensor operational:/{print $3}'
/Applications/Falcon.app/Contents/Resources/falconctl: line 5: 20933 Killed: 9 ../MacOS/Falcon --ctl $PARAMS
We enhanced our kickstart script to first validate the Configuration Profile-defined ccid and working with CrowdStrike Support, we also added a licensing step for good measure.
Results
If there’s any silver lining in the sideways installation cloud, it’s that a Maintenance Token doesn’t appear to be required to uninstall via ${falconBinary} uninstall -verbose.
In less than 18 hours, we were able to reduce the number of sideways installations from 13 percent to well less than 1 percent. (This exercise also helped us to better detect sideways MDM enrollments.)
Script
The following script presumes:
- Prior implementation of the CrowdStrike Falcon Tags script
- Prior implementation of the bonus hack (since Falcon doesn’t store its preferences in the standard
/Library/Preferences/directory) - A Jamf Pro Policy to re-install CrowdStrike Falcon with a Custom Trigger of
crowdStrikeFalcon
csf-Kickstart.bash
#!/bin/bash
####################################################################################################
#
# CrowdStrike Falcon Kickstart
#
# Purpose: Load CrowdStrike Falcon's Sensor
#
####################################################################################################
#
# HISTORY
#
# Version 0.0.1, 28-Feb-2023, Dan K. Snelson (@dan-snelson)
# Original version
#
# Version 0.0.2, 10-Mar-2023, Dan K. Snelson (@dan-snelson)
# Added licensing step
#
####################################################################################################
####################################################################################################
#
# Variables
#
####################################################################################################
scriptVersion="0.0.2"
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"}" # Parameter 4: Full path to your company's client-side log
exitCode="0"
####################################################################################################
#
# Pre-flight Checks
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Client-side Logging
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ ! -f "${scriptLog}" ]]; then
touch "${scriptLog}"
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Client-side Script Logging Function
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function updateScriptLog() {
echo -e "$( date +%Y-%m-%d\ %H:%M:%S ) - ${1}" | tee -a "${scriptLog}"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Logging Preamble
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
updateScriptLog "\n\n###\n# CrowdStrike Falcon Kickstart (${scriptVersion})\n###\n"
updateScriptLog "PRE-FLIGHT CHECK: Initiating …"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Confirm script is running as root
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ $(id -u) -ne 0 ]]; then
updateScriptLog "PRE-FLIGHT CHECK: This script must be run as root; exiting."
exit 1
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Confirm CrowdStrike Falcon is installed
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ -f "${falconBinary}" ]]; then
updateScriptLog "PRE-FLIGHT CHECK: CrowdStrike Falcon installed; proceeding …"
else
updateScriptLog "PRE-FLIGHT CHECK: CrowdStrike Falcon NOT found; exiting."
exit 1
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Confirm CrowdStrike Falcon CCID
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
ccidTest=$( defaults read "/Library/Preferences/com.crowdstrike.falcon.plist" ccid 2>&1 )
if [[ "${ccidTest}" == *"does not exist"* ]]; then
updateScriptLog "PRE-FLIGHT CHECK: CrowdStrike Falcon CCID NOT found; exiting."
exit 1
else
updateScriptLog "PRE-FLIGHT CHECK: CrowdStrike Falcon CCID found; proceeding …"
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Confirm CrowdStrike Falcon System Extension is running
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
systemExtensionTest=$( systemextensionsctl list | grep -o "com.crowdstrike.falcon.Agent.*" | cut -f2- -d" " )
if [[ -n "${systemExtensionTest}" ]]; then
systemExtensionStatus="${systemExtensionTest}"
else
systemExtensionStatus="Not Found"
fi
updateScriptLog "PRE-FLIGHT CHECK: CrowdStrike Falcon System Extension Status:"
updateScriptLog "${systemExtensionStatus}"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Pre-flight Check: Complete
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
updateScriptLog "PRE-FLIGHT CHECK: Complete"
####################################################################################################
#
# Program
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Process CrowdStrike Falcon System Extension Status
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
updateScriptLog "Processing System Extension Status …"
case ${systemExtensionStatus} in
*"[activated enabled]"* )
updateScriptLog "CrowdStrike Falcon System Extension enabled"
updateScriptLog "Validating Sensor Operation …"
sensorOperationalStatus=$( $falconBinary stats agent_info | awk '/Sensor operational:/{print $3}' )
if [[ "${sensorOperationalStatus}" == "true" ]]; then
updateScriptLog "Falcon Sensor Operational: ${sensorOperationalStatus}"
updateScriptLog "Updating inventory …"
jamf recon
exitCode="0"
else
updateScriptLog "Attempting to kickstart Falcon Sensor …"
falconKickStartLicense=$( ${falconBinary} license "$( defaults read /Library/Managed\ Preferences/com.crowdstrike.falcon.plist ccid )" --noload --verbose)
updateScriptLog "Falcon Kickstart License Result: ${falconKickStartLicense}"
falconKickStartLoad=$( ${falconBinary} load -verbose )
updateScriptLog "Falcon Kickstart Load Result: ${falconKickStartLoad}"
if [[ "${falconKickStartLoad}" == "Falcon sensor is loaded" ]]; then
sensorOperationalStatus=$( $falconBinary stats agent_info | awk '/Sensor operational:/{print $3}' )
if [[ "${sensorOperationalStatus}" == "true" ]]; then
updateScriptLog "Falcon Sensor Operational: ${sensorOperationalStatus}"
updateScriptLog "Updating inventory …"
jamf recon
exitCode="0"
fi
else
exitCode="1"
fi
exitCode="0"
fi
;;
"Not Found" )
updateScriptLog "CrowdStrike Falcon System Extension NOT found"
updateScriptLog "Attempting re-installation …"
falconKickStartUninstall=$( ${falconBinary} uninstall -verbose )
updateScriptLog "Falcon Kickstart Uninstall Result: ${falconKickStartUninstall}"
updateScriptLog "Updating computer inventory …"
jamf recon
updateScriptLog "Re-installing CrowdStrike Falcon …"
jamf policy -trigger crowdStrikeFalcon
exitCode="1"
;;
* )
updateScriptLog "Code for 'Catch-all' goes here"
exitCode="1"
;;
esac
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Exit
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
updateScriptLog "Exit Code: ${exitCode}"
exit "${exitCode}"