Posted on 08-29-2018 01:08 PM
I have a script that prompts a tech to set the department of a computer:
#!/bin/sh
## 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 'salt' 'passphrase')
apiPassword=$(DecryptString $apiPassEncrypt 'salt' 'passphrase')
## Use API to get computer Site from UUID
# Get computer's UUID
compUUID=$(system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }')
compRaw=$(curl https://jssurl/JSSResource/computers/udid/${compUUID} --user "$apiUsername:$apiPassword")
echo $compRaw
compSite=$(echo $compRaw | xpath '//general/site/name' 2>&1 | awk -F'<name>|</name>' '{print $2}')
echo "compSite is"$compSite
if [[ $compSite == *"Example" ]]; then
deptName="Example"
elif [[ $compSite = *"Example2" ]]; then
deptName="Example2"
elif [[ $compSite == *"Example3" ]]; then
deptName="Example3"
fi
echo "deptName is "$deptName
## Use API to get list of departments
deptRaw=$(curl https://jssurl/JSSResource/departments --user "$apiUsername:$apiPassword")
echo $deptRaw
# https://bryson3gps.wordpress.com/2014/03/30/the-jss-rest-api-for-everyone/
deptList=$(echo $deptRaw | xpath '//department/name' 2>&1 | awk -F'<name>|</name>' '{print $2}')
echo $deptList
if [ -z "$deptName" ]; then
echo "deptName not defined"
else
for department in ${deptList[@]}
do
if [[ $department == "$deptName"* ]]; then
# https://macscripter.net/viewtopic.php?id=35318
f=${department##*/}
if [ "${f:0:1}" = "_" ] ; then
echo "NOT Processing $department" 1>&2 # for now just a test
else
if [[ ! -z ${deptParsed} ]] ; then
deptParsed=${deptParsed}","
fi
echo "Processing $department" 1>&2
deptParsed=${deptParsed}"""${f}""" # to create "item1","item2","item..n"
fi
done
# https://macscripter.net/viewtopic.php?id=35318
deptChosen="$(/usr/bin/osascript -e 'tell application "System Events" to activate' -e 'tell application "System Events" to return (choose from list {'"$deptParsed"'} with prompt "Choose a Department:" with title "Department Chooser" OK button name "Select" cancel button name "Quit")')"
fi
sudo /usr/local/bin/jamf recon -department "$deptChosen"
sudo /usr/local/bin/jamf recon
If I run this in Self Service it works fine. However if I try to run it on enroll and have Console open to jamf.log, I see that it starts to run the policy, then hangs, then moves onto the next policy without opening up the AppleScript window.
Any idea why this would happen? I'd like to set this on enroll if possible.
Posted on 08-29-2018 01:16 PM
Why don't you write your echos to a file so you can see at what point the script might stop? Also I think the double recons are redundant. Specifying the department in the recon will still do a full recon.
Posted on 08-30-2018 05:11 AM
@ryan.ball thanks, I thought the double recon might be redundant, added the 2nd after the last time this didn't work. Will remove the 2nd.
If I look in the logs in jamf, it looks like it gives a
36:44: execution error: An error of type -10810 has occurred. (-10810)message when it's trying to run the AppleScript command. It shows "Processing" for all the departments that I'd expect to see, and then in my actual script I have it echo $deptParsed and $deptChosen after the AppleScript command. It echos $deptParsed so I know it was defined correctly, but $deptChosen is blank (which makes sense; since the popup window didn't come up I couldn't choose anything). Maybe I'll try to build it so that if $deptChosen isn't defined it'll run the AppleScript command again (giving up after a certain amount of tries to it doesn't get stuck in a loop).
Posted on 08-30-2018 06:13 AM
Osascript is running as Root I believe. So that's why it's bombing....I THINK. I could be wrong about that.
Posted on 08-30-2018 06:16 AM
After looking at it a bit more closely, I have a few things to point out. The biggest one would be that you were missing a 'fi' in this section which would cause an issue:
if [ "${f:0:1}" = "_" ] ; then
echo "NOT Processing $department" 1>&2 # for now just a test
else
if [[ ! -z ${deptParsed} ]] ; then
deptParsed=${deptParsed}","
fi
echo "Processing $department" 1>&2
deptParsed=${deptParsed}"""${f}""" # to create "item1","item2","item..n"
Next, the applescript list seems to be populated by the deptParsed variable, which to me seems like it is undefined. You are setting deptParsed to itself at one point, but at that point in the script deptParsed is null, so I don't see how this would work at all.
I linted the script and quoted a bunch of the variables to prevent globbing and word splitting as shown below (added the missing 'fi'):
#!/bin/bash
## 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" 'salt' 'passphrase')
apiPassword=$(DecryptString "$apiPassEncrypt" 'salt' 'passphrase')
## Use API to get computer Site from UUID
# Get computer's UUID
compUUID=$(system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }')
compRaw=$(curl "https://jssurl/JSSResource/computers/udid/${compUUID}" --user "$apiUsername:$apiPassword")
echo "$compRaw"
compSite=$(echo "$compRaw" | xpath '//general/site/name' 2>&1 | awk -F'<name>|</name>' '{print $2}')
echo "compSite is $compSite"
if [[ $compSite == *"Example" ]]; then
deptName="Example"
elif [[ $compSite = *"Example2" ]]; then
deptName="Example2"
elif [[ $compSite == *"Example3" ]]; then
deptName="Example3"
fi
echo "deptName is "$deptName
## Use API to get list of departments
deptRaw=$(curl https://jssurl/JSSResource/departments --user "$apiUsername:$apiPassword")
echo "$deptRaw"
# https://bryson3gps.wordpress.com/2014/03/30/the-jss-rest-api-for-everyone/
deptList=$(echo "$deptRaw" | xpath '//department/name' 2>&1 | awk -F'<name>|</name>' '{print $2}')
echo $deptList
if [[ -z "$deptName" ]]; then
echo "deptName not defined"
else
for department in $"{deptList[@]}"
do
if [[ $department == "$deptName"* ]]; then
# https://macscripter.net/viewtopic.php?id=35318
f=${department##*/}
if [[ "${f:0:1}" = "_" ]]; then
echo "NOT Processing $department" 1>&2 # for now just a test
else
if [[ ! -z ${deptParsed} ]]; then
deptParsed=${deptParsed}","
fi
echo "Processing $department" 1>&2
deptParsed=${deptParsed}"""${f}""" # to create "item1","item2","item..n"
fi
fi
done
# https://macscripter.net/viewtopic.php?id=35318
deptChosen="$(/usr/bin/osascript -e 'tell application "System Events" to activate' -e 'tell application "System Events" to return (choose from list {'"$deptParsed"'} with prompt "Choose a Department:" with title "Department Chooser" OK button name "Select" cancel button name "Quit")')"
fi
sudo /usr/local/bin/jamf recon -department "$deptChosen"
sudo /usr/local/bin/jamf recon
Posted on 08-30-2018 06:24 AM
@boberito thanks, I did see on https://jacobsalmela.com/2014/08/04/infamous-execution-error-error-type-10810-occurred-10810/ that one of the causes of the error message could be if it's running as root. Though wouldn't running it through Self Service (where it worked fine) also qualify as running it as root?
In either case, I'm trying to figure out how to change the command so that it runs as the currently logged in user (it's tripping me up because of the "quotation marks inside quotation marks" thing). Maybe it'd be easier to just call it as a function?
loggedInUser=$(stat -f "%Su" /dev/console)
userprompt() {
/usr/bin/osascript -e 'tell application "System Events" to activate' -e 'tell application "System Events" to return (choose from list {'"$deptParsed"'} with prompt "Choose a Department:" with title "Department Chooser" OK button name "Select" cancel button name "Quit")')
}
su "$loggedInUser" -c userprompt
I'll have to test that and check
Posted on 08-30-2018 06:36 AM
So multiple ways to get the currently logged in User
This is the way I like.
LoggedInUser=$(ls -l /dev/console | awk '{ print $3 }')
echo ${LoggedInUser}
But Jamf supplies the currently logged in user as $3. But I've found it to not be as reliable. There are other ways to grab it as well.
LoggedInUser=$3
echo ${LoggedInUser}
I think this may be the more universally liked way. But all 3 do it the same way.
LoggedInUser=$(/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')
echo ${LoggedInUser}
so then to run as another user
sudo -u ${LoggedInUser} /my/command/I/want/run
Posted on 08-30-2018 06:39 AM
@ryan.ball thanks for catching the missing "fi", I actually do have it in the script I'm using but I must've accidentally deleted it when stripping out any personal information before posting the script here. If I didn't have it, though, your catch would've been very helpful.
I don't 100% understand how $deptParsed is set (I got the procedure from somewhere else), but I believe the line deptParsed=${deptParsed}"""${f}"""
is saying to take the existing $deptParsed value and append $f, which is the current department that's being parsed. So it's not actually setting $deptParsed it to itself. In any case, when the AppleScript does run, the items in $deptParsed are presented the way I want them to be.
Posted on 08-30-2018 06:50 AM
It is odd, but if it works then that is the important part.
You could try this:
loggedInUID=$(ls -ln /dev/console | awk '{ print $3 }')
deptChosen="$(launchctl asuser "$loggedInUID" /usr/bin/osascript -e 'tell application "System Events" to activate' -e 'tell application "System Events" to return (choose from list {'"$deptParsed"'} with prompt "Choose a Department:" with title "Department Chooser" OK button name "Select" cancel button name "Quit")')"
Also, have you ever looked at CocoaDialog? There are a lot of threads about it here. You can display a list much easier than with applescript without all the odd escaping and whatnot. Just a thought.
Posted on 08-30-2018 06:52 AM
@boberito thanks for the many options, I was more concerned if I'm going to have problems when I try to run the command and have quotes in quotes:
su "$loggedInUser" -c "/usr/bin/osascript -e 'tell application "System Events" to activate' -e 'tell application "System Events" to return (choose from list {'"$deptParsed"'} with prompt "Choose a Department:" with title "Department Chooser" OK button name "Select" cancel button name "Quit")'"
#or your version, which I think you say doesn't require the quotes
sudo -u ${LoggedInUser} /usr/bin/osascript -e 'tell application "System Events" to activate' -e 'tell application "System Events" to return (choose from list {'"$deptParsed"'} with prompt "Choose a Department:" with title "Department Chooser" OK button name "Select" cancel button name "Quit")'
Will try yours first or play around with these to get something working.
Posted on 08-30-2018 06:52 AM
I'd avoid CocoaDialog since it's dead basically.
Pashua is harder and more complex but still alive as a project.
I wish jamfnotifier did all this stuff :(
Posted on 08-30-2018 07:02 AM
@ryan.ball we do install CocoaDialog (I use it on a separate script that sets a computer's hostname), but try to avoid using it in most cases since:
a) I'm not overly familiar with it.
b) I've heard (like @boberito said) that it's not being developed anymore, so if I'm building something new and fairly simple I figure AppleScript is probably more future-proof (though doesn't seem to have as many features as CocoaDialog).
@boberito I've read a little about Pashua, but I feel like (as you pointed out) from what I read it was going to be too difficult for me at the time.
Thank you both again for your assistance, this has been very helpful and hopefully will solve the issue!
Posted on 08-30-2018 07:56 AM
A recent blog post addresses a few of these points, including the problem with nested quotes (search for 'here document').
Posted on 08-30-2018 08:14 AM
@cdenesha thanks, that's a very well-written and thorough article! Bookmarking it for any other time I need to use display dialog.