Using API to Unmange Computers and Remove MDM Profile

cyberotter
New Contributor II

Hi there! I'm tasked with migrating our devices from Jamf to WorkspaceONE. Working on a migration script to unmange computers automatically and have the user install an MDM profile for automated enrollment. 

My issue is the JamfPro API Command to UnmanageDevice. Its just not going through. Here is the command I am using: 

curl -X POST --header "Authorization: Bearer $bearer_token" "$JamfProURL/JSSResource/computercommands/command/UnmanageDevice/id/$DeviceID"

The variables are working for everything else so it can authenticate into jamf and pull the device ID using the computers serial number, but this is the main blocker. Below is the response I get:

<html>
<head>
   <title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Not Found</p>
<p>The server has not found anything matching the request URI</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>
1 ACCEPTED SOLUTION

Well I got it working showhow. Guess it was just tweaking with the variable until it starts to work. 

# Get Mac serial number
serialNumber=`system_profiler SPHardwareDataType | awk '/Serial/ {print $4}'`
echo "Mac serial: $serialNumber"

# Curl to get Mac Jamf ID. Adding text()' will just return the Jamf ID without bracked info.
# determine Jamf Pro device id
deviceID=$(curl -s -H "Accept: text/xml" -H "Authorization: Bearer ${bearer_token}" ${JamfProURL}/JSSResource/computers/serialnumber/"$serialNumber" | xmllint --xpath '/computer/general/id/text()' -)
echo "Jamf ID: $deviceID"

# Remove Jamf Framework
echo "Removing Jamf Framework..."
/usr/local/bin/jamf removeFramework

# Curl to send command to remove MDM profile from the Mac
echo "Removing Jamf MDM via CURL $JamfProURL/JSSResource/computercommands/command/UnmanageDevice/id/$deviceID"
curl -v -X POST --header "Authorization: Bearer $bearer_token" "$JamfProURL/JSSResource/computercommands/command/UnmanageDevice/id/$deviceID"

exit 0

So there's the code I'm using in case someone else has a similar issue or If I run into this again.  

View solution in original post

9 REPLIES 9

sdagley
Esteemed Contributor II

What happens if you try BlankPush instead of UnmanagedDevice? And/or if you hardcode the ID of a specific Mac?

cyberotter
New Contributor II

So putting the DeviceID hardcoded into the URL actually seemed to correct the issue (Device is now unmanaged)

<?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>UnmanageDevice</name><command_uuid>9c5b938b-e310-4407-93a9-d13fc93d7ed9</command_uuid><computer_id>7744</computer_id></command></computer_command>%  

But if that's the case, what is my bash script doing wrong to put in the deviceID it pulls, this script needs to run an any machine that's in Jamf and unenroll it.

cyberotter
New Contributor II

Couldn't edit my response. This is the script for pulling the ID (Hardcoded the Serial Number and commented out the other script because this is for a different machine than I'm debugging the script with)

# Get Mac serial number
#serialNumber=`system_profiler SPHardwareDataType | awk '/Serial/ {print $4}'`
serialNumber="H4HRPKVFH3"
echo "Mac serial: $serialNumber"

# Curl to get Mac Jamf ID. Adding text()' will just return the Jamf ID without bracked info.
# determine Jamf Pro device id
deviceID=$(curl -s -H "Accept: text/xml" -H "Authorization: Bearer ${bearer_token}" ${JamfProURL}/JSSResource/computers/serialnumber/"$serialNumber" | xmllint --xpath '/computer/general/id/text()' -)
echo "Jamf ID: $deviceID"

This is the output

Mac serial: H4HRPKVFH3
Jamf ID: 7744

 

sdagley
Esteemed Contributor II

That should work. Any chance the Mac you're trying to u-manage is already un-managed? 

cyberotter
New Contributor II

No I'm watching like a hawk next to me. 
When I ran the unmanage command with the hardcoded deviceID (7744), it worked and all the profiles disappeared and jamf couldn't do anything. 

I re-enrolled it fine, ran the command again with the variable $deviceID and it doesn't work

Running -v with curl (should've done that before)

Its the variable. Its not passing into curl

 

* Host [REDACTED].jamfcloud.com:443 was resolved.
* IPv6: (none)
* IPv4: [REDACTED]
*   Trying [REDACTED]:443...
* Connected to [REDACTED].jamfcloud.com ([REDACTED]) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES128-GCM-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=*.jamfcloud.com
*  start date: Jan  3 00:00:00 2024 GMT
*  expire date: Feb  1 23:59:59 2025 GMT
*  subjectAltName: host "[REDACTED].jamfcloud.com" matched cert's "*.jamfcloud.com"
*  issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M02
*  SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://[REDACTED].jamfcloud.com/JSSResource/computercommands/command/UnmanageDevice/id/
* [HTTP/2] [1] [:method: POST]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: [REDACTED].jamfcloud.com]
* [HTTP/2] [1] [:path: /JSSResource/computercommands/command/UnmanageDevice/id/]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
* [HTTP/2] [1] [authorization: Bearer [REDACTED]
> POST /JSSResource/computercommands/command/UnmanageDevice/id/ HTTP/2
> Host: [REDACTED].jamfcloud.com
> User-Agent: curl/8.7.1
> Accept: */*
> Authorization: Bearer [REDACTED]
> 
* Request completely sent off
< HTTP/2 404 
< date: Thu, 31 Oct 2024 20:58:36 GMT
< content-type: text/html;charset=UTF-8
< content-length: 439
< x-frame-options: DENY
< x-content-type-options: nosniff
< cache-control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
< content-security-policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob: *.jamf.net *.jamf.build *.jamfcloud.com *.jamf.com *.jamfnebula.com *.jamfsoftware.com *.jamf.io *.inf.jamf.one *.jamfnimbus.cloud *.amazonaws.com *.mzstatic.com *.googleapis.com *.gstatic.com *.googletagmanager.com *.zoominsoftware.io *.nr-data.net *.newrelic.com *.youtube.com *.pendo.io; frame-ancestors 'self' *.jamf.net *.jamf.build *.jamfcloud.com app.pendo.io
< permissions-policy: geolocation=(), fullscreen=(self)
< referrer-policy: strict-origin-when-cross-origin
< vary: Origin
< vary: Access-Control-Request-Method
< vary: Access-Control-Request-Headers
< accept-ranges: bytes
< server: Jamf
< x-xss-protection: 0
< strict-transport-security: max-age=63072000; includeSubDomains;
< set-cookie: jpro-ingress=1323a41cff8ce6db; path=/; HttpOnly; Secure; SameSite=None
< 
<html>
<head>
   <title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Not Found</p>
<p>The server has not found anything matching the request URI</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>
* Connection #0 to host [REDACTED].jamfcloud.com left intact

 

 

Well I got it working showhow. Guess it was just tweaking with the variable until it starts to work. 

# Get Mac serial number
serialNumber=`system_profiler SPHardwareDataType | awk '/Serial/ {print $4}'`
echo "Mac serial: $serialNumber"

# Curl to get Mac Jamf ID. Adding text()' will just return the Jamf ID without bracked info.
# determine Jamf Pro device id
deviceID=$(curl -s -H "Accept: text/xml" -H "Authorization: Bearer ${bearer_token}" ${JamfProURL}/JSSResource/computers/serialnumber/"$serialNumber" | xmllint --xpath '/computer/general/id/text()' -)
echo "Jamf ID: $deviceID"

# Remove Jamf Framework
echo "Removing Jamf Framework..."
/usr/local/bin/jamf removeFramework

# Curl to send command to remove MDM profile from the Mac
echo "Removing Jamf MDM via CURL $JamfProURL/JSSResource/computercommands/command/UnmanageDevice/id/$deviceID"
curl -v -X POST --header "Authorization: Bearer $bearer_token" "$JamfProURL/JSSResource/computercommands/command/UnmanageDevice/id/$deviceID"

exit 0

So there's the code I'm using in case someone else has a similar issue or If I run into this again.  

karthikeyan_mac
Valued Contributor

 Hi @cyberotter ,

You can try with the script below. You need to have basic auth allowed for API for this script to work else you can modify for bearer token.

https://github.com/kc9wwh/removeJamfProMDM/blob/master/removeMDM.sh

 

Thanks.

 

Unfortunately, our organization has turned off Basic API usage, so that broke a lot of our old scripts. I started using Bearer tokens and got most things to work with just a couple extra steps. 

 

# As of JamfPro V 11.5.0, Basic Token is disabled for security. We have to use the API Token above to create a bearer token. 
# Retrieve Bearer Token using APIToken. This is a shortlived token. 
bearer_token_response=$(curl -s --request POST \
  --url "$JamfProURL/api/v1/auth/token" \
  --header "Authorization: Basic $APIToken" \
  --header "Accept: application/json")
#echo "Bearer Token Response: $bearer_token_response"

# Extract the Bearer token from the response
bearer_token=$(echo $bearer_token_response | awk -F'"token" : "' '{print $2}' | awk -F'"' '{print $1}')
#echo "Bearer Token: $bearer_token"