├── AutoPruneJamf.py ├── EADump.py ├── README.md ├── departmentinfo.sh ├── departmentlist.py ├── facultystaffdepartmentinfo.sh ├── index2.0.php ├── index2.5-loanercheckout.php ├── index2.8-loanercheckout.php ├── non-admin-set-date-and-time.sh ├── pivenforcement.py ├── printerlist.py ├── scriptdump.py ├── setuser-json.sh ├── setuser.sh ├── sonicwallgroup.sh ├── student list.py ├── student mass email.py └── update-group.sh /AutoPruneJamf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ##################################################################### 4 | # 5 | # Scrapes the more the Advanced Computer Search -Hasn't checked in for more than 6 months 6 | # Moves machines that haven't checked in for more than 6 months to Unmanaged 7 | # Writes a file of what was moved and some details about it to /Library/Logs/Moved-to-Unmanaged.log 8 | # Scrapes that log file, if the machine hasn't Recon'd in more than a year 9 | # Downloads an individual xml file for each to /Library/Logs/unmanaged_computers_deleted/ 10 | # Then deletes the record from Jamf 11 | # 12 | ##################################################################### 13 | 14 | import urllib2 15 | import base64 16 | import json 17 | import os 18 | import ssl 19 | import csv 20 | import plistlib 21 | from datetime import date, timedelta 22 | from time import gmtime, strftime 23 | import subprocess 24 | 25 | #Base64 of credentials 26 | # format username:password 27 | credentials = '' 28 | 29 | #Advanced Computer Search ID of machines that have a last checkin or inventory of more than 6 months 30 | ACS = '421' 31 | 32 | outputcsv = "/Library/Logs/Moved-to-Unmanaged.log" 33 | target = open(outputcsv, 'a') 34 | 35 | #You can set jamfURL to https://jamfserver:8443/ or read from the plist 36 | #whatever is more fun for you, and just comment out line 41-43 37 | pref_path = "/Library/Preferences/com.jamfsoftware.jamf.plist" 38 | 39 | jamfURL = "" 40 | 41 | if os.path.exists(pref_path) is True and jamfproserver == "": 42 | command = "defaults read " + pref_path + " jss_url" 43 | jamfURL = subprocess.check_output(command,stderr=subprocess.STDOUT,shell=True)[:-1] 44 | 45 | 46 | today = date.today() 47 | todayDate=today.strftime('%m-%d-%y') 48 | 49 | 50 | jamfproserver = jamfURL + 'JSSResource/advancedcomputersearches/id/' + ACS 51 | request = urllib2.Request(jamfproserver) 52 | request.add_header('Accept', 'application/json') 53 | request.add_header('Authorization', 'Basic ' + credentials) 54 | jamfresponse = urllib2.urlopen(request) 55 | response_data = json.loads(jamfresponse.read()) 56 | 57 | computers = response_data['advanced_computer_search']['computers'] 58 | newlist = [] 59 | previous_entry = "" 60 | 61 | 62 | #### 63 | # This is the portion that moves old machines to unmanaged 64 | ### 65 | for computer in computers: 66 | if computer['Managed'] == "Managed": 67 | xmldata = "false" 68 | jamfcomputer = jamfproserver + "JSSResource/computers/serialnumber/" + computer['Serial_Number'] 69 | 70 | opener = urllib2.build_opener(urllib2.HTTPSHandler) 71 | request = urllib2.Request(jamfcomputer, data=xmldata) 72 | 73 | request.add_header('content-type', 'application/xml') 74 | request.add_header('Authorization', 'Basic ' + credentials) 75 | request.get_method = lambda: 'PUT' 76 | 77 | response = opener.open(request) 78 | now = strftime("%m-%d-%y %H:%M", gmtime()) 79 | print >>target, now, ",", computer['Computer_Name'] + "," + computer['Serial_Number'] + ",Moved to Unmanaged,Last Recon: " + computer['Last_Inventory_Update'] + ",Last CheckIn: " + computer['Last_Check_in'] 80 | 81 | target.close() 82 | 83 | logfile = file("/Library/Logs/Moved-to-Unmanaged.log") 84 | unmanaged = csv.reader(logfile) 85 | 86 | #### 87 | # This is the portion that deletes old machines 88 | ### 89 | 90 | ### comment out all below if you dont want deleting 91 | for row in unmanaged: 92 | checkIn = row[4].split(": ") 93 | justDate = checkIn[1].split(" ") 94 | 95 | yearAgo = date.today() - timedelta(365) 96 | yearAgoDate = yearAgo.strftime('%Y-%m-%d') 97 | if justDate[0] < yearAgoDate: 98 | 99 | computerRecordOutput = "/Library/Logs/unmanaged_computers_deleted/" + row[1][1:] + ".xml" 100 | #print computerRecordOutput 101 | if os.path.exists(computerRecordOutput) is False: 102 | computerXML = open(computerRecordOutput, "w") 103 | jamfProServerComputer = jamfproserver + 'JSSResource/computers/serialnumber/' + row[2] 104 | request = urllib2.Request(jamfProServerComputer) 105 | request.add_header('Accept', 'text/xml') 106 | request.add_header('Authorization', 'Basic ' + credentials) 107 | jamfresponse = urllib2.urlopen(request) 108 | print jamfProServerComputer 109 | print >> computerXML, jamfresponse.read() 110 | computerXML.close() 111 | 112 | computerToDelete = jamfproserver + "JSSResource/computers/serialnumber/" + row[2] 113 | #print computerToDelete 114 | #computerToDelete = jamfproserver + "JSSResource/computers/serialnumber/" + computer['Serial_Number'] 115 | #print computerToDelete 116 | opener = urllib2.build_opener(urllib2.HTTPSHandler) 117 | request = urllib2.Request(computerToDelete) 118 | request.add_header('Authorization', 'Basic ' + credentials) 119 | request.get_method = lambda: 'DELETE' 120 | response = opener.open(request) 121 | #print computerToDelete 122 | 123 | logfile.close() 124 | -------------------------------------------------------------------------------- /EADump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | #/Users/Shared/ExtensionAttributes/ has to exist or it fails 4 | 5 | import urllib2 6 | import base64 7 | import json 8 | import sys 9 | import ssl 10 | import os 11 | import requests 12 | import requests.packages.urllib3 13 | 14 | APIUsername='username' 15 | APIPassword='password' 16 | JamfProServer='https://YOURJAMFPROSERVER:8443/' 17 | 18 | r=requests.get(JamfProServer + 'JSSResource/computerextensionattributes', auth=(APIUsername,APIPassword), headers={'accept': 'application/json'}) 19 | EAs = r.json()['computer_extension_attributes'] 20 | 21 | requests.packages.urllib3.disable_warnings() 22 | 23 | for record in EAs: 24 | z=requests.get(JamfProServer + 'JSSResource/computerextensionattributes/id/%s' % record['id'], auth=(APIUsername,APIPassword), headers={'accept': 'application/json'}) 25 | if z.json()['computer_extension_attribute']['input_type']['type'] == "script": 26 | scriptfile = "/Users/Shared/ExtensionAttributes/" + record['name'] + ".sh" 27 | contents = z.json()['computer_extension_attribute']['input_type']['script'].encode("ascii", 'ignore')) 28 | contents = contents.replace("\r","") 29 | target = open(scriptfile, 'w') 30 | target.write(contents) 31 | target.close() 32 | 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jamfapi 2 | JAMF Pro API Scripts I use 3 | 4 | I've taken out the username and password and the address of our server in these scripts. So make sure you fill them in. Over time I'll also go back and comment them deeper so people know what they do. 5 | -------------------------------------------------------------------------------- /departmentinfo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #API login info 4 | apiuser='' 5 | apipass='' 6 | jamfProURL="" 7 | 8 | #update via serial number 9 | apiURL="JSSResource/computers/serialnumber" 10 | MacSerial=`system_profiler SPHardwareDataType | grep 'Serial Number (system)' | awk '{print $NF}'` 11 | 12 | #XML header stuff 13 | xmlHeader="" 14 | 15 | #get current user info from AD 16 | getUser=`ls -l /dev/console | awk '{ print $3 }'` 17 | getclass=`dscl '/Active Directory/ACADEMIC/All Domains' -read /Users/$getUser dsAttrTypeNative:distinguishedName | awk '{ FS=","; print $2 }' | awk '{ FS="="; print $2 }' | tail -1` 18 | getRealName=`dscl '/Active Directory/ACADEMIC/All Domains' -read /Users/$getUser RealName | grep -v ":"` 19 | 20 | #API data load 21 | apiData="$getUser$getRealName$getclass" 22 | curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}/${MacSerial}" \ 23 | -H "Content-Type: text/xml" \ 24 | -d "${xmlHeader}${apiData}" \ 25 | -X PUT > /dev/null 26 | 27 | 28 | #Old Way 29 | #jamf recon -endUsername $getUser -department "$getclass" -building "Postoak" -realname "$getRealName" -email "$getUser@saes.org" 30 | 31 | -------------------------------------------------------------------------------- /departmentlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import urllib2 4 | import base64 5 | import json 6 | import sys 7 | import ssl 8 | import urllib 9 | 10 | requestURL ="https://myjamfpro:8443/JSSResource/departments" 11 | 12 | #build the request 13 | 14 | request = urllib2.Request(requestURL) 15 | _create_unverified_https_context = ssl._create_unverified_context 16 | ssl._create_default_https_context = _create_unverified_https_context 17 | request.add_header('Accept', 'application/json') 18 | request.add_header('Authorization', 'Basic ' + base64.b64encode('USERNAME' + ':' + 'PASSWORD')) 19 | 20 | 21 | #request the json data 22 | response = urllib2.urlopen(request) 23 | response_data = json.loads(response.read()) 24 | 25 | #set the layer we're looking into 26 | departmentinfo = response_data['departments'] 27 | 28 | fulldepartment = "" 29 | 30 | #loops for every instance of mapped printers 31 | for ea in departmentinfo: 32 | departmentname = ea['name'] 33 | fulldepartment = fulldepartment + departmentname + '\" \"' 34 | 35 | 36 | print '\"' + fulldepartment 37 | -------------------------------------------------------------------------------- /facultystaffdepartmentinfo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | OLDIFS="$IFS" 4 | IFS=$',' 5 | 6 | #API login info 7 | apiuser='APIUSERNAME' 8 | apipass='APIPASSWORD' 9 | jamfProURL="https://myjamfpro:8443" 10 | 11 | #update via serial number 12 | apiURL="JSSResource/computers/serialnumber" 13 | MacSerial=`system_profiler SPHardwareDataType | grep 'Serial Number (system)' | awk '{print $NF}'` 14 | 15 | #XML header stuff 16 | xmlHeader="" 17 | 18 | #get current user info from AD 19 | getUser=`ls -l /dev/console | awk '{ print $3 }'` 20 | getRealName=`dscl '/Active Directory/ACADEMIC/All Domains' -read /Users/$getUser RealName | grep -v ":" | tail -1` 21 | 22 | #API data load 23 | xmlresult=`curl -k "$jamfProURL/JSSResource/departments" --user "$apiuser:$apipass" -H "Accept: application/xml" --silent | xmllint --format - | awk -F'>|<' '//{print $3","}'` 24 | 25 | 26 | selectedDepartment=`/usr/local/saes/CocoaDialog.app/Contents/MacOS/CocoaDialog dropdown --title "Select Department" --text "Select the Department to assign your computer to: 27 | " --items $xmlresult --button1 "Ok" --float --string-output | awk -F 'Ok' '{print $1}' | tail -1` 28 | 29 | 30 | apiData="$getUser$getRealName$selectedDepartment" 31 | 32 | curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}/${MacSerial}" \ 33 | -H "Content-Type: text/xml" \ 34 | -d "${xmlHeader}${apiData}" \ 35 | -X PUT > /dev/null 36 | 37 | 38 | curl -k -H "Content-Type: text/json" "$jamfProURL/JSSResource/departments" --user "$apiuser:$apipass" | cut -c 18- | rev | cut -c 4- | rev | awk -F "},{" '{ for (i=1;i<= NF; i++)print $i }' | awk -F ":" '{print $3}' 39 | -------------------------------------------------------------------------------- /index2.0.php: -------------------------------------------------------------------------------- 1 | 69AvailabilityString".$Avail."68DateReturnedDate".$_POST['DateReturned'].""; 19 | 20 | } elseif ($Avail == "No"){ 21 | #checking in a laptop 22 | $xml = "".$_POST['User']."69AvailabilityString".$Avail."67DateOutDate".$_POST['DateOut'].""; 23 | 24 | } 25 | 26 | $ch = curl_init(); 27 | 28 | curl_setopt($ch, CURLOPT_URL, $remote_url); 29 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 30 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 31 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Accept: text/xml', 'Content-Length: ' . strlen($xml),'X-HTTP-Method-Override: PUT')); 32 | curl_setopt($ch, CURLOPT_FAILONERROR, true); 33 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 34 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); 35 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 36 | curl_setopt($ch, CURLOPT_USERPWD, $GLOBALS['username'].":".$GLOBALS['password']); 37 | curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 38 | curl_setopt($ch, CURLOPT_STDERR, $out); 39 | 40 | $response = curl_exec($ch); 41 | curl_close($ch); 42 | 43 | fclose($out); 44 | 45 | 46 | 47 | } 48 | 49 | function ReadJSS($JSSResource) { 50 | #GET info from JSS using the API 51 | 52 | $remote_url = $GLOBALS['jssAPI'] . $JSSResource; 53 | 54 | $curl = curl_init(); 55 | curl_setopt($curl, CURLOPT_URL, $remote_url); 56 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 57 | curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); 58 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Accept: application/json')); 59 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 60 | curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); 61 | curl_setopt($curl, CURLOPT_USERPWD, $GLOBALS['username'].":".$GLOBALS['password']); 62 | 63 | $result = curl_exec($curl); 64 | curl_close($curl); 65 | 66 | return $result; 67 | 68 | } 69 | 70 | If ($_POST){ 71 | #If there's a POST available 72 | 73 | if ($_POST["avail"] == "checkout"){ 74 | 75 | PUTintoCasper("computers/serialnumber/".$_POST['laptop'], "No"); 76 | 77 | } 78 | if ($_POST["avail"] == "checkin"){ 79 | 80 | PUTintoCasper("computers/serialnumber/".$_POST['laptop'], "Yes"); 81 | 82 | } 83 | 84 | } 85 | 86 | ?> 87 | 88 | 89 | 90 | 135 | 154 | Loaner Checkout 155 | 156 | 157 |
158 |
159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | "; 181 | echo ""; 182 | echo ""; 183 | echo ""; 184 | 185 | $UniqueJSSResource = "computers/serialnumber/". $device['serial_number']; 186 | $device_lookups=ReadJSS($UniqueJSSResource); 187 | $cpu_array = json_decode($device_lookups, true); 188 | $location = $cpu_array['computer']['location']; 189 | $extensionattributes = $cpu_array['computer']['extension_attributes']; 190 | 191 | 192 | foreach($extensionattributes as $ext){ 193 | 194 | 195 | if($ext['name'] == "Availability" && $ext['value'] == "No"){ 196 | 197 | 198 | echo ""; 199 | foreach($extensionattributes as $ext2){ 200 | if($ext2['name'] == "DateOut"){ 201 | echo ""; 202 | echo ""; 203 | echo ""; 204 | 205 | echo ""; 206 | echo ""; 207 | } 208 | } 209 | 210 | 211 | } else if ($ext['name'] == "Availability" && $ext['value'] == "Yes"){ 212 | 213 | foreach($extensionattributes as $ext2){ 214 | if($ext2['name'] == "DateReturned"){ 215 | 216 | echo ""; 217 | 218 | echo ""; 219 | echo ""; 220 | 221 | echo ""; 222 | echo ""; 223 | echo ""; 224 | } 225 | } 226 | 227 | } 228 | } 229 | } 230 | 231 | ?> 232 | 233 | 234 | 235 | -------------------------------------------------------------------------------- /index2.5-loanercheckout.php: -------------------------------------------------------------------------------- 1 | 69AvailabilityString".$Avail."68DateReturnedDate".$_POST['DateReturned'].""; 35 | 36 | } elseif ($Avail == "No"){ 37 | #checking in a laptop 38 | $xml = "".$_POST['User']."69AvailabilityString".$Avail."67DateOutDate".$_POST['DateOut'].""; 39 | 40 | } 41 | 42 | $ch = curl_init(); 43 | 44 | curl_setopt($ch, CURLOPT_URL, $remote_url); 45 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 46 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 47 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Accept: text/xml', 'Content-Length: ' . strlen($xml),'X-HTTP-Method-Override: PUT')); 48 | curl_setopt($ch, CURLOPT_FAILONERROR, true); 49 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 50 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); 51 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 52 | curl_setopt($ch, CURLOPT_USERPWD, $GLOBALS['username'].":".$GLOBALS['password']); 53 | curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 54 | curl_setopt($ch, CURLOPT_STDERR, $out); 55 | 56 | $response = curl_exec($ch); 57 | curl_close($ch); 58 | 59 | fclose($out); 60 | 61 | 62 | 63 | } 64 | 65 | function ReadJSS($JSSResource) { 66 | #GET info from JSS using the API 67 | 68 | $remote_url = $GLOBALS['jssAPI'] . $JSSResource; 69 | 70 | $curl = curl_init(); 71 | curl_setopt($curl, CURLOPT_URL, $remote_url); 72 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 73 | curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); 74 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Accept: application/json')); 75 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 76 | curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); 77 | curl_setopt($curl, CURLOPT_USERPWD, $GLOBALS['username'].":".$GLOBALS['password']); 78 | 79 | $result = curl_exec($curl); 80 | curl_close($curl); 81 | 82 | return $result; 83 | 84 | } 85 | 86 | If ($_POST){ 87 | #If there's a POST available 88 | 89 | if ($_POST["avail"] == "checkout"){ 90 | 91 | PUTintoCasper("computers/serialnumber/".$_POST['laptop'], "No"); 92 | 93 | } 94 | if ($_POST["avail"] == "checkin"){ 95 | 96 | PUTintoCasper("computers/serialnumber/".$_POST['laptop'], "Yes"); 97 | 98 | } 99 | 100 | } 101 | 102 | ?> 103 | 104 | 105 | 106 | 151 | 170 | Loaner Checkout 171 | 172 | 173 |
174 |
175 |
LaptopUserDate OutDate Returned
".$device['name']."".$location['username']."".$ext2['value']."".$ext2['value']."
176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | "; 195 | echo ""; 196 | echo ""; 197 | echo ""; 198 | if($device['Availability'] == "No"){ 199 | echo ""; 200 | echo ""; 201 | echo ""; 202 | echo ""; 203 | 204 | echo ""; 205 | echo ""; 206 | } else if ($device['Availability'] == "Yes"){ 207 | echo ""; 208 | 209 | echo ""; 210 | echo ""; 211 | 212 | echo ""; 213 | echo ""; 214 | echo ""; 215 | } 216 | 217 | } 218 | 219 | ?> 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /index2.8-loanercheckout.php: -------------------------------------------------------------------------------- 1 | ".$GLOBALS['availabilityID']."".$Avail."".$GLOBALS['returnedID']."".$_POST['DateReturned'].""; 43 | 44 | } elseif ($Avail == "No"){ 45 | #checking in a laptop 46 | $xml = "".$_POST['User']."".$GLOBALS['availabilityID']."String".$Avail."".$GLOBALS['outID']."Date".$_POST['DateOut'].""; 47 | 48 | } 49 | 50 | $ch = curl_init(); 51 | 52 | curl_setopt($ch, CURLOPT_URL, $remote_url); 53 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 54 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 55 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Accept: text/xml', 'Content-Length: ' . strlen($xml),'X-HTTP-Method-Override: PUT')); 56 | curl_setopt($ch, CURLOPT_FAILONERROR, true); 57 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 58 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); 59 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 60 | curl_setopt($ch, CURLOPT_USERPWD, $GLOBALS['username'].":".$GLOBALS['password']); 61 | curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 62 | curl_setopt($ch, CURLOPT_STDERR, $GLOBALS['outID']); 63 | 64 | $response = curl_exec($ch); 65 | curl_close($ch); 66 | 67 | fclose($GLOBALS['outID']); 68 | 69 | 70 | 71 | } 72 | 73 | function ReadJSS($JSSResource) { 74 | #GET info from JSS using the API 75 | 76 | $remote_url = $GLOBALS['jssAPI'] . $JSSResource; 77 | 78 | $curl = curl_init(); 79 | curl_setopt($curl, CURLOPT_URL, $remote_url); 80 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 81 | curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); 82 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Accept: application/json')); 83 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 84 | curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); 85 | curl_setopt($curl, CURLOPT_USERPWD, $GLOBALS['username'].":".$GLOBALS['password']); 86 | 87 | $result = curl_exec($curl); 88 | curl_close($curl); 89 | 90 | return $result; 91 | 92 | } 93 | 94 | If ($_POST){ 95 | #If there's a POST available 96 | 97 | if ($_POST["avail"] == "checkout"){ 98 | 99 | PUTintoCasper("computers/serialnumber/".$_POST['laptop'], "No"); 100 | 101 | } 102 | if ($_POST["avail"] == "checkin"){ 103 | 104 | PUTintoCasper("computers/serialnumber/".$_POST['laptop'], "Yes"); 105 | 106 | } 107 | 108 | } 109 | 110 | ?> 111 | 112 | 113 | 114 | 159 | 178 | Loaner Checkout 179 | 180 | 181 |
182 |
183 |
LaptopUserDate OutDate Returned
".$device['Computer_Name']."".$device['Username']."".$device['DateOut']."".$device['DateReturned']."
184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | "; 203 | echo ""; 204 | echo ""; 205 | echo ""; 206 | if($device['LoanerAvailability'] == "No"){ 207 | echo ""; 208 | echo ""; 209 | echo ""; 210 | echo ""; 211 | 212 | echo ""; 213 | echo ""; 214 | } else if ($device['LoanerAvailability'] == "Yes"){ 215 | echo ""; 216 | 217 | echo ""; 218 | echo ""; 219 | 220 | echo ""; 221 | echo ""; 222 | echo ""; 223 | } 224 | 225 | } 226 | 227 | ?> 228 | 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /non-admin-set-date-and-time.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pashuapath="/usr/local/saes/Pashua.app/Contents/MacOS/Pashua" 4 | 5 | 6 | pashua_run() { 7 | 8 | # Write config file 9 | local pashua_configfile=`/usr/bin/mktemp /tmp/pashua_XXXXXXXXX` 10 | echo "$1" > "$pashua_configfile" 11 | 12 | if [ "" = "$pashuapath" ] 13 | then 14 | >&2 echo "Error: Pashua could not be found" 15 | exit 1 16 | fi 17 | 18 | # Get result 19 | local result=$("$pashuapath" "$pashua_configfile") 20 | 21 | # Remove config file 22 | rm "$pashua_configfile" 23 | 24 | oldIFS="$IFS" 25 | IFS=$'\n' 26 | 27 | # Parse result 28 | for line in $result 29 | do 30 | local name=$(echo $line | sed 's/^\([^=]*\)=.*$/\1/') 31 | local value=$(echo $line | sed 's/^[^=]*=\(.*\)$/\1/') 32 | eval $name='$value' 33 | done 34 | 35 | IFS="$oldIFS" 36 | } 37 | 38 | REFERENCEDATE=$(date -r /System/Library/CoreServices/XProtect.bundle +%Y%m%d) 39 | CURRENTSYSTEMDATE=$(date +%Y%m%d) 40 | 41 | if [ "$CURRENTSYSTEMDATE" -ge "$REFERENCEDATE" ]; then 42 | exit 0 43 | else 44 | echo "Going into one-time clock set..." 45 | 46 | conf=" 47 | # Set window title 48 | *.title = Date and Time 49 | *.floating = 1 50 | 51 | img.type = image 52 | img.x = 0 53 | img.y = 125 54 | img.maxwidth = 50 55 | img.maxheight = 50 56 | img.path = /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertNoteIcon.icns 57 | 58 | # Message 59 | txt.type = text 60 | txt.default = Your current date and time is incorrect. This will result in problems connecting to the network. 61 | txt.width = 200 62 | txt.x = 60 63 | txt.y = 110 64 | 65 | # Date and time picker 66 | d.type = date 67 | d.label = Please set the Date and Time 68 | d.textual = 1 69 | d.date = 1 70 | d.time = 1 71 | " 72 | pashua_run "$conf" "$customLocation" 73 | 74 | newmonth=$(echo $d | awk '{ print $1 }' | awk -F "-" '{ print $2 }') 75 | newday=$(echo $d | awk '{ print $1 }' | awk -F "-" '{ print $3 }') 76 | newyear=$(echo $d | awk '{ print $1 }' | awk -F "-" '{ print $1 }' | cut -c 3-) 77 | UserSetDate="$(echo $d | awk '{ print $1 }' | awk -F "-" '{ print $2 }'):$(echo $d | awk '{ print $1 }' | awk -F "-" '{ print $3 }'):$(echo $d | awk '{ print $1 }' | awk -F "-" '{ print $1 }' | cut -c 3-)" 78 | UserSetClock=$(echo $d | awk '{ print $2 }') 79 | 80 | systemsetup -setusingnetworktime off 81 | systemsetup -setdate $UserSetDate 82 | systemsetup -settime $UserSetClock 83 | shutdown -r NOW 84 | fi 85 | -------------------------------------------------------------------------------- /pivenforcement.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | #Create an extension attribute 4 | #Create a smart group based off of that extension attribute 5 | #Scope policies or configuration profiles to that smart group. 6 | #Now you have an easy way to toggle that setting on/off for a computer without digging through the JSS 7 | 8 | import urllib2 9 | import base64 10 | import json 11 | import sys 12 | import ssl 13 | import getpass 14 | import os 15 | import subprocess 16 | 17 | #Delete keychain entry 18 | def delete_keychain(): 19 | FNULL = open(os.devnull, 'w') 20 | delete_keychain_command ="security delete-generic-password -s piv-enforce" 21 | delete_keychain = subprocess.call(delete_keychain_command,stdout=FNULL, stderr=subprocess.STDOUT, shell=True) 22 | if delete_keychain == 0: 23 | print "Keychain entry deleted successfully" 24 | else: 25 | print "Keychain entry not found" 26 | 27 | #Login function 28 | def login(): 29 | #check if the keychain entry is there and use it if it is 30 | keychaincheck_command = "security find-generic-password -s piv-enforce -w" 31 | FNULL = open(os.devnull, 'w') 32 | keychain_entry = subprocess.call(keychaincheck_command,stdout=FNULL, stderr=subprocess.STDOUT, shell=True) 33 | if keychain_entry == 0: 34 | usercommand = "security find-generic-password -s piv-enforce | grep \"acct\" | awk -F \"=\" '{print $2}' | tr -d '\"'" 35 | jssuser = subprocess.check_output(usercommand,stderr=subprocess.STDOUT,shell=True)[:-1] 36 | passcommand = "security find-generic-password -s piv-enforce -w" 37 | jsspass = subprocess.check_output(passcommand,stderr=subprocess.STDOUT,shell=True)[:-1] 38 | 39 | #otherwise use the prompt 40 | else: 41 | jssuser = raw_input("Enter Your JSS Account:") 42 | jsspass = getpass.getpass("Password: ") 43 | while True: 44 | save_to_keychain = raw_input("Save to Keychain? (Y/N)") 45 | if save_to_keychain.lower() == "y": 46 | keychain_entry = "security add-generic-password -U -a " + jssuser + " -s piv-enforce -p '" + jsspass + "'" 47 | keychain_entry_command = subprocess.call(keychain_entry,stdout=FNULL,stderr=subprocess.STDOUT,shell=True) 48 | break 49 | elif save_to_keychain.lower() == "n": 50 | break 51 | 52 | return {'user':jssuser, 'pass':jsspass} 53 | 54 | #Function to build the Jamf Pro Classic API URL Request 55 | def jssapi(arg, item): 56 | #if enrolled, use the current jamf server or set the server below 57 | #example jamfproserver = "https://YOURJAMFPROSERVER:8443/" 58 | #if set to nothing, and it finds the jamf.plist then use the enrolled server 59 | jamfproserver = "" #<---- If you want to hardcode the jamfpro url 60 | pref_path = "/Library/Preferences/com.jamfsoftware.jamf.plist" 61 | 62 | if os.path.exists(pref_path) is True and jamfproserver == "": 63 | command = "defaults read " + pref_path + " jss_url" 64 | jamfproserver = subprocess.check_output(command,stderr=subprocess.STDOUT,shell=True)[:-1] 65 | elif os.path.exists(pref_path) is False and jamfproserver =="": 66 | print "No JamfPro server set. Please set one." 67 | quit() 68 | 69 | if arg == "-u": 70 | jamfproserver = jamfproserver + "JSSResource/users/name/" + item 71 | return jamfproserver 72 | elif arg == "-c": 73 | jamfproserver = jamfproserver + "JSSResource/computers/name/" + item 74 | return jamfproserver 75 | 76 | #If you are enabling or disabling function 77 | def PIVAction(url, action, credentials="MISSING"): 78 | if credentials == "MISSING": 79 | credentials = login() 80 | 81 | #makes sure everything is the same case 82 | action = action.lower() 83 | action = action.capitalize() 84 | #script is nice and fixes your mistake 85 | if action == "Enable" or action == "Disable": 86 | action = action + "d" 87 | 88 | if action == "Enabled" or action == "Disabled": 89 | ########################################################### 90 | #Extension Attribute ID and Name WILL need to be changed # 91 | #Set EA_ID and EA_name # 92 | ########################################################### 93 | EA_ID = "497" #<------Here, extension attribute ID! 94 | EA_name = ".PIV Enforced" #<----Here, extension attribute name! 95 | #################################### 96 | xmldata = "" + EA_ID + "" + EA_name + "String" + action + "" 97 | 98 | try: 99 | opener = urllib2.build_opener(urllib2.HTTPSHandler) 100 | request = urllib2.Request(url, data=xmldata) 101 | 102 | request.add_header('content-type', 'application/xml') 103 | request.add_header('Authorization', 'Basic ' + base64.b64encode(credentials['user'] + ':' + credentials['pass'])) 104 | request.get_method = lambda: 'PUT' 105 | 106 | response = opener.open(request) 107 | if response.getcode() != "200": 108 | computer = url.split("/", 6) 109 | print "PIV Enforcement has been " + action + " for computer " + computer[6] 110 | else: 111 | print "Something went wrong" 112 | 113 | except urllib2.URLError, error: 114 | #ERROR Checking, returns HTTP Error Codes 115 | print "Something went wrong.\n", error 116 | return error.code 117 | 118 | else: 119 | print action + " is not an appropriate action." 120 | 121 | 122 | #if you enter the user it will display the computers assigned to that user 123 | def computerlist(requestURL, credentials="MISSING"): 124 | if credentials == "MISSING": 125 | credentials = login() 126 | try: 127 | request = urllib2.Request(requestURL) 128 | request.add_header('Accept', 'application/json') 129 | request.add_header('Authorization', 'Basic ' + base64.b64encode(credentials['user'] + ':' + credentials['pass'])) 130 | response = urllib2.urlopen(request) 131 | 132 | if response.getcode() != "200": 133 | response_data = json.loads(response.read()) 134 | print "-----------------------------------------------" 135 | print "|\tFull Name: " + response_data['user']['full_name'] 136 | print "|\tEmail: " + response_data['user']['email_address'] 137 | print "|\tPhone Number: " + response_data['user']['phone_number'] 138 | print "-----------------------------------------------" 139 | computers = response_data['user']['links']['computers'] 140 | for computer in computers: 141 | print "|\tComputer: " + computer['name'] 142 | print "-----------------------------------------------" 143 | return response.getcode() 144 | except urllib2.URLError, error: 145 | #ERROR Checking, returns HTTP Error Codes 146 | print "Something went wrong.\n", error 147 | return error.code 148 | 149 | #Main Function 150 | def main(): 151 | if len(sys.argv) > 1: 152 | options = sys.argv[1] 153 | if options == "-h": 154 | print " -h \t\t\t\t\t List help" 155 | print " -u [Username]\t\t\t List the computers assigned to the user" 156 | print " -c [Computer] [enabled/disabled]\t Computer to enable/disable Forced PIV" 157 | print " -d \t\t\t\t\t Delete keychain entry" 158 | elif options == "-d": 159 | delete_keychain() 160 | elif options == "-u": 161 | if len(sys.argv) > 2: 162 | url = jssapi(options, sys.argv[2]) 163 | computerlist(url) 164 | else: 165 | print "----------------------------" 166 | print "*** No username inputted ***" 167 | print "----------------------------" 168 | elif options == "-c": 169 | if len(sys.argv) > 3: 170 | PIVAction(jssapi(options, sys.argv[2]), sys.argv[3]) 171 | else: 172 | print "------------------------------" 173 | print "*** Missing item or action ***" 174 | print "------------------------------" 175 | else: 176 | print "Command not found" 177 | else: 178 | ######################### 179 | #INTERACTIVE MODE BEGINS# 180 | ######################### 181 | 182 | print "Interactive Mode!" 183 | print "------------------------------------" 184 | 185 | apilogin = "MISSING" 186 | print "" 187 | print " -h \t\t\t\t\t List help" 188 | print " -u [Username]\t\t\t List the computers assigned to the user" 189 | print " -c [Computer] [enabled/disabled]\t Computer to enable/disable Forced PIV" 190 | print " -d \t\t\t\t\t Delete keychain entry" 191 | print " quit\t\t\t\t\t Type \'quit\' to quit interactive mode" 192 | 193 | while True: 194 | 195 | user_input = raw_input("Please enter an option: ") 196 | if user_input.strip().lower() == "quit" or user_input.strip().lower() == "q": 197 | break 198 | 199 | the_input = user_input.split(" ", 3) 200 | the_input += [None] * (3 - len(the_input)) 201 | options, item, action = the_input 202 | action = str(action) 203 | if options == "-h": 204 | print " -h \t\t\t\t\t List help" 205 | print " -u [Username]\t\t\t List the computers assigned to the user" 206 | print " -c [Computer] [enabled/disabled]\t Computer to enable/disable Forced PIV" 207 | print " -d \t\t\t\t\t Delete keychain entry" 208 | print " quit\t\t\t\t\t Type \'quit\' to quit interactive mode" 209 | elif options == "-u": 210 | if item == None: 211 | print "----------------------------" 212 | print "*** No username inputted ***" 213 | print "----------------------------" 214 | else: 215 | if apilogin == "MISSING": 216 | apilogin = login() 217 | 218 | url = jssapi(options, item) 219 | print url 220 | Notsuccessful = str(computerlist(url, apilogin)) 221 | if Notsuccessful == "401": 222 | apilogin = "MISSING" 223 | elif options == "-d": 224 | delete_keychain() 225 | 226 | elif options == "-c": 227 | if item == None: 228 | print "--------------------" 229 | print "*** Missing item ***" 230 | print "--------------------" 231 | else: 232 | if action == "None": 233 | print "----------------------" 234 | print "*** Missing action ***" 235 | print "----------------------" 236 | else: 237 | if apilogin == "MISSING": 238 | apilogin = login() 239 | 240 | Notsuccessful = str(PIVAction(jssapi(options, item), action, apilogin)) 241 | 242 | if Notsuccessful == "401": 243 | apilogin = "MISSING" 244 | else: 245 | print "-------------------------" 246 | print "*** Command not found ***" 247 | print "-------------------------" 248 | 249 | if __name__== "__main__": 250 | main() 251 | -------------------------------------------------------------------------------- /printerlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import urllib2 4 | import base64 5 | import json 6 | import sys 7 | import ssl 8 | import urllib 9 | 10 | 11 | #Enter computer name (for example EA1234) 12 | computer_name = sys.argv[1] 13 | 14 | requestURL ="https://myjamfpro:8443/JSSResource/computers/name/" + computer_name 15 | 16 | #build the request 17 | request = urllib2.Request(requestURL) 18 | _create_unverified_https_context = ssl._create_unverified_context 19 | ssl._create_default_https_context = _create_unverified_https_context 20 | 21 | request.add_header('Accept', 'application/json') 22 | request.add_header('Authorization', 'Basic ' + base64.b64encode('JAMF API USERNAME' + ':' + 'JAMF API PASSWORD')) 23 | 24 | response = urllib2.urlopen(request) 25 | response_data = json.loads(response.read()) 26 | 27 | #set the layer we're looking into 28 | printers = response_data['computer']['hardware']['mapped_printers'] 29 | 30 | 31 | #loops for every instance of mapped printers 32 | for ea in printers: 33 | printer_name = ea['name'] 34 | printer_type = ea['type'] 35 | print "Printer Name: %s" % printer_name 36 | print "Printer Type: %s" % printer_type 37 | print "" 38 | -------------------------------------------------------------------------------- /scriptdump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import urllib2 4 | import base64 5 | import json 6 | import sys 7 | import ssl 8 | import getpass 9 | import os 10 | 11 | JSSServer='https://Jamf Pro Server:8443' 12 | 13 | JSSUser = raw_input("Enter Your JSS Account:") 14 | JSSPass = getpass.getpass("Password: ") 15 | 16 | ScriptrequestURL = JSSServer + "/JSSResource/scripts" 17 | request = urllib2.Request(ScriptrequestURL) 18 | request.add_header('Accept', 'application/json') 19 | request.add_header('Authorization', 'Basic ' + base64.b64encode(JSSUser + ':' + JSSPass)) 20 | response = urllib2.urlopen(request) 21 | 22 | response_data = json.loads(response.read()) 23 | JamfScripts = response_data['scripts'] 24 | for record in JamfScripts: 25 | scriptrequest = JSSServer + '/JSSResource/scripts/id/%s' % record['id'] 26 | request = urllib2.Request(scriptrequest) 27 | request.add_header('Accept', 'application/json') 28 | request.add_header('Authorization', 'Basic ' + base64.b64encode(JSSUser + ':' + JSSPass)) 29 | response = urllib2.urlopen(request) 30 | response_data = json.loads(response.read()) 31 | contents = str(response_data['script']['script_contents'].encode("ascii", 'ignore')) 32 | contents = contents.replace("\r","") 33 | scriptfile = "/Users/Shared/JAMFScripts/" + record['name'] 34 | if scriptfile[-3:] != ".sh": 35 | scriptfile = scriptfile + ".sh" 36 | scriptfile = scriptfile.replace(" ", "_") 37 | target = open(scriptfile, 'w') 38 | target.write(contents) 39 | target.close() 40 | -------------------------------------------------------------------------------- /setuser-json.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #API login info 4 | apiuser='username' 5 | apipass='password' 6 | jamfProURL="https://myjamfpro:8443" 7 | 8 | ComputerName=$1 9 | getUser=$2 10 | 11 | #update via serial number 12 | apiURL="JSSResource/computers/name" 13 | 14 | #XML header stuff 15 | xmlHeader="" 16 | 17 | 18 | #API data load 19 | #apiData="$getUser" 20 | 21 | apiData="{ 22 | \"computer\": { 23 | 24 | \"extension_attributes\": [ 25 | 26 | { 27 | \"id\": 69, 28 | \"name\": \"Availability\", 29 | \"type\": \"String\", 30 | \"value\": \"Yes\" 31 | }, 32 | { 33 | \"id\": 67, 34 | \"name\": \"DateOut\", 35 | \"type\": \"Date\", 36 | \"value\": \"11/26/81\" 37 | }, 38 | { 39 | \"id\": 68, 40 | \"name\": \"DateReturned\", 41 | \"type\": \"Date\", 42 | \"value\": \"11/26/81\" 43 | } 44 | 45 | ] 46 | } 47 | }" 48 | 49 | curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}/${ComputerName}" \ 50 | -H "Content-Type: text/xml" \ 51 | -d "${xmlHeader}${apiData}" \ 52 | -X PUT > /dev/null 53 | -------------------------------------------------------------------------------- /setuser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #API login info 4 | apiuser='username' 5 | apipass='passowrd' 6 | jamfProURL="https://myjamfpro:8443" 7 | 8 | ComputerName=$1 9 | getUser=$2 10 | 11 | #update via serial number 12 | apiURL="JSSResource/computers/name" 13 | 14 | #XML header stuff 15 | xmlHeader="" 16 | 17 | 18 | #API data load 19 | apiData="$getUser" 20 | curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}/${ComputerName}" \ 21 | -H "Content-Type: text/xml" \ 22 | -d "${xmlHeader}${apiData}" \ 23 | -X PUT > /dev/null 24 | -------------------------------------------------------------------------------- /sonicwallgroup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #API login info 4 | apiuser='username' 5 | apipass='password' 6 | jamfProURL="https://myjamfpro:8443" 7 | 8 | ComputerName=`hostname` 9 | 10 | #update via serial number 11 | #moves them into the static group 12 | apiURL="JSSResource/computergroups/id/232" 13 | 14 | #XML header stuff 15 | xmlHeader="" 16 | 17 | apiData=" 18 | 232 19 | SonicWall Mobile Connect 20 | 21 | 22 | $ComputerName 23 | 24 | 25 | " 26 | 27 | curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}" \ 28 | -H "Content-Type: text/xml" \ 29 | -d "${xmlHeader}${apiData}" \ 30 | -X PUT > /dev/null 31 | -------------------------------------------------------------------------------- /student list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import urllib2 4 | import base64 5 | import json 6 | import sys 7 | import ssl 8 | 9 | 10 | 11 | #Pass graduation year in 2 number format 12 | classYear = sys.argv[1] 13 | 14 | requestURL = "https://myjamfpro/JSSResource/computerreports/id/61" 15 | 16 | #build the request 17 | request = urllib2.Request(requestURL) 18 | context = ssl._create_unverified_context() 19 | _create_unverified_https_context = ssl._create_unverified_context 20 | ssl._create_default_https_context = _create_unverified_https_context 21 | 22 | request.add_header('Accept', 'application/json') 23 | request.add_header('Authorization', 'Basic ' + base64.b64encode('ENTER USERNAME' + ':' + 'ENTER PASSWORD')) 24 | 25 | reponse = urllib2.urlopen(request, context=context) 26 | 27 | #request the json data 28 | response = urllib2.urlopen(request) 29 | response_data = json.loads(response.read()) 30 | 31 | #set the layer we're looking into 32 | computers = response_data['computer_reports'] 33 | 34 | #loops and stuff 35 | counter = 0 36 | for record in computers: 37 | if record['Department'] == "Class of " + classYear: 38 | counter+=1 39 | student_laptop = record['Computer_Name'] 40 | student_username = record['Username'] 41 | print "Student UserName: %s" % student_username 42 | print "Student Computer: %s" % student_laptop 43 | print "" 44 | print "Number of Students in Class of " + classYear + " NOT on macOS Sierra:", counter 45 | print -------------------------------------------------------------------------------- /student mass email.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import urllib2 4 | import base64 5 | import json 6 | import sys 7 | import ssl 8 | import os 9 | 10 | 11 | requestURL = "https://myjamfpro:8443/JSSResource/computerreports/id/67" 12 | 13 | #build the request 14 | request = urllib2.Request(requestURL) 15 | context = ssl._create_unverified_context() 16 | _create_unverified_https_context = ssl._create_unverified_context 17 | ssl._create_default_https_context = _create_unverified_https_context 18 | 19 | request.add_header('Accept', 'application/json') 20 | request.add_header('Authorization', 'Basic ' + base64.b64encode('API-USERNAME' + ':' + 'API-PASS')) 21 | 22 | reponse = urllib2.urlopen(request, context=context) 23 | 24 | #request the json data 25 | response = urllib2.urlopen(request) 26 | response_data = json.loads(response.read()) 27 | 28 | #set the layer we're looking into 29 | computers = response_data['computer_reports'] 30 | 31 | #loops and stuff 32 | for record in computers: 33 | student_laptop = record['Computer_Name'] 34 | student_username = record['Username'] 35 | Email = record['Email_Address'] 36 | FullName = record['Full_Name'] 37 | FirstName = FullName.strip(" ") 38 | FirstName = FirstName.split(' ')[0] 39 | mycommand = "echo 'Hello "+FirstName+",\n\nYour computer has not reported into our inventory system in a while. It is reporting your computer missing or stolen. It is nothing you have done, these things sometimes happen. If you can swing by with your computer, it should only take a few minutes to get it to check back in with our system. \n\nThanks, Mr. Gendler' | mail -s 'Please swing by the Tech Department' " + Email 40 | os.system(mycommand) 41 | print mycommand 42 | -------------------------------------------------------------------------------- /update-group.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #API login info 4 | apiuser="USERNAME" 5 | apipass='PASSWORD' 6 | jamfProURL="https://jamfproserver:8443" 7 | 8 | ComputerName=$(hostname) 9 | 10 | #update group with ID 232 aka group you want 11 | GroupID="1234" 12 | apiURL="JSSResource/computergroups/id/${GroupID}" 13 | 14 | #XML header stuff 15 | xmlHeader="" 16 | 17 | apiData="${GroupID}Whatever the GroupName Is$ComputerName" 18 | 19 | curl -sSkiu ${apiuser}:${apipass} "${jamfProURL}/${apiURL}" \ 20 | -H "Content-Type: text/xml" \ 21 | -d "${xmlHeader}${apiData}" \ 22 | -X PUT > /dev/null 23 | --------------------------------------------------------------------------------
LaptopUserDate OutDate Returned
".$device['Computer_Name']."".$device['Username']."".$device['DateCheckedOut']."".$device['DateCheckedIn']."