Posted on 09-15-2017 01:08 PM
Hello,
I am in need of a script to rename hundreds of ios devices. I would like to do it using a CSV file. One column with the serial number and the next column with the name of the ios device. I know about the mut software, however we are unable to use it as we have different IT departments and the mut software tests privileges that we do not want to give the users.
Any help with this dilemma would be greatly appreciated as I am sure someone has the script handy.
Posted on 09-15-2017 01:09 PM
please
Posted on 09-15-2017 01:13 PM
You should be able to modify this to fit your needs.
#!/bin/sh
# Name: leaseupdate.sh
# Date: 9 March 2015
# Author: Steve Wood (swood@integer.com)
# Purpose: used to read in lease data from a CSV file and update the record in the JSS
# The CSV file needs to be saved as a UNIX file with LF, not CR
# Version: 1.0
#
# A good portion of this script is re-purposed from the script posted in the following JAMF Nation article:
#
# https://jamfnation.jamfsoftware.com/discussion.html?id=13118#respond
#
jssAPIUsername="<apiuser>"
jssAPIPassword="<apipassword>"
jssAddress="https://your.jss.com:8443"
file="<path-to-csv-file>"
#Verify we can read the file
data=`cat $file`
if [[ "$data" == "" ]]; then
echo "Unable to read the file path specified"
echo "Ensure there are no spaces and that the path is correct"
exit 1
fi
#Find how many computers to import
computerqty=`awk -F, 'END {printf "%s
", NR}' $file`
echo "Computerqty= " $computerqty
#Set a counter for the loop
counter="0"
duplicates=[]
id=$((id+1))
#Loop through the CSV and submit data to the API
while [ $counter -lt $computerqty ]
do
counter=$[$counter+1]
line=`echo "$data" | head -n $counter | tail -n 1`
serialNumber=`echo "$line" | awk -F , '{print $1}'`
leaseExpires=`echo "$line" | awk -F , '{print $2}'`
echo "Attempting to update lease data for $serialNumber"
# use serialNumber to locate the ID of the comptuer
### Add some logic to test for an empty set coming back from serial number check.
myOutput=`curl -su ${jssAPIUsername}:${jssAPIPassword} -X GET ${jssAddress}/JSSResource/computers/serialnumber/$serialNumber`
myResult=`echo $myOutput | xpath /computer/general/id[1] | awk -F'>|<' '/id/{print $3}'`
myID=`echo $myResult | tail -1`
echo $serialNumber " " $myID " " $leaseExpires
apiData="<computer><purchasing><lease_expires>$leaseExpires</lease_expires></purchasing></computer>"
output=`curl -sS -k -i -u ${jssAPIUsername}:${jssAPIPassword} -X PUT -H "Content-Type: text/xml" -d "<?xml version="1.0" encoding="ISO-8859-1"?>$apiData" ${jssAddress}/JSSResource/computers/id/$myID`
echo $output
#Error Checking
error=""
error=`echo $output | grep "Conflict"`
if [[ $error != "" ]]; then
duplicates+=($serialnumber)
fi
#Increment the ID variable for the next user
id=$((id+1))
done
echo "The following computers could not be created:"
printf -- '%s
' "${duplicates[@]}"
exit 0
Posted on 09-15-2017 01:31 PM
The MUT also does this and makes it simple with a nice UI.
Posted on 09-15-2017 03:07 PM
Yeah we would love to use the MUT but are not able to because of how our jss is set up. We are a tunnel on another JSS account for a sister IT department... Its really confusing and frustrating as MUT would be the answer to our dilemma.
Is there anyway you can advise me on how to setup your code to rename the ios devices? How do I change lease to device name? I understand CSV loop however this is confusing. If our devices are already in DEP do I need to locate them by serial number?
Posted on 09-15-2017 05:16 PM
Remember you could also use variables to set the name of a device. Anytime the device checks-in, the name will change back.
http://krypted.com/mac-security/using-payload-variables-in-profile-manager/
Posted on 09-15-2017 06:17 PM
Yes! However I am getting a little bit of a crash course on some of this coding... (I am a junior in college and know enough to be dangerous lol) any help anyone can contribute would be of great appreciation... I am learning a lot through forums like these that is for sure.
Posted on 09-15-2017 11:22 PM
@jay216 Ey! I'm a young'n also (21). Basically change the variable name in line where it it says leaseExpires=echo "$line" | awk -F , '{print $2}'
so change it to name or something like that. If you do your csv's in excel like i do then column 1 is your device serial number and column 2 is the name for it. The other thing you have to do is modify the xml portion. Where it says apiData="<computer><purchasing><lease_expires>$leaseExpires</lease_expires></purchasing></computer>" you need to change it to the xml format for the ios devices. I don't know it because we only do mac's here. Basically go to yourjss.com:8443/api and the should be an IOS get command somewhere. use it to get the XML structure you need for you "put" in the API. You don't need all the data. Just the data that's being changed. So the hierarchy is computer>purchasing>lease expires and then closing brackets for that respectively. Yours would be something like mobiledevices>name or something along those lines. Make sure when you change any variables in one place of the script you change them in any others. Find and replace all will be your friend for that but be careful to not changing something you don't want to.
Posted on 09-16-2017 08:17 AM
ahhhh you have shown me the light... I am busting notepad out now and will keep you updated.
Posted on 09-16-2017 08:43 AM
Okay I have everything except the API data. I am unsure of where to find it. I do not see anything that says IOS in the API let alone rename.
It would have to be under mobile devices I am sure
Posted on 09-16-2017 09:05 AM
Posted on 09-16-2017 09:05 AM
Posted on 09-16-2017 09:05 AM
anything look like api data?
Posted on 09-16-2017 10:09 AM
That's the right information. I think you would put your ${name} Variable inside of <device_name> so it would be <mobile_device><device_name>${namevariable}</device_name></mobile_device>
You also need to change the myoutput variable and the output variable tot he correct api call. so your myoutput ending should be something like GET /mobiledevices/serialnumber/$serialnumber
and your output ending would be something like /mobiledevices/id/${myid}
Posted on 11-21-2017 09:33 AM
Anyone interested in taking a call on this and discussing how this worked for you. Let me know
Posted on 11-21-2017 06:41 PM
When I set mine up I couldn't get the xml method to work, It would update JAMF Pro but the name would not stick We wound up using the rename command in the code below and this has worked well for us. Please ignore the bad formatting and underlining. Regards GraemePreamble
import urllib.parse import urllib.request import urllib.response import urllib import pypyodbc import sys import csv import codecs import xml.etree.cElementTree as etree import getpass from urllib.request import urlopen import time import datetime from time import strftime from datetime import datetime from datetime import date from operator import itemgetter, attrgetter import mysql.connectorglobal set to not verify ssl certificate. Bad practice but works here.
import ssl ssl._create_default_https_context = ssl._create_unverified_context userName=input('Username: ') passWord=getpass.getpass('Password: ') top_level_url = "https://mdm.ourschool.edu.au:8443/JSSResource" #create an authorization handler and add to all requests p = urllib.request.HTTPPasswordMgrWithDefaultRealm() p.add_password(None, top_level_url, userName, passWord); auth_handler = urllib.request.HTTPBasicAuthHandler(p) opener = urllib.request.build_opener(auth_handler) opener.addheaders.append(('Accept', 'application/xml')) urllib.request.install_opener(opener)This will post an XML but is not used here.
def sendXMLtoJSS(resource, method = '', data = None): request = urllib.request.Request(resource) #if method.upper() in ('POST', 'PUT', 'DELETE'): #request.get_method = lambda: method if method.upper() in ('POST', 'PUT') and data: headers = { 'Content-Type' : 'text/xml' } #data = urllib.parse.urlencode(data) data = data.encode('ascii') req = urllib.request.Request(resource, data, headers) req.get_method = lambda: method #req.get_method = method with urllib.request.urlopen(req) as response: the_page = response.read() return the_page #opener.addheaders.append('Content-Type', 'text/xml') #request.add_header('Content-Type', 'text/xml') #return opener.open(request, data) else: try: return opener.open(resource) except IOError as e: print (e) logData(e)This is the rename command.
def sendRenameCommandtoJSS(id, New_Name): # JAMF says if we are enforcing the name send a command because it is friendlier for cloud customers # but uploading an xml updated the jss but did not save the settings. Had to manually go to the device # properties in JSS and click the edit and then save. # Will error out with a 500 error if a rename command is still outstanding. Devicename = urllib.parse.quote(New_Name) command = top_level_url "/mobiledevicecommands/command/DeviceName/" Devicename "/id/" str(id) req = urllib.request.Request(command) req.get_method = lambda: 'POST' #request = urllib.request.Request(resource) try: response = opener.open(req) strResponse = response.read().decode('utf-8') logData(strResponse) print(New_Name " has been successfully renamed.") #logData(response.read().decode('utf-8')) except urllib.error.HTTPError as e: if e.code == 400: print(New_Name " has an outstanding rename request. Rename failed.") else: print("Rename Error" str(e), command)This gets the list of devices from the JSS so we can extract the ID
def getDevices(): #Download from JSS an xml list of devices and basic attributes. response = sendXMLtoJSS(top_level_url '/mobiledevices') responseBytes = response.read() responsetext = responseBytes.decode("utf-8", 'ignore') responsetext = unicodeToAscii(responsetext)#Remove special characters. #print(responsetext) xml = etree.fromstring(responsetext) #text_file = open("Output.xml", "wb") #text_file.write(responsetext) #text_file.close() return xml def getDeviceList(xmlOfDevices): for child in xmlOfDevices: #print(child.tag, child.text) deviceId = "" deviceSerial = "" deviceUsername = "" deviceName = "" deviceSupervised = "" try: temp = len(devices) except: devices = [] for group in child: #print(group.tag, group.text) if group.tag == "id": deviceId = group.text if group.tag == "serial_number": deviceSerial = group.text if group.tag == "username": deviceUsername = group.text if group.tag == "device_name": deviceName = group.text if group.tag == "supervised": deviceSupervised = group.text #if deviceId == "63": # print ("ID = 63") device = [deviceId, deviceSerial, deviceUsername, deviceName, deviceSupervised] devices.append(device) return devices
Posted on 11-22-2017 12:18 PM
I have a FileMaker database that does this (and more).
It uses the API to first GET all your mobile devices from your JSS and puts them into FileMaker. Then you can use FileMaker to name them however you want. You can then PUT (update) them back into the JSS. Works great.
You can also PUT the Department, Room, Username, Real_Name, email, Building all at the same time as well.
Send me an email (if you use FileMaker) and I will share my database with you.