I have a script that's supposed to run at the end of enrollment and it asks a tech whether they want to run an "Initial Setup" Policy, which if run would trigger a bunch of apps to install. It uses Pashua and the API so that if the user clicks a button that says "Info" it will give them a list of software that would be installed.
The script is:
#!/bin/sh -v
# Where's the jamf binary stored? This is for SIP compatibility.
jamf_binary=`/usr/bin/which jamf`
if [[ "$jamf_binary" == "" ]] && [[ -e "/usr/sbin/jamf" ]] && [[ ! -e "/usr/local/bin/jamf" ]]; then
jamf_binary="/usr/sbin/jamf"
elif [[ "$jamf_binary" == "" ]] && [[ ! -e "/usr/sbin/jamf" ]] && [[ -e "/usr/local/bin/jamf" ]]; then
jamf_binary="/usr/local/bin/jamf"
elif [[ "$jamf_binary" == "" ]] && [[ -e "/usr/sbin/jamf" ]] && [[ -e "/usr/local/bin/jamf" ]]; then
jamf_binary="/usr/local/bin/jamf"
fi
## Establish API Credentials
# https://github.com/jamfit/Encrypted-Script-Parameters
function DecryptString() {
# Usage: ~$ DecryptString "Encrypted String" "Salt" "Passphrase"
echo "${1}" | /usr/bin/openssl enc -aes256 -d -a -A -S "${2}" -k "${3}"
}
apiUserEncrypt=$4
apiPassEncrypt=$5
apiUsername=$(DecryptString $apiUserEncrypt '20d17db979f2b85b' '5106e04c01e15cb3654e93da')
apiPassword=$(DecryptString $apiPassEncrypt '50ed367f279afee5' '8bd4ab4a94dc898d7d12ac3d')
## Use API to get computer Department from UUID
# Get computer's UUID
compUUID=$(system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }')
#echo "compUUID is "$compUUID
compRaw=$(curl https://jssurl/JSSResource/computers/udid/${compUUID} --user "$apiUsername:$apiPassword")
#echo $compRaw
compDept=$(echo $compRaw | xpath '//location/department' 2>&1 | awk -F'<department>|</department>' '{print $2}')
compDept="${compDept:2}"
echo "compDept is "$compDept
##Define Initial Setup Trigger and ID of the Initial Setup script based on Department
if [[ "$compDept" == "Department1"* ]]; then
initialSetup="Department1Initial"
msgPolicy="Department1"
scriptID=[ID of the Policy that's triggered by Department1Initial trigger, I could probably get this from the API but it's easier for me just to define it]
[A FEW ELIFS FOR OTHER DEPARTMENTS]
fi
echo "initialSetup is "$initialSetup
if [[ -z "$scriptID" ]]; then
echo "no initial setup policy defined for department"
exit 0
fi
##Pashua (for prompts)
pashuaApp="/Applications/Utilities/Pashua.app/Contents/MacOS/Pashua"
configDest="/tmp/conf.pash"
if [[ -e "$pashuaApp" ]]; then
echo "pashua installed at expected location"
else
echo "pashua not installed at expected location"
exit 1
fi
## Use API to show the contents of the script with the ID defined above by $scriptID
scriptRaw=$(curl https://jssurl/JSSResource/scripts/id/${scriptID} --user "$apiUsername:$apiPassword")
#echo "scriptRaw results "$scriptRaw
scriptContents=$(echo $scriptRaw | xpath '//script_contents' 2>&1 | awk -F'<script_contents>|</script_contents>' '{print $2}')
#Delete everything before "for each"
scriptPolicies=$(echo "$scriptContents" | sed 's/^.*for each//')
#echo "scriptPolicies results "$scriptPolicies
appList=""
while IFS='#' read -ra DELIMITED; do
for i in "${DELIMITED[@]}"; do
if [[ "$i" != " " ]]; then
i="${i:-2}"
policyShort=$(echo "$i" | sed 's/ $jamf.*//')
#policyShort="$policyShort[return]"
#echo "$policyShort"
appList+=("$policyShort")
fi
done
done <<< "$scriptPolicies"
##THE ABOVE CREATES AN ARRAY THAT HAS THE NAMES OF APPLICATIONS THAT ARE GOING TO BE INSTALLED
function joinBy () {
local d=$1; shift; echo "$1"; shift; printf "%s" "${@/#/$d}";
}
appString=$(joinBy '[return]' "${appList[@]}")
appString="${appString:9}"
#echo $appString
##THE ABOVE CREATES A STRING WITH THE NAMES OF APPS SEPARATED BY "[RETURN]", WHICH IS HOW PASHUA NEEDS IT FORMATTED TO DISPLAY IN A TEXTBOX
function enrollmentCompleteWindow () {
# Create a temp conf file to prompt user
rm $configDest
cat <<EOT >> $configDest
*.title = Enrollment Complete
txt.type = text
txt.default = Enrollment is complete. Detected Department is ${compDept}.[return][return]Would you like to run the ${msgPolicy} Initial Setup policy to install Applications?
txt.width = 310
txt.height = 310
cb.type = cancelbutton
cb.label = No
b.type = button
b.label = Info
db.type = defaultbutton
db.label = Yes
EOT
# Run Pashua and store the variable
enrollButton=$($pashuaApp $configDest)
}
function appListWindow () {
# Create a temp conf file to list apps
rm $configDest
cat <<EOT >> $configDest
*.title = Policy List
tb.type = textbox
tb.label = The following apps/policies will be installed:
tb.default = $appString
tb.width = 310
tb.height = 310
tb.disabled = 1
cb.type = cancelbutton
cb.label = Cancel
db.type = defaultbutton
db.label = Install
EOT
# Run Pashua and store the variable
appListButton=$($pashuaApp $configDest)
}
enrollmentCompleteWindow
if [[ "$enrollButton" == *"cb=1"* ]]; then
echo "user clicked no"
exit 0
elif [[ "$enrollButton" == *"db=1"* ]]; then
echo "user clicked yes"
#$jamf_binary policy -trigger $initialSetup
elif [[ "$enrollButton" == "b=1"* ]]; then
echo "user clicked info"
appListWindow
if [[ "$appListButton" == *"cb=1"* ]]; then
echo "user clicked cancel"
exit 0
elif [[ "$appListButton" == *"db=1"* ]]; then
echo "user clicked install"
#$jamf_binary policy -trigger $initialSetup COMMENTED OUT WHILE TESTING
fi
fi
Whenever I run the script locally (apart from Jamf) it takes less than a second to do everything and give me the popup window every single time. I tried to run it from Jamf through Self Service a few times and found that it seemed to freeze. It would show as Installing but would get about half done (based on the progress circle) and not do anything further, forcing me to cancel it (I've waited over 5 minutes and it just stays there). Oddly, sometimes about a minute after cancelling it I would get the popup window, which I thought was weird.
I tried setting it to Recurring Checkin, did a sudo jamf policy
and the window immediately popped up. Just to be safe I cleared the logs (since it was set to run once per computer) and waited for the computer to checkin normally, and when it did that it showed in jamf.log in Console that it started running the policy, but then 25 minutes later it still hadn't gotten farther than that and I didn't have any way to cancel it (and it was holding up other Policies that needed to run at Recurring Checkin).
Does anyone have any idea what could be wrong with the script that makes it not work well in Jamf? I know it's a pretty complicated script (particularly the $scriptPolicies, $appList, and appStrings sections, which effectively just format a list of apps that will be installed in a way that can be used by Pashua) and I'm sure it could be done better, so if anyone has some general recommendations about how to troubleshoot something like this so I at least can get a log of where it's hanging, that would also be helpful. If I end up cancelling it through Self Service I don't get any logs, which makes it tricky to troubleshoot.