Posted on 11-01-2023 08:05 PM
Hey Guys!
I'm looking to gather insights on the best practices for using a script to bench and store devices while also ensuring the removal of all essential settings, including management licenses, to free up licenses until the devices are reactivated.
#!/bin/bash
LOGFILE="/var/log/jamf_script.log"
log_message() {
echo "$1" >> "$LOGFILE"
echo "$1"
}
log_message "Script started on $(date)"
log_message ""
invalidateToken() {
/usr/bin/curl --header "Authorization: Bearer $token" --request POST --silent --url "$jamfProURL/api/v1/auth/invalidate-token"
log_message "Token invalidated."
log_message ""
}
trap 'invalidateToken' EXIT
function sendToGoogleSheet {
# Gather system details
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
hostname=$(hostname)
loggedinuser=$(stat -f%Su /dev/console)
serialnumber=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')
macosversion=$(sw_vers -productVersion)
# Check for the presence of the jamf binary
if which jamf > /dev/null 2>&1; then
jamfBinaryStatus="Active"
log_message "Jamf Status Active"
log_message ""
else
jamfBinaryStatus="Removed"
log_message "Jamf Removed"
log_message ""
fi
# This will base64-encode your data
DATA_TO_SEND="$timestamp,$hostname,$loggedinuser,$serialnumber,$macosversion,Unmannaged,$jamfBinaryStatus"
ENCODED_DATA=$(echo -n "$DATA_TO_SEND" | base64)
# Ensure DATA_TO_SEND is not empty
if [[ -z "$DATA_TO_SEND" ]]; then
log_message "Error: DATA_TO_SEND is empty."
return 1
fi
# Ensure ENCODED_DATA is not empty
if [[ -z "$ENCODED_DATA" ]]; then
log_message "Error: ENCODED_DATA is empty."
return 1
fi
# URL of the deployed Google Apps Script web app
WEB_APP_URL="$4?encodedValue=$ENCODED_DATA"
# Use curl with the -L flag to follow redirects and send a GET request to the Google Apps Script web app
curl -L "$WEB_APP_URL"
log_message "Data sent to Google Sheet."
}
# Get the logged in user
LOGGED_IN_USER=$(stat -f%Su /dev/console)
log_message "Logged in user: $LOGGED_IN_USER"
# Function to prompt for Jamf admin credentials
getJamfCredentials() {
local uname=$(sudo -u $LOGGED_IN_USER osascript -e 'tell app "System Events" to text returned of (display dialog "Enter Jamf admin username:" default answer "" buttons {"OK"} default button "OK")')
local pwd=$(sudo -u $LOGGED_IN_USER osascript -e 'tell app "System Events" to text returned of (display dialog "Enter Jamf admin password:" default answer "" with hidden answer buttons {"OK"} default button "OK")')
echo "$uname:$pwd"
}
# Prompt technician for Jamf admin credentials
credentials=$(getJamfCredentials)
uname="${credentials%%:*}"
pwd="${credentials##*:}"
jamfProURL="https://**siteaddress**.jamfcloud.com"
# Request auth token
#authToken=$( /usr/bin/curl --request POST --silent --url "$jamfProURL/api/v1/auth/token" --user "$username:$password" )
#token=$(echo "$authToken" | /usr/bin/plutil -p - | awk -F\" '/"token"/ {print $4}')
# Request auth token
authToken=$( /usr/bin/curl --request POST --silent --url "$jamfProURL/api/v1/auth/token" --user "$username:$password" )
token=$( /usr/bin/plutil -extract token raw - <<< "$authToken" )
# Error handling for missing token
if [[ -z "$token" ]]; then
log_message "Failed to retrieve authentication token."
sudo -u $LOGGED_IN_USER osascript -e 'display dialog "Failed to retrieve authentication token from Jamf server. Check your credentials and ensure Jamf Pro is reachable." buttons {"OK"} default button "OK"'
exit 1
fi
log_message "Token acquired: $token"
udid=$(system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }')
log_message "Machine UDID: $udid"
compIdResponse=$(curl -H "Authorization: Bearer $token" -H "Accept: application/xml" "${jamfProURL}/JSSResource/computers/udid/${udid}/subset/general")
# Check for curl errors
if [ $? -ne 0 ]; then
log_message "Error encountered while fetching Comp ID:"
log_message "$compIdResponse"
exit 1
fi
compId=$(echo "$compIdResponse" | xpath -e "//computer/general/id/text()" 2>/dev/null)
# Error handling for missing Computer ID
if [[ -z "$compId" ]]; then
log_message "Error: Computer ID is missing."
exit 1
fi
echo "Computer ID is: $compId"
architecture=$(uname -m)
log_message "Machine architecture: $architecture"
case "$architecture" in
# ... [No changes to the "x86_64" section]
"arm64")
recoveryPassword="" # Note: This should be securely populated
response=$(curl --request POST \
--url "$jamfProURL/api/preview/mdm/commands" \
--header "Authorization: Bearer $token" \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"clientData": [
{
"managementId": "'$udid'",
"clientType": "COMPUTER"
}
],
"commandData": {
"commandType": "SetRecoveryLockCommand",
"newPassword": ""
}
}
') 2>&1
# Check for curl errors
if [ $? -ne 0 ]; then
log_message "Error encountered while setting recovery lock:"
log_message "$response"
exit 1
fi
log_message "Recovery lock set successfully"
;;
*)
log_message "Unknown architecture. Exiting script."
exit 1
;;
esac
# Updating Computer Name and Reporting Back to Jamf Pro
currentName=$(hostname)
newName="SPR23_$currentName"
log_message "Renaming computer from '${currentName}' to '${newName}'"
log_message ""
/usr/local/jamf/bin/jamf setComputerName -name "$newName"
/usr/local/jamf/bin/jamf recon
log_message "Sending info to Google..."
sendToGoogleSheet
sudo -u $LOGGED_IN_USER osascript -e "display dialog \"The device has been renamed to $newName and will be wiped shortly. Please ensure you've backed up any important data.\" buttons {\"OK\"} default button \"OK\" giving up after 5" &
sleep 5
# Send the EraseDevice command
response=$( /usr/bin/curl \
--header "Authorization: Bearer $token" \
--header "Content-Type: text/xml" \
--request POST \
--silent \
--url "$jamfProURL/JSSResource/computercommands/command/EraseDevice/passcode/164700/id/$compId" )
# Check for curl errors
if [ $? -ne 0 ]; then
log_message "Error encountered while attempting to wipe the device:"
log_message "$response"
exit 1
fi
log_message ""
log_message "Device wipe command sent successfully."
log_message "Script completed on $(date)"
exit 0
The script I'm currently using does the following:
The script's primary goals are:
My principal concern pertains to the persistence of the 'Recovery Lock' after initiating the 'Erase Device' command. Curiously, no errors are flagged during the process, yet the 'Recovery Lock' remains intact. If anyone has devised a reliable method to effectively clear the 'Recovery Lock', ensuring that it's fully removed following an erase, I'd be eager to review your approach.
Additionally, I would be very happy to look at alternative processes if someone has found a different effective pathway.
I'm grateful for any assistance and the opportunity to learn from the community's collective wisdom.