Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save angelorobo/71e723c94b220123b4ac94037d6cd40f to your computer and use it in GitHub Desktop.

Select an option

Save angelorobo/71e723c94b220123b4ac94037d6cd40f to your computer and use it in GitHub Desktop.
Huntress post-install script for Swif
#!/bin/zsh
#
# Huntress post-install script for Swif.ai
#
# Requirements:
# 1. Deploy HuntressSystemExtensionProfile.mobileconfig before this script.
# 2. Replace ACCOUNT_KEY and ORGANIZATION_KEY below.
# 3. Run as root through Swif/Munki.
#
set -u
readonly ACCOUNT_KEY="REPLACE_WITH_32_CHARACTER_ACCOUNT_KEY"
readonly ORGANIZATION_KEY="REPLACE_WITH_EXACT_ORGANIZATION_KEY"
readonly TAGS=""
readonly DEPLOYMENT_SCRIPT_URL="https://raw.githubusercontent.com/huntresslabs/deployment-scripts/refs/heads/main/Bash/mac/InstallHuntress-macOS-bash.sh"
readonly HUNTRESS_APP="/Applications/Huntress.app"
readonly HUNTRESS_BINARY="${HUNTRESS_APP}/Contents/MacOS/Huntress"
readonly LOG_FILE="/var/log/HuntressSwifInstaller.log"
TEMP_SCRIPT=""
REINSTALL_REQUIRED=false
log()
{
local message="$*"
echo "$(date '+%Y-%m-%d %H:%M:%S') -- ${message}" | /usr/bin/tee -a "$LOG_FILE"
}
cleanup()
{
local exit_code=$?
trap - EXIT
if [[ -n "$TEMP_SCRIPT" && -f "$TEMP_SCRIPT" ]]; then
/bin/rm -f "$TEMP_SCRIPT"
fi
exit "$exit_code"
}
trap cleanup EXIT
is_huntress_healthy()
{
[[ -x "$HUNTRESS_BINARY" ]] || return 1
/usr/bin/pgrep -x "HuntressAgent" >/dev/null 2>&1 || return 1
/usr/bin/pgrep -x "HuntressUpdater" >/dev/null 2>&1 || return 1
local status_output
status_output="$("$HUNTRESS_BINARY" status 2>&1)" || return 1
echo "$status_output" | /usr/bin/grep -Eiq \
'Full Disk Access for Agent:[[:space:]]*true' || return 1
echo "$status_output" | /usr/bin/grep -Eiq \
'Extension Status:[[:space:]]*installed' || return 1
echo "$status_output" | /usr/bin/grep -Eiq \
'Full Disk Access for Extension:[[:space:]]*true' || return 1
echo "$status_output" | /usr/bin/grep -Eiq \
'EDR status:[[:space:]]*enabled' || return 1
echo "$status_output" | /usr/bin/grep -Eiq \
'Preauthorization Status:[[:space:]]*granted' || return 1
return 0
}
log "Starting Huntress installation through Swif.ai."
if [[ "$EUID" -ne 0 ]]; then
log "ERROR: This script must run as root."
exit 1
fi
if [[ ! "$ACCOUNT_KEY" =~ ^[[:xdigit:]]{32}$ ]]; then
log "ERROR: ACCOUNT_KEY must be a 32-character hexadecimal Huntress Account Key."
exit 1
fi
if [[ -z "$ORGANIZATION_KEY" ||
"$ORGANIZATION_KEY" == "REPLACE_WITH_EXACT_ORGANIZATION_KEY" ]]; then
log "ERROR: ORGANIZATION_KEY has not been configured."
exit 1
fi
#
# Confirm that the Huntress MDM profile arrived before activating the
# system extension. This prevents approval prompts on the endpoint.
#
profile_output="$(/usr/bin/profiles show -type configuration 2>/dev/null || true)"
if ! echo "$profile_output" | /usr/bin/grep -q "com.huntress.sysext" ||
! echo "$profile_output" | /usr/bin/grep -q "7W6HQ9J9XA"; then
log "ERROR: The Huntress system-extension configuration profile is not installed."
log "Deploy HuntressSystemExtensionProfile.mobileconfig before installing Huntress."
exit 2
fi
log "Huntress MDM permission profile is installed."
#
# Make retries idempotent. A complete, healthy installation is success,
# not an installation error.
#
if [[ -d "$HUNTRESS_APP" ]]; then
if is_huntress_healthy; then
log "Huntress is already installed, provisioned, and running."
exit 0
fi
log "An incomplete or unhealthy Huntress installation was found."
log "The deployment script will run with the reinstall option."
REINSTALL_REQUIRED=true
fi
TEMP_SCRIPT="$(/usr/bin/mktemp /private/tmp/HuntressDeployment.XXXXXX)" || {
log "ERROR: Could not create temporary deployment script."
exit 1
}
/usr/bin/curl \
--fail \
--location \
--silent \
--show-error \
--retry 3 \
--connect-timeout 30 \
"$DEPLOYMENT_SCRIPT_URL" \
--output "$TEMP_SCRIPT"
curl_exit=$?
if [[ "$curl_exit" -ne 0 ]]; then
log "ERROR: Failed to download the official Huntress deployment script."
exit "$curl_exit"
fi
/bin/chmod 700 "$TEMP_SCRIPT"
#
# Identify Swif.ai as the deployment tool in Huntress support logs.
#
/usr/bin/sed -i '' \
's/^rmm="Unspecified RMM"$/rmm="Swif.ai"/' \
"$TEMP_SCRIPT"
install_arguments=(
-a "$ACCOUNT_KEY"
-o "$ORGANIZATION_KEY"
-i
)
if [[ -n "$TAGS" ]]; then
install_arguments+=(-t "$TAGS")
fi
if [[ "$REINSTALL_REQUIRED" == true ]]; then
install_arguments+=(-r)
fi
log "Running the official Huntress deployment script."
#
# Do not enable shell tracing here because it would expose the Account Key.
#
/bin/zsh "$TEMP_SCRIPT" "${install_arguments[@]}" >>"$LOG_FILE" 2>&1
install_exit=$?
if [[ "$install_exit" -ne 0 ]]; then
log "ERROR: Huntress deployment failed with exit code ${install_exit}."
log "Review ${LOG_FILE} and /Users/Shared/HuntressInstaller.log."
exit "$install_exit"
fi
log "Huntress deployment script completed successfully."
#
# Readiness can take a short time after installation. Do not return failure
# solely because the extension has not finished activating yet.
#
if is_huntress_healthy; then
log "Huntress installation and EDR readiness verification succeeded."
else
log "WARNING: The installer succeeded, but Huntress readiness is still initializing."
log "Verify later with: ${HUNTRESS_BINARY} status"
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment