Generate report of macs not enrolled in Casper

Allenhiko
New Contributor

Hi All,

For general auditing purposes, is there an easy way to generate a report in Casper that can cross check Active directory computer names to the computer names in currently enrolled in Casper?

I am hoping that a report will show me computer names that exists in Active Directory but not in Casper so I can re-enrolled them.

Any advice would be greatly appreciated.

Allen

5 REPLIES 5

mm2270
Legendary Contributor III

How do you differentiate between Macs in AD versus Windows machines? Are you putting them into a specific container in AD? Because if not, you'd have to do the AD search based on computer name format, which may or may not be tricky.
Basically, it's not impossible to do a cross reference of computer names using the API for Jamf, but you'll need some way of only extracting Macs out of AD, and that part I'm not so sure about. It will all depend on how you've been joining them to AD.

Last thing is, unless you are cleaning up AD records every time a Mac gets retired or reimaged and thus potentially renamed, you might end up with more computer names than you actually have in the wild.

ryan_ball
Valued Contributor

@Allenhiko

Ive done this before. Install xmlstarlet with homebrew on the system you run this on:

#!/bin/bash

domain=""                                     # Example: contoso.com
shortDomain=""                                       # Example: CONTOSO
searchBase=""         # Example OU=Computers,DC=contoso,DC=com
jssURL=""               # Example: https://jamfpro.contoso.com:8443
outputFile="$HOME/Documents/Macs_In_AD_Cross_Ref_JSS_$(date +%m-%d-%Y)"

function decode_sid () {
    # Base-64 encoded objectSid
    OBJECT_ID="$1"

    # Decode it, hex-dump it and store it in an array
    G=($(echo -n "$OBJECT_ID" | base64 -D | hexdump -v -e '1/1 " %02X"'))

    BESA2=${G[8]}${G[9]}${G[10]}${G[11]}
    BESA3=${G[12]}${G[13]}${G[14]}${G[15]}
    BESA4=${G[16]}${G[17]}${G[18]}${G[19]}
    BESA5=${G[20]}${G[21]}${G[22]}${G[23]}
    BERID=${G[24]}${G[25]}${G[26]}${G[27]}${G[28]}
    LESA1=${G[2]}${G[3]}${G[4]}${G[5]}${G[6]}${G[7]}
    LESA2=${BESA2:6:2}${BESA2:4:2}${BESA2:2:2}${BESA2:0:2}
    LESA3=${BESA3:6:2}${BESA3:4:2}${BESA3:2:2}${BESA3:0:2}
    LESA4=${BESA4:6:2}${BESA4:4:2}${BESA4:2:2}${BESA4:0:2}
    LESA5=${BESA5:6:2}${BESA5:4:2}${BESA5:2:2}${BESA5:0:2}
    LERID=${BERID:6:2}${BERID:4:2}${BERID:2:2}${BERID:0:2}
    LE_SID_HEX=${LESA1}-${LESA2}-${LESA3}-${LESA4}-${LESA5}-${LERID}

    # Initial SID value which is used to construct actual SID
    SID="S-1"

    # Convert LE_SID_HEX to decimal values and append it to SID as a string
    IFS='-' read -ra ADDR <<< "${LE_SID_HEX}"
    for OBJECT in "${ADDR[@]}"; do
        SID=${SID}-$((16#${OBJECT}))
    done

#echo ${SID}
}

# Make sure xmlstarlet is installed
if ! which xmlstarlet ; then
    echo "You must install xmlstarlet before using this script."
    echo "Try "brew install xmlstarlet""
    exit 1
fi

# Create output file and headings
echo "Mac Name,AD OS Field,AD ObjectSID,AD LastLogonDate,AD Account Status,JSS ID" > "$outputFile"

clear
echo -n "Enter JSS Username: "
read -r jssUser
clear

echo -n "Enter $jssUser's Pass: "
read -r -s jssPass
clear

echo -n "Enter AD Username: "
read -r ldapUser
ldapUser="$shortDomain\$ldapUser"
clear

echo -n "Enter $ldapUser's Pass: "
read -r -s ldapPass
clear

# Get full list of computers from AD where the operating system is like "Mac"
echo "Retreiving list of computers from Active Directory..."
computers=($(ldapsearch -LLL -h "$domain" -x -D "$ldapUser" -w "$ldapPass" -b "$searchBase"  "(&(OperatingSystem=*Mac*)(ObjectCategory=Computer))" sAMAccountName | grep "sAMAccountName" | awk '{print $2}' | sed 's/$//'))

echo "About to process ${#computers[@]} computers..."
sleep 5

# Obtain details of each machine using the JSS API and ldapsearch
for computer in "${computers[@]}"; do
    echo "Searching for $computer in the JSS..."
    jssRecord=$(/usr/bin/curl -H "accept: application/xml" -s -u "$jssUser:$jssPass" "$jssURL/JSSResource/computers/name/$computer" | xmlstarlet sel -t -v '//computer/general/name' 2>/dev/null)
    if [[ -n "$jssRecord" ]]; then
        echo "Success; Found $computer in the JSS."
        matchedJSSID=$(/usr/bin/curl -H "accept: application/xml" -s -u "$jssUser:$jssPass" "$jssURL/JSSResource/computers/name/$computer/subset/general" | xmlstarlet sel -t -v '//computer/general/id')
    else
        echo "Bummer; $computer not found in the JSS"
        matchedJSSID="Not found in JSS"
    fi

    objectDetailSearch=$(ldapsearch -LLL -h "$domain" -x -D "$ldapUser" -w "$ldapPass" -b "$searchBase"  "(&(name=$computer)(ObjectCategory=Computer))" operatingSystem lastLogon objectSid userAccountControl)
    adOS=$(echo "$objectDetailSearch" | grep operatingSystem | awk -F": " '{print $2}')
    objectSid=$(echo "$objectDetailSearch" | grep objectSid | awk '{print $2}')
    lastLogon=$(echo "$objectDetailSearch" | grep lastLogon | awk '{print $2}')
    lastLogon=$(echo "$lastLogon" | perl -pne 's/(d{11})d{7}/"".scalar(localtime($1-11644473600)).""/e')
    userAccountControl=$(echo "$objectDetailSearch" | grep userAccountControl | awk '{print $2}')

    # Decode the SID and get it in a readable format
    decode_sid "$objectSid"

    if [[ "$userAccountControl" == "4096" ]]; then
        enabled="Enabled"
    elif [[ "$userAccountControl" == "2" ]]; then
        enabled="Disabled"
    fi

    # Write the lines to the file
    echo "$computer,$adOS,${SID},$lastLogon,$enabled,$matchedJSSID" >> "$outputFile"
done

# Rename the file to a csv
mv "$outputFile" "$outputFile.csv"

exit 0

dan-snelson
Valued Contributor II

@Allenhiko The following may both be off-topic and a "solution in search of a problem," but if you're using DEP, it may prove helpful:

DEP-assigned, Un-enrolled Devices

The following query will output all DEP-assigned, un-enrolled devices.

SELECT serial_number, description, server_name, FROM_UNIXTIME(substring(device_assigned_date_epoch,1,10)) AS 'Date_Assigned'
FROM device_enrollment_program_devices
INNER JOIN device_enrollment_program_instances ON device_enrollment_program_instances.device_enrollment_program_instance_id = device_enrollment_program_devices.device_enrollment_program_instance_id
WHERE device_enrollment_program_device_id and device_type = 0
IN (select device_enrollment_program_device_id from computer_dep_prestages) and serial_number NOT IN (select serial_number from computers_denormalized)
ORDER BY server_name, Date_Assigned, description
INTO OUTFILE '/allowed/path/to/output/files/DEP-assigned_NOT_enrolled-yyyy-mm-dd-hhmmss.csv'
FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '
';

chris_miller
Contributor

Perhaps you could create an extension attribute that stores the output of a script using something like:

#!/bin/sh

ADname=`dsconfigad -show | grep -i "Computer Account" | sed -n 's/[^.]*= // ; s/.$//p'`
/bin/echo "$ADname"

exit

Then add that extension attribute value to your Inventory Display under computer management. That way you can export an inventory search as a csv. Wouldn't be 100%, but definitely a simpler approach.

https://www.jamf.com/jamf-nation/discussions/5623/find-a-mac-s-active-directory-name

ryan_ball
Valued Contributor

I think what he is wanting to do is to find computer accounts in Active Directory that might not be enrolled into the Jamf Pro Server. My script above will do that.