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:
Jamf Pro’s Blueprints supports managing these services via the Service configuration files component. Let’s see how this looks, using management of the sudo command line tool‘s configuration as an example. For more details, please see below the jump.
By default, macOS 15.5.0 ships with a sudo configuration file that looks like this:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Sample /etc/sudoers file. | |
# | |
# This file MUST be edited with the 'visudo' command as root. | |
# | |
# See the sudoers man page for the details on how to write a sudoers file. | |
## | |
# Override built-in defaults | |
## | |
Defaults env_reset | |
Defaults env_keep += "BLOCKSIZE" | |
Defaults env_keep += "COLORFGBG COLORTERM" | |
Defaults env_keep += "__CF_USER_TEXT_ENCODING" | |
Defaults env_keep += "CHARSET LANG LANGUAGE LC_ALL LC_COLLATE LC_CTYPE" | |
Defaults env_keep += "LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME" | |
Defaults env_keep += "LINES COLUMNS" | |
Defaults env_keep += "LSCOLORS" | |
Defaults env_keep += "SSH_AUTH_SOCK" | |
Defaults env_keep += "TZ" | |
Defaults env_keep += "DISPLAY XAUTHORIZATION XAUTHORITY" | |
Defaults env_keep += "EDITOR VISUAL" | |
Defaults env_keep += "HOME MAIL" | |
Defaults lecture_file = "/etc/sudo_lecture" | |
# Remove this line to log successful sudo launches. May contain sensitive | |
# information passed as arguments to the command | |
Defaults !log_allowed | |
## | |
# User alias specification | |
## | |
# User_Alias FULLTIMERS = millert, mikef, dowdy | |
## | |
# Runas alias specification | |
## | |
# Runas_Alias OP = root, operator | |
## | |
# Host alias specification | |
## | |
# Host_Alias CUNETS = 128.138.0.0/255.255.0.0 | |
# Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0 | |
# Host_Alias SERVERS = master, mail, www, ns | |
# Host_Alias CDROM = orion, perseus, hercules | |
## | |
# Cmnd alias specification | |
## | |
# Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less | |
## | |
# User specification | |
## | |
# root and users in group wheel can run anything on any machine as any user | |
root ALL = (ALL) ALL | |
%admin ALL = (ALL) ALL | |
## Read drop-in files from /private/etc/sudoers.d | |
## (the '#' here does not indicate a comment) | |
#includedir /private/etc/sudoers.d |
We’re going to change the following line:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
To now read as follows:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
otheruser ALL = (ALL) ALL |
What this change does is remove the ability for all users of the admin group to use all available privileges for the sudo tool. In its place, now only a user account with the account shortname of otheruser has all available privileges for the sudo tool.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Sample /etc/sudoers file. | |
# | |
# This file MUST be edited with the 'visudo' command as root. | |
# | |
# See the sudoers man page for the details on how to write a sudoers file. | |
## | |
# Override built-in defaults | |
## | |
Defaults env_reset | |
Defaults env_keep += "BLOCKSIZE" | |
Defaults env_keep += "COLORFGBG COLORTERM" | |
Defaults env_keep += "__CF_USER_TEXT_ENCODING" | |
Defaults env_keep += "CHARSET LANG LANGUAGE LC_ALL LC_COLLATE LC_CTYPE" | |
Defaults env_keep += "LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME" | |
Defaults env_keep += "LINES COLUMNS" | |
Defaults env_keep += "LSCOLORS" | |
Defaults env_keep += "SSH_AUTH_SOCK" | |
Defaults env_keep += "TZ" | |
Defaults env_keep += "DISPLAY XAUTHORIZATION XAUTHORITY" | |
Defaults env_keep += "EDITOR VISUAL" | |
Defaults env_keep += "HOME MAIL" | |
Defaults lecture_file = "/etc/sudo_lecture" | |
# Remove this line to log successful sudo launches. May contain sensitive | |
# information passed as arguments to the command | |
Defaults !log_allowed | |
## | |
# User alias specification | |
## | |
# User_Alias FULLTIMERS = millert, mikef, dowdy | |
## | |
# Runas alias specification | |
## | |
# Runas_Alias OP = root, operator | |
## | |
# Host alias specification | |
## | |
# Host_Alias CUNETS = 128.138.0.0/255.255.0.0 | |
# Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0 | |
# Host_Alias SERVERS = master, mail, www, ns | |
# Host_Alias CDROM = orion, perseus, hercules | |
## | |
# Cmnd alias specification | |
## | |
# Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less | |
## | |
# User specification | |
## | |
# root and users in group wheel can run anything on any machine as any user | |
root ALL = (ALL) ALL | |
otheruser ALL = (ALL) ALL | |
## Read drop-in files from /private/etc/sudoers.d | |
## (the '#' here does not indicate a comment) | |
#includedir /private/etc/sudoers.d |
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 sudo configuration file is stored in the /etc directory and the file is named sudoers, so a zip file containing a directory named etc, with a file inside the etc directory named sudoers, is needed for this.
For this example, we’ll name the zip file as sudoers_configuration.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:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sha256sum /path/to/sudoers_configuration.zip |
Assuming our SHA-256 hash is a0bac25baf21f3e507120940d65d6ff856472baf6d1b778aafe7c076023cd9d0, you should see output like this when you run the command above:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
username@ZPVVQN9WPH ~ % sha256sum /Users/username/Desktop/sudoers_configuration.zip | |
a0bac25baf21f3e507120940d65d6ff856472baf6d1b778aafe7c076023cd9d0 /Users/username/Desktop/sudoers_configuration.zip | |
username@ZPVVQN9WPH ~ % |
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 sudoers_configuration.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 sudo configuration file as a Service configuration file using the following procedure:
1. Log into Jamf Pro.
2. Select Blueprints
3. Click the Open button for Service configuration.
4. Give it a name when prompted. For this example, I’m using Sudo Configuration.
5. Select a Jamf Pro smart or static group. For this example, I’m selecting a static group named Sudo Configuration Deployment Group.
6. Provide the necessary information to download the sudoers_configuration.zip file. For this example, the following information is being used:
Once everything has been configured, Jamf Pro should inform you that you have undeployed changes. Click the Deploy button to deploy the new sudo configuration to the Macs you want to manage.
Once deployed, the Blueprints screen in Jamf Pro should show the newly-created Sudo Configuration Blueprint as being deployed.
On your managed devices, you can verify that the new sudo configuration has been deployed by clicking on the MDM enrollment profile, then scrolling to the bottom of the screen. You should see a Device Declarations section, with a listing for Configuration Files: com.apple.sudo.
If you click on the Configuration Files: com.apple.sudo listing, it should provide the path to the tamper-resistant directory where it stored the new sudo configuration file. This should be the following location:
/private/var/db/ManagedConfigurationFiles/com.apple.sudo
Inside that directory will be the etc directory containing the sudoers file you configured for the Blueprint’s zip file. The complete file path to the new sudo configuration should be the following:
/private/var/db/ManagedConfigurationFiles/com.apple.sudo/etc/sudoers
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 only the otheruser user account can use the sudo command line tool.