Skip to main content
Solved

Question about: Bring Lost Sheep Back to the Flock - Using Automation to Manage Your Fleet

  • September 28, 2022
  • 32 replies
  • 339 views

Show first post

32 replies

Forum|alt.badge.img+8
  • Contributor
  • October 6, 2022

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

 


Forum|alt.badge.img+8
  • Contributor
  • October 6, 2022

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. 


Forum|alt.badge.img+8
  • Contributor
  • October 6, 2022

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 . 


Forum|alt.badge.img+15
  • Author
  • Valued Contributor
  • October 6, 2022

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

Forum|alt.badge.img+8
  • Contributor
  • October 6, 2022

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

 


Forum|alt.badge.img+8
  • Contributor
  • October 7, 2022

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.

TheITGuy69
Forum|alt.badge.img+7
  • Contributor
  • May 24, 2025

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()" - ))