Posted on 07-05-2015 11:45 AM
I just inherited a JSS one week after a 650 Macbook Air deploy. In this deploy, no machines have been bound or named, but asset tag info was recorded into the JSS (in the asset_tag field). Each of them has the name "Macbook Air" or "User's Macbook Air".
What I need to do:
Rename the devices (both in actuality and in the JSS) using data already stored in the asset_tag field of the JSS record for each machine.
The names need to be changed to the asset tag with “-MAC” after it. An example is: If my asset tag is 12345, my computer name needs to be “12345-MAC”.
I need to be able to run this script in a policy, once against each machine to change its name. Only after this is done can I move forward and begin to bind machines to active directory.
Any assistance would be great, and thanks in advance!
Solved! Go to Solution.
Posted on 07-05-2015 07:36 PM
Hello,
After working with Sean_M_Harper for about 30 minutes or so, we were able to come up with this working solution.
#!/bin/bash
MACADDRESS=$(networksetup -getmacaddress en0 | awk '{ print $3 }')
JSS=https://jss.example.com:8443
API_USER=username
API_PASS=password
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | cut -d "," -f 12 | cut -d ":" -f 2 | sed 's/"//g')
SERIAL_NUMBER=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')
SUFFIX="-MAC"
if [ -n "$ASSET_TAG_INFO" ]; then
echo "Processing new name for this client..."
echo "Changing name..."
scutil --set HostName "$ASSET_TAG_INFO"$SUFFIX
scutil --set ComputerName "$ASSET_TAG_INFO"$SUFFIX
echo "Name change complete. ("$ASSET_TAG_INFO"$SUFFIX)"
else
echo "Asset Tag information was unavailable. Using Serial Number instead."
echo "Changing Name..."
scutil --set HostName $SERIAL_NUMBER$SUFFIX
echo "Name Change Complete ($SERIAL_NUMBER$SUFFIX)"
fi
Basically, the first 'if' statement will check if the string $ASSET_TAG_INFO is null; if so, proceed to rename with serial number (as to not end up with blank or weird names) and your preferred suffix. If not, continue on and rename with info pulled from the JSS and preferred suffix. Quite simple, actually.
With the flexibility of cut, you can determine any field you would like to pull and perform similar actions for other requests. Either way, hopefully someone will find this helpful in the future.
Regards.
Posted on 07-05-2015 07:36 PM
Hello,
After working with Sean_M_Harper for about 30 minutes or so, we were able to come up with this working solution.
#!/bin/bash
MACADDRESS=$(networksetup -getmacaddress en0 | awk '{ print $3 }')
JSS=https://jss.example.com:8443
API_USER=username
API_PASS=password
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | cut -d "," -f 12 | cut -d ":" -f 2 | sed 's/"//g')
SERIAL_NUMBER=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')
SUFFIX="-MAC"
if [ -n "$ASSET_TAG_INFO" ]; then
echo "Processing new name for this client..."
echo "Changing name..."
scutil --set HostName "$ASSET_TAG_INFO"$SUFFIX
scutil --set ComputerName "$ASSET_TAG_INFO"$SUFFIX
echo "Name change complete. ("$ASSET_TAG_INFO"$SUFFIX)"
else
echo "Asset Tag information was unavailable. Using Serial Number instead."
echo "Changing Name..."
scutil --set HostName $SERIAL_NUMBER$SUFFIX
echo "Name Change Complete ($SERIAL_NUMBER$SUFFIX)"
fi
Basically, the first 'if' statement will check if the string $ASSET_TAG_INFO is null; if so, proceed to rename with serial number (as to not end up with blank or weird names) and your preferred suffix. If not, continue on and rename with info pulled from the JSS and preferred suffix. Quite simple, actually.
With the flexibility of cut, you can determine any field you would like to pull and perform similar actions for other requests. Either way, hopefully someone will find this helpful in the future.
Regards.
Posted on 07-05-2015 07:36 PM
Thanks derivethegeek, I appreciate the help! Lets hope this script will help others begin to use the API :)
Posted on 07-06-2015 11:22 AM
Another option besides cut is xpath, something like:
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | xpath /computer/general/asset_tag | awk '{gsub(/<[^>]*>/,"")};1')
I use xpath because it lets me drill right to the node I need by name, it sounds like cut might be relying on data being on a specific line in the API result every time?
Posted on 07-06-2015 02:57 PM
Personally I have never used xpath, but its likely a far more "fool proof" method. I will look into this as a way to enhance this script.
Posted on 09-20-2016 07:22 AM
I did this before I saw ajaxdale's post. Same concept of grabbing the correct value no matter what the position in the results.
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | awk 'BEGIN { FS = "asset_tag" } ; {print $2}' | awk -F, '{print $1}' | awk 'BEGIN { FS = """ } ; { print $3}')
Posted on 09-20-2016 10:20 AM
If you're extracting a value using xpath you don't need to pipe out to awk of another utility:
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | xpath '/computer/general/asset_tag/text()')
Posted on 09-23-2016 09:43 AM
@brysontyrrell Excellent! Jamf changed the formatting between 9.93 and 9.96 from "," to "<>". I assume it's xml. Anyway what I wrote immediately stopped working after upgrading. Using your line grabs the value perfectly.
Posted on 09-28-2020 09:40 AM
Don't mean to hijack this thread but.....Is there an update for the script to do it with Jamf Cloud? I tried and it won't connect.
Posted on 12-08-2020 06:06 PM
So, for our purposes, we're using the UUID (local) as UDID (Jamf Pro field) for record matching purposes.
This following works, and eliminates xpath (which was erroring out):
assettag=$(curl -k -u "${user}:${pass}" ${jssurl}/JSSResource/computers/udid/${udid} -X GET | awk 'BEGIN { FS = "asset_tag" } ; {print $2}' | cut -f2 -d ">" | cut -f1 -d "<")
Thanks everyone, for all of the data parsing wizardry!
Posted on 12-09-2020 11:33 PM
Big Sur has changed the xpath
For an explanation:
https://scriptingosx.com/2020/10/dealing-with-xpath-changes-in-big-sur/
To make this call work
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | xpath '/computer/general/asset_tag/text()')
Change it to
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | xmllint --xpath '/computer/general/asset_tag/text()' -)
01-14-2022 01:55 AM - edited 03-16-2022 06:38 AM
So, updated for Big Sur it should be like this:
#!/bin/bash
MACADDRESS=$(networksetup -getmacaddress en0 | awk '{ print $3 }')
JSS=https://xxxxxx.jamfcloud.com:8443
API_USER=username
API_PASS=password
ASSET_TAG_INFO=$(curl -k $JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS | xmllint --xpath '/computer/general/asset_tag/text()' -)
SERIAL_NUMBER=$(system_profiler SPHardwareDataType | awk '/Serial/ {print $4}')
PREFIX="Company"
SUFFIX="MAC"
if [ -n "$ASSET_TAG_INFO" ]; then
echo "Processing new name for this client..."
echo "Changing name..."
scutil --set HostName $PREFIX"$ASSET_TAG_INFO"$SUFFIX
scutil --set ComputerName $PREFIX"$ASSET_TAG_INFO$"SUFFIX
echo "Name change complete. ($PREFIX"$ASSET_TAG_INFO"$SUFFIX)"
else
echo "Asset Tag information was unavailable. Using Serial Number instead."
echo "Changing Name..."
scutil --set HostName $PREFIX$SERIAL_NUMBER$SUFFIX
echo "Name Change Complete ($PREFIX$SERIAL_NUMBER$SUFFIX)"
fi
I still get an issue with the assetTag not populating, and still reverting to serial number.
Edit: Proofreading is not my strong side. Reverting to port 443(For Jamf Pro cloud deployment) instead of 8443(Jamf Pro On-prem) solved it. Naming based on asset tag info is now working in Mac OS Monterey :)
Posted on 01-14-2022 02:14 AM
set the bash script to verbose so you can see where the issue is
#!/bin/bash
set -x
....
Is happening in all runs? Some devices?
It could be MACADDRESS mismatch, non existent in Jamf.
ASSET_TAG_INFO could not return anything, if there are duplicates you will get a 409 (Conflict), maybe API account...
I would add extra checks for any API call just in case it fails (and it does)
Posted on 01-26-2022 01:24 AM
It happens in the test environment at the customer(scoped to 2 computers) og my own setup. Total of 3 computers running Monterey.
The ASSET_TAG_INFO is definitely not populating, as it reverts to the ELSE command. If that is due to the MACADRESS or the actual ASSET_TAG_INFO I have not yet figured out. The Api works, at it is able to set the alternative name with serial in the ELSE command.
Posted on 02-03-2022 09:13 AM
You can get the ASSET_TAG_INFO in the else part because of the SERIAL_NUMBER variable is local.
Have you added the
set -x
in the script and got all info rom those test Macs?
Post the findings here so we can have a look
Posted on 03-16-2022 06:36 AM
It seems that my testing with ports 443 and 8443 was not complete. It seems to me port 443 is for external/Jamf Cloud, 8443 for Jamf On-prem instances.
Following your -x approach, and letting BBEdit output to file(Unix script output halted, never completed), the script worked! Thanks @Mauricio !
Posted on 03-23-2022 01:52 AM
It is amazing how external factors put a spanner in the works.
Glad that you got it sorted
Posted on 03-30-2022 05:43 AM
In this case the customer in question had an on-prem setup, and my test instance of Jamf is in the cloud. Different environments, different settings to apply.
07-28-2022 07:04 AM - edited 07-28-2022 08:02 AM
Edit: Nevermind, it's working now. Had to get the JSS admin password from above my paygrade to put in for the API user variables. Thanks to everyone that helped make this easier.
Maybe you or anyone else may be able to help me figure out what I have going on with this script. The error is occurring when trying to pull the asset tag info.
Script result: % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 422 100 422 0 0 695 0 --:--:-- --:--:-- --:--:-- 700
100 422 100 422 0 0 694 0 --:--:-- --:--:-- --:--:-- 699
-:10: parser error : Opening and ending tag mismatch: br line 8 and p
</p>
^
-:11: parser error : Opening and ending tag mismatch: p line 8 and body
</body>
^
-:12: parser error : Opening and ending tag mismatch: body line 5 and html
</html>
^
-:12: parser error : Premature end of data in tag html line 1
</html>
^
Asset Tag information was unavailable. Using Serial Number instead.
I don't do a lot of coding, but I know enough to look for those opening tags it thinks should be there and I don't have any idea. I found a different proposed solution here to add -H and GET to the curl line. if I change mine to
ASSET_TAG_INFO=$(curl -k -H "$JSS/JSSResource/computers/macaddress/$MACADDRESS --user $API_USER:$API_PASS" GET | xmllint --xpath '/computer/general/asset_tag/text()' -)
I get the following error:
Could not resolve host: GET
-:1: parser error : Document is empty
^
That feels like a step in the right direction due to less issues but may be completely off track. I reverted back to how it is originally written and added in the 'set -x' line but it doesn't seem to be giving me any more information. I still get "Asset Tag information was unavailable" and it shows "ASSET_TAG_INFO= "; I set the Asset Tag manually in this particular computer's record and it's still there even after the script changes the name correctly albeit with serial number.
I am personally okay with using the serial number for the name but I have had serious fights with teachers over computer names; it was too much trouble to remember the two digit number I assigned to the computers to give students for AirDrop so I can only imagine the fit that will be thrown if they have to use the serial number.