Skip to main content

Did anyone attend the "Interactive Lab: Bring Lost Sheep Back to the Flock - Using Automation to Manage Your Fleet" session? If you have did you try out the script to see if it works?

 

I tried it on a test Mac but I don't see it populating the Jamf Management Framework even though the script says it completed successfully. Not sure what I'm missing here. I tried the original script posted in the session. NOTE: There is a typo in the beginning of the script 😉. Not sure how to get ahold of the speaker to have it updated. 
Says: #!/bih/bash

Should say: #!/bin/bash

 

Note: Some people were asking about a way to encrypt the generic Jamf Pro user account you have to create for this process so it doesn't show in clear text in the script. I followed the process used here to encrypt the password. Start at Step 3. I started with using Parameter 5 and left out the "Log Files" parameter. FYI, I did try the script as is to rule out changes I did but I had the same result - script finished successfully but no change on the test Mac.

 

Can you post your script in here making sure to sanitize anything specific to your environment?


Sure, here it is: 

#!/bin/bash #Testing within QA Environment # The purpose of this script is to send a repair command (Redeploy Jamf Management Framework) via MDM to a smart group of devices• # that have not checked in after a certain amount of time. ########### COPYRIGHT AND DISCLAIMER ######################################################## # Copyright notice - 0 2022, Erin Mcdonald, JAMF Software, LIC # THE SOFTWARE IS PROVIDED "AS-IS, " WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL # JAMF SOFTWARE, LLC OR ANY OF ITS AFFILIATES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN- # CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER # DEALINGS IN THE SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL # OR PUNITIVE DAMAGES AND OTHER DAMAGES SUCH AS LOSS OF USE, PROFITS, SAVINGS, TIME OR DATA, BUSINESS INTERRUPTION, # OR PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES. ############################################################################################ # Variables # Replace with your environment's values # Jamf Pro URL including 'https://' and port, if needed URL="https://url.com:8443" # Jamf Pro User account with the following permissions # Jamf Pro Server Objects: Computers, Smart Computer Groups (Read Only), Jamf Pro Server Settings: Check-In, Computer Check-In (Read Only) # Jamf Pro Server Actions: Sent remote Command to Install Package username="apiuser" # Password of the Jamf Pro User account password="password" # Smart Group of computers that have not checked in for X amount of days, replace the # after the = with the ID of the smart group smartGroup=29 # Get a bearer token for all API calls encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) bearerToken=$(/usr/bin/curl "$URL/uapi/auth/tokens" \\ --silent \\ -- request POST \\ --header "Authorization: Basic $encodedCredentials" ) # parse authToken for token, omit expiration token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$bearerToken" | /usr/bin/xargs ) # Execute the mdm command # Get membership details of Computer Group that contains computers that have not checked in in a set amount of days ids+=($(curl --request GET ${URL}/JSSResource/computergroups/id/$smartGroup \\ --header 'Accept: application/xml' \\ --header "Authorization: Bearer ${token}"| xmllint --xpath '//computer_group/computers/computer/id' - 2> /dev/null | sed s/'<id>'//g | sed s/'<\\/ id>'/','/g | sed 's/.$//' | sort -n | tr ',' ' ')) # for loop to go through all IDs in the group and send the remote command to redeplopy the framework for id in "${ids[@]}"; do if [[ $id -gt 0 ]]; then echo "$id" # Post Redeploy command to computer curl --request POST \\ --url ${URL}/api/v1/jamf-management-framework/redeploy/${id} \\ --header 'Content-Type: application/ison' \\ --header "Authorization: Bearer ${token}" else echo "Device id {$id} invalid, skipping..." fi done # Invalidate the token curl --request POST \\ --url ${URL}/api/v1/auth/invalidate-token \\ --header 'Accept: application/ison' \\ --header "Authorization: Bearer ${token}" exit 0

 


Sure, here it is: 

#!/bin/bash #Testing within QA Environment # The purpose of this script is to send a repair command (Redeploy Jamf Management Framework) via MDM to a smart group of devices• # that have not checked in after a certain amount of time. ########### COPYRIGHT AND DISCLAIMER ######################################################## # Copyright notice - 0 2022, Erin Mcdonald, JAMF Software, LIC # THE SOFTWARE IS PROVIDED "AS-IS, " WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL # JAMF SOFTWARE, LLC OR ANY OF ITS AFFILIATES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN- # CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER # DEALINGS IN THE SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL # OR PUNITIVE DAMAGES AND OTHER DAMAGES SUCH AS LOSS OF USE, PROFITS, SAVINGS, TIME OR DATA, BUSINESS INTERRUPTION, # OR PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES. ############################################################################################ # Variables # Replace with your environment's values # Jamf Pro URL including 'https://' and port, if needed URL="https://url.com:8443" # Jamf Pro User account with the following permissions # Jamf Pro Server Objects: Computers, Smart Computer Groups (Read Only), Jamf Pro Server Settings: Check-In, Computer Check-In (Read Only) # Jamf Pro Server Actions: Sent remote Command to Install Package username="apiuser" # Password of the Jamf Pro User account password="password" # Smart Group of computers that have not checked in for X amount of days, replace the # after the = with the ID of the smart group smartGroup=29 # Get a bearer token for all API calls encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) bearerToken=$(/usr/bin/curl "$URL/uapi/auth/tokens" \\ --silent \\ -- request POST \\ --header "Authorization: Basic $encodedCredentials" ) # parse authToken for token, omit expiration token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$bearerToken" | /usr/bin/xargs ) # Execute the mdm command # Get membership details of Computer Group that contains computers that have not checked in in a set amount of days ids+=($(curl --request GET ${URL}/JSSResource/computergroups/id/$smartGroup \\ --header 'Accept: application/xml' \\ --header "Authorization: Bearer ${token}"| xmllint --xpath '//computer_group/computers/computer/id' - 2> /dev/null | sed s/'<id>'//g | sed s/'<\\/ id>'/','/g | sed 's/.$//' | sort -n | tr ',' ' ')) # for loop to go through all IDs in the group and send the remote command to redeplopy the framework for id in "${ids[@]}"; do if [[ $id -gt 0 ]]; then echo "$id" # Post Redeploy command to computer curl --request POST \\ --url ${URL}/api/v1/jamf-management-framework/redeploy/${id} \\ --header 'Content-Type: application/ison' \\ --header "Authorization: Bearer ${token}" else echo "Device id {$id} invalid, skipping..." fi done # Invalidate the token curl --request POST \\ --url ${URL}/api/v1/auth/invalidate-token \\ --header 'Accept: application/ison' \\ --header "Authorization: Bearer ${token}" exit 0

 


I think it's erroring on the bearer credentials.  If i encrypt username / password and then attempt to call bearerToken command, it fails with 401 there. 


I think it's erroring on the bearer credentials.  If i encrypt username / password and then attempt to call bearerToken command, it fails with 401 there. 


I've noticed another type-o.  when calling POST to update the API call says "application/ison", this should be application/json with a "j"..

curl --request POST \\ --url ${URL}/api/v1/jamf-management-framework/redeploy/${id} \\ --header 'Content-Type: application/ison' \\ --header "Authorization: Bearer ${token}"

 continuing to test . 


I've noticed another type-o.  when calling POST to update the API call says "application/ison", this should be application/json with a "j"..

curl --request POST \\ --url ${URL}/api/v1/jamf-management-framework/redeploy/${id} \\ --header 'Content-Type: application/ison' \\ --header "Authorization: Bearer ${token}"

 continuing to test . 


Yep, I saw a couple typos and a couple formatting things. Try this - make sure to put your environment stuff back in there.

#!/bin/bash #Testing within QA Environment # The purpose of this script is to send a repair command (Redeploy Jamf Management Framework) via MDM to a smart group of devices• # that have not checked in after a certain amount of time. ########### COPYRIGHT AND DISCLAIMER ######################################################## # Copyright notice - 0 2022, Erin Mcdonald, JAMF Software, LIC # THE SOFTWARE IS PROVIDED "AS-IS, " WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL # JAMF SOFTWARE, LLC OR ANY OF ITS AFFILIATES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN- # CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER # DEALINGS IN THE SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL # OR PUNITIVE DAMAGES AND OTHER DAMAGES SUCH AS LOSS OF USE, PROFITS, SAVINGS, TIME OR DATA, BUSINESS INTERRUPTION, # OR PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES. ############################################################################################ # Variables # Replace with your environment's values # Jamf Pro URL including 'https://' and port, if needed URL="https://url.com:8443" # Jamf Pro User account with the following permissions # Jamf Pro Server Objects: Computers, Smart Computer Groups (Read Only), Jamf Pro Server Settings: Check-In, Computer Check-In (Read Only) # Jamf Pro Server Actions: Sent remote Command to Install Package username="apiuser" # Password of the Jamf Pro User account password="password" # Smart Group of computers that have not checked in for X amount of days, replace the # after the = with the ID of the smart group smartGroup=29 # Get a bearer token for all API calls encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) bearerToken=$( /usr/bin/curl "$URL/uapi/auth/tokens" \\ --silent \\ --request POST \\ --header "Authorization: Basic $encodedCredentials" ) # parse authToken for token, omit expiration token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$bearerToken" | /usr/bin/xargs ) # Execute the mdm command # Get membership details of Computer Group that contains computers that have not checked in in a set amount of days ids+=($(curl --request GET \\ --url ${URL}/JSSResource/computergroups/id/$smartGroup \\ --header 'Accept: application/xml' \\ --header "Authorization: Bearer ${token}"| xmllint --xpath '//computer_group/computers/computer/id' - 2> /dev/null | sed s/'<id>'//g | sed s/'<\\/ id>'/','/g | sed 's/.$//' | sort -n | tr ',' ' ')) # for loop to go through all IDs in the group and send the remote command to redeplopy the framework for id in "${ids[@]}"; do if [[ $id -gt 0 ]]; then echo "$id" # Post Redeploy command to computer curl --request POST \\ --url ${URL}/api/v1/jamf-management-framework/redeploy/${id} \\ --header 'Content-Type: application/json' \\ --header "Authorization: Bearer ${token}" else echo "Device id {$id} invalid, skipping..." fi done # Invalidate the token curl --request POST \\ --url ${URL}/api/v1/auth/invalidate-token \\ --header 'Accept: application/json' \\ --header "Authorization: Bearer ${token}" exit 0

Yep, I saw a couple typos and a couple formatting things. Try this - make sure to put your environment stuff back in there.

#!/bin/bash #Testing within QA Environment # The purpose of this script is to send a repair command (Redeploy Jamf Management Framework) via MDM to a smart group of devices• # that have not checked in after a certain amount of time. ########### COPYRIGHT AND DISCLAIMER ######################################################## # Copyright notice - 0 2022, Erin Mcdonald, JAMF Software, LIC # THE SOFTWARE IS PROVIDED "AS-IS, " WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL # JAMF SOFTWARE, LLC OR ANY OF ITS AFFILIATES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN- # CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER # DEALINGS IN THE SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL # OR PUNITIVE DAMAGES AND OTHER DAMAGES SUCH AS LOSS OF USE, PROFITS, SAVINGS, TIME OR DATA, BUSINESS INTERRUPTION, # OR PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES. ############################################################################################ # Variables # Replace with your environment's values # Jamf Pro URL including 'https://' and port, if needed URL="https://url.com:8443" # Jamf Pro User account with the following permissions # Jamf Pro Server Objects: Computers, Smart Computer Groups (Read Only), Jamf Pro Server Settings: Check-In, Computer Check-In (Read Only) # Jamf Pro Server Actions: Sent remote Command to Install Package username="apiuser" # Password of the Jamf Pro User account password="password" # Smart Group of computers that have not checked in for X amount of days, replace the # after the = with the ID of the smart group smartGroup=29 # Get a bearer token for all API calls encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) bearerToken=$( /usr/bin/curl "$URL/uapi/auth/tokens" \\ --silent \\ --request POST \\ --header "Authorization: Basic $encodedCredentials" ) # parse authToken for token, omit expiration token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$bearerToken" | /usr/bin/xargs ) # Execute the mdm command # Get membership details of Computer Group that contains computers that have not checked in in a set amount of days ids+=($(curl --request GET \\ --url ${URL}/JSSResource/computergroups/id/$smartGroup \\ --header 'Accept: application/xml' \\ --header "Authorization: Bearer ${token}"| xmllint --xpath '//computer_group/computers/computer/id' - 2> /dev/null | sed s/'<id>'//g | sed s/'<\\/ id>'/','/g | sed 's/.$//' | sort -n | tr ',' ' ')) # for loop to go through all IDs in the group and send the remote command to redeplopy the framework for id in "${ids[@]}"; do if [[ $id -gt 0 ]]; then echo "$id" # Post Redeploy command to computer curl --request POST \\ --url ${URL}/api/v1/jamf-management-framework/redeploy/${id} \\ --header 'Content-Type: application/json' \\ --header "Authorization: Bearer ${token}" else echo "Device id {$id} invalid, skipping..." fi done # Invalidate the token curl --request POST \\ --url ${URL}/api/v1/auth/invalidate-token \\ --header 'Accept: application/json' \\ --header "Authorization: Bearer ${token}" exit 0

Interestingly enough, I've had to use double quotes in a couple of locations in order to have it run successfully.  In addition when parsing with the SED command, this failed all-together.  I reverted to calling for just the text() of the value within the container 

This finally worked for me.  Thank you @bcbackes for reviewing and assisting me.  

#!/bin/bash #Testing within QA Environment # The purpose of this script is to send a repair command (Redeploy Jamf Management Framework) via MDM to a smart group of devices• # that have not checked in after a certain amount of time. ########### COPYRIGHT AND DISCLAIMER ######################################################## # Copyright notice - 0 2022, Erin Mcdonald, JAMF Software, LIC # THE SOFTWARE IS PROVIDED "AS-IS, " WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL # JAMF SOFTWARE, LLC OR ANY OF ITS AFFILIATES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN- # CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER # DEALINGS IN THE SOFTWARE, INCLUDING BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL # OR PUNITIVE DAMAGES AND OTHER DAMAGES SUCH AS LOSS OF USE, PROFITS, SAVINGS, TIME OR DATA, BUSINESS INTERRUPTION, # OR PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES. ############################################################################################ # Variables # Replace with your environment's values # Jamf Pro URL including 'https://' and port, if needed URL="https://url.com:8443" # Jamf Pro User account with the following permissions # Jamf Pro Server Objects: Computers, Smart Computer Groups (Read Only), Jamf Pro Server Settings: Check-In, Computer Check-In (Read Only) # Jamf Pro Server Actions: Sent remote Command to Install Package username="apiuser" # Password of the Jamf Pro User account password="password" # Smart Group of computers that have not checked in for X amount of days, replace the # after the = with the ID of the smart group smartGroup=29 # Get a bearer token for all API calls encodedCredentials=$( printf "$username:$password" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - ) bearerToken=$( /usr/bin/curl "$URL/uapi/auth/tokens" \\ --silent \\ --request POST \\ --header "Authorization: Basic $encodedCredentials" ) # parse authToken for token, omit expiration token=$( /usr/bin/awk -F \\" '{ print $4 }' <<< "$bearerToken" | /usr/bin/xargs ) # Execute the mdm command # Get membership details of Computer Group that contains computers that have not checked in in a set amount of days ids+=($(curl --request GET \\ --url ${URL}/JSSResource/computergroups/id/$smartGroup \\ --header 'Accept: application/xml' \\ --header "Authorization: Bearer ${token}"| xmllint --xpath "/computer_group/computers/computer/id/text()" - )) # for loop to go through all IDs in the group and send the remote command to redeplopy the framework for id in "${ids[@]}"; do if [[ $id -gt 0 ]]; then echo "$id" # Post Redeploy command to computer curl --request POST \\ --url ${URL}/api/v1/jamf-management-framework/redeploy/${id} \\ --header 'Content-Type: application/json' \\ --header "Authorization: Bearer ${token}" else echo "Device id {$id} invalid, skipping..." fi done # Invalidate the token curl --request POST \\ --url ${URL}/api/v1/auth/invalidate-token \\ --header 'Accept: application/json' \\ --header "Authorization: Bearer ${token}" exit 0

 


Question -- Is anyone running 12.6 and also trying to test?  Working through the encrypted script now and getting a 402 error.  I'm almost positive it's related to token encryption.  I notice the following when using encrypted script method.

*** WARNING : deprecated key derivation used. Using -iter or -pbkdf2 would be better.

Does anyone have the updated script for this? it seems the Api changed for getting the membership of a smart group. I cant figure it out .

 

old:

ids+=($(curl --request GET \\
--url ${URL}/JSSResource/computergroups/id/$smartGroup \\
--header 'Accept: application/xml' \\
--header "Authorization: Bearer ${token}"| xmllint --xpath "/computer_group/computers/computer/id/text()" - ))

 

New:

ids+=($(curl -X 'GET' \\
'https://$URL.jamfcloud.com/api/v2/computer-groups/smart-group-membership/$id' \\
-H 'accept: application/json' \\
-H 'Authorization: Bearer ${token}"| xmllint --xpath "/computer_group/computers/computer/id/text()" - ))