Skip to main content

I'm wondering if there is a way to bring up a GUI (jamfhelper, cocoadialog, etc) to give a device an already created EA. As mentioned, the EA is created, I just need a way for a technician who is setting up the computer to assign it to the right EA so that it drops into scope for some policies to run based on the EA. The EA I created has the following characteristics: Data Type: String, Input Type: Pop-Up Menu . I then have a few items in the dropdown to choose. I'm hoping to be able to assign one of those dropdown items directly from the computer.

You need to be careful about passing credentials into scripts as it's not a safe practice


So I have a suggestion that might work and something we use here during the build process. When the ADE process starts it brings up DepNotify and asks the user for certain information (computer name, user assigned to, location, and persona). What I did was I had the script default write those values to a plist file.

So you can create a GUI to get the data and send it to the plist file. Then you can use a EA that uses a script to read the information from the plist file.

But I do think that giving techs access do to do it themselves might be faster.


Does anyone have this same script or something similar which is using basic authentication changed over to token authentication?

For starters I have, the following ground work to get the token but I'm not sure how to use the token to authenticate to the API so I can run scripts similar to the ones shared on this thread.

#!/bin/bash username="username_here" password="password_here" URL="https://someplace.jamfcloud.com" # created base64-encoded credentials encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) # echo encodedCredentials: "$encodedCredentials" # generate an auth token authToken=$( /usr/bin/curl "$URL/api/v1/auth/token" \\ --silent \\ --request POST \\ --header "Authorization: Basic $encodedCredentials" ) # echo authToken: "$authToken" # parse authToken for token, omit expiration if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then token=$(/usr/bin/awk -F \\" 'NR==2{print $4}' <<< "$authToken" | /usr/bin/xargs) else token=$(/usr/bin/plutil -extract token raw -o - - <<< "$authToken") fi

 


Does anyone have this same script or something similar which is using basic authentication changed over to token authentication?

For starters I have, the following ground work to get the token but I'm not sure how to use the token to authenticate to the API so I can run scripts similar to the ones shared on this thread.

#!/bin/bash username="username_here" password="password_here" URL="https://someplace.jamfcloud.com" # created base64-encoded credentials encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) # echo encodedCredentials: "$encodedCredentials" # generate an auth token authToken=$( /usr/bin/curl "$URL/api/v1/auth/token" \\ --silent \\ --request POST \\ --header "Authorization: Basic $encodedCredentials" ) # echo authToken: "$authToken" # parse authToken for token, omit expiration if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then token=$(/usr/bin/awk -F \\" 'NR==2{print $4}' <<< "$authToken" | /usr/bin/xargs) else token=$(/usr/bin/plutil -extract token raw -o - - <<< "$authToken") fi

 


This is a template I work from, it might need some tweaking at the command part on the bottom, but the token stuff should work.

 

#!/bin/sh # Set some variables username=$4 password=$5 jssURL="https://company.jamfcloud.com" # Get the token authBasic=$(echo '$username:$password\\c' | base64) # "\\c" is required to get the right format authToken=$(curl -sk "$jssURL/api/v1/auth/token" -H "Accept: application/json" -H "Authorization: Basic $authBasic" -X POST --connect-timeout 10) curlRes=$? # Check the token result if [[ $curlRes -gt 0 ]] then echo "CURL return code: $curlRes" exit 1 fi # We got a token, lets parse the data for the token itself read -r -d '' JXA <<EOF function run() { var tokenInfo = JSON.parse(\\`$authToken\\`); return tokenInfo.token; } EOF OAuthToken=$( osascript -l 'JavaScript' <<< "${JXA}" ) read -r -d '' JXA <<EOF function run() { var tokenInfo = JSON.parse(\\`$authToken\\`); return tokenInfo.expires; } EOF # Set a variable with the expiration if your script will be running a while and you need to refer back OAuthExpires=$( osascript -l 'JavaScript' <<< "${JXA}" ) # Run a Classic API call with bearer token auth serialNum=$(ioreg -l | grep IOPlatformSerialNumber | awk '{print $4}' | cut -d "\\"" -f 2) cloudCompID=$(curl -sk "$jssURL/JSSResource/computers/serialnumber/$serialNum" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $OAuthToken" -X GET --connect-timeout 10 | xmllint --xpath "/computer/general/id/text()" - ) echo "Current machine computer ID: $cloudCompID" # Run an Jamf Pro API call with bearer token auth computersJSON=$(curl -Ls -X GET "$jssURL/api/v1/computers-inventory?section=&page=0&page-size=100&sort=id%3Aasc" -H "Accept: application/json" -H "Authorization: Bearer $OAuthToken") echo "Computers: $computersJSON"

 

 


This is a template I work from, it might need some tweaking at the command part on the bottom, but the token stuff should work.

 

#!/bin/sh # Set some variables username=$4 password=$5 jssURL="https://company.jamfcloud.com" # Get the token authBasic=$(echo '$username:$password\\c' | base64) # "\\c" is required to get the right format authToken=$(curl -sk "$jssURL/api/v1/auth/token" -H "Accept: application/json" -H "Authorization: Basic $authBasic" -X POST --connect-timeout 10) curlRes=$? # Check the token result if [[ $curlRes -gt 0 ]] then echo "CURL return code: $curlRes" exit 1 fi # We got a token, lets parse the data for the token itself read -r -d '' JXA <<EOF function run() { var tokenInfo = JSON.parse(\\`$authToken\\`); return tokenInfo.token; } EOF OAuthToken=$( osascript -l 'JavaScript' <<< "${JXA}" ) read -r -d '' JXA <<EOF function run() { var tokenInfo = JSON.parse(\\`$authToken\\`); return tokenInfo.expires; } EOF # Set a variable with the expiration if your script will be running a while and you need to refer back OAuthExpires=$( osascript -l 'JavaScript' <<< "${JXA}" ) # Run a Classic API call with bearer token auth serialNum=$(ioreg -l | grep IOPlatformSerialNumber | awk '{print $4}' | cut -d "\\"" -f 2) cloudCompID=$(curl -sk "$jssURL/JSSResource/computers/serialnumber/$serialNum" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $OAuthToken" -X GET --connect-timeout 10 | xmllint --xpath "/computer/general/id/text()" - ) echo "Current machine computer ID: $cloudCompID" # Run an Jamf Pro API call with bearer token auth computersJSON=$(curl -Ls -X GET "$jssURL/api/v1/computers-inventory?section=&page=0&page-size=100&sort=id%3Aasc" -H "Accept: application/json" -H "Authorization: Bearer $OAuthToken") echo "Computers: $computersJSON"

 

 


Here is a the original script shared in this thread (thanks @mm2270 ) converted to token authentication, however I'm getting a permissions error message at one part.

#!/bin/bash username="username_here" password="password_here" URL=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url | sed 's|/$||') EA_ID="$6" # Make sure xpath changes won't bother us! xpath() { # the xpath tool changes in Big Sur if [[ $(sw_vers -buildVersion) > "20A" ]]; then /usr/bin/xpath -e "$@" else /usr/bin/xpath "$@" fi } ######################################## ## This section is getting the token ## ######################################## # created base64-encoded credentials encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) # generate an auth token (This is not the sanitized version) authToken=$( /usr/bin/curl "$URL/api/v1/auth/token" \\ --silent \\ --request POST \\ --header "Authorization: Basic $encodedCredentials" ) # parse authToken for token, omit expiration (this is the sanitized version) if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then token=$(/usr/bin/awk -F \\" 'NR==2{print $4}' <<< "$authToken" | /usr/bin/xargs) else token=$(/usr/bin/plutil -extract token raw -o - - <<< "$authToken") fi ######################################################################## ######## This is the start of the Computer Role API Commands ########### ######################################################################## if [ -z "$username" ] || [ -z "$password" ] || [ -z "$EA_ID" ]; then echo "One of the required script parameters was not filled in. Please check the policy script parameters and try again." exit 1 fi # Computer's UUID/UDID string UDID=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}') ## The logged in user and their UID LOGGED_IN_USER=$(stat -f%Su /dev/console) LOGGED_IN_UID=$(id -u "$LOGGED_IN_USER") ## API call to obtain the Extension Attribute and store in file curl -sk "$URL/JSSResource/computerextensionattributes/id/$EA_ID" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $token" -X GET --connect-timeout 10 | xmllint --format - > /tmp/${EA_ID}.xml ## Get the EA display name EA_NAME=$(xpath '/computer_extension_attribute/name/text()' < /tmp/${EA_ID}.xml) ## API call to obtain a list of drop down values from the Extension Attribute VALUES_ALL=$(xpath '/computer_extension_attribute/input_type/popup_choices' < /tmp/${EA_ID}.xml 2>/dev/null | xmllint --format - | awk -F'>|<' '/<choice>/{print $3}') if [ ! -z "$VALUES_ALL" ]; then ## Values were obtained for the EA. Prompt user to make a selection from a list SELECTION=$(/bin/launchctl asuser "$LOGGED_IN_UID" sudo -iu "$LOGGED_IN_USER" /usr/bin/osascript << EOD tell application "System Events" activate set Values to do shell script "echo \\"$VALUES_ALL\\"" set ValuesList to paragraphs of Values choose from list ValuesList with prompt "Choose the appropriate computer role:" end tell EOD) else echo "No values obtained in the API" exit 1 fi function updateEAValue () { ## Create an xml file containing the EA settings cat << EOF > /tmp/EA_${EA_ID}.xml <computer> <extension_attributes> <extension_attribute> <id>${EA_ID}</id> <name>${EA_NAME}</name> <type>String</type> <value>${SELECTION}</value> </extension_attribute> </extension_attributes> </computer> EOF ## Update the current computer's server record with the updated EA value curl -sk "$URL/JSSResource/computers/udid/${UDID}" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $token" -X PUT --connect-timeout 10 | "/tmp/${EA_ID}.xml" -X PUT if [ $? == 0 ]; then echo "Extension Attribute value updated successfully" /usr/local/bin/jamf displayMessage -message "Computer role updated successfully" rm /tmp/EA_${EA_ID}.xml; rm /tmp/${EA_ID}.xml exit 0 else echo "Error when attempting to update the Extension Attribute value" /usr/local/bin/jamf displayMessage -message "Error when attempting to update the Extension Attribute value" rm /tmp/EA_${EA_ID}.xml; rm /tmp/${EA_ID}.xml exit 1 fi } if [ "$SELECTION" != "false" ]; then updateEAValue else echo "User canceled from selection. Nothing to do" exit 0 fi

 The part that I'm not able to get past for this API call to write the EA to the computer record is at this point:

curl -sk "$URL/JSSResource/computers/udid/${UDID}" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $token" -X PUT --connect-timeout 10 | "/tmp/${EA_ID}.xml" -X PUT

I suspect it has something to do with the syntax- possibly the method that I'm using (PUT vs GET vs POST) to update the record or something not correct in the command.  The exact error message I'm getting is: /tmp/6.xml: Permission denied.

Any guidance would be appreciated!


Here is a the original script shared in this thread (thanks @mm2270 ) converted to token authentication, however I'm getting a permissions error message at one part.

#!/bin/bash username="username_here" password="password_here" URL=$(/usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf.plist jss_url | sed 's|/$||') EA_ID="$6" # Make sure xpath changes won't bother us! xpath() { # the xpath tool changes in Big Sur if [[ $(sw_vers -buildVersion) > "20A" ]]; then /usr/bin/xpath -e "$@" else /usr/bin/xpath "$@" fi } ######################################## ## This section is getting the token ## ######################################## # created base64-encoded credentials encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) # generate an auth token (This is not the sanitized version) authToken=$( /usr/bin/curl "$URL/api/v1/auth/token" \\ --silent \\ --request POST \\ --header "Authorization: Basic $encodedCredentials" ) # parse authToken for token, omit expiration (this is the sanitized version) if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then token=$(/usr/bin/awk -F \\" 'NR==2{print $4}' <<< "$authToken" | /usr/bin/xargs) else token=$(/usr/bin/plutil -extract token raw -o - - <<< "$authToken") fi ######################################################################## ######## This is the start of the Computer Role API Commands ########### ######################################################################## if [ -z "$username" ] || [ -z "$password" ] || [ -z "$EA_ID" ]; then echo "One of the required script parameters was not filled in. Please check the policy script parameters and try again." exit 1 fi # Computer's UUID/UDID string UDID=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}') ## The logged in user and their UID LOGGED_IN_USER=$(stat -f%Su /dev/console) LOGGED_IN_UID=$(id -u "$LOGGED_IN_USER") ## API call to obtain the Extension Attribute and store in file curl -sk "$URL/JSSResource/computerextensionattributes/id/$EA_ID" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $token" -X GET --connect-timeout 10 | xmllint --format - > /tmp/${EA_ID}.xml ## Get the EA display name EA_NAME=$(xpath '/computer_extension_attribute/name/text()' < /tmp/${EA_ID}.xml) ## API call to obtain a list of drop down values from the Extension Attribute VALUES_ALL=$(xpath '/computer_extension_attribute/input_type/popup_choices' < /tmp/${EA_ID}.xml 2>/dev/null | xmllint --format - | awk -F'>|<' '/<choice>/{print $3}') if [ ! -z "$VALUES_ALL" ]; then ## Values were obtained for the EA. Prompt user to make a selection from a list SELECTION=$(/bin/launchctl asuser "$LOGGED_IN_UID" sudo -iu "$LOGGED_IN_USER" /usr/bin/osascript << EOD tell application "System Events" activate set Values to do shell script "echo \\"$VALUES_ALL\\"" set ValuesList to paragraphs of Values choose from list ValuesList with prompt "Choose the appropriate computer role:" end tell EOD) else echo "No values obtained in the API" exit 1 fi function updateEAValue () { ## Create an xml file containing the EA settings cat << EOF > /tmp/EA_${EA_ID}.xml <computer> <extension_attributes> <extension_attribute> <id>${EA_ID}</id> <name>${EA_NAME}</name> <type>String</type> <value>${SELECTION}</value> </extension_attribute> </extension_attributes> </computer> EOF ## Update the current computer's server record with the updated EA value curl -sk "$URL/JSSResource/computers/udid/${UDID}" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $token" -X PUT --connect-timeout 10 | "/tmp/${EA_ID}.xml" -X PUT if [ $? == 0 ]; then echo "Extension Attribute value updated successfully" /usr/local/bin/jamf displayMessage -message "Computer role updated successfully" rm /tmp/EA_${EA_ID}.xml; rm /tmp/${EA_ID}.xml exit 0 else echo "Error when attempting to update the Extension Attribute value" /usr/local/bin/jamf displayMessage -message "Error when attempting to update the Extension Attribute value" rm /tmp/EA_${EA_ID}.xml; rm /tmp/${EA_ID}.xml exit 1 fi } if [ "$SELECTION" != "false" ]; then updateEAValue else echo "User canceled from selection. Nothing to do" exit 0 fi

 The part that I'm not able to get past for this API call to write the EA to the computer record is at this point:

curl -sk "$URL/JSSResource/computers/udid/${UDID}" -H "Content-Type: application/xml" -H "Accept: application/xml" -H "Authorization: Bearer $token" -X PUT --connect-timeout 10 | "/tmp/${EA_ID}.xml" -X PUT

I suspect it has something to do with the syntax- possibly the method that I'm using (PUT vs GET vs POST) to update the record or something not correct in the command.  The exact error message I'm getting is: /tmp/6.xml: Permission denied.

Any guidance would be appreciated!


Ironically, I was looking at that script myself today trying to update my old auth scripts. I got that same error, I suspect there might be another xml file in tmp with that name (since it's just a number). I updated my code to "/tmp/$Jamf_EA_{EA_ID}.xml" in a few spots and it seems to be working now (although I'm getting a HTTP 401 return code trying to get the token). Slow progress is still progress, right?

 

Edit: 

My credentials were setup like this:

encodedCredentials=$(echo "$APIUSER:$APIPASS\\c" | base64)

This worked fine when I ran the script locally, but failed when running through my Self Service policy. When I swapped in the `printf` command above, I got the prompt below and clicking that worked.


Ironically, I was looking at that script myself today trying to update my old auth scripts. I got that same error, I suspect there might be another xml file in tmp with that name (since it's just a number). I updated my code to "/tmp/$Jamf_EA_{EA_ID}.xml" in a few spots and it seems to be working now (although I'm getting a HTTP 401 return code trying to get the token). Slow progress is still progress, right?

 

Edit: 

My credentials were setup like this:

encodedCredentials=$(echo "$APIUSER:$APIPASS\\c" | base64)

This worked fine when I ran the script locally, but failed when running through my Self Service policy. When I swapped in the `printf` command above, I got the prompt below and clicking that worked.


@PhillyPhoto , did you ever get this to work?