Skip to main content
Question

Scripting DDM Sync


Mithrandir
Forum|alt.badge.img+7

Was having some trouble with our instance. Turns out it was multifaceted-part my org, and part a Jamf thing (apparently). Upgrade to 11.17 seems to have rectified things on the Jamf side.

To that end I was trying to figure out how to script DDM sync, and seem to have gotten it sorted:

#!/bin/bash

JSS_URL="https://[your_jss_urll_here]"
API_USER=""
API_PASS=""

log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >&2
}

fail_exit() {
log "โŒ ERROR: $1"
exit 1
}

get_token() {
log "๐Ÿ” Requesting Jamf Pro API token..."
auth_response=$(curl --silent --request POST \\
--url "$JSS_URL/api/v1/auth/token" \\
--user "$API_USER:$API_PASS")

token=$(echo "$auth_response" | jq -r '.token // empty')
if [[ -z "$token" ]]; then
echo "$auth_response" > /tmp/jamf_token_error.json
fail_exit "Unable to extract token. Response saved to /tmp/jamf_token_error.json"
fi
echo "$token"
}

get_all_ids() {
local token="$1"
local page=0
local page_size=100
local all_ids=()

while true; do
log "๐Ÿ“ฆ Fetching computer ID page $((page + 1))..."
response=$(curl --silent --request GET \\
--url "$JSS_URL/api/v1/computers-inventory?page=$page&page-size=$page_size" \\
--header "Authorization: Bearer $token" \\
--header "Accept: application/json")

clean=$(echo "$response" | tr -d '\\000-\\037')

if ! echo "$clean" | jq -e .results > /dev/null 2>&1; then
log "โŒ JSON parsing failed for page $((page + 1)). Saved to /tmp/ddm_bad_page_${page}.json"
echo "$response" > "/tmp/ddm_bad_page_${page}.json"
break
fi

ids=$(echo "$clean" | jq -r '.results[].id')
[[ -z "$ids" ]] && break

while IFS= read -r id; do
all_ids+=("$id")
done <<< "$ids"

((page++))
done

printf "%s\\n" "${all_ids[@]}"
}

get_management_id() {
local token="$1"
local id="$2"

response=$(curl --silent --request GET \\
--url "$JSS_URL/api/v1/computers-inventory-detail/$id" \\
--header "Authorization: Bearer $token" \\
--header "Accept: application/json")

mgmt_id=$(echo "$response" | plutil -extract general.managementId raw - 2>/dev/null)
name=$(echo "$response" | jq -r '.general.name // "Unnamed"')

if [[ -z "$mgmt_id" ]]; then
log "โš ๏ธ No Management ID for Jamf ID $id ($name). Skipping."
return 1
fi

echo "$id,$mgmt_id,$name"
}

trigger_ddm_then_fallback() {
local token="$1"
local id="$2"
local mgmt_id="$3"
local name="$4"

log "๐Ÿ” Syncing [$name] - ID $id | MGMT ID $mgmt_id"
log "๐Ÿ”— Jamf UI: $JSS_URL/computers.html?id=$id"

ddm_response=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" --request POST \\
--url "$JSS_URL/api/v1/ddm/$mgmt_id/sync" \\
--header "Authorization: Bearer $token" \\
--header "Content-Type: application/json")

ddm_code=$(echo "$ddm_response" | tr -d '\\n' | sed -e 's/.*HTTPSTATUS://')

if [[ "$ddm_code" == "204" ]]; then
log "โœ… DDM Sync successful for [$name]"
elif [[ "$ddm_code" == "404" ]]; then
log "โš ๏ธ [$name] not DDM-enabled. Trying Classic..."

classic_response=$(curl --silent --write-out "HTTPSTATUS:%{http_code}" --request POST \\
--url "$JSS_URL/JSSResource/computercommands/command/InventoryUpdate/id/$id" \\
--header "Authorization: Bearer $token")

classic_code=$(echo "$classic_response" | tr -d '\\n' | sed -e 's/.*HTTPSTATUS://')

if [[ "$classic_code" == "201" || "$classic_code" == "200" ]]; then
log "โœ… Classic InventoryUpdate triggered for [$name]"
else
log "โŒ Classic update failed for [$name]. Status: $classic_code"
fi
else
log "โŒ Unexpected DDM response for [$name]. Status: $ddm_code"
fi
}

main() {
token=$(get_token) || fail_exit "Authentication failed."
ids=$(get_all_ids "$token")
count=$(echo "$ids" | wc -l | xargs)
log "๐Ÿ”Ž Found $count total managed Macs."

if [[ $count -eq 0 ]]; then
fail_exit "No managed devices found."
fi

echo "$ids" | while read -r id; do
[[ -z "$id" ]] && continue
entry=$(get_management_id "$token" "$id") || continue
IFS=',' read -r id mgmt_id name <<< "$entry"
trigger_ddm_then_fallback "$token" "$id" "$mgmt_id" "$name"
sleep 0.3
done

log "๐ŸŽ‰ All sync attempts complete."
}

main

-------------
Passing on in the hopes that someone else may be helped by this. And yes I know the password needs to be obfuscated.



5 replies

Forum|alt.badge.img+4

Hey, thanks I was getting HTTP 500 no matter what format of the curl command I tried, but yours above got me to HTTP 401. Can you tell me what API Permissions you have set? I already have the Send Declarative Management Command permission assigned. Not sure what else would be missing. Thanks


Mithrandir
Forum|alt.badge.img+7
  • Author
  • Contributor
  • 34 replies
  • June 4, 2025
wewenttothemoon wrote:

Hey, thanks I was getting HTTP 500 no matter what format of the curl command I tried, but yours above got me to HTTP 401. Can you tell me what API Permissions you have set? I already have the Send Declarative Management Command permission assigned. Not sure what else would be missing. Thanks


Hi, wewenttothemoo,

I'm using my admin account to request the bearer token as trying the "script" api account I created just wasn't working--and this despite granting it umpty-dump perms.

Forum|alt.badge.img+4
Mithrandir wrote:
Hi, wewenttothemoo,

I'm using my admin account to request the bearer token as trying the "script" api account I created just wasn't working--and this despite granting it umpty-dump perms.

Gotcha, well seems like deflounder just updated his site with this: Forcing a DDM sync on a Jamf Pro-managed device via the Jamf Pro API | Der Flounder

I'm trying now with the View MDM command information in Jamf Pro API


Forum|alt.badge.img+4
Mithrandir wrote:
Hi, wewenttothemoo,

I'm using my admin account to request the bearer token as trying the "script" api account I created just wasn't working--and this despite granting it umpty-dump perms.

I got it working you need these API permissions at the minimum:

API client permissions:

  • View MDM command information in Jamf Pro API
  • Send Declarative Management Command

User account permissions:

Jamf Pro Server Actions:

  • View MDM command information in Jamf Pro API
  • Send Declarative Management Command

Mithrandir
Forum|alt.badge.img+7
  • Author
  • Contributor
  • 34 replies
  • June 4, 2025
wewenttothemoon wrote:

I got it working you need these API permissions at the minimum:

API client permissions:

  • View MDM command information in Jamf Pro API
  • Send Declarative Management Command

User account permissions:

Jamf Pro Server Actions:

  • View MDM command information in Jamf Pro API
  • Send Declarative Management Command

Sweet, and thanks for the update! I need the proverbial โ€œquick and dirtyโ€ due to some issues with my cloud tenant which seemed to have introduced with the advent of Pro 11.16, and which havenโ€™t been fully addressed by either 11.17, or 11.17.1.

Iโ€™ll likely be making that change myself.

Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings