Computer Naming through DEP Enrollment

chris_denoia
New Contributor II

Hi everyone,

Does anyone have a solution to the following:

Automatically applying computer names to macOS devices that enroll via DEP?

Thanks!

10 REPLIES 10

m_donovan
Contributor III

Here is a blog post I saw on slack that may be beneficial. I have not tried it myself but it looks pretty straight forward.

Eigger
Contributor III

Here is what we are using on our DEP build and This is the workflow we are following. We add the naming and bind last before reboot.

Look
Valued Contributor III

We have an external Asset Database, I had the support team for that create an API that machines could use to pull some of their own details using curl, this includes the desired device name, this is run from an enrollment triggered script that also renames the machine locally.
I then delayed the AD domain binding until after the first restart to ensure it happened after the device had been renamed.

alv2015591
New Contributor III

https://www.jamf.com/jamf-nation/feature-requests/6193/dep-computer-naming

Check out the bottom of this nation article my workflow might help you too.

kerouak
Valued Contributor

I use this little script to run before Binding.
It presents a dialog box for Computer Name manual Entry

>> #!/bin/bash

functions

function machinename () { osascript <<EOT tell application "Finder" activate set nameentry to text returned of (display dialog "Please Input New Computer Name" default answer "" with icon 2) end tell
EOT
}

function renameComputer(){ #Set New Computer Name echo "The New Computer name is: $ComputerName" scutil --set HostName $ComputerName scutil --set LocalHostName $ComputerName scutil --set ComputerName $ComputerName

echo Rename Successful
}

Script

ComputerName=$(machinename) renameComputer
exit 0

signetmac
Contributor

We've done it with an event handler that calls a script. First the .jar file:

package com.yourorg.renameonenroll;

import java.io.File;
import java.io.IOException;

import com.jamfsoftware.eventnotifications.JAMFEventNotificationMonitor;
import com.jamfsoftware.eventnotifications.JAMFEventNotificationMonitorResponse;
import com.jamfsoftware.eventnotifications.JAMFEventNotificationParameter;
import com.jamfsoftware.eventnotifications.events.EventType.EventTypeIdentifier;
import com.jamfsoftware.eventnotifications.shellobjects.ComputerEventShell;

public class RenameOnEnroll implements JAMFEventNotificationMonitor {

    @Override
    public JAMFEventNotificationMonitorResponse eventOccurred(JAMFEventNotificationParameter param) {
            ComputerEventShell newEnrollObject = (ComputerEventShell)param.getEventObject();
            String deviceUDID = newEnrollObject.getUdid();      

            ProcessBuilder pb = new ProcessBuilder("sh", "/usr/local/jss/scripts/postDEPnaming.sh", deviceUDID);
            pb.directory(new File("/usr/local/jss/scripts"));

            try {
                @SuppressWarnings("unused")
                Process p = pb.start();
            } catch (IOException e) {
                e.printStackTrace();
            }

        return null;
    }

    @Override
    public boolean isRegisteredForEvent(EventTypeIdentifier e) {
        switch (e) {
        case ComputerAdded:
          return true;
        default:
          return false;
        }
    }   
}

Last time I tried to program in Java was ~20 years ago, so if the code is inelegant and you have tips to make it better, I'd love to hear from you. But it works so I'm not complaining.

Then the script that it calls is located on the server under the path /usr/local/jss/scripts/postDEPnaming.sh:

#!/bin/bash 
# Written Nov, 2016 by: 
# Mac Scott: signetmac on jamfnation. Look for me on LinkedIn

########################
## Globals - Set as appropriate to your environment
########################
JSS_URL=https://localhost:8443
AUTH="Basic XXXXXXXXXXXXXXXXXXXXXXXXX"
SITE=XXXXXXX
EXT_ATTRIB_ID=XX
EXT_ATTRIB_NAME='XXXX XXXXXX'
EXT_ATTRIB_VALUE=Renamed
UDID=$1

########################
## Functions
########################
limit_to_proper_site() {

  if [[ $(xmllint --xpath '//computer/general/site/name/text()' - <<< "$jssData") != "$SITE" ]]; then
    exit
  fi
}

get_jss_data() {

  jssData=$(curl -s -k -X "GET" $JSS_URL/JSSResource/computers/udid/$UDID 
    -H "Authorization: $AUTH" 
    -H "Accept: application/xml" ) 
}

create_name() {
  city=$(xmllint --xpath '//computer/location/room/text()' - <<< "$jssData")
  full_name=$(xmllint --xpath '//computer/location/real_name/text()' - <<< "$jssData")
  type=$(xmllint --xpath '//computer/hardware/model_identifier/text()' - <<< "$jssData")

  if [[ "$city" == Vancouver ]] || [[ "$city" == Quebec ]] ||
     [[ "$city" == Toronto ]] || [[ "$city" == Montreal ]]; then
    co=CA
  else
    co=US
  fi 

  if [[ $(wc -w <<< "$city") -eq 1 ]] && [[ $(wc -c <<< "$city") -le 3 ]]; then
    ci=$city
  elif [[ $(wc -w <<< "$city") -eq 1 ]] && [[ $(wc -c <<< "$city") -gt 3 ]]; then
    ci=${city:0:3}
  elif [[ $(wc -w <<< "$city") -gt 1 ]]; then
    city1=$(awk '{print $1}' <<< "$city")
    city2=$(awk '{print $2}' <<< "$city")
    ci="${city1:0:1}${city2:0:2}"
  else
    ci=""
  fi

  firstn=$(awk '{print $1}' <<< "$full_name")
  lastn=$(awk '{print $2}' <<< "$full_name")
  fn="${firstn:0:1}${lastn:0:2}"

  if grep MacBook <<< "$type" 1> /dev/null; then
    ty=ML
  else
    ty=MD
  fi

  comp_name=$co$ci$fn-$ty
  new_name=$(echo $comp_name | awk '{print toupper($0)}')
}

put_jss_data() {

  curl -k -s -X "PUT" "$JSS_URL/JSSResource/computers/udid/$UDID/subset/general" 
    -H "Content-Type: application/xml" 
    -H "Authorization: $AUTH" 
    -H "Accept: application/xml" 
    -d "<computer><general><name>$new_name</name></general></computer>"

  curl -k -s -X "PUT" "$JSS_URL/JSSResource/computers/udid/$UDID/subset/extension_attributes" 
    -H "Content-Type: application/xml" 
    -H "Authorization: AUTH" 
    -H "Accept: application/xml" 
    -d "<computer><extension_attributes><extension_attribute><id>$EXT_ATTRIB_ID</id><name>$EXT_ATTRIB_NAME</name><type>String</type><value>$EXT_ATTRIB_VALUE</value></extension_attribute></extension_attributes></computer>"
}

########################
## Logic starts here
########################
sleep 600            # If we set name too early it will be overwritten by initial recon on enroll.
get_jss_data         # Poll JSS for computer's data
limit_to_proper_site # Target script only to sites that use it
create_name          # Parse JSS data for name
put_jss_data         # PUT both new name in computer's record on JSS and mark the "Renamed" ext attrib.

# There is a followup policy that runs on the computer's next JSS check-in and pushes the
# new name from the computer record on JSS down to the computer. 

stamp=$(date)
echo "$stamp: $new_name renamed for user $full_name" >> /tmp/renaming.log

We name our computers with the following convention: [country][city][first initial and first two of last name]-[ML or MD for laptop or desktop] ie USSFMSC-ML for my MacBook in San Francisco. Since JSS LDAP doesn't map City from AD and we don't utilize the "Room" value in AD, we remapped the LDAP value for "Room" on the JSS to 'l', which returns the City from AD values.

The above script renames the computer on JSS and then a subsequent policy pushes that name to the computer on next check-in. It requires creating an extension attribute with a blank string field or pop-up menu with "Renamed" as its only value. Set the ID and name for that EA in the Globals. The script writes "Renamed" to this EA after the successful completion. A smart group tracks computers with this value in that EA and uses that membership to scope a policy to push the rename to the computer.

calvins
New Contributor III

We do DEP enrollment per-department, with a corresponding smart group for that department's PreStage.

So department's PreStage > Smart Group for computers enrolled with that PreStage > Check-in policy that runs the below script with department's prefix as a parameter in the policy. If we didn't have to account for Sophos Safeguard not liking names longer than 15 characters, this would be way simpler.

#!/bin/bash

#Script goal is to name a Mac as "Department-SerialNumber" since that is our standard naming convention.
#v1.0 by Calvin S. 04/28/2017.

#####################################################################################
#Variables. Don't touch. Pass parameters in via the JAMF policy instead.
#####################################################################################
deptPrefix="$4-"                                                                                              #Pass in a department prefix in parameter 4. We add the dash for "dept-serial" right here.
deptPrefixLength=${#deptPrefix}                                                                                 #Count the number of digits in the department prefix parameter.
serialNumber="$(ioreg -c IOPlatformExpertDevice -d 2 | awk -F" '/IOPlatformSerialNumber/{print $(NF-1)}')"        #Just get the serial number.
serialNumberLength=${#serialNumber}                                                                             #Count the number of characters in the Serial Number. This is a variable because they could be 12 or 13 characters OR "Not Available" on a Mac with a bricked mobo.
newName="$deptPrefix$serialNumber"                                                                                #Mash the dept prefix and serial number together. Note the - character is added in the initial deptPrefix declaration.
newNameLength=$(( $deptPrefixLength + $serialNumberLength ))                                                    #Count the number of characters in the department prefix + the serial number. If this is over 15, we have problems with Safeguard and occasionally AD depending on your bind method.
NetBIOSName="$(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName)"      #JAMF's binary won't update the NetBIOS Name by default. Reading it here for logging later.
echo ""                                                                                                           #To make the JAMF policy logs prettier by starting the logging with a blank line.

#Variable validation.
    if [ -z "$4" ]; then
        echo "Department prefix not specified, so we are stopping."
        exit 1
    fi

    if [ "$(echo $deptPrefix | grep -e "--")" ]; then
        echo "There was a dash in the department name parameter, remove it and try again"
        exit 1
    fi

    if [ -z "$serialNumber" ]; then
        echo "Serial Number was null for some reason. Stopping..."
        exit 1
    fi

    #If the newName length is over 15 characters, we need to trim it. Safeguard doesn't like names longer than this.
    if [ $newNameLength -gt 15 ]; then                                                                          #15 is the max name length we want. 
        trimBy=$(( $newNameLength - 15 ))                                                                       #Take the total starting name length, subtract 15 to find the number we need to trim by.
            echo "The name is going to be more than 15 characters as-is, trimming the serial by "$trimBy" leading character(s)"
        trimmedSerialNumber=`echo "${serialNumber:$trimBy}"`                                                  #Trim the leading part of the serial number by # $trimBy characters.
        newName="$deptPrefix$trimmedSerialNumber"                                                             #Redeclare newName with the trimmed serial number.
    fi

#Logging
    echo "The department prefix we are going to use is "$deptPrefix""
    echo "The serial number is "$serialNumber""
    echo "The computer name will be changed to "$newName""
    echo "The current NetBIOSName is "$NetBIOSName""

#Actually set the computer names.
jamf setComputerName -name "$newName"                                                                         #The JAMF binary will handle the LocalHostName, HostName, and ComputerName names.                                                       

#Set the NetBIOS Name.
defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName -string "$newName"       #Write the new NetBIOS Name.
NetBIOSName="$(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName)"      #Re-do this variable so we can read what it became.
echo "The new NetBIOSName is "$NetBIOSName""

#Inventory in the script to avoid situations where it runs as the same time as other policies as gets the name overwritten.
jamf recon

jconte
Contributor II

This is what I am using, the L and W are what we use to differentiate between laptops and workstations.

############## Set Computer Name ##############
# Get device serial number
SERIAL=$(system_profiler SPHardwareDataType | grep 'Serial Number (system)' | awk '{print $NF}')

# Get device model name
MODEL=$(sysctl hw.model)

# Set prefix based upon model
if [[ $MODEL == *"Book"* ]]
then
    PREFIX="L-A"
else
    PREFIX="W-A"
fi

# Build Computer Name
COMPUTERNAME="$PREFIX$SERIAL"

# Set computername
/usr/bin/sudo /usr/sbin/scutil --set ComputerName $COMPUTERNAME

# Set hostname
/usr/bin/sudo /usr/sbin/scutil --set HostName $COMPUTERNAME

# Set Bonjour Name
/usr/bin/sudo /usr/sbin/scutil --set LocalHostName $COMPUTERNAME

GregE
Contributor

We modified a pretty neat one that has likely been listed above. It pops up and asks the client to enter their Asset Tag number then renames the Mac locally and in the JSS. A policy runs this after pre-stage enrollment (we're aiming for zero touch).

I had to put a 30 second delay on it. If it runs while the client is in the "Security & Privacy" acceptance screen, the Asset Tag popup hangs and you can't enter any information in to it (pressing 'submit' works but you can't edit the field). This works on the presumption that the client won't start setting it up, then leave it on the Security & Privacy screen for longer than half a minute.

Simple and effective!

fbfad092a483417a88ef45b602de3d80

#!/bin/sh sleep 35 computerName=$(osascript -e 'tell application "SystemUIServer" set myComputerName to text returned of (display dialog "Please insert your Asset Tag (CQUTxxxxx) and click Submit." default answer "" with title "Asset ID" buttons {"Submit"} with icon caution) end tell') /usr/sbin/scutil --set ComputerName "${computerName}" /usr/sbin/scutil --set LocalHostName "${computerName}" /usr/sbin/scutil --set HostName "${computerName}" dscacheutil -flushcache echo "Computer name has been set..." echo "<result>scutil --get ComputerName</result>" exit 0

mhegge
Contributor III

@GregE Testing out your script on High Sierra. Is it set on Enrollment Complete or at Login? I was getting an error ) checked the policy logs)having it run at Enrollment complete, leaving Privacy Window open. No dialog popped up.