Is there a way to show "Locked" computers in the Dashboard?

forrest99
New Contributor III

Is there a way to display a computer group in the Jamf Pro Dashboard based on whether it is Locked in Computer > Management? I tried all the advanced options but could not find anything that seems to work.

1 ACCEPTED SOLUTION

sdagley
Esteemed Contributor II

@forrest99 There's no mechanism to display that I'm aware of, and that's why I always append a Lock Pending to the device name when I send a Lock request. I have looked at the Jamf API (both old and new) to see if there's a way to access that info and it doesn't look like it.

If you're self hosted you should be able to extract that info from your Jamf Pro MySQL database, and Jamf Support should be able to provide the query to do that.

EDIT: There is a way, see @mm2270's post for the actual solution.

View solution in original post

14 REPLIES 14

sdagley
Esteemed Contributor II

@forrest99 There's no mechanism to display that I'm aware of, and that's why I always append a Lock Pending to the device name when I send a Lock request. I have looked at the Jamf API (both old and new) to see if there's a way to access that info and it doesn't look like it.

If you're self hosted you should be able to extract that info from your Jamf Pro MySQL database, and Jamf Support should be able to provide the query to do that.

EDIT: There is a way, see @mm2270's post for the actual solution.

mm2270
Legendary Contributor III

Actually, there is a way to see if an MDM command, such as the Remote Lock command has been received by the Mac, or is still pending, using the API. This doesn't actually mean the Mac is locked, since I've seen odd cases of a Mac "receiving" the lock command and then taking a little longer for the lock to actually kick in. Sometimes many minutes before it actually takes place, which is annoying to be honest. But knowing it received it versus the command still "pending" is better than nothing.

The API path (classic) is /JSSResource/computercommands/name/DeviceLock Some of the xml tags that show up in the result are <command> <date_sent> <apns_result_status> and <serial_number>. The apns_result_status is the one that tells you if it was received or not.

sdagley
Esteemed Contributor II

Thanks for the correction @mm2270 - this is very useful.

sdagley
Esteemed Contributor II

@mm2270 Your clue on the proper API endpoint inspired me to write a script to pull the list of Macs sent a Lock command, and uses an XSLT to report the serial number and the status of the command:

 

#!/bin/bash

# Quick and dirty script to query a JSS for any computers that have been sent a Lock Computer
# command. Returns the serial number of any computers that were targeted, and if the Mac
# responded to the command appends an "Acknowledged" after the serial number
#
# Written by @sdagley with some advice from @mm2270

jssURL="https://yourjss.url.here:8443"

apiID="$(osascript -e 'Tell application "System Events" to display dialog "Enter a Jamf Pro API ID:" default answer ""' -e 'text returned of result' 2>/dev/null)"
apiPassword="$(osascript -e 'Tell application "System Events" to display dialog "Enter the password for the Jamf Pro API ID:" default answer ""' -e 'text returned of result' 2>/dev/null)"

cat << EOF > /var/tmp/ComputerLockStylesheet.xslt
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 
<xsl:template match="/computer_commands"> 
<xsl:for-each select="computer_command"> 
<xsl:value-of select="computers/computer/serial_number"/> 
<xsl:text>,</xsl:text> 
<xsl:value-of select="apns_result_status"/> 
<xsl:text>&#xa;</xsl:text> 
</xsl:for-each> 
</xsl:template> 
</xsl:stylesheet>
EOF

GetJamfProAPIToken() {
	apiToken=""
	
    # This function uses Basic Authentication to get a new bearer token for API authentication.
    # Use user account's username and password credentials with Basic Authorization to request a bearer token.

    if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then
        apiToken=$(/usr/bin/curl -X POST --silent -u "${apiID}:${apiPassword}" "${jssURL}/api/v1/auth/token" | python -c 'import sys, json; print json.load(sys.stdin)["token"]')
    else
        apiToken=$(/usr/bin/curl -X POST --silent -u "${apiID}:${apiPassword}" "${jssURL}/api/v1/auth/token" | plutil -extract token raw -)
    fi
}

APITokenValidCheck() {
    # Verify that API authentication is using a valid token by running an API command
    # which displays the authorization details associated with the current API user. 
    # The API call will only return the HTTP status code.

    api_authentication_check=$(/usr/bin/curl --write-out %{http_code} --silent --output /dev/null "${jssURL}/api/v1/auth" --request GET --header "Authorization: Bearer ${apiToken}")
}

InvalidateToken() {
    # Verify that API authentication is using a valid token by running an API command
    # which displays the authorization details associated with the current API user. 
    # The API call will only return the HTTP status code.

    APITokenValidCheck

    # If the api_authentication_check has a value of 200, that means that the current
    # bearer token is valid and can be used to authenticate an API call.

    if [[ ${api_authentication_check} == 200 ]]; then

        # If the current bearer token is valid, an API call is sent to invalidate the token.

        authToken=$(/usr/bin/curl "${jssURL}/api/v1/auth/invalidate-token" --silent  --header "Authorization: Bearer ${apiToken}" -X POST)
    fi
}

GetJamfProAPIToken

apiURL="JSSResource/computercommands/name/DeviceLock"

curl -s \
	--header "Authorization: Bearer ${apiToken}" --header "accept: text/xml" \
	--url "${jssURL}/${apiURL}" \
	--data "${apiData}" \
    --request GET | xsltproc /var/tmp/ComputerLockStylesheet.xslt -

InvalidateToken

exit 0

 

mm2270
Legendary Contributor III

Nice work @sdagley! I'm examining your script and will put some of it to good use, because I really need to learn how to use those xsltproc commands and xslt style sheets for output.

I had to do something similar to this last year to generate some reports for devices we needed to issue locks to (that's how I found the correct API endpoint), and I just fudged it by pulling the result in xml format and using some awk and paste commands to pipe it out to a .csv file. It worked, but it's nowhere near as elegant as what you have :)

sdagley
Esteemed Contributor II

@mm2270 I'm glad to repay the favor for the endpoint education :-)

XSLT was one of the topics added to the Jamf 400 course when it was updated from the CCE curriculum (or at least I don't remember it being part of the CCE). I don't make much use of it in my "regular" API scripts, but it definitely makes parsing the Lock commands much easier.

dungeonadept
New Contributor III

I'm having trouble with this script. Do you know if it still works? I'm getting the below error in the curl command when I use my JSS username and password for the script.

 

-:1: parser error : Document is empty

^
unable to parse -

 

sdagley
Esteemed Contributor II

I haven't used this in over a year but I don't think anything has changed the would break it. When you say you're using your JSS username and password do you mean you're entering them when the script prompts, or you changed the script to use them for Basic Auth? If the former is your JSS account an admin account?

dungeonadept
New Contributor III

Entering my admin JSS account info in the scripts prompts.

sdagley
Esteemed Contributor II

Try adding a " -x" after #!/bin/bash so you can see exactly what the script is doing and if the Jamf API call is working

forrest99
New Contributor III

Thank you for taking the time to respond. It is helpful to know when something is not possible. 

frodo7200
New Contributor

Nice little script, will be giving it a try. I've used the classic API computercommands/name/DeviceLock which returns the complete list of locked devices, seems the last one locked is last entry if that helps. What doesnt seem to happen though is that this flag doesnt get reset once the device is unlocked. It will remain showing locked/pending even once unlocked in my testing. Also worth noting off site devices may lock but only show as pending. Seems to work correctly onsite but not getting the set message for offsite. I'm sure I've seen something about once its locked it stop talking so its a timing thing when offsite. Anyone else finding that?

sdagley
Esteemed Contributor II

@frodo7200 Is your Jamf Pro server only accessible to your managed Macs when they're onsite?

frodo7200
New Contributor

No its not that, just found that some never actually lock when offsite, or do but never show as locked (even when I know they are as had user call in about it). I ended up making a full screen helper lockout screen policy which I add them to as well as locking. Seems to get more of the ones that dont lock. Same as some where the MDM profile isnt there (uninstalled by user) so when you look in management there are no options. And if you try to do a lock from 'send command' from a search (bottom right), the send fails. Which is odd as I thought that went via Apple so not sure why that would often fail to send.