Script to give unique hostname based on username

steviethetv
New Contributor III

Hey everyone,
I spent a bit of time working on a script that allows you to create a unique hostname to every device based on the users' username in the JSS and making it as vendor agnostic as possible so anyone can plug-and-play. This script makes an API call with a JSS account that only has read permissions on Computers. The credentials used in the API call are also encrypted, so you don't have to worry about users knowing API credentials.

There's a couple of steps to implementing this, first you need to create a script, GenerateEncryptedString.sh, which is below.

#!/bin/bash

STRING="${1}"
SALT=$(openssl rand -hex 8)
K=$(openssl rand -hex 12)
ENCRYPTED=$(echo "${STRING}" | openssl enc -aes256 -a -A -S "${SALT}" -k "${K}")
echo "Encrypted String: ${ENCRYPTED}"
echo "Salt: ${SALT} | Passphrase: ${K}"

This script is meant to encrypt your credentials so that you can pass them as parameters from a policy. This means your clients can run a GET API call without having plain text credentials visible to users. Once you have this script created you simply enter in the command in a terminal to generated the parameters: /path/to/GenerateEncryptedString.sh PasswordOrHostnameToBeEncrypted
example: ./GenerateEncryptedString.sh banana

You will want to record those values for use later as parameter values in a policy as shown here
29feb8fc573d4e26a7e8fc0c09c8e155

The script that allows you to change the hostname per userid is below (mind my amateur coding skills)

#!/bin/bash

# Include DecryptCredentials() with your script to decrypt the parameters sent by the JSS
# The 'Salt' and 'Passphrase' values would be present in the script
function DecryptCredentials() {
    # Usage: ~$ DecryptString "Encrypted String" "Salt" "Passphrase"
    echo $1 | /usr/bin/openssl enc -aes256 -d -a -A -S $2 -k $3
}

################
################
################

# Set CURL command values
DEVICE_SERIALNUMBER=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')

API_USER=$(DecryptCredentials $4 $5 $6)
API_PASSWORD=$(DecryptCredentials $7 $8 $9)

MY_JSS_BASEURL=$( /usr/bin/defaults read /Library/Preferences/com.jamfsoftware.jamf jss_url )
MY_JSS_APIURL="${MY_JSS_BASEURL}JSSResource/"
CURL_OPTIONS="--silent --show-error --connect-timeout 30"

################
################
################

# Get username of device searching by Serial Number
/usr/bin/curl ${CURL_OPTIONS} --output tmp0.xml --request GET --user "${API_USER}":"${API_PASSWORD}" "${MY_JSS_APIURL}computers/serialnumber/${DEVICE_SERIALNUMBER}/subset/location&username"
DEVICE_USERNAME=$(sed -E 's/.*username"*>([a-zA-Z0-9]+)<.*/1/' tmp0.xml)
rm tmp0.xml

################
################
################

# Get list of computers
/usr/bin/curl ${CURL_OPTIONS} --output tmp1.xml --request GET --user "${API_USER}":"${API_PASSWORD}" "${MY_JSS_APIURL}computers"

# Set up values for redundant computer names
DEVICE_NAME="${DEVICE_USERNAME}-mac-0"

# create list of computers and see if name exists. If the name already exists, add a +1 to the value
let itemsCount=$(xmllint --xpath 'count(//computers/computer)' tmp1.xml)
for (( i=1; i<=$itemsCount; i++ )); do
    names[$i]=$(xmllint --xpath '//computers/computer['$i']/name/text()' tmp1.xml)
    for (( x=0; x<=20; x++ )); do
        if [[ " ${names[$i]} " =~ " ${DEVICE_USERNAME}-mac-$x " ]]; then
            let USER_DEVICE_COUNT=$x+1
            DEVICE_NAME="${DEVICE_USERNAME}-mac-${USER_DEVICE_COUNT}"
        fi
    done
done
rm tmp1.xml

################
################
################

# Set new hostname, localhostname, computername
/usr/sbin/scutil --set HostName "${DEVICE_NAME}"
/usr/sbin/scutil --set LocalHostName "${DEVICE_NAME}"
/usr/sbin/scutil --set ComputerName "${DEVICE_NAME}"
/usr/bin/dscacheutil -flushcache

################
################
################

/usr/local/bin/jamf recon
0 REPLIES 0