An Introduction to SimpleMDM custom attributes

13 May 2024

Custom attributes are SimpleMDM’s superpower. You can do all kinds of clever things with them… and I’m convinced I’m barely scratching the surface in the way I’m using them… Anyway - have a quick introduction, and then go off and do some really clever things with them. And then blog about it so I can borrow your excellent ideas…

The thing is… if you start with SimpleMDM’s documentation it’s not immediately obvious what you might want to do with them. There are built in values, like serial number - and I first used these built in attributes when creating SimpleMDM device names… (you define the name SimpleMDM uses when a device enrolls, so {{serial_number}} – {{device_name}}) for example… But other than that, I wasn’t quite sure why they were useful.

The penny really dropped for me when I watched Lucas Hall’s session from MacDevOps a few years ago. Wait? I can use these attributes in custom configuration profiles? I can set true/false or any other value I care to name? And the profiles are dynamically generated (and re-generated) and delivered to a managed device when I edit these values? I mean really, feel free to stop reading right now - and just watch Lucas explain it all properly…

Oh? You’re still reading? Cool…

The magical world of custom attributes…

Why not just hard code these values in a common profile?

I’m glad you asked…

Custom attributes allow for a lot of flexibility

When you create one it can:

  • have a default value… that applies everywhere.
  • OR the default value can be overridden at a group level
  • OR you can override at the device level.

Baby steps… the first thing I did was modify our password policy. We had a requirement for a 12 character minimum… but making that a custom attribute means we can set different passcode length requirements dynamically.

<key>minLength</key>
<integer>{{passcode_length}}</integer>

So now we can override passcode length based on group membership - or even on a per-device level if we want to.

I also experimented with using custom attributes to drive the Privileges app. It’s used to manage admin rights, allowing an end user to add or remove admin powers as required. But it can also be managed using a configuration profile - so you can turn admin rights on or off for an end user by just modifying the custom attribute value at the individual device level.

<array>
	<dict>
		<key>mcx_preference_settings</key>
		<dict>
		<!--
		key: EnforcePrivileges
		value: "admin", "user" or "none" (string)
		Enforces certain privileges. Whenever the Privileges app or PrivilegesCLI is launched,
		the corresponding privileges are set (if needed):
		admin = administrator rights always set by Privileges.
		user = standard user rights are always set by Privileges.
		none = the Privileges app or PrivilegesCLI apps are disabled and it is not possible to
		change privileges using these tools.
		-->
		<key>EnforcePrivileges</key>
		<string>{{admin_rights}}</string>
		</dict>
	</dict>
</array>

Now SimpleMDM will regenerate the profile - when you modify the admin_rights value. Provided it’s set to a valid value - so admin, user or none - you can grant or remove admin rights.

In general, devices respond at the speed of the Apple Push Notifications Service (so - reasonably fast - usually within seconds, worst case a minute or two…) so, set the custom attribute for my device to admin and bingo, I’ve got my admin rights back.

That said, when you modify a profile that’s going to need updating on every device in your fleet of thousands, it can take a little longer…

Using them in anger…

If you want a real world example, last year we rolled out the macOS patching tool Nudge at Thoughtworks. At the most basic level with Nudge you’re defining what version of MacOS you want end users to upgrade to, and by when. There are also plenty of user experience flags you may choose to toggle on or off… (so aggressiveUserExperience and aggressiveUserFullScreenExperience anyone?)

We set custom attributes for the required version and the required install date. We also set a true/false toggle for the more aggressive user experience toggles (with a default of false I hasten to add!)

Later based on user feedback - we modified the setup to allow for flexibility in the “elapsed Refresh Cycle” key. This governs how frequently you get Nudged once you’re past the deadline. Out of the box it’s every 5 minutes. By turning it into an attribute we could easily experiment with different values, rapidly respond to feedback, and retain the option of a naggier Nudge if it’s required.

So the user experience keys look like this:

<key>userExperience</key>
<dict>
    <key>elapsedRefreshCycle</key>
    <integer>{{nudge_reappearance_time_post_deadline_in_seconds}}</integer>   
</dict>
<key>optionalFeatures</key>
<dict>
    <key>aggressiveUserExperience</key>
    {{nudge_AgressiveMode}}
    <key>aggressiveUserFullScreenExperience</key>
    {{nudge_AgressiveMode}}
</dict>

Real world Nudge use? Set a global value of required OS to $latest - so at time of writing this 14.4.1. This applies to all the laptops at the organisation. But wait? What about the devices that need to remain on an older version of macOS? Easy. Pop ‘em in a group and set different values at a group level for required OS version and required install date.

Want to test your Nudge triggers by requiring a non-existent version of macOS? Do so at the device level on your test device. Bingo! You’re now being asked to install macOS 15…

Have a group of users ignoring Nudge? - enable the more aggressive notification options for that group or even on a per device basis.

IDP magic

It gets better. If you’ve enabled modern authentication against an Identity provider (IDP) - you can configure your IDP to send additional user attributes in the SAML assertion when you enrol. If you have a matching attribute, SimpleMDM will set that value for a device.

So - we send first name, last name, username and working office from our IDP Okta into SimpleMDM… so going back to the Nudge example, we can add a custom message:

Hey {{first name}}… update your Mac.

screenshot

Want a Lock Screen message that says if lost, return to $Office? There’s all sorts of stuff you can do when you send SAML user attributes into Simple.

You want more?

OK then - if you’re using SimpleMDM’s scripting engine (and I’m really not in anger…) you can run a script on a device - and store the output against a custom attribute. I’m experimenting with this right now, running a device compliance script from the MacOS Compliance Project - and storing how compliant (or not) a device is as a custom attribute.

A screenshot of the SimpleMDM scripting UI, showing the option to store script output in a device attribute.

Now I can query that device attribute, to see how “compliant” my device is the last time the script was run.

This feels like it could be really useful when troubleshooting a remote device - by sending a script to tail specific log entries and storing them in a SimpleMDM custom attribute.

So - there you go, a quick guide to custom attributes and why they could be your new best friend. And thanks to Mat X on the Mac Admins Slack for giving me the kick I needed to actually get this written up for others to learn from. (Although it’s taken me so long he’s figured it all out himself now…)

Published on 13 May 2024 Find me on Twitter and Mastodon.