A few helpful JAMF extension attributes for Computers
As I continue to build out my JAMF Github Repo it was no surprise that JAMF Extensions are one of the key and fundamental elements and features that gives JAMF that edge as an MDM. Scoping is a key part of what makes an MDM so powerful and the ability to group, report and then scope to specific custom values is what sets it apart.
In that vein, I have put together some of my computer JAMF extensions that I use and thought others would find helpful.
Computer Uptime in Hours
One of the things I love the most about JAMF is its community. That said, this script came to us courtesy of Jason Bush in this accepted solution on JAMF Nation. The script when used as an extension attriute allows you to target computers via their uptime in hours.
Display Name: Computer Uptime in Hours
Enabled (script input type only): Select the checkbox.
Description: This attribute displays the current uptime in hours.
Data Type: String
Inventory Display: Extension Attributes
Input Type: Script
Code (be sure to preserve line breaks as shown below): Shell Default Theme
#!/bin/sh
DAYS="days,"
HRS=" hrs"
DAYScheck=$(uptime | awk {'print $4'})
if [ $DAYScheck = "$DAYS" ]; then
result=$(uptime | awk {'print $3.$4.$5'} | sed 's/,/ /g' | sed 's/d/ d/g')
echo "<result>$result$HRS</result>"
else
result=$(uptime | awk {'print $3'} | sed 's/,//g')
echo "<result>$result$HRS</result>"
fi
exitSecure Tokens
I often need to know and see a full list of all users on and endpoint and which ones are secure token holders and not. bp88 SecureToken Script has come in handy for me in my ecosystem and I highly recommend implementing this as an extension attribute.
Display Name: Secure Tokens
Enabled (script input type only): Select the checkbox.
Description: This attribute displays the secure tokens on the workstation.
Data Type: String
Inventory Display: Extension Attributes
Input Type: Script
Code (be sure to preserve line breaks as shown below): Shell Default Theme
#!/bin/zsh
# Extension attribute to report all user accounts who have a secure token
# If a user is found to have a secure token, the results will be displayed as:
# Admins: user1, user2 (or "None" if none found)
# Non-Admins: user1, user2 (or "None" if none found)
#
# If no user is found to have a secure token, the result will be:
# "No Secure Token Users"
# If an unsupported file system is found, the result will be:
# Unsupported File System: (File System Type)
# Variable to determine File System Personality
fsType="$(/usr/sbin/diskutil info / | /usr/bin/awk 'sub(/File System Personality: /,""){print $0}')"
if [[ "$fsType" != *APFS* ]]; then
echo "<result>Unsupported File System: $fsType</result>"
exit 0
fi
secureTokenAdmins=()
secureTokenUsers=()
# Loop through UUIDs of secure token holders
for uuid in ${$(/usr/sbin/diskutil apfs listUsers / | /usr/bin/awk '/\+\-\-/ {print $2}')}; do
username="$(/usr/bin/dscl . -search /Users GeneratedUID ${uuid} | /usr/bin/awk 'NR==1{print $1}')"
if /usr/sbin/dseditgroup -o checkmember -m "$username" admin &>/dev/null; then
secureTokenAdmins+=($username)
else
secureTokenUsers+=($username)
fi
done
if [[ -z ${secureTokenAdmins[@]} ]]; then
stList="$(echo "Admins: None")"
else
stList="$(echo "Admins: ${secureTokenAdmins[1]}")"
for user in ${secureTokenAdmins[@]:1}; do
stList+=", $user"
done
fi
if [[ -z ${secureTokenAdmins[@]} ]] && [[ -z ${secureTokenUsers[@]} ]]; then
stList="$(echo "No Secure Token Users")"
elif [[ -z ${secureTokenUsers[@]} ]]; then
stList+="\n$(echo "Non-Admins: None")"
else
stList+="\n$(echo "Non-Admins: ${secureTokenUsers[1]}")"
for user in ${secureTokenUsers[@]:1}; do
stList+=", $user"
done
fi
echo "<result>$stList</result>"Screensaver Lock
I got this one from Drata our security GRC tool.
Display Name: Screen Saver Lock
Enabled (script input type only): Select the checkbox.
Description: This attribute displays the current Screen Saver Lock time. The value to be verified is the time before the password is required to unlock the machine, as specified in System Preferences -> Security & Privacy -> General. Example: ‘screenLock delay is 60 seconds’ verifies that a password will be required after the machine is idle for 1 minute.
Data Type: String
Inventory Display: Extension Attributes
Input Type: Script
Code (be sure to preserve line breaks as shown below): Shell Default Theme
NOTE: use this code for any devices running Catalina OS version 10.15.4 or earlier.
#!/bin/sh
askForPassword=$(sysadminctl -screenLock status 2>&1 | awk '{split($0,a,"]"); print a[2]}' | xargs)
user=$( ls -la /dev/console | cut -d " " -f 4 )
idle_time=$(sudo -u $user defaults -currentHost read com.apple.screensaver idleTime)
if [[ ! -z "$askForPassword" && $idle_time -le 900 ]]; then
echo "<result> $askForPassword </result>"
else
echo "<result>Disabled</result>"
fiLast Restart
this script came to us courtesy of Jason Bush in this accepted solution on JAMF Nation. This shows the last reboot of a workstation and can be used in conjunction with the Uptime in Hours attribute to track uptime and restarts.
Display Name: Last Restart
Enabled (script input type only): Select the checkbox.
Description: This attribute shows the last time a computer was restarted.
Data Type: String
Inventory Display: Extension Attributes
Input Type: Script
Code (be sure to preserve line breaks as shown below): Shell Default Theme
#!/bin/bash
lastReboot=`who -b | awk '{print $3" "$4}'`
echo "<result>"$lastReboot"</result>"
exit 0iCloud Logged in Status
For many tracking who is logged into iCloud is a good indicator of users using personal iCloud accounts. This extension by BlackGloveEng1 allows us to do just that. Posted on 3/31/24 this is a great way to report on this.
Display Name: iCloud Logged In Status
Enabled (script input type only): Select the checkbox.
Description: This attribute shows the status of iCloud.
Data Type: String
Inventory Display: Extension Attributes
Input Type: Script
Code (be sure to preserve line breaks as shown below): Shell Default Theme
#!/bin/bash
currentUser=$(stat -f%Su /dev/console)
iCloudLoggedInCheck=$(defaults read /Users/$currentUser/Library/Preferences/MobileMeAccounts Accounts)
if [[ "$iCloudLoggedInCheck" = *"AccountID"* ]]; then
echo "<result>LOGGED IN</result>"
else
echo "<result>NOT LOGGED IN</result>"
fiFirewall State
I got this one from Drata our security GRC tool.
Display Name: Firewall
Enabled (script input type only): Select the checkbox.
Description: This attribute displays whether or not the system firewall is enabled. This attribute applies to both Mac and Windows.
Data Type: String
Inventory Display: Extension Attributes
Input Type: Script
Code (be sure to preserve line breaks as shown below): Shell Default Theme
#!/bin/bash
OS=`/usr/bin/sw_vers -productVersion | /usr/bin/colrm 5`
if [[ "$OS" < "10.5" ]]; then
result=`/usr/bin/defaults read /Library/Preferences/com.apple.sharing.firewall state`
if [ "$result" == "YES" ]; then
echo "<result>On</result>"
elif [ "$result" == "NO" ]; then
echo "<result>Off</result>"
fi
else
result=`/usr/bin/defaults read /Library/Preferences/com.apple.alf globalstate`
if [ "$result" == "0" ]; then
echo "<result>Off</result>"
else echo "<result>On</result>"
fi
fiConclusion
I hope you enjoyed these JAMF Computer Extentions and that they help you in your environment. These super helpful extensions shared with me via various methods have worked well in my environment. I hope that now that you are aware of them continue making them great!
If you found this post useful, Follow me and comment with questions, or feedback. As always here are the sources I referenced throughout this blog post.
Sources
- JAMF Github Repo
- Uptime in Hours
- Jason Bush - LinkedIn
- bp88 SecureToken Script
- Drata Screensaver Screen Lock
- BlackGloveEng1 iCloud Logged In Status
AI Usage Transparency Report
AI Era · Written during widespread use of AI tools
AI Signal Composition
Score: 0.3 · Moderate AI Influence
Summary
As I continue to build out my JAMF Github Repo, it was no surprise that JAMF Extensions are one of the key and fundamental elements and features that gives JAMF its edge as an MDM. Scoping is a crucial part of what makes an MDM effective, allowing for granular control over device management. The ability to group, report, and then scope to specific custom values is what sets it apart from other MDM solutions, providing a level of precision that's essential for large-scale deployments.
Related Posts
Scoring AI Influence in Jekyll Posts with Local LLMs
There’s a moment that kind of sneaks up on you when you’ve been writing for a while, especially if you’ve started using AI tools regularly. You stop asking whether AI was used at all, and instead start wondering how much it actually shaped what you’re reading. That shift is subtle, but once you notice it, you can’t really unsee it.
Automating JAMF Pro Email Notifications with SendGrid (Smart Group Driven Workflows)
Modern device management isn't just about enforcing policies—it's about communicating effectively with users at the right time. In JAMF Pro, Smart Groups give you powerful visibility into device state, but they don't natively solve the problem of proactive, automated user communication. Whether you're trying to prompt users to restart their machines, complete updates, or take action on compliance issues, bridging that gap requires a flexible and scalable notification system.
Leaving Flickr: Migrating 20,000+ Photos to Synology and Taking Back Control
There’s a certain kind of friction you start to notice when you’ve been using a service for a long time. Not enough to make you leave immediately, but enough to make you pause. Flickr had been that kind of service for me. It quietly held years of photos, uploads from old phones, albums I hadn’t looked at in ages, and a massive "Auto Upload" collection that had grown into something I didn’t fully understand anymore.
Exploring the Apple Business Manager API: A Hands-On Playground
If you’ve ever tried to talk directly to the **Apple Business Manager (ABM) API**, you already know the process can feel like deciphering a secret code. Between private keys, encrypted certificates, ES256 signatures, and OAuth2 flows... there’s a lot going on under the hood. This complexity is what makes direct communication with ABM so challenging, requiring a deep understanding of its intricacies to navigate successfully.
Updating Safari on macOS with Jamf Pro: Three Practical Strategies
Keeping Safari updated is one of the simplest ways to harden a macOS fleet. Apple ships security fixes for Safari frequently, and those patches often land before a full macOS point release. This means that by keeping Safari up-to-date, you can ensure your users have access to the latest security protections without having to wait for a major operating system update. If Safari is lagging behind, your users are browsing the web with a larger attack surface than necessary.
Hunting Down Jamf Profile Payloads with Python
If you've spent enough time living inside Jamf Pro, you eventually run into the same problem: someone set a configuration somewhere, sometime, and nobody remembers where. It might be something obscure – a certificate payload, a conditional SSO predicate, or that one security preference quietly misbehaving on three machines in accounting. And when you have dozens of configuration profiles, each with multiple payloads, nested keys, and XML-wrapped values, finding that setting can feel like forensic archaeology.
Keeping Jamf Security Cloud Current for Microsoft 365: Updated Routing Policies
When I first wrote about troubleshooting Standard Routing Policies in Jamf Security Cloud, the goal was simple: help admins keep Microsoft Teams and Microsoft 365 traffic flowing smoothly through Jamf Trust + App-Based VPN. This straightforward objective remains unchanged, as the complexities of network configurations can often lead to frustrating issues that hinder productivity.
Ensuring Jamf Trust VPN Stays Connected with Jamf Pro
Keeping your organization's VPN always connected is crucial—especially with Zero Trust Network Access (ZTNA) frameworks like **Jamf Trust**. One of the challenges with **Jamf Trust** is that it does *not* automatically open or reconnect on startup or login by default. However, with a combination of Jamf Pro policies, a custom script, and an extension attribute, you can ensure your users stay securely connected at all times, even when their devices are restarted or logged out. This setup helps maintain continuous access to network resources while adhering to the security standards...
Troubleshooting Standard Routing Policies in JAMF Security Cloud
As a fairly new administrator of JAMF Security Cloud, it was the ease of which its administration that admittedly drew me in. Quite an elegant solution for securing the various apps on business workstations with premade app-based VPN routing rules built right in, I was hooked. The concept is simple: turn on the policies, create your enrollment, and deploy – and you're done. This straightforward approach has made it easy to integrate into our existing workflow, allowing us to focus on more critical tasks.
Enrolling M1-M4 Devices into Automox with JAMF with secure tokens
Managing Secure Tokens on macOS has long been a challenge for administrators using JAMF and Automox. In my previous post, Managing the macOS Secure Token with JAMF Pro, I discussed a script-based approach to grant Secure Tokens to additional users. However, this method required administrators to manually pass usernames and passwords into the JAMF configuration—an approach that, while effective, was not ideal from a security or usability perspective. This manual process introduced unnecessary risks and added complexity to the overall management of Secure Tokens.