PPPC device management settings visible in System Settings on macOS Tahoe 26.2.0

As part of the What’s new for enterprise in macOS Tahoe 26 release notes for macOS Tahoe 26.2.0, there’s this note:

App privacy permissions configured by device management are now shown in System Settings > Privacy & Security.

What this indicates is that a long-standing feature request by Mac admins has been fulfilled by Apple. For more details, please see below the jump.

As part of macOS 10.14 Mojave, Apple introduced a number of privacy controls for user data. At the same time, Apple also introduced device management options to allow authorized applications to access data protected by those privacy controls. These permissions are referred to collectively as Privacy Preferences Policy Control (PPPC) and are deployed via management profiles from an MDM server. However, up until macOS Tahoe 26.2, there was no way to see in the Privacy & Security section of System Settings which applications had which permissions granted via PPPC management profiles.

As an example, by default, Macs managed by Jamf Pro will get a management profile which allows the Jamf agent permission to access data stored in the user home folder via the PPPC permission known as full disk access. Here’s how this looks on macOS Tahoe 26.1.0:

Privacy Preferences Policy Control profile installed which enables full disk access to the Jamf agent.

No mention of the full disk access permissions granted to the Jamf agent in the Privacy & Security section of System Settings.

How this looks on macOS Tahoe 26.2.0:

Privacy Preferences Policy Control profile installed which enables full disk access for the Jamf agent.

Full disk access permissions granted to the Jamf agent are disclosed in the Privacy & Security section of System Settings. It is also disclosed that the permissions setting is configured by a profile.

Updating management status in Jamf Pro computer inventory records using the Jamf Pro API

A while back, I wrote a post on how to set Jamf Pro computer inventory records to be managed using a script. I recently revisited this script as part of a general effort on my part to update scripts which have been using the now-deprecated computers Classic API endpoint, to now use the Jamf Pro API’s computers-inventory-detail API endpoint.

As part of this effort, I decided to not only update my existing script for setting the management status in Jamf Pro computer inventory records to be managed but also write a second script for setting the management status to be unmanaged. For more details, please see below the jump.

You can set the management status in a Jamf Pro computer inventory record using the computers-inventory-detail endpoint for the Jamf Pro API. The API command to change the management status in a Jamf Pro computer inventory record to Managed should look similar to this:


/usr/bin/curl -H "Content-Type: application/json" "https://jamf.pro.server.here/api/v3/computers-inventory-detail/jamf_pro_computer_ID_goes_here" –header "Authorization: Bearer api_token_goes_here" -X PATCH -d '{"general":{"managed":"true"}}'

view raw

gistfile1.txt

hosted with ❤ by GitHub

It’s sending the following JSON block to update the relevant computer inventory record and make the management change:


{
"general": {
"managed": "true"
}
}

view raw

gistfile1.txt

hosted with ❤ by GitHub

The API command to change the management status in a Jamf Pro computer inventory record to Not Managed should look similar to this:


/usr/bin/curl -H "Content-Type: application/json" "https://jamf.pro.server.here/api/v3/computers-inventory-detail/jamf_pro_computer_ID_goes_here" –header "Authorization: Bearer api_token_goes_here" -X PATCH -d '{"general":{"managed":"false"}}'

view raw

gistfile1.txt

hosted with ❤ by GitHub

It’s sending the following JSON block to update the relevant computer inventory record and make the management change:


{
"general": {
"managed": "false"
}
}

view raw

gistfile1.txt

hosted with ❤ by GitHub

I was able to use the API information discussed above to create a couple of scripts which a) update the management status in specified computer inventory records and b) generates a report of the Macs whose computer inventory records were updated.

The scripts are named Set_Jamf_Pro_Computers_To_Managed_Status.sh and Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh and are available via the links below:

https://github.com/rtrouton/rtrouton_scripts/tree/main/rtrouton_scripts/Casper_Scripts/Set_Jamf_Pro_Computers_To_Managed
https://github.com/rtrouton/rtrouton_scripts/tree/main/rtrouton_scripts/Casper_Scripts/Set_Jamf_Pro_Computers_To_Unmanaged

Both scripts are designed to take in a set of Jamf Pro ID numbers in a plaintext file, where the Jamf Pro ID numbers correspond the Macs where you want to change the management status in their Jamf Pro computer inventory records. The plaintext file should look similar to this:


416462
842736
434703
338517
481915
596669

view raw

gistfile1.txt

hosted with ❤ by GitHub

Four items are required to use these scripts:

  • A text file containing the Jamf Pro IDs of the computer(s) you wish to delete.
  • The URL of the appropriate Jamf Pro server.
  • The username of an account on the Jamf Pro server with sufficient privileges to delete computers from the Jamf Pro server.
  • The password for the relevant account on the Jamf Pro server.
  • Jamf Pro account privileges required by the Jamf Pro server account referenced above:

Jamf Pro Server Objects:

  • Computers: Read, Update
  • Users: Update

Once the four specified items are available, the scripts can be run using the following commands:

For Set_Jamf_Pro_Computers_To_Managed_Status.sh:


/path/to/Set_Jamf_Pro_Computers_To_Managed_Status.sh /path/to/plaintext_filename_here.txt

view raw

gistfile1.txt

hosted with ❤ by GitHub

For Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh:


/path/to/Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh /path/to/plaintext_filename_here.txt

view raw

gistfile1.txt

hosted with ❤ by GitHub

For Set_Jamf_Pro_Computers_To_Managed_Status.sh, you should see output that looks like this:


username@computername ~ % /Users/Shared/Set_Jamf_Pro_Computers_To_Managed/Set_Jamf_Pro_Computers_To_Managed_Status.sh /Users/Shared/jamfpro_computer_ids.txt
Please enter your Jamf Pro server URL : https://jamf.pro.server.here
Please enter your Jamf Pro user account : username_goes_here
Please enter the password for the username_goes_here account:
Report being generated. File location will appear below once ready.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=416462 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=842736 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=434703 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=338517 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=481915 from unmanaged to managed.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=596669 from unmanaged to managed.
Report on Macs available here: /var/folders/ps/2_yw29gj711c9d7c5w5jhyv80000gp/T/tmp.eFStgTqa5l.tsv
username@computername ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

As part of the script’s run, a report will be generated and you’ll be notified of where it is stored. The report will be in TSV format and appear similar to what’s shown below:



Jamf Pro ID Number Make Model Serial Number UDID Computer Management Status Jamf Pro URL
416462 Apple MacBook Pro (16-inch, 2019) WD8JB8F49YS4 4D8CD419-1892-4CFE-8D18-D1DD53CC7970 Managed https://jamf.pro.server.here/computers.html?id=416462
842736 Apple MacBook Pro (16-inch, 2019) R6JG7GYVNORW 904418F7-3695-44BF-9A00-74F5CF617377 Managed https://jamf.pro.server.here/computers.html?id=842736
434703 Apple MacBook Pro (16-inch, 2019) FWPATJHWC92O 5CF418CE-3E46-481C-A171-7ACC9E1E2E7A Managed https://jamf.pro.server.here/computers.html?id=434703
338517 Apple MacBook Pro (16-inch, 2019) CVZVJ8R55467 E82C6C63-5F49-4DD3-90A0-E01EC11F6954 Managed https://jamf.pro.server.here/computers.html?id=338517
481915 Apple MacBook Pro (13-inch, M1, 2020) QL6ROPPB1SK5 CBC87B4C-28DA-417F-8790-411AF9F105AD Managed https://jamf.pro.server.here/computers.html?id=481915
596669 Apple MacBook Pro (16-inch, 2021) CNA11CBMJSNI 72811617-8C97-4EB6-BC4B-B9FA9C87B259 Managed https://jamf.pro.server.here/computers.html?id=596669

For Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh, you should see output that looks like this:


username@computername ~ % /Users/Shared/Set_Jamf_Pro_Computers_To_Unmanaged/Set_Jamf_Pro_Computers_To_Unmanaged_Status.sh /Users/Shared/jamfpro_computer_ids.txt
Please enter your Jamf Pro server URL : https://jamf.pro.server.here
Please enter your Jamf Pro user account : username_goes_here
Please enter the password for the username_goes_here account:
Report being generated. File location will appear below once ready.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=416462 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=842736 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=434703 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=338517 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=481915 from managed to unmanaged.
Updated management status in the computer inventory record for https://jamf.pro.server.here/computers.html?id=596669 from managed to unmanaged.
Report on Macs available here: /var/folders/ps/2_yw29gj711c9d7c5w5jhyv80000gp/T/tmp.6Ic4bx2sT8.tsv
username@computername ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

As part of the script’s run, a report will be generated and you’ll be notified of where it is stored. The report will be in TSV format and appear similar to what’s shown below:



Jamf Pro ID Number Make Model Serial Number UDID Computer Management Status Jamf Pro URL
416462 Apple MacBook Pro (16-inch, 2019) WD8JB8F49YS4 4D8CD419-1892-4CFE-8D18-D1DD53CC7970 Unmanaged https://jamf.pro.server.here/computers.html?id=416462
842736 Apple MacBook Pro (16-inch, 2019) R6JG7GYVNORW 904418F7-3695-44BF-9A00-74F5CF617377 Unmanaged https://jamf.pro.server.here/computers.html?id=842736
434703 Apple MacBook Pro (16-inch, 2019) FWPATJHWC92O 5CF418CE-3E46-481C-A171-7ACC9E1E2E7A Unmanaged https://jamf.pro.server.here/computers.html?id=434703
338517 Apple MacBook Pro (16-inch, 2019) CVZVJ8R55467 E82C6C63-5F49-4DD3-90A0-E01EC11F6954 Unmanaged https://jamf.pro.server.here/computers.html?id=338517
481915 Apple MacBook Pro (13-inch, M1, 2020) QL6ROPPB1SK5 CBC87B4C-28DA-417F-8790-411AF9F105AD Unmanaged https://jamf.pro.server.here/computers.html?id=481915
596669 Apple MacBook Pro (16-inch, 2021) CNA11CBMJSNI 72811617-8C97-4EB6-BC4B-B9FA9C87B259 Unmanaged https://jamf.pro.server.here/computers.html?id=596669

In addition to the scripts described above which use user accounts for authentication, there are also matching scripts which use API client authentication available on GitHub via the links above. If setting up an API client with limited rights, here are the required API role privileges for the API client on the Jamf Pro server:

  • Computers Read
  • Computers Update
  • Users Update

New application version smart group and advanced computer search criteria available as of Jamf Pro 11.23.0

In macOS, applications record version information in the Information Property List file. This file is stored inside the Contents directory of the application bundle and is named Info.plist.

There are two keys inside the Info.plist file for an application which store version information:

What’s the difference between the two?

  • CFBundleVersion: This is the version information used by macOS to determine which version is the most recent version of an application.
  • CFBundleShortVersionString: This is the version information which is displayed to the user in a Finder window or a Get Info window.

There is no requirement in macOS that both the CFBundleVersion and CFBundleShortVersionString keys in the Info.plist file contain the same version information. What can happen as a result? Let’s take a look at that the context of some Microsoft applications which record different information in the Info.plist file for those two keys. For more details, please see below the jump.

For this example, I installed the following Microsoft apps on a macOS 26.1.0 VM:

  • Microsoft Excel.app
  • Microsoft PowerPoint.app
  • Microsoft OneNote.app
  • Microsoft Outlook.app
  • Microsoft Word.app
  • OneDrive.app
  • Windows App.app

For each app, I checked the following:

  • CFBundleShortVersionString
  • CFBundleVersion
  • Reported version on the Mac

Microsoft Excel.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft PowerPoint.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft OneNote.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft Outlook.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

Microsoft Word.app

  • CFBundleShortVersionString: 16.103.3
  • CFBundleVersion: 16.103.25113013
  • Reported version on the Mac: 16.103.3

OneDrive.app

  • CFBundleShortVersionString: 25.209.1026
  • CFBundleVersion: 25209.1026.0002
  • Reported version on the Mac: 25.209.1026

Windows App.app

  • CFBundleShortVersionString: 11.2.9
  • CFBundleVersion: 2810
  • Reported version on the Mac: 11.2.9

As you can observe, what’s reported in these two fields can be very different. How does this affect Jamf Pro? Up until Jamf Pro 11.23.0, only one of those keys in the Info.plist file was being used to get version information for a macOS application:

CFBundleShortVersionString

This was reported as part of a computer inventory record as the following field:

  • Version

The Version reporting also has matching smart group and advanced computer search criteria:

  • Application Version

However, version information for Microsoft applications in particular were often being reported in Jamf Pro using the information contained in the following key:

  • CFBundleVersion

If CFBundleVersion and CFBundleShortVersionString did not have the same version information, now you have a problem because what you see in Jamf Pro for version information for that Microsoft app and what you’re seeing reported in a Finder window for version infomation are two different things. To help address this, as of Jamf Pro 11.23 two new reporting fields as well as matching smart group and advanced computer search criteria have been added:

  • Bundle Short Version
  • Bundle Version

Here’s how they’re mapping to the keys in the application’s Info.plist file:

  • Bundle Short Version: CFBundleShortVersionString
  • Bundle Version: CFBundleVersion

The existing Version reporting field and matching Application Version smart group and advanced computer search criteria have not gone away, since up until Jamf Pro 11.23 it was your only option. The new reporting information has been added and does not replace previously gathered data, so nothing in anyone’s existing version reporting setup should break.

Here’s how it should look as of Jamf Pro 11.23.0 for a computer inventory record’s application listing:

  • Name
  • Version
  • Bundle Short Version
  • Bundle Version
  • Path
  • App Store

Note: The Bundle Short Version and Bundle Version fields may initially be blank for devices which have not sent in an inventory update since Jamf Pro was upgraded to 11.23.

The matching smart group and advanced computer search criteria are as follows:

  • Applications inventory listing: Bundle Short Version
  • Smart and advanced computer search criteria: Application Bundle Short Version

  • Applications inventory listing: Bundle Version
  • Smart and advanced computer search criteria: Application Bundle Version

Suppressing the Welcome to macOS Tahoe 26 screen with a configuration profile on macOS Tahoe 26.1.0

Over the years, Apple has introduced a number of screens which appear the first time you log into a Mac. Among those which appear following an upgrade to macOS Tahoe 26 is the Welcome to macOS Tahoe 26 screen, which provides a walkthrough of selected new features available in macOS Tahoe.

I have not found a way to suppress this screen using a defaults command, but it is possible to suppress the Welcome to macOS Tahoe 26 screen on macOS Tahoe 26.1.0 using a configuration profile. For more details, please see below the jump.

The relevant preference domain and key values are below:

  • Preference domain: com.apple.SetupAssistant.managed
  • Key: SkipSetupItems
  • Value: OSShowcase

The profile is available on GitHub via the link below:

https://github.com/rtrouton/profiles/blob/main/SkipOSShowcaseSetup

Disabling the floating thumbnail preview for screenshots on macOS Tahoe

One of the features available when taking screenshots is the option to see a floating thumbnail preview of the screenshot before it gets saved to the location you’ve chosen to save screenshots to. This option is enabled by default and looks like this on macOS Tahoe.

  1. Screenshot is taken.
  2. Floating thumbnail preview appears and slides off-screen.
  3. Screenshot file icon appears (in this example, screenshots are being saved to the desktop.)

I prefer to have this option turned off, as I’d rather have the ability to select and work with the screenshot file right away in place of waiting for the floating thumbnail to appear and disappear.

Fortunately, this option can be turned off in a couple of ways. The first is through using Screenshot.app, which is included with macOS.

When you use Screenshot.app, it will provide a toolbar for selecting screenshot image or screencapture movie options. As part of that toolbar, there is an Options button.

When you click the Options button, you get a menu where one of the selections is Show Floating Thumbnail. If you unselect that, the floating thumbnail preview no longer appears when taking screenshots or making screencapture movies.

You can also disable this from the command line, by running the two following commands in Terminal:


/usr/bin/defaults write com.apple.screencapture show-thumbnail -bool false
killall SystemUIServer

view raw

gistfile1.txt

hosted with ❤ by GitHub

In my case, I wanted to disable the floating thumbnail preview on my Macs so I’ve written a profile which can enforce this. It’s available via the link below:

https://github.com/rtrouton/profiles/blob/main/DisableScreenshotFloatingThumbnail

Deploying custom DDM declarations using Blueprints in Jamf Pro

One of the management options Jamf Pro provides with Blueprints is the ability to create and deploy custom declarative declarations to managed Macs. What this means that if you can manually build the JSON payload for a DDM declaration, you should now be able to deploy it using Blueprints even if Jamf does not have a Blueprint template available yet for that declaration. This is conceptually similar to Jamf Pro’s ability to deploy custom configurations in management profiles to macOS using the Application & Custom Settings management profile payload

For more details, please see below the jump.

For this example, I am using the following custom declaration to set disk management settings. Blueprints also has a declaration template for disk management, but using a custom declaration to deploy disk management settings allows the use of an example where that declaration is all in one JSON payload and doesn’t need to refer to other components (an example of a declaration which needs to refer to other components is a service configuration declaration deploying a sudo configuration, where files need to be downloaded from an external source.)


{
"Restrictions": {
"ExternalStorage": "Disallowed",
"NetworkStorage": "Disallowed"
}
}

In this case, the declaration is setting the following disk management settings:

  • External storage devices are disallowed: the system can’t mount any external storage.
  • Network storage is disallowed: the system can’t mount any storage from a network server.

As of Jamf Pro 11.22.1, there is not a Blueprints template available for creating blueprints which deploy custom declarations so the blueprint will need to be configured manually. To do this, use the following procedure:

1. Log into Jamf Pro.

2. Select Blueprints

3. Click the Create blueprint button.

4. You should see an unconfigured Blueprint. Click where it says Untitled blueprint and provide a name.

For this example, I’m using Disk Management Settings.

5. Scroll down in the list on the left-hand side of the browser window to locate the Custom Declarations component.

6. Click on the Custom Declarations component and drag the Custom Declarations component to the Declaration group section.

Drag custom declarations component.

7. Once added to the Declaration group section, click anywhere on the Custom Declarations component to open it for editing.

When the Custom Declarations component opens for editing, there is an explanation about custom configurations and a warning that using custom configurations can come with risks and to carefully test all configurations built using the Custom Declarations component before deploying them in a production environment.

8. Once you’ve read through the warnings and understand the potential risks, click the Get Started button.

9. Click the Add item button. The custom declarations settings will open and show a set of placeholder settings.

Before continuing further, if you have not already, I strongly recommend reading the Creating a Custom Declaration Blueprint documentation to understand all the parts involved in creating a custom declaration using the Custom Declarations Blueprints component.

In the Kind field of the Custom Declarations component, there are two choices:

  • Configuration
  • Asset

Configuration: Settings and policies that define how devices should be configured, functioning similarly to profile payloads.
Asset: Data used by configurations such as certificates, configuration files, scripts or other data supported for use in a DDM declaration.

For our example, we’re choosing Configuration.

In the Channel field of the Custom Declarations component, there are two choices:

  • System
  • User

System: applies management settings to the device.
User: applies management settings to the MDM-managed user or users.

For our example, we’re choosing System.

In the Type field, enter the declaration type.

For our example, we’re using the declaration type for disk management: com.apple.configuration.diskmanagement.settings

In the Payload field, enter the configuration of the declaration in JSON format. For our example, here’s the configuration we’re using:


{
"Restrictions": {
"ExternalStorage": "Disallowed",
"NetworkStorage": "Disallowed"
}
}

10. Once the Kind, Channel, Type and Payload settings have been configured and verified, click the Update button.

11. Verify that all settings look as expected, then click the Save button.

12. At this point, you should have a blueprint which has all settings configured but where no target scope has been set. To scope this blueprint, go to the Scope section and click the arrow button.

13. Select a Jamf Pro smart or static group. For this example, I’m selecting a static group named Disk Management Deployment Group.

14. Once everything has been configured, click the Deploy button to deploy the changes to the Macs you want to manage.

15. Once deployed, the Blueprints screen in Jamf Pro should show the newly-created Disk Management Settings Blueprint as being deployed.

On your managed devices, you can verify that the new custom declaration has been deployed by clicking on the enrollment profile, then scrolling to the bottom. In the case of this example, because you’re deploying a disk management configuration you should see a Device Declarations section with a listing for Disk Management.

If you click on the Disk Management listing, it should report the following:

  • External Storage Restriction: Not Allowed
  • Network Storage Restriction: Not Allowed

Granting a local user account administrator rights on a Mac which only has accounts with standard user rights

I recently saw a post on LinkedIn where the poster had apparently removed all accounts which were assigned administrator rights on the Mac from the local group named admin on macOS and then had difficulty recovering from this state.

On macOS, membership in the admin group is what grants administrator rights, so now this meant that the Mac only had accounts which had standard user rights.

There have been methods available in the past for fixing this from the Recovery environment which used the chroot command line tool in the Recovery environment to change the active filesystem from the Recovery environment to the Mac’s regular boot drive, then run the dseditgroup command line tool to re-add one or more local user accounts to the admin group on the boot drive.

However, it looks like the chroot command does not work currently in the Recovery environment available to macOS Tahoe on Apple Silicon Macs. When launched, it reports an error and then exits.

With the chroot command line tool no longer working in Recovery, that would seem to close off most avenues to re-adding users to the admin group for Apple Silicon Macs running macOS Tahoe. However, after some research, I’ve discovered an alternative method which uses the sudo command line tool. For more details, please see below the jump.

This method uses the ability on macOS for the sudo command line tool to use properly formatted configurations for the sudo tool, where those configuration files are stored as plaintext files in the /private/etc/sudoers.d directory. The following process will create a sudo configuration which is stored in a plaintext file named fixadmin which will be created from the Recovery environment and stored in the /private/etc/sudoers.d directory in the writeable part of the Mac’s boot drive.

What this configuration file will do is allow a user account which otherwise has standard user rights to run the dseditgroup command line tool with root privileges, which in turn will enable the user account to add itself (or another account) to the local group named admin using the dseditgroup command line tool. The end result of this process is that administrator rights will be granted to the account being added to the admin group.

Pre-requisites:

Once the pre-requisites are handled, use the following process to create the configuration file for the sudo command line tool:

1. Boot to the Recovery environment.
2. If required, enter the FileVault recovery key to access the Recovery environment.

3. If you needed to unlock using the FileVault recovery key, once unlocked choose the Exit to Recovery option.

4. From the Recovery window, click on Disk Utility.

5. Verify that the Data volume is mounted.

If the Data volume is not mounted, click the Mount button in Disk Utility to mount it.

If FileVault is enabled, you will need to enter the password of a FileVault-enabled account to mount the Data volume.

6. Quit out of Disk Utility.
7. Open Terminal using the Utilities menu.

8. Run the following command to create a file named fixadmin in the /Volumes/Data/private/etc/sudoers.d directory:


touch /Volumes/Data/private/etc/sudoers.d/fixadmin

view raw

gistfile1.txt

hosted with ❤ by GitHub

9. Run the following command to edit the /Volumes/Data/private/etc/sudoers.d/fixadmin file using the nano command line text editor:


/Volumes/Macintosh\ HD/usr/bin/nano /Volumes/Data/private/etc/sudoers.d/fixadmin

view raw

gistfile1.txt

hosted with ❤ by GitHub

10. Add the following line to the fixadmin file:


username_goes_here ALL = (ALL) /usr/sbin/dseditgroup

view raw

gistfile1.txt

hosted with ❤ by GitHub

This file should be formatted as follows:

A. Enter the account shortname of the user account that you want to grant rights to in order to run the dseditgroup command line tool using sudo.
B. Hit the Tab key to create a tabbed space
C. Enter the rest of the line:

ALL = (ALL) /usr/sbin/dseditgroup

For example, if the user account in question has the account shortname of username, the entry should look like this:


username ALL = (ALL) /usr/sbin/dseditgroup

view raw

gistfile1.txt

hosted with ❤ by GitHub

11. Verify that the line is formatted correctly.
12. To save changes, press the Control key and the X key together (Control + X) on your keyboard.
13. You will be prompted to save unsaved changes. When prompted, save the changes.

14. Boot back to macOS.
15. Log in as the account to which you granted rights to run the dseditgroup command line tool using sudo.
16. Open Terminal and run the following command to grant admin rights to a specified user account:


sudo dseditgroup -o edit -a username_goes_here -t user admin

view raw

gistfile1.txt

hosted with ❤ by GitHub

For example, if the user account in question has the account shortname of username, the command should look like this:


sudo dseditgroup -o edit -a username -t user admin

view raw

gistfile1.txt

hosted with ❤ by GitHub

17. Verify that the desired account now has administrator rights.

18. Remove the fixadmin file from the /private/etc/sudoers.d directory by running the following command:


sudo rm /private/etc/sudoers.d/fixadmin

view raw

gistfile1.txt

hosted with ❤ by GitHub

Enabling Touch ID authentication for sudo using Blueprints in Jamf Pro

One of the capabilities Apple added in macOS Sonoma was a pluggable authentication module (PAM) configuration option to enable Touch ID authentication for the sudo tool which would persist and not be overwritten by software updates.

To enable this option, there is a /etc/pam.d/sudo_local.template file on macOS Sonoma and later which appears as shown below:


# sudo_local: local config file which survives system update and is included for sudo
# uncomment following line to enable Touch ID for sudo
#auth sufficient pam_tid.so

view raw

gistfile1.txt

hosted with ❤ by GitHub

Copying the /etc/pam.d/sudo_local.template file to /etc/pam.d/sudo_local and uncommenting the indicated line allows Touch ID to work as authentication for the sudo tool.


# sudo_local: local config file which survives system update and is included for sudo
# uncomment following line to enable Touch ID for sudo
auth sufficient pam_tid.so

view raw

gistfile1.txt

hosted with ❤ by GitHub

A number of Mac admins have written scripts to apply this PAM configuration to Macs, but there didn’t seem to be a good way to handle this without scripting. However, as part of Apple’s unveiling of Declarative Device Management (DDM) at WWDC 2023, Apple announced that DDM management included the ability to manage sets of tamper-resistant system configuration files for different system services. As of this date, the following services built into macOS can be managed this way:

  • sshd
  • sudo
  • PAM
  • CUPS
  • Apache httpd
  • bash
  • zsh

Jamf Pro’s Blueprints supports managing these services via the Service configuration files component. Since enabling Touch ID authentication for sudo is managed using a PAM configuration file, that means that enabling Touch ID authentication for the sudo tool can be accomplished via Blueprints. For more details, please see below the jump.

By default, macOS Tahoe 26.1 ships with a /etc/pam.d/sudo_local.template file that looks like this:


# sudo_local: local config file which survives system update and is included for sudo
# uncomment following line to enable Touch ID for sudo
#auth sufficient pam_tid.so

view raw

gistfile1.txt

hosted with ❤ by GitHub

To prepare the desired PAM configuration, you can use the process described below:

  1. Make a copy of the /etc/pam.d/sudo_local.template file to a convenient location.
  2. Uncomment the last line
  3. Save the file and rename it to a file named sudo_local.

The newly-created sudo_local file should appear similar to what’s shown below:


# sudo_local: local config file which survives system update and is included for sudo
# uncomment following line to enable Touch ID for sudo
auth sufficient pam_tid.so

view raw

gistfile1.txt

hosted with ❤ by GitHub

To deploy this change with Blueprints, three things are needed.

1. A zip file which contains both the directory and file structure of the configuration file in question.

The PAM configuration file is stored in the /etc directory, with a directory inside named pam.d, with a file inside the pam.d directory named sudo_local, so a zip file containing a directory named etc, with a directory inside named pam.d, with a file inside the pam.d directory named sudo_local, is needed for this.

For this example, we’ll name the zip file as enable_touch_id_for_sudo.zip.

2. The SHA-256 hash of the zip file

You can use the sha256sum command line tool to get the SHA-256 hash of the zip file, so using a command similar to the one shown below should provide that information:


sha256sum /path/to/enable_touch_id_for_sudo.zip

view raw

gistfile1.txt

hosted with ❤ by GitHub

Assuming our SHA-256 hash is 0ac032ffc0d173ec102ee2d580de2c7511ab59606a56239b8c9a0fd88452c368, you should see output like this when you run the command above:


username@ZPVVQN9WPH ~ % sha256sum /Users/username/Desktop/sudoers_configuration.zip
0ac032ffc0d173ec102ee2d580de2c7511ab59606a56239b8c9a0fd88452c368 /Users/username/Desktop/sudoers_configuration.zip
username@ZPVVQN9WPH ~ %

view raw

gistfile1.txt

hosted with ❤ by GitHub

3. A place to download the zip file from which allows downloading without authentication.

For this example, I’ve set up an S3 bucket in Amazon Web Services named 75d831079efb4d02ada44eed4f8ae093 and set the enable_touch_id_for_sudo.zip file to be publicly accessible from that S3 bucket.

Once I have all the above available, I can set up a Blueprint in Jamf Pro to deploy the Touch ID PAM configuration file as a Service configuration file.

1. Log into Jamf Pro.
2. Select Blueprints
3. Click on Service configuration.

4. Give it a name when prompted. For this example, I’m using Touch ID PAM Configuration.

5. Select a Jamf Pro smart or static group. For this example, I’m selecting a static group named Touch ID PAM Configuration Deployment Group.

6. Provide the necessary information to download the enable_touch_id_for_sudo.zip file. For this example, the following information is being used:

Once everything has been configured, click the Deploy button to deploy the changes to the Macs you want to manage.

Once deployed, the Blueprints screen in Jamf Pro should show the newly-created Touch ID PAM Configuration Blueprint as being deployed.

On your managed devices, you can verify that the new Touch ID PAM configuration has been deployed by clicking on the enrollment profile, then scrolling to the bottom. You should see a Device Declarations section, with a listing for Configuration Files: com.apple.pam.

If you click on the Configuration Files: com.apple.pam listing, it should provide the path to the tamper-resistant directory where it stored the new Touch ID PAM configuration file. This should be the following location:

/private/var/db/ManagedConfigurationFiles/com.apple.pam

Inside that directory will be the etc directory with a directory inside named pam.d, with a file inside the pam.d directory named sudo_local file that you configured for the Blueprint’s zip file. The complete file path to the new Touch ID PAM configuration should be the following:

/private/var/db/ManagedConfigurationFiles/com.apple.pam/etc/pam.d/sudo_local

You will not be able to write to this location, as it is protected by System Integrity Protection (SIP), but you should be able to read from the file and verify the contents are what’s expected.

You should also be able to verify that Touch ID authentication is now working when you use the sudo command line tool.

Hat tip to my colleague Matt Vlasach for coming up with and sharing this idea of enabling Touch ID authentication for sudo using Blueprints.

Session videos from Jamf Nation User Conference 2025 now available

Jamf has posted the session videos for from Jamf Nation User Conference 2025, including the video for my “MDM and DDM 101” session.

For those interested, all of the the JNUC 2025 session videos are available on YouTube, though it doesn’t appear that there’s a dedicated YouTube playlist at this point. For convenience, I’ve linked my session here.

Deploying software update declarations for automatic OS upgrades using Blueprints in Jamf Pro

One of the management options Jamf Pro provides with Blueprints is sending DDM declarations to managed Macs run macOS software updates automatically. This is comparable to Jamf Pro’s managed software update functionality, which also provides the ability to send a DDM declaration to run software updates.

Previously, the only option for deploying software update declarations via Blueprints was to specify an individual OS version. Now there is a new option for upgrading the OS version to the latest version a particular Mac can support.

For those familiar with Jamf Pro’s managed software update functionality, the new software update declaration functionality provides the following update options:

  • Download and schedule to install
  • Latest version based on device eligibility

The Latest version based on device eligibility functionality in the managed software update functionality tells the managed Mac to download and install the latest version of macOS that a particular Mac can support. The Blueprints software update declaration functionality provides that same experience, where you can do the following:

  • Set that you want the managed Macs to update their OS version to the latest version of macOS a particular Mac can support.
  • Set a deadline that you want to have your Macs updated by.

For more details, please see below the jump.

For this example, I have the goal of updating managed Macs to the latest available version of macOS. As of November 6 2025, that is the following version of macOS:

  • macOS 26.1

I want to have them all updated within one day of the release of new OS versions, with the install time set as being 6:00 PM (18:00)

I can set up a Blueprint in Jamf Pro to deploy a software update declaration to enforce this using the following procedure:

1. Log into Jamf Pro.

2. Select Blueprints

3. Click on Update software to latest version.

4. Give it a name when prompted. For this example, I’m using Update to latest macOS version.

5. Select a Jamf Pro smart or static group. For this example, I’m selecting a static group named Managed Software Update Deployment Group.

6. In the Software Updates section, I’m choosing the following settings:

  • Enforcement type:
    • Latest OS version
  • Days after release to enforce update:
    • 1
  • Install at (local device time):
    • 18:00

7. Once all the information has been entered and verified to be correct, click the Save button.

8. Click the Deploy button to deploy the changes to the Macs you want to manage.

Note: The days after release refers to the date that the latest version was released. In the case of macOS 26.1, that was on the following date:

  • November 3, 2025

By setting the Days after release to enforce update setting to 1 day, that means that Macs receiving this software update declarations will have this deadline to install macOS 26.1:

  • November 4, 2025 at 18:00 (6:00 PM in the Mac’s local time zone)

Devices receiving the Blueprint will detect that they are past the deadline set by the software update declaration if the Blueprint is being deployed on the following date:

  • November 6, 2025

In this case, the Mac will try to update as soon as possible and provide notifications that it is past the deadline for updating.

Once deployed, the Blueprints screen in Jamf Pro should show the newly-created Update to latest macOS version Blueprint as being deployed.

Note: The options available via Blueprints for software declarations are the ones Apple has specified for software update declarations. For more information about this topic, please see the following link:

https://support.apple.com/guide/deployment/software-update-declarative-configuration-depca14ecd4d/web

On your managed devices, you can verify that the new service background task configuration has been deployed by clicking on the enrollment profile, then scrolling to the bottom. In the case of this example, you should see a Device Declarations section with a listing for Required Software Update. The Required Software Update listing will include the OS version number for the required update.

If you click on that listing, you should see the details of the software update declaration. In this case, since the latest available version of macOS is 26.1, that’s what is listed as part of the software update declaration.

From the user’s perspective, they should see a Notifications center notification appear with two available options:

  • Details
  • Update

When you click the Details button, you should see behavior similar to what’s shown below:

When you click the Update button, you should see behavior similar to what’s shown below:

Note: The video above has been edited to artificially reduce the amount of time the OS update took to run. Run time of the pre-edited video was 12 minutes 33 seconds.