Skip to main content

Greetings Jamf Nation!  


I have been woking on a more comprehensive Falcon repair script to assist in detecting and/or trying to repair any potential issues found in the sensors.  This is strictly a WIP and I would love to get everyone's feedback on ideas or items that I might have missed.  This script is borrowing heavily from Dan K Snelson, so kudos for him creating the original concept...I just want to take it a "one step further"...


#!/bin/zsh
#
# Written by: Scott Kendall
# Date Created: 01/21/2025
# Date Last Revised: 01/23/2025
#
# Borrowed heavily from @snelson: source code @ https://snelson.us/2023/03/crowdstrike-falcon-kickstart-0-0-2/
#
######################################################################################################
#
# Gobal "Common" variables (do not change these!)
#
######################################################################################################
export PATH=/usr/bin:/usr/local/bin:/bin:/usr/sbin:/sbin

SUPPORT_DIR="<your support log folder>"

LOG_DIR="${SUPPORT_DIR}/logs"
LOG_FILE="${LOG_DIR}/FalcanSensor.log"
LOG_STAMP=$(echo $(/bin/date +%Y%m%d))

falconBinary="/Applications/Falcon.app/Contents/Resources/falconctl"
falcanJAMFtrigger="crowdstrike"

exitCode="0"

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

function create_log_directory ()
{
# Ensure that the log directory and the log files exist. If they
# do not then create them and set the permissions.
#
# RETURN: None

# If the log directory doesnt exist - create it and set the permissions
[[ ! -d "${LOG_DIR}" ]] && /bin/mkdir -p "${LOG_DIR}"
/bin/chmod 755 "${LOG_DIR}"

# If the log file does not exist - create it and set the permissions
[[ ! -f "${LOG_FILE}" ]] && /usr/bin/touch "${LOG_FILE}"
/bin/chmod 644 "${LOG_FILE}"
}

function logMe ()
{
# Basic two pronged logging function that will log like this:
#
# 20231204 12:00:00: Some message here
#
# This function logs both to STDOUT/STDERR and a file
# The log file is set by the $LOG_FILE variable.
#
# RETURN: None
echo "${1}" 1>&2
echo "$(/bin/date '+%Y-%m-%d %H:%M:%S'): ${1}" | tee -a "${LOG_FILE}"
}

function preflight_check ()
{
# Pre-flight Check: Confirm script is running as root

[[ $(id -u) -ne 0 ]] && {logMe "PRE-FLIGHT CHECK: This script must be run as root; exiting."; exit 1}


# 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"
logMe "Falcon not installed: Loading policy from JAMF"
fi

logMe "CrowdStrike Falcon System Extension Status: ${systemExtensionStatus}"

###################################################
# Pre-flight Check: Complete
###################################################

logMe "PRE-FLIGHT CHECK: Complete"
}

function log_sensor_updates()
{
logMe "Falcon Sensor Operational: ${1}"
logMe "Updating inventory …"
jamf recon
}

function connection_test()
{
test=$("nc -vz ts01-b.cloudsink.net 443")
"${test}" == *"succedded!"* ]] && echo "true" || echo "false"
}

function load_sensor()
{
echo $( ${falconBinary} load --verbose)
}

function load_jamf_policy ()
{
jamf policy -trigger "${falcanJAMFtrigger}"
}

function get_agent_info ()
{
echo $( $falconBinary stats agent_info 2>&1 )
}
####################################################################################################
#
# Program
#
####################################################################################################

create_log_directory
preflight_check
exitCode="0"

###################################################
# Process CrowdStrike Falcon System Extension Status
###################################################

logMe "Processing System Extension Status …"

systemExtensionStatus=$(systemextensionsctl list | grep -o "com.crowdstrike.falcon.Agent.*" | cut -f2- -d" ")

# Check the extension status first and evaluate

case ${systemExtensionStatus} in

*" activated enabled]"* )

logMe "CrowdStrike Falcon System Extension enabled"
logMe "Validating Sensor Operation …"
sensorOperationalStatus=$( get_agent_info ) #| awk '/Sensor operational:/{print $3}')

# check for specific issues in regards to the status

case ${sensorOperationalStatus:l} in

*"true"* )
# sensors are loaded and functioning correclty
log_sensor_updates "${sensorOperationalStatus}"
;;

*"sensor has not loaded."* | *"sensor is unknown."* | *"sensor is unloaded."* )
# Sensors are not loaded properly
sensorOperationalStatus=$( load_sensor)
logMe "Attempting to Load the Falcon Sensor"
log_sensor_updates "${sensorOperationalStatus}"
;;

*"not licensed"* )
# product is not licensed...perform a license command and then make sure that the sensors are loaded
logMe "Attempting to License the Falcon Sensor"
falconKickStartLicense=$( $falconBinary license "$( defaults read /Library/Managed\\ Preferences/com.crowdstrike.falcon.plist ccid )" --noload --verbose)
log_sensor_updates "${falconKickStartLicense}"

logMe "Attempting to Load the Falcon Sensor"
sensorOperationalStatus=$( load_sensor)
log_sensor_updates "${sensorOperationalStatus}"
;;

esac
;;

*"uninstall on reboot"* )

# It looks like a restart might be in order

logMe "The system needs to be restarted for the sensor to load properly"
exitCode="1"
;;

*"waiting for user"* )
# it appears that everything is working OK, but the user needs to start doing "something"
logMe "Falcon Sensor Status: ${sensorOperationalStatus}"
;;

"Not Found" )
# Crowdstrike not found, so lets try to remove any previous install and try to reinstall it

logMe "CrowdStrike Falcon System Extension NOT found: Attempting Re-installation"
falconKickStartUninstall=$( ${falconBinary} uninstall -verbose )
log_sensor_updates "${falconKickStartUninstall}"

logMe "Re-installing CrowdStrike Falcon …"
load_jamf_policy

exitCode="1"
;;
* )
# Catch all if we got a different error

logMe "Attempting to kickstart Falcon Sensor …"

falconKickStartLicense=$( ${falconBinary} license )
logMe "Falcon Kickstart License Result: ${falconKickStartLicense}"

falconKickStartLoad=$( load_sensor )
logMe "Falcon Kickstart Load Result: ${falconKickStartLoad}"

if "${falconKickStartLoad}" == "Falcon sensor is loaded" ]]; then
sensorOperationalStatus=$( get_agent_info )
"${sensorOperationalStatus}" == "true" ]] && logMe "Falcon Sensor Status: ${sensorOperationalStatus}"
else
exitCode="1"
fi
esac

logMe "Exit Code: ${exitCode}"
exit "${exitCode}"

 

I used to do something similar where I had an extension attribute that reported an error and if there was an error it went to a smart group that triggered a policy to uninstall and reinstall. That fixed 90% of issues.


Anyone looking to deploy, and or remove/remediate, CrowdStrike on Macs should really do themselves a favor and look at @franton's guide on scripting that process with the CS API :


https://richard-purves.com/2022/05/03/downloading-crowdstrike-via-api-for-fun-and-profit/


And the associated GitHub repo:


https://github.com/franton/Crowdstrike-API-Scripts?tab=readme-ov-file


 


Reply