Skip to content

Commit 8de1cd4

Browse files
author
Todd McDaniel
committed
Initial release.
Initial release of SCL JAMF EA Collection.
1 parent c178cdf commit 8de1cd4

14 files changed

+850
-0
lines changed

README.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# SCL JAMF Pro Extension Attribute collection
2+
3+
This repository contains a collection of scripts written to perform as extension attributes for the JAMF Pro of management tool. They have been written to suit our specific environment and may need to be modified to operate correctly in others.
4+
5+
## Contents
6+
7+
* [Download](#download) - get the .dmg
8+
* [Contact](#contact)
9+
* [System Requirements](#system-requirements)
10+
* [Install](#install)
11+
* [Uninstall](#uninstall)
12+
* [Purpose](#purpose)
13+
* [The Scripts](#scripts)
14+
* [Bluetooth device battery level](#bluetooth-device-battery-level)
15+
* [Disk free space reporter](#disk-free-space-reporter)
16+
* [Estimated date of manufacture](#estimated-date-of-manufacture)
17+
* [Estimated Age](#estimated-age)
18+
* [SMARTmon check](#smartmon-check)
19+
* [Time Machine Status](#time-machine-status)
20+
* [Attached Displays](#attached-displays)
21+
* [External Encrypted Disks](#external-encrypted-disks)
22+
* [Notes](#notes)
23+
* [Update History](#update-history)
24+
25+
## Download
26+
27+
[Download the latest installer here!](../../releases/)
28+
29+
## Contact
30+
31+
If you have any comments, questions, or other input, either [file an issue](../../issues) or [send us an email](mailto:mlib-its-mac-github@lists.utah.edu). Thanks!
32+
33+
## System Requirements
34+
These scripts are designed to be as extension attributes within Casper's JAMF Software Server (JSS). Most of them are written in Python.
35+
36+
* Python 2.7 (included in MacOS)
37+
38+
## Install
39+
40+
These scripts are designed to be copy-and-pasted into a script field in a JSS extension attribute field.
41+
42+
## Uninstall
43+
44+
Delete the extension attribute.
45+
46+
## Purpose
47+
48+
These scripts are meant to expand the capabilities of JAMF Pro utilizing the Extension Attribute mechanism. JAMF's EA documentation can be found [here](http://docs.jamf.com/10.0.0/jamf-pro/administrator-guide/Computer_Extension_Attributes.html). Using the information returned by an EA, you can build [smart groups](http://docs.jamf.com/10.0.0/jamf-pro/administrator-guide/Smart_Computer_Groups.html). Being a member of a specific smart group can cause additional actions to take place. For example, if the Bluetooth battery level is low, an email could be sent to the user remining them to change the batteries.
49+
50+
Please feel free to use the code provided to build your own scripts.
51+
52+
## The scripts
53+
54+
### Bluetooth device battery level
55+
56+
Detects keyboards, mice and trackpads. Reports if the battery for a device is less than 30%.
57+
58+
![Bluetooth battery display](imgs/bluetooth.png)
59+
60+
61+
62+
### Disk free space reporter
63+
64+
Returns the name, free space, total space and percentage of drive used for each disk attached to a machine.
65+
66+
![](imgs/diskspace.png)
67+
68+
69+
70+
### Estimated date of manufacture
71+
72+
Parses a machines serial number to estimate date of manufacture. Borrows heavily from [this script](https://github.com/pudquick/pyMacWarranty/blob/master/getwarranty.py).
73+
74+
![](imgs/manufacturedate.png)
75+
76+
77+
78+
### Estimated Age
79+
80+
Similar to the Estimated date of manufacture script, but returns a simpler value. Also borrows heavily from [this script](https://github.com/pudquick/pyMacWarranty/blob/master/getwarranty.py).
81+
82+
![](imgs/estimatedage.png)
83+
84+
85+
86+
### SMARTmon check
87+
88+
This EA was written to check all of the disks attached to the local machine. It returns a string containing a single character for each disk. The following table describes the characters and their meanings:
89+
90+
| Symbol | Meaning |
91+
| ------- | ---------------------------------------- |
92+
| . | No errors detected on that disk. |
93+
| Numeral | An error was detected on that disk. |
94+
| ? | SMARTmon suffered an error while checking that disk. |
95+
96+
Example reports:
97+
98+
| Sample reports | |
99+
| -------------- | ---------------------------------------- |
100+
| . | A single disk was checked and no errors were detected. |
101+
| 0... | Four disks were checked and disk0 is returning SMART errors. |
102+
| ..? | Three disks were available and disk2 had a SMARTmon error. |
103+
104+
Note: This EA requires that [SMARTmon tools](https://www.smartmontools.org/) is installed on each client.
105+
106+
107+
108+
### Time Machine Status
109+
110+
This EA checks if Time Machine itself is configured, whether a Time Machine volume is available, and the current capacity of the Time Machine volume.
111+
112+
| Possible returns | Meaning |
113+
| -------------------------------- | ---------------------------------------- |
114+
| Good 10/31 Good 24% free of 713G | Time Machine is configured and working as of 10/31 and the drive has 24% of 713 GB available. |
115+
| Last Backup: 11/02 Not SCL drive | Time Machine is configured and working, but the drive being used is not standard. |
116+
| Not configured, no drive | Time Machine is not configured and no standard drive is attached. |
117+
| Not configured, drive available | Time Machine is not configured and there is a standard drive attached. |
118+
119+
![](imgs/timemachine.png)
120+
121+
122+
123+
###Attached Displays
124+
125+
This EA returns the number and information about the displays attached to a machine.
126+
127+
Here is the data returned for each display:
128+
* Model/Name
129+
* Primary (if set)
130+
* Built-in (if built into machine)
131+
* Retina (if capable)
132+
* Current resolution, refresh rate and maximum resolution
133+
134+
| Possible returns | Meaning |
135+
| ---------------------------------------- | ---------------------------------------- |
136+
| 3: iMac, Primary, Built-in, Retina, 2048 x 1152 (4096 x 2304); VS248, 1920 x 1080 @ 60 Hz (1920 x 1080); ASUS VS247, 1920 x 1080 @ 60 Hz (1920 x 1080) | 3 displays attached: iMac built-in, VS248 and VS247. |
137+
| 2: iMac, Built-in, Retina, 2560 x 1440 (5120 x 2880); ASUS VH236H, Primary, 1920 x 1080 @ 60 Hz (1920 x 1080) | 2 displays attached: iMac built-in, VH236H primary display. |
138+
| 1: SHARP HDMI, Primary, 1920 x 1080 @ 60 Hz (1920 x 1080) | Single Sharp display. |
139+
140+
141+
###External Encrypted Disks
142+
143+
This EA was written to [assist another JAMF user](https://www.jamf.com/jamf-nation/discussions/25854/inventory-report-external-hard-drive). It returns the number of attached hard drives, and the number of encrypted drives.
144+
145+
146+
147+
## Notes
148+
149+
150+
151+
## Update History
152+
153+
| Date | Version | Notes |
154+
| ---------- | ------- | ---------------- |
155+
| 2017.11.24 | 1.0.0 | Initial release. |

attached_displays.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/python
2+
"""
3+
This should not be blank.
4+
"""
5+
6+
# Copyright (c) 2017 University of Utah Student Computing Labs. ################
7+
# All Rights Reserved.
8+
#
9+
# Permission to use, copy, modify, and distribute this software and
10+
# its documentation for any purpose and without fee is hereby granted,
11+
# provided that the above copyright notice appears in all copies and
12+
# that both that copyright notice and this permission notice appear
13+
# in supporting documentation, and that the name of The University
14+
# of Utah not be used in advertising or publicity pertaining to
15+
# distribution of the software without specific, written prior
16+
# permission. This software is supplied as is without expressed or
17+
# implied warranties of any kind.
18+
################################################################################
19+
20+
# attached_displays.py #########################################################
21+
#
22+
# A Python script/Jamf Pro Extension Attribute to inventory and report on
23+
# attached displays.
24+
#
25+
# 1.0.0 2017.09.08 Initial release. tjm
26+
#
27+
################################################################################
28+
29+
# Notes ########################################################################
30+
#
31+
# The output is set up to split three times. Once on ':' will give you the count
32+
# of displays and the description string. And then splitting the description
33+
# string on ':' will give you individual displays. Finally on ',' will give
34+
# features. You can also split the resolution if you need to, for height,
35+
# width, etc.
36+
#
37+
# 2: iMac, Built-in, Retina, 2560 x 1440 (5120 x 2880); ASUS VH236H, Primary, 1920 x 1080 @ 60 Hz (1920 x 1080)
38+
# ^ ^
39+
# | 1. split on ':" |
40+
# | 2. split on ';'
41+
# Continue spliting on ',' for indiviual features
42+
# Current resolution is displayed, Maximum resolution available in parentheses
43+
#
44+
################################################################################
45+
46+
from __future__ import print_function
47+
import subprocess
48+
import plistlib
49+
50+
51+
def main():
52+
"""
53+
This should not be blank.
54+
"""
55+
56+
count_displays = 0
57+
master_string = ""
58+
59+
raw_displays = subprocess.check_output(["system_profiler", "SPDisplaysDataType", "-xml"])
60+
plist_displays = plistlib.readPlistFromString(raw_displays)
61+
list_of_displays = plist_displays[0]['_items']
62+
63+
for item in list_of_displays:
64+
sublist = item['spdisplays_ndrvs']
65+
count_displays = str(len(sublist))
66+
67+
for subitem in sublist:
68+
feature_list = []
69+
70+
try:
71+
name_string = subitem['_name']
72+
except:
73+
name_string = ""
74+
75+
# Build list of resolution strings
76+
try:
77+
resolution_string = subitem['_spdisplays_resolution']
78+
except:
79+
resolution_string = ""
80+
81+
try:
82+
resolution_string = resolution_string + " (" + subitem['_spdisplays_pixels'] + ")"
83+
except:
84+
resolution_string = resolution_string + ""
85+
86+
# Build list of individual features
87+
try:
88+
display_type = subitem['spdisplays_display_type']
89+
except:
90+
display_type = ""
91+
92+
try:
93+
display_main_raw = subitem['spdisplays_main']
94+
if 'yes' in display_main_raw:
95+
feature_list.append("Primary")
96+
except:
97+
pass
98+
99+
if 'built' in display_type:
100+
feature_list.append("Built-in")
101+
102+
if 'retina' in display_type:
103+
feature_list.append("Retina")
104+
105+
if 'spdisplays_on' in subitem['spdisplays_mirror']:
106+
feature_list.append("Mirrored")
107+
108+
if feature_list:
109+
output_string = name_string + ", " + ", ".join(feature_list) + ", " + resolution_string
110+
else:
111+
output_string = name_string + ", " + resolution_string
112+
113+
if master_string:
114+
master_string = master_string + "; " + output_string
115+
else:
116+
master_string = output_string
117+
118+
master_string = count_displays + ": " + master_string
119+
print("<result>" + master_string + "</result>")
120+
121+
122+
if __name__ == '__main__':
123+
main()

bluetooth_device_battery_level.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/python
2+
3+
# Copyright (c) 2017 University of Utah Student Computing Labs. ################
4+
# All Rights Reserved.
5+
#
6+
# Permission to use, copy, modify, and distribute this software and
7+
# its documentation for any purpose and without fee is hereby granted,
8+
# provided that the above copyright notice appears in all copies and
9+
# that both that copyright notice and this permission notice appear
10+
# in supporting documentation, and that the name of The University
11+
# of Utah not be used in advertising or publicity pertaining to
12+
# distribution of the software without specific, written prior
13+
# permission. This software is supplied as is without expressed or
14+
# implied warranties of any kind.
15+
################################################################################
16+
17+
# bluetooth_device_battery.py #################################################
18+
#
19+
# A Python script monitor and report Bluetooth device battery levels.
20+
#
21+
# 1.0.0 2016.03.xx Initial release tjm
22+
#
23+
#
24+
#
25+
################################################################################
26+
27+
# Notes ########################################################################
28+
#
29+
#
30+
#
31+
#
32+
#
33+
#
34+
################################################################################
35+
36+
from __future__ import print_function
37+
import subprocess
38+
import re
39+
40+
def main():
41+
potential_devices = ["AppleBluetoothHIDKeyboard", "BNBTrackpadDevice", "BNBMouseDevice"]
42+
output_string = None
43+
44+
bluetooth_power_state = subprocess.check_output(["defaults", "read", "/Library/Preferences/com.apple.Bluetooth.plist", "ControllerPowerState"])
45+
46+
# exit if bluetooth is off
47+
if "0" in bluetooth_power_state:
48+
quit()
49+
50+
for device in potential_devices:
51+
raw_output = subprocess.check_output(["/usr/sbin/ioreg", "-r", "-c", device])
52+
53+
if raw_output == '':
54+
continue
55+
else:
56+
match = re.search('.*"BatteryPercent" = (.*)\n', raw_output)
57+
58+
if int(match.group(1)) < 30:
59+
if "AppleBluetoothHIDKeyboard" in device:
60+
device_output = "BlueTooth Keyboard at " + match.group(1) + "%"
61+
elif "BNBTrackpadDevice" in device:
62+
device_output = "BlueTooth Trackpad at " + match.group(1) + "%"
63+
elif "BNBMouseDevice" in device:
64+
device_output = "BlueTooth Mouse at " + match.group(1) + "%"
65+
else:
66+
continue
67+
else:
68+
continue
69+
70+
if output_string is None:
71+
output_string = device_output
72+
else:
73+
output_string = output_string + " " + device_output
74+
75+
if output_string is not None:
76+
print("<result>" + output_string + "</result>")
77+
78+
if __name__ == '__main__':
79+
main()

0 commit comments

Comments
 (0)