Update Jamf API endpoints (#39146)

Discussed at
https://macadmins.slack.com/archives/C0214NELAE7/p1769719765777279
- The endpoints for marking a device as unmanaged and sending an
unmanage command were deprecated and no longer work. The endpoint for
looking up a device by serial number was also deprecated, so I've
proactively updated it.
- The whole story is now refactored and simplified.
- Also fixed a link in the `tines` README.
This commit is contained in:
Steven Palmesano
2026-02-06 13:58:40 -06:00
committed by GitHub
parent f3133fd0f5
commit 6a3578ce46
3 changed files with 72 additions and 126 deletions
@@ -0,0 +1,37 @@
#!/bin/bash
# This script runs one last recon and then removes the Jamf framework.
# Must be run as root. Deploy with Fleet, NOT Jamf Pro.
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root." >&2
exit 1
fi
jamf_binary=$(command -v jamf)
if [ -z "$jamf_binary" ]; then
for path in "/usr/local/bin/jamf" "/usr/local/jamf/bin/jamf" "/usr/sbin/jamf"; do
if [ -x "$path" ]; then
jamf_binary="$path"
break
fi
done
fi
if [ -z "$jamf_binary" ]; then
echo "Jamf binary not found. Exiting." >&2
exit 1
fi
echo "Jamf binary found at: $jamf_binary"
echo "Running final inventory update..."
$jamf_binary recon || echo "Warning: recon command failed (continuing anyway)"
echo "Removing Jamf framework..."
if $jamf_binary removeFramework; then
echo "Jamf removal successful!"
else
echo "Error: removeFramework command failed." >&2
exit 1
fi
+1 -1
View File
@@ -36,6 +36,6 @@ Originally created for `customer-reedtimmer`.
Used when migrating from Jamf Pro to Fleet. This receives the migration web hook from Fleet, looks up that serial number in Jamf Pro via Jamf's API, then sends an unenroll command from Jamf.
## [Import IdP users] (import-idp-users.json)
## [Import IdP users](import-idp-users.json)
An example workflow for mapping Fleet hosts to the associated user in asset management. This workflow iterates over hosts in Fleet, uses the Oomnitza API to retrieve the assigned user, and updates Fleet's device mapping with the correct user.
+34 -125
View File
@@ -1,10 +1,10 @@
{
"schema_version": 27,
"standard_lib_version": 85,
"action_runtime_version": 63,
"standard_lib_version": 86,
"action_runtime_version": 66,
"name": "MDM Migration (Jamf Pro)",
"description": "",
"guid": "2448e973a07b9f4421f839439918d608",
"guid": "a3f3b56b19119971a105c0220502f640",
"slug": "mdm_migration_jamf_pro",
"agents": [
{
@@ -12,14 +12,14 @@
"name": "Lookup device ID in Jamf Pro by Serial Number",
"disabled": false,
"description": "",
"guid": "d892c18b1cd658d2b44dd6e50aedc3cd",
"guid": "656d4a952012df4a938ea7b4a741eb8e",
"origin_story_identifier": "cloud:4be52380e9d25dfd9c0431229580c706:2a298336c7bd82875939c82f2005137f",
"options": {
"url": "https://<<RESOURCE.jamf_pro_server_url>>/JSSResource/computers/serialnumber/<<webhook_action.body.host.hardware_serial>>",
"url": "https://<<RESOURCE.jamf_pro_server_url>>/api/v3/computers-inventory?filter=hardware.serialNumber==<<migrate_to_fleet_webhook.body.host.hardware_serial>>",
"method": "get",
"headers": {
"accept": "application/xml",
"Authorization": "Bearer <<CREDENTIAL.jamf_pro_bearer_token>>"
"accept": "application/json",
"Authorization": "Bearer <<CREDENTIAL.jamf_pro>>"
}
},
"reporting": {
@@ -41,14 +41,14 @@
},
{
"type": "Agents::WebhookAgent",
"name": "Webhook Action",
"name": "Migrate to Fleet Webhook",
"disabled": false,
"description": null,
"guid": "5947334e8496a0dd0668b5d6142ec35b",
"guid": "64d007a331aa81eb9eae027691219933",
"origin_story_identifier": "cloud:4be52380e9d25dfd9c0431229580c706:2a298336c7bd82875939c82f2005137f",
"options": {
"path": "3beaf49cd9b1a06bcf32a3b3ba47841c",
"secret": "9b0e8a27d869df162274f95128267d19",
"path": "56e1286b9a654f1b4137dc07cff3874d",
"secret": "34510f3726157a3bd2b69ffe4ebe8af1",
"verbs": "get,post"
},
"reporting": {
@@ -72,15 +72,15 @@
"name": "Send unmanage command using ID",
"disabled": false,
"description": "",
"guid": "96fe6acaf63c0d3b548affa7fc122e47",
"guid": "7d85b634d0b5e52c0dbe1f0ad4cfce1e",
"origin_story_identifier": "cloud:4be52380e9d25dfd9c0431229580c706:2a298336c7bd82875939c82f2005137f",
"options": {
"url": "https://<<RESOURCE.jamf_pro_server_url>>/JSSResource/computercommands/command/UnmanageDevice/id/<<lookup_device_id_in_jamf_pro_by_serial_number.body.computer.general.id>>",
"url": "https://<<RESOURCE.jamf_pro_server_url>>/api/v1/computer-inventory/<<lookup_device_id_in_jamf_pro_by_serial_number.body.results[0].id>>/remove-mdm-profile",
"method": "post",
"content_type": "form",
"headers": {
"accept": "application/xml",
"Authorization": "Bearer <<CREDENTIAL.jamf_pro_bearer_token>>"
"accept": "application/json",
"Authorization": "Bearer <<CREDENTIAL.jamf_pro>>"
}
},
"reporting": {
@@ -105,24 +105,20 @@
"name": "Mark device as unmanaged in Jamf Pro",
"disabled": false,
"description": "",
"guid": "e3f317deaf1bd01ebbee629bfce6d156",
"guid": "e314f6726f0745ed647f95e55f575e2c",
"origin_story_identifier": "cloud:4be52380e9d25dfd9c0431229580c706:2a298336c7bd82875939c82f2005137f",
"options": {
"url": "https://<<RESOURCE.jamf_pro_server_url>>/JSSResource/computers/id/19",
"method": "put",
"content_type": "xml",
"url": "https://<<RESOURCE.jamf_pro_server_url>>/api/v3/computers-inventory-detail/<<lookup_device_id_in_jamf_pro_by_serial_number.body.results[0].id>>",
"method": "patch",
"content_type": "application_json",
"payload": {
"computer": {
"general": {
"remote_management": {
"managed": "false"
}
}
"general": {
"managed": "false"
}
},
"headers": {
"Accept": "application/xml",
"Authorization": "Bearer <<CREDENTIAL.jamf_pro_bearer_token>>"
"Accept": "application/json",
"Authorization": "Bearer <<CREDENTIAL.jamf_pro>>"
}
},
"reporting": {
@@ -141,113 +137,26 @@
},
"width": null,
"schedule": null
},
{
"type": "Agents::HTTPRequestAgent",
"name": "Get Bearer_Token",
"disabled": false,
"description": "",
"guid": "3b1e201200c199d3c218f5d06e600b77",
"origin_story_identifier": "cloud:4be52380e9d25dfd9c0431229580c706:2a298336c7bd82875939c82f2005137f",
"options": {
"url": "https://<<RESOURCE.jamf_pro_server_url>>/api/v1/auth/token",
"method": "post",
"content_type": "form",
"basic_auth": [
"<<RESOURCE.jamf_pro_basic_auth_username>>",
"<<RESOURCE.jamf_pro_basic_auth_password>>"
]
},
"reporting": {
"time_saved_value": 0,
"time_saved_unit": "minutes"
},
"monitoring": {
"monitor_all_events": false,
"monitor_failures": true,
"monitor_no_events_emitted": null
},
"template": {
"created_from_template_guid": null,
"created_from_template_version": null,
"template_tags": []
},
"width": null,
"schedule": null
}
],
"diagram_notes": [
{
"content": "Receive Webook",
"content": "## Command to test\n\n```bash\ncurl -X POST $YOUR_WEBHOOK_ACTION_URL -H \"Content-Type: application/json\" -d '{\n \"timestamp\": \"0000-00-00T00:00:00Z\",\n \"host\": {\n \"id\": $DEVICE_ID_IN_JAMF_PRO,\n \"uuid\": \"1234-5678-9101-1121\",\n \"hardware_serial\": \"$SERIAL_NUMBER\"\n }\n}'\n```",
"position": [
-495,
-255
],
"guid": "ee605b6b36c4e56bede006cfa27aaf0f",
"width": 180
},
{
"content": "Lookup JAMF ID by Serial Number provided by Fleet\n\nJAMF_ID=$(curl -X GET \"https://<server>.jamfcloud.com/JSSResource/computers/serialnumber/$SERIAL\" -H \"accept: application/xml\" -H \"Authorization: Bearer $BEARER_TOKEN\" ",
"position": [
-15,
-255
],
"guid": "37c34f2422a04d327f6a372e9db7a3b1",
"width": 270
},
{
"content": "Send UnmanageDevice using JAMF ID\n\ncurl -X POST \"https://<server>.jamfcloud.com/JSSResource/computercommands/command/UnmanageDevice/id/$JAMF_ID\" -H \"accept: application/xml\" -H \"Authorization: Bearer $BEARER_TOKEN\"\n",
"position": [
270,
-255
],
"guid": "db8523dfa563cc114677515f914715c1",
"width": 270
},
{
"content": "Mark device as Unmanaged in Jamf Pro \n\ncurl --request PUT --url \"https://<server>.jamfcloud.com/JSSResource/computers/id/$JAMF_ID\" -H \"Content-Type: application/xml\" -H \"Accept: application/xml\" -H \"Authorization: Bearer $BEARER_TOKEN\" -d '<computer><general><remote_management><managed>false</managed></remote_management></general></computer>'\n",
"position": [
570,
-255
],
"guid": "ce06da35f2a6e0e18414c39a24354df1",
"width": 270
},
{
"content": "Get BEARER_TOKEN\n\nRESPONSE=$(curl -s -u \"$USERNAME\":\"$PASSWORD\" \"https://<server>.jamfcloud.com/api/v1/auth/token\" -X POST)\n\nThis is now stored as a Credential. ",
"position": [
-300,
-255
],
"guid": "d13dbd2dbff32767582029e69cbbb776",
"width": 270
},
{
"content": "Command to test:\n\n% curl -X POST $YOUR_WEBHOOK_ACTION_URL -H \"Content-Type: application/json\" -d '{\n \"timestamp\": \"0000-00-00T00:00:00Z\",\n \"host\": {\n \"id\": $DEVICE_ID_IN_JAMF_PRO,\n \"uuid\": \"1234-5678-9101-1121\",\n \"hardware_serial\": \"$SERIAL_NUMBER\"\n }\n}'",
"position": [
-585,
240
-600,
195
],
"guid": "7a88223a0cf93204dd6f81375b28b8a2",
"width": 515
"width": 570
},
{
"content": "Configuration: \n1. Replace Jamf Pro server URL resource. ex: \"myserver.jamfcloud.com\"\n2. Update name and password in Jamf Pro Bearer Token Credentials with an account that has the following permissions:\nJamf Pro Server Objects > Computers Create, Read and Update\nJamf Pro Server Actions > Send Computer Unmanage Command\n\n** You can also update the values in the resources Jamf Pro Basic Auth Username and Jamf Pro Basic Auth Password. **",
"content": "# Configuration\n\n## Jamf\n\nSet up a Jamf Pro [API Role and Client](https://learn.jamf.com/en-US/bundle/jamf-pro-documentation-current/page/API_Roles_and_Clients.html) with these permissions:\n\n- Computers Create\n- Computers Read\n- Computers Update\n- Send Computer Unmanage Command\n\n## Tines\n\n- Replace Resource: Jamf Pro server URL (`myserver.jamfcloud.com`).\n- Set up Credential: Jamf Pro with the API Client from step 2.\n\n## Fleet\n\n**Read our [macOS MDM migration](https://fleetdm.com/guides/mdm-migration) guide!** At the least:\n\n- Set up MDM in **Settings** > **Integrations** > **MDM**.\n- Then, scroll down to **End user migration workflow**, enable the toggle, choose the **Mode**, and paste the **Webhook URL** from the Migrate to Fleet webhook action on the right. Don't forget to select **Save**!\n\n# Migration\n\n- Assign the device to your Fleet server in ABM.\n- Within 30 minutes, the Fleet Desktop menu bar icon on the device will have a **Migrate to Fleet** button. Select this, and then **Start**. Within a couple of minutes, the webhook will fire off.\n\n## Cleanup\n\nAfter the device is migrated, use Fleet to [deploy a script](https://github.com/fleetdm/fleet/tree/main/docs/solutions/macos/scripts/remove-jamf.sh) to remove the Jamf framework from the device.",
"position": [
-585,
-495
-600,
-375
],
"guid": "b160cbd5ee73744ce498306a7f2e8bec",
"width": 514
},
{
"content": "Final clean-up (deploy from Fleet):\n[https://github.com/allenhouchins/scripts/blob/main/remove_jamf.sh](https://github.com/allenhouchins/scripts/blob/main/remove_jamf.sh)",
"position": [
570,
345
],
"guid": "43439dee9945d2427917a3685073a0bf",
"width": 280
"width": 570
}
],
"links": [
@@ -264,7 +173,7 @@
"receiver": 3
}
],
"diagram_layout": "{\"3b1e201200c199d3c218f5d06e600b77\":[-255,-75],\"5947334e8496a0dd0668b5d6142ec35b\":[-495,-75],\"96fe6acaf63c0d3b548affa7fc122e47\":[285,90],\"d892c18b1cd658d2b44dd6e50aedc3cd\":[0,0],\"e3f317deaf1bd01ebbee629bfce6d156\":[585,180]}",
"diagram_layout": "{\"64d007a331aa81eb9eae027691219933\":[-15,-285],\"656d4a952012df4a938ea7b4a741eb8e\":[-15,-165],\"7d85b634d0b5e52c0dbe1f0ad4cfce1e\":[-15,-30],\"e314f6726f0745ed647f95e55f575e2c\":[-15,105]}",
"story_library_metadata": {},
"monitor_failures": true,
"synchronous_webhooks_enabled": false,
@@ -272,7 +181,7 @@
"parent_only_send_to_story": false,
"send_to_story_timeout_enabled": false,
"send_to_story_timeout_duration_seconds": null,
"keep_events_for": 604800,
"keep_events_for": 86400,
"reporting_status": true,
"send_to_story_enabled": false,
"entry_agent_guid": null,
@@ -294,6 +203,6 @@
"integration_vendor": null,
"llm_product_instructions": "",
"send_to_stories": [],
"exported_at": "2025-12-17T15:25:04Z",
"exported_at": "2026-02-04T21:20:38Z",
"icon": ":magic_wand:"
}