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 "${idsd@]}"; do
if f $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 "${idsd@]}"; do
if f $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 "${idsd@]}"; do
if f $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 "${idsd@]}"; do
if f $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 i $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()" - ))


Reply