diff --git a/docs/solutions/macos/scripts/remove-jamf.sh b/docs/solutions/macos/scripts/remove-jamf.sh new file mode 100644 index 0000000000..7f6a21ecc0 --- /dev/null +++ b/docs/solutions/macos/scripts/remove-jamf.sh @@ -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 diff --git a/docs/solutions/tines/README.md b/docs/solutions/tines/README.md index fca037fefc..ce414d6cfe 100644 --- a/docs/solutions/tines/README.md +++ b/docs/solutions/tines/README.md @@ -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. diff --git a/docs/solutions/tines/mdm-migration-jamf-pro.json b/docs/solutions/tines/mdm-migration-jamf-pro.json index a557727f2b..529c2ea667 100644 --- a/docs/solutions/tines/mdm-migration-jamf-pro.json +++ b/docs/solutions/tines/mdm-migration-jamf-pro.json @@ -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://<>/JSSResource/computers/serialnumber/<>", + "url": "https://<>/api/v3/computers-inventory?filter=hardware.serialNumber==<>", "method": "get", "headers": { - "accept": "application/xml", - "Authorization": "Bearer <>" + "accept": "application/json", + "Authorization": "Bearer <>" } }, "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://<>/JSSResource/computercommands/command/UnmanageDevice/id/<>", + "url": "https://<>/api/v1/computer-inventory/<>/remove-mdm-profile", "method": "post", "content_type": "form", "headers": { - "accept": "application/xml", - "Authorization": "Bearer <>" + "accept": "application/json", + "Authorization": "Bearer <>" } }, "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://<>/JSSResource/computers/id/19", - "method": "put", - "content_type": "xml", + "url": "https://<>/api/v3/computers-inventory-detail/<>", + "method": "patch", + "content_type": "application_json", "payload": { - "computer": { - "general": { - "remote_management": { - "managed": "false" - } - } + "general": { + "managed": "false" } }, "headers": { - "Accept": "application/xml", - "Authorization": "Bearer <>" + "Accept": "application/json", + "Authorization": "Bearer <>" } }, "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://<>/api/v1/auth/token", - "method": "post", - "content_type": "form", - "basic_auth": [ - "<>", - "<>" - ] - }, - "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://.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://.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://.jamfcloud.com/JSSResource/computers/id/$JAMF_ID\" -H \"Content-Type: application/xml\" -H \"Accept: application/xml\" -H \"Authorization: Bearer $BEARER_TOKEN\" -d 'false'\n", - "position": [ - 570, - -255 - ], - "guid": "ce06da35f2a6e0e18414c39a24354df1", - "width": 270 - }, - { - "content": "Get BEARER_TOKEN\n\nRESPONSE=$(curl -s -u \"$USERNAME\":\"$PASSWORD\" \"https://.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:" }