The Next Age of the Mac

Yesterday marked the day where Mac OS X has been available to the public longer than the previous Macintosh operating system (known as ‘Mac OS’ [with a space] or ‘Classic’ towards the end of its lifetime).

This has been noted by many on Twitter and on the Mac news sites.

I do think it is a milestone worth noting. Darwin/Mac OS X/OS X/macOS has served as a stable foundation not just for the Mac but also for the iPhone, iPad, Apple TV, Apple Watch and now even the HomePod.

However, I have also seen comments that the “next age of the Mac” will have to happen soon, because Mac OS X/macOS is so old now. That statement really bugs me.

Mac OS X was not Apple’s first attempt at an operating system to replace ‘Classic.’ In the late 80s and early 90s it was already obvious that the Macintosh System architecture would not scale to modern CPUs and work requirements. An application that crashed would normally take down the entire OS. You had to assign memory to an application manually. System Extensions would frequently conflict with each other and also crash the entire system. There was no concept protected memory or segregating processes from each other. There were no multiple users with access privileges in the file system.

The operating system had been designed for a 8MHz 16-bit CPU with 128KiloByte of RAM where every cycle and every byte had to count! Apple was now in the PowerPC era and the requirements for the system were vastly different.

Taligent, Copland and Gershwin were successive efforts and promises for a better system that each failed for various reasons. Some of the parts of each did find their way into Mac OS. Then Apple bought NeXT (and Steve Jobs) and the rest is history.

So, for most of the nineties, it was obvious that the classic Macintosh system needed replacement something newer. Microsoft had Windows NT and alternative operating systems like BeOS and NeXTStep were showing the way. By the time Mac OS X arrived, classic Mac OS was old, but users needed to hang on to it because of critical applications and workflows.

Now, in 2018, macOS might be as old as Classic was in 2001, but it doesn’t feel as old. Like the original system for the Macintosh 128K, Mac OS X 10.0 was designed for entirely different hardware and use cases. In 2001 only the high-end PowerMacs had two CPUs. Mac OS X required at least 64MB of RAM (a 500 fold increase over the original Macintosh). Laptop batteries would last for three to four hours under the most ideal circumstances. Digital photography and video was still vastly inferior to analog. Music came from CDs. Screens had far lower resolutions and security meant requiring a password to login. Wifi was new, and hardly ubiquitous. Bluetooth was brand new and used in expensive cell phones which where used for talking, not data. There was no App Store.

All of this would change, sometimes quickly, over the next years.

Mac OS X and Apple as a whole were able to adapt to these changes. Hardware and software were optimized to deal with video and media. Multi-tasking and threading were improved as multiple CPUs and cores became cheaper and common, even in laptops, tablets and phones. As mobility and power consumption got more important the hardware and software was adapted to take that into account. Security and privacy became more and more important and integrated in the operating systems and file systems.

Apple used Mac OS X as the basis for iPhone OS, porting a Unix system to a phone. There has also been much back and forth of software and technology between the two systems (or three or four). macOS and iOS have evolved, changed and adapted in a way that the classic Mac OS in the 80s and 90s did not.

I am not claiming that macOS in its current form is perfect and cannot or should not be improved. In a few days at WWDC Apple will show us how they plan to further evolve macOS and iOS to adapt further to the future and I am looking forward to it.

When you wonder ‘what is next for the Mac’ you are ignoring that in 2018, the Mac and macOS are not an isolated platform any more.

All my Apple devices talk with each other and exchange data. My Mac shows me which website I am reading on the phone. My phone unlocks my watch and my watch can unlock my Mac. I can create a note on my tablet, add pictures from the phone and finish it on my Mac. I can read messages on my Mac or have them read to me by the phone through my headphones. When I say ‘Hey Siri’ the devices that can hear me decide among themselves which should answer.

macOS and the Mac are now just a part of larger ‘system.’ This system runs on different devices: from my headphones to the iMac on my desk to servers on Apple’s data centers. It includes custom silicone, software, and data stores and relies on communication and local cached data and protocols to communicate locally and all around the world.

The digital hub has grown to the ‘digital net’, where everything is connected and (ideally) everything is available everywhere.

Not all of this works all the time yet. Why the iPhone still cannot pickup a playlist from where I paused it on the Mac is still an absolute mystery to me.

When this new system fails, we get very frustrated, there is no ‘shell’ we can drop down to, to fix a thing. It is often quite impossible to even figure out in which part of this net of devices and services the problem is occuring.

macOS, iOS, iCloud, Siri, HomeKit, Bluetooth and Wifi, Messaging, email, App Stores and third party apps, devices and services like Google, Office 365, 1Password, etc.

Hardware, software and services. All have to work together in the digital net.

When Apple introduced Mac OS X one of the main benefits was that you could easily manage multiple users on one device.

Now, 17 years later, we have multiple devices per user.

I want is the Mac to keep evolving and adapting with my digital net, so I can continue to use its strengths (large screen, CPU/GPU power, storage, high throughput I/O) and supplement its weaknesses (not mobile, few sensors) with the other devices and services. I don’t want the Mac to fall behind or out of the digital net.

I want to stop having to think about whether something I want to do is a “Mac” task or a “phone” task, but whether I’d rather have a keyboard and a large screen or maybe prefer to do it in a chair in the backyard or by talking with Siri, while walking somewhere. Not all those options will work for every task, but I’d like the options to increase. And I want the Mac to be part of that.

I don’t expect a new age for the Mac. I don’t want a new age for the Mac. That would be too small, too myopic, too limiting.

The next age of the Mac is with the digital net and it has already begun.

BBEdit at 25 and why I still use it

BBEdit turned 25 last week! Belated Happy Birthday!

I am not shy that BBEdit is my favorite text editor. I don’t remember when exactly I got my first copy, but it must have soon after it came out. I have been using it one form or another since then.

It is usually the first application I install on a new Mac. I don’t bother to add the icon to my dock because it is open all the time. (and it doesn’t hog memory)

Recently, someone asked me why I prefer BBEdit. I was caught a bit off-guard but gave my honest answer: habit.

However, this answer doesn’t really do BBEdit much justice. Now I realize it is a habit formed over two-and-a-half decades. When BBEdit came out I was a student and used it for LaTeX documents, shell scripts and Fortran code on my PowerBook 160.

Back then Mac text files preferred a different line break character (carriage return: \r) than Unix (line feed: \n) and Windows (line feed and carriage return: \r\n). BBEdit was able to read, convert and write all of them.

BBEdit transitioned to PowerPC. It was one of the first applications to have a native Mac OS X version (the Mac/Unix text file compatibility was really valuable then). BBEdit made the Intel transition and is ready for the 64-bit only future of macOS.

All along the way, BBEdit has always stayed true to the Mac environment, however the Mac changed. When you expect native ‘Mac-like’ behavior that’s how BBEdit behaves. It supports AppleScript, but also has powerful command line tools. It will parse a binary property list to XML and it will ask for authorization to read and edit root-owned files.

But, BBEdit also has always been a great way to talk with things outside of the Mac.

When I have to edit files over ssh I will grudgingly use nano or (in desperate situations) vi, but then I remember that BBEdit has direct editing over sftp.

BBEdit has supported three version control systems I have used over the years and (so far) survived two.

I have built web pages in BBEdit, trawled through truly gigantic log files, written code in secveral languages, and documents in LaTeX, Markdown and various other file formats. Some of the files were even just plain text.

If you have read anything I have written on this website, or my books, it very likely started out as a draft in BBEdit.

Right now I am writing a book with the experimental Markua language on LeanPub. In BBEdit, of course.

The advantage of text files is that they can be opened everywhere. Trying out a new text editor has virtually no barrier. Over the years I have used and tried out uncountable different editors and many of them had some features I liked. Right now I have Atom and Sublime Text on my Mac, as well. Those are great tools with some wonderful features. However, they are not native to the Mac and that often adds friction to the workflow.

Now that I have thought about it, habit is only part of the answer. It is not just habit, it is a trust they have built and earned over more than two decades.

When Apple does their next transition, I can expect BBEdit to be right there with me, still not sucking. As long as there is still a need to edit text files on Macintosh/Mac OS/Mac OS X/OS X/macOS or whatever it is going to be called, I am looking forward to the next 25 years of working with BBEdit.

Weekly News Summary for Admins — 2018-05-18

BBEdit turned 25 years old this week! Congratulations! (I will have a few thoughts on that later.)

I also posted a sneak peak on my next book: “macOS Installation for Apple Administrators”

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

#! On Scripting OS X

📰News and Opinion

🐦MacAdmins on Twitter

🔨Support and HowTos

🤖Scripting and Automation

♻️Updates and Releases

🎧To Listen

📚Support

I do not have any ads on my webpage or this newsletter. However, if you want to support me and this website, then please consider buying one (or both) of my books. (Imagine it’s like a subscription fee, but you also get one or two useful books on top!)

If you have already bought and read the books, please leave a review on the iBooks Store. Reviews are important to help new potential readers make the purchase decision. Thank you (again)!

macOS Installation: Strange New World

This is a section out of my next book: “macOS Installation for Apple Administrators”
This book is not quite finished and I don’t have a fixed timeline, other than “soon…” I will post more about this book as things get more concise.

High Sierra came with many changes for Mac administrators. Some of them were anticipated, some of them weren’t.

When Apple announced APFS would be deployed to every OS by 2018, Mac Admins thought that would be the main challenge and the reason for sweeping changes in the structure and functionality of macOS.

At the same time it was obvious that Apple liked the way MDM was in the center of all management for iOS and wanted to have it play a similar role for macOS. The extent how far Apple would push it was unclear.

While APFS has certainly come with some challenges, mainly for managed FileVault users, it was not the “Macnarök” that we were expecting.

I am not including these links to make fun of the authors – quite the opposite. At the time there was justified anxiety about the future of macOS adminstration and these posts (and many others) put this into words. I believe that because of MacAdmins blogging and presenting about their concerns and anxiety, talking with Apple Reps and filing bugs, as a community, were able to influence the course Apple is taking. It is definitely a slow, frustrating and opaque process, but not entirely fruitless.

However, other new “features” of High Sierra such as UAKEL and, later with 10.13.4, UAMDM provide their own set of hurdles administrators have to clear.

These are the main challenges for macOS deployment:

  • Imaging is Dead, Long Live the Installer
  • MDM is Essential
  • Secure Boot

Let’s look at these challenges and some solutions to them in detail.

Imaging is Dead, Long Live the Installer

Imaging has been the means to quickly and reliably install macOS to clients. It could scale from an external drive for a few clients to a NetBoot infrastructure for large deployments.

Apple has come out explicitly and said that imaging in most forms is not recommended or supported any more.

In the early days imaging meant building a ‘Golden Master’ image with all configuration and software ‘baked in,’ which then would be deployed to all the Macs. Creating this ‘Golden Master’ image was a lot of work and the result quite fragile and error-prone. Macs would usually be kept on a specific version of ‘the image’ for months or a year without updates.

Since the process of manually building the Golden Master was tedious and error-prone, administrators started to automate the process. Tool chains of packages, scripts and other tools could build the master image (or most of it) automatedly.

InstaDMG was one of the first tools to do this. AutoDMG is a direct successor of this approach and still useful for many tasks today.

The same packages and scripts that automated the configuration of the master image could be used to install and update software on ‘live’ Macs. Management tools, like Munki, Casper (now Jamf Pro) and Filewave, can deploy updates to clients automatically without user interaction. As work was moved from preparing the master image to maintaining the live system, the master image became thinner and thinner.

This resulted in the ‘thin imaging’ approach, where the image only had the minimal ‘base OS’ plus enough configuration to connect it to the management system. Once the Mac booted the management system takes over. Imaging would only be used to wipe a Mac and lay down a ‘base image.’

While this approach is slower than monolithic imaging, it is more flexible and allows to keep the system and software on the client continually updated, without having to re-image.

Some workflows even skipped the imaging entirely. When you get a Mac out of the box it already has macOS installed, all you need is to configure it to connect to your management system, which will take care of the rest.

Some administrators had already moved to ‘thin’ imaging or ‘no-imaging’ workflows before High Sierra and pronouncements that ‘Imaging is Dead!’ have been made years ago. Administrators using thin imaging or no-imaging workflows will find they are better prepared for the High Sierra installation workflows.

Mac administrators now have to build new workflows based on the Apple’s supported installation methods for High Sierra. These all rely on the macOS Installer application in one form or another.

The supported means of installing macOS High Sierra are:

  • the macOS Installer application
  • a bootable installer on an external drive
  • the macOS Recovery System
  • a NetInstall image built with Apple’s System Image Utility

Using the macOS installer application to upgrade a system from 10.12 is straightforward enough and similar to what was possible with the startosinstall command since OS X Yosemite 10.11.

The main challenge are ‘nuke-n pave’ workflows, where the system on a Mac is erased and overwritten with a new system.

This workflow is easy with traditional imaging. In fact, it was easier and faster to just image over a system, rather than upgrade.

The startosinstall --eraseinstall option added in 10.13.4 makes an installer based ‘nuke’n pave’ workflow possible with the macOS Installer application.

In the new High Sierra world of Mac deployment, we face the same challenge: how do you connect an ‘out-of-the-box’ macOS to your management system.

Apple’s answer to that is clearly DEP.

MDM is Essential

DEP will tell a freshly installed Mac which MDM server is ‘responsible’ for it. The MDM server can then use the InstallApplication MDM command to install and configure a management agent, which together with the mdmclient performs the remaining configuration and software installation.

Up until 10.13 Mac administrators could ignore and not use an MDM for Mac deployment and management. There were a few useful features, but there are also many tasks an MDM cannot do or that a local agent can do better.

With High Sierra MDM became essential to manage and support UAKEL. In the early versions of High Sierra, merely being connected to an MDM would disable UAKEL, starting with 10.13.4 UAKEL can be managed with a configuration profile which has to be pushed from a user approved MDM.

Prepare for changes to kernel extensions in macOS High Sierra – Apple Support

Like supervison for iOS devices, UAMDM adds an extra level of approval and provides an additional level of control over the macOS client device. UAMDM will be required for more and more essential functionality going forward.

However, as the name implies, a ‘user approved’ MDM needs to be interactively approved by a user at some time during deployment which creates an enormous challenge for automated workflows.

Apple claims that DEP enrolled devices are automatically user-approved. However, even the DEP enrollment still requires user interaction in the Setup Assistant.

Also DEP is not available in all regions and it may not be possible for organizations to add all existing Macs to their DEP account. DEP also requires Apple DEP servers to be accessible. So during this transition phase and for some other situations, Mac administrators have to have a non-DEP workflow solution to get a UAMDM enrolled device.

Secure Boot

Finally the iMac Pro introduces a new system controller with secure boot. By default all external means of booting an iMac Pro are disabled.

NetBoot/NetInstall is not supported on the iMac Pro at all. You can enable booting off external drives, but the process to do so is quite convoluted and cannot be automated. So for administrators, the option is fairly useless.

With the startosinstall command administrators can achieve the necessary management steps from within the local system. You can either upgrade the existing system or ‘nuke’n pave’ with the eraseinstall option.

However, the eraseinstall option is limited to systems that are already on 10.13 with an APFS file system. On the iMac Pro you can safely make that assumption, but for ‘older’ Macs and systems you usually cannot.

So administrators need a second workflow for systems and hardware that cannot run the eraseinstall option (yet).

The Recovery system, external installer volume or NetInstall are the Apple Supported means which can ‘nuke’n pave’ a Mac. NetInstall is the only means that can be automated.

However, there are other solutions such as Imagr or a modified DeployStudio workflow which can achieve the same goal using the macOS Installer application and startosinstall.

The New macOS Deployment Workflow

Deployment strategies and workflows are as varied and individual as the organizations that use them. But with the challenges listed above, I believe we can state a few pieces that are necessary for a new deployment workflow for High Sierra and hopefully going forward.

Enrolling a ‘new’ Mac

First, any deployment workflow should be designed to start with a clean ‘out-of-box’ macOS. This way the same workflow can be applied to new Macs and to Macs that were just re-installed.

At the end of the installation workflow the Mac is enrolled and user-approved with your management system, so that it can take over and perform the remaining configuration and installation. All configuration steps should be controlled from the management system and be executed independently of which deployment workflow was used.

Deployment Workflows from an out-of-box Mac

DEP is the Apple-preferred means of connecting a new device to your MDM. Even when you require a non-DEP workflow for older Macs you should implement a DEP workflow. It is likely that Apple may make DEP enrollment mandatory in the future.

However, right now in the transition phase, you will need a second workflow for machines that cannot be registered with DEP.

For the non-DEP workflow, you can choose between manual enrollment, which happens after the user has booted and logged in for first time, or some sort of ‘side-loading’ where you add the MDM and management system configuration to a system, before it even boots for the first time.

For sideloading you can boot to Recovery and install software on the system volume. (Bootstrappr)

On Macs that still support NetBoot, you can also use tools like NetInstall, Imagr or DeployStudio. Either way you should do this before first boot of the system.

UAMDM requires user interaction to approve the management in some form or another. This is a change from previous deployment workflows which could be ‘fully automated.’

You will have to plan for this user interaction. In some cases, such as individual-use devices, the approval of the management will be part of standard first setup and will be done by the end user. In other situations such as classroom setups, it will be harder to make this part of the workflow.

Some management systems let you scope software installations and configurations depending on criteria reported from the device. In this case you can set up your workflow so that installations that rely on UAMDM (third party kernel extensions) are deferred until the MDM is approved.

Either way, the end-result of each of these paths should be a Mac that is enrolled (user-approved) with your MDM where the management system is installing, configuring, maintaining the system and software.

Restoring a Mac to ‘new’

You will also need a second set of workflows that bring a Mac from any state (even a broken one) back to the ‘out-of-box’ state so that you can start over (or retire it).

Restoring a Mac to new

The first option uses the startosinstall --eraseinstall command. This is easiest to automate and works on new hardware like the iMac Pro. However, it will not work on Macs without APFS systems and older versions of macOS.

The Macs that cannot use the eraseinstall option, however, can use NetInstall or a similar NetBoot based tool. You can use the macOS Install application and startosinstall with Imagr and DeployStudio, so this combination will run the installer and can make sure the firmware is up to date as well.

Note that the workflows and tools for restoring a Mac are also used to ‘sideload’ the agent configuration on to a Mac. You can add the MDM/agent configuration to the restore workflow to save some steps here. However, since NetBoot based workflows are transition solutions to support ‘old’ Macs and systems, your deployment workflows need to work with ‘out-of-box’ systems as well as pre-configured systems.

In the transition phase until all hardware supports eraseinstall you will need both workflows available.

You should also have documentation, training, and support articles to instruct administrators, techs, and users to restore a Mac to ‘out-of-box’ state with (Internet) Recovery or an external boot drive. While this should be an option of last resort, it will be necessary in situations where a Mac cannot boot otherwise.

Obviously, these are very high level views of the workflow and the devil is very much in the details of the implementation. Even a book can only skim the surface of any implementation. Nevertheless, once you understand and accept this framework, the necessary detailed steps become obvious, though not necessarily easy.

Many thanks and credit need to go to Anthony Reimer, whose excellent presentation at MacAD.UK 2018 helped me sort through my own thoughts on this topic.

Weekly News Summary for Admins — 2018-05-11

Not so busy this week. I have the impression we are entering the calm before the WWDC storm.

I had already mentioned the 20-year anniversary of the iMac last week. However, I have to add this post by Horace Dediu of Asymco where he posted the best infographics on the topic.

I have added two more conferences to the list. X world in Sydney and MacTech in Los Angeles. I put up this list because there were quite a few announcements and schedules published in the last two weeks. I do not plan to make this a permanent section as the MacAdmins Podcast team already has a great list of events nearly every week.

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

#! On Scripting OS X

🎤Conferences

📰News and Opinion

🐦MacAdmins on Twitter

🐞Bugs and Security

🔨Support and HowTos

🤖Scripting and Automation

♻️Updates and Releases

🎧To Listen

📚Support

There are no ads on my webpage or this newsletter. If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!

If you want to support me and this website even further, then consider buying one (or both) of my books. It’s like a subscription fee, but you also get a useful book or two extra!

If you have already bought and read the books, please leave a review on the iBooks Store. Reviews are important to help new potential readers make the purchase decision. Thank you (again)!

PLIST Editor

I recently stumbled over a Property List Editor on the Mac AppStore that I had not seen before.

PLIST Editor

My favorite graphical property list editor so far is PlistEdit Pro from FatCat Software. True to its name, PlistEdit Pro has a few nice “pro” features that PLIST Editor lacks: Preference Browsing, Browser windows, AppleScript, Plist Structure definitions

However, PLIST Editor comes in at a much lower price point (US$3.99 on the Mac AppStore). Its feature set covers all the necessities. It can open property list files with file extensions other than .plist (for those pkginfo or recipe files you want to edit) and supports drag and drop and undo and even the macOS versioning system.

PLIST Editor can open and save XML and binary property lists and can open legacy ASCII/Openstep property lists. To convert from binary to XML or vice versa you have to duplicate a file.

It does not have a command line tool to quickly open a property list file from Terminal. This is a limitation imposed by being on the AppStore. However, you can use the open command:

$ open -a 'PLIST Editor' sample.plist
You can add an alias to your shell profile to simplify this: `alias pacifist='open -a "PLIST Editor"'`

Overall it seems like a useful tool that serves its purpose well. It is being actively updated. So, go and check it out!

Dutch MacAdmins Meeting: 8 June

The (ir)regular meeting of Dutch MacAdmins will happen again! We will meet on June 8, 14:00-17:00 at SAP Netherlands in ‘s-Hertogenbosch. Main topics will be:

  • WWDC news and how it affects MacAdmins
  • Mac management at SAP
  • anything else you may want to bring up

Join #thenetherlands channel on MacAdmins Slack for questions, feedback and great discussions or if you want to volunteer to present.

Registration (Eventbrite, free)

Demystifying `root` on macOS, Part 4 —The Authorization Database

Beyond the Shell

sudo allows you to gain super user privileges from the interactive shell. launchd, installer Packages, management systems and other tools will run scripts as root when required. This covers many cases where administrators need to influence the system on macOS.

However, for most users, macOS is exclusively the graphical interface. Users can authorize to perform certain tasks when they are administrators, like unlocking a Preference Pane or running an installer package.

These tasks are not controlled by sudo but by a separate mechanism. The data for that mechanism is stored in the authorization database.

Here there be Dragons!

As mentioned in earlier parts of this series, many pieces of macOS assume users have administrator accounts. This might not be a possible or useful configuration in your environment. But you still need to provide access to some privileges without giving a user full administrator accounts and access.

However, if you find yourself frequently editing the authorization database, you should re-evaluate your approach. Future macOS updates might change privileges or rules and then your heaviliy modified setup will need to be adpated. Small modifications or granting users admin privileges will be the the least fragile configuration going forward with future macOS releases.

What is it?

The active authorization database lives in sqlite3 database files in /var/db/auth.db.

You can use the sqlite3 command or another tool to read the database directly.

$ sudo sqlite3 /var/db/auth.db .dump

You can use this database access to change the settings directly. However, this is not recommended. The only way sanctioned by Apple to access and change the authorization database is through the security authorization command.

This layer of abstraction allows Apple to change the underlying data store, while keeping tools and frameworks that access the data same.

The authorization database is intialized from the property list file /System/Library/Security/authorization.plist. In older versions of macOS administrators could replace this file with a modified version and delete the database files to have the modified property list initialize the database with the new settings. However, in current versions of macOS this file is protected by SIP, so this strategy is no longer useful.

However, the authorization.plist file is still useful to look at the default values and get an idea of how the authorization database is configured and works. Since there is quite a lot of data in this file, it is best to open it in a graphical property list editor such as Xcode or PlistEdit Pro.

The authorization property list consists of two main dictionaries: rights and rules. There are also comment fields distributed all through the file, which provide some context to what the individual elements are for.

rights designate a certain context that permits a certain action, group of actions or access to configure some part of the os. The names of the rights follow a hierarchy and are denoted in reverse DNS notation.

This website has an overview of all the rights and rules from the authorization.plist. More importantly it shows which rights and rules are available in which version of macOS.

How it works

Within the dictionary for a given right you can find the requirements that a user needs to fulfill to gain the right. There are two main classes: user and rule.

(There is also a third possible value for the class: evaluate-mechanisms will test multiple mechanisms in order. This is used for more complex processes such as the login window.)

The user class will verify whether the user asking to gain the right is in a particular user group. Usually this is the admin group. for example you can inspect the configuration of the system.preferences.datetime right with:

$ security authorizationdb read system.preferences.datetime
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>allow-root</key>
    <true/>
    <key>authenticate-user</key>
    <true/>
    <key>class</key>
    <string>user</string>
    <key>comment</key>
    <string>Checked by the Admin framework when making changes to the Date &amp; Time preference pane.</string>
    <key>created</key>
    <real>522083506.22018802</real>
    <key>group</key>
    <string>admin</string>
    <key>modified</key>
    <real>522083506.22018802</real>
    <key>session-owner</key>
    <false/>
    <key>shared</key>
    <false/>
    <key>timeout</key>
    <integer>2147483647</integer>
    <key>tries</key>
    <integer>10000</integer>
    <key>version</key>
    <integer>1</integer>
</dict>
</plist>
YES (0)

(The YES (0) at the end of the command’s output means that retrieving the data was successful.)

You can also look for the system.preferences.datetime entry in the authorization.plist. This tells us that when a user clicks on the lock in the ‘Date & Time’ preference pane the system will ask for authentication (authenticate-user is true) to check if the user a member of the admin group.

Read the com.apple.configurationprofiles.userprofile.trustcert right to see an example for a rule based right:

$ security authorizationdb read com.apple.configurationprofiles.userprofile.trustcert
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>class</key>
    <string>rule</string>
    <key>comment</key>
    <string>Install user configuration profile with certificate requiring trust change.</string>
    <key>created</key>
    <real>529239529.937994</real>
    <key>modified</key>
    <real>529239529.937994</real>
    <key>rule</key>
    <array>
        <string>authenticate-session-owner-or-admin</string>
    </array>
    <key>version</key>
    <integer>0</integer>
</dict>
</plist>
YES (0)

Rather than defining the approving criteria in the right itself, this right references the authenticate-session-owner-or-admin rule. This name is already quite self-explanatory. However, we can also read the definition of the rule:

$ security authorizationdb read authenticate-session-owner-or-admin
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>allow-root</key>
    <false/>
    <key>authenticate-user</key>
    <true/>
    <key>class</key>
    <string>user</string>
    <key>comment</key>
    <string>Authenticate either as the owner or as an administrator.</string>
    <key>created</key>
    <real>522083506.22018802</real>
    <key>group</key>
    <string>admin</string>
    <key>modified</key>
    <real>522083506.22018802</real>
    <key>session-owner</key>
    <true/>
    <key>shared</key>
    <false/>
    <key>timeout</key>
    <integer>2147483647</integer>
    <key>tries</key>
    <integer>10000</integer>
    <key>version</key>
    <integer>0</integer>
</dict>
</plist>
YES (0)

Requests to grant a right are logged. When you are unsure what the name of right is you can perform/unlock the right or task in the interface and then read the log with:

$ sudo log show --style syslog --predicate 'subsystem == "com.apple.Authorization" && eventMessage CONTAINS[c] "validating credential"' --last 1h

This will list the rights (and rules) that were requested in the last hour.

(Thanks to Erik Berglund on the MacAdmins Slack for showing me how to do this.)

Changing Behavior

You can use the security authorizationdb command to change rights and rules in the authorization database.

WARNING: you can really mess up your system and make it unusable with the wrong settings in the authorization database. You should not test these commands on your (or anybody else’s) work machine. You should do your experimentation and testing on a virtual machine, where you can quickly revert the system to a known working state. You should only use these commands on production Macs when they have been thoroughly tested.

You need super user privileges to change the authorization db. I will use sudo for the interactive examples.

The easiest way to change behavior is to change the right to a different preset rule. The most permissive rule is allow which allow any user the right and not even prompt for authorization.

When you change the ‘Date & Time’ right with:

$ sudo security authorizationdb write system.preferences.datetime allow
Password:
YES (0)

And then open the ‘Date & Time’ preference pane with any user. You will see the pane is unlocked by default.

This may be just a bit too permissive. A more useful rule to use is the authenticate-session-owner-or-admin rule, which will prompt for authentication, and accept the currently logged in user (session-owner) or any admin. This provides for some security so that other people cannot walk up and change the current user’s settings.

$ sudo security authorizationdb write system.preferences.datetime authenticate-session-owner-or-admin
YES (0)

This will allow the any user to unlock the preference pane in their own session. Note that the dialog to unlock does not prefill the user’s name and the text in the dialog still asks for an ‘administrator’s name and password’. So this may be confusing for users. Proper documentation for the user’s affected will help.

Another use case for this rule is to allow administrator account to unlock a locked screen in another user’s session (particularly useful in lab or classroom settings).

$ sudo security authorizationdb write system.login.screensaver authenticate-session-owner-or-admin
Password:
YES (0)

Now, any admin user can unlock any other user’s locked screen. This will of course drop them in that user’s login session so the admin’s have to be responsible with this privilege.

When you take a look through the rules, you will notice that some start with authenticate- and other with is-. The difference is that the authenticate- rules will prompt for user name and password, while the is- rules will grant the privilege when the user satisfies the rule with out a prompt.

There are also some rules whose names end in -nonshared. These have the shared key set to false. This means that these rules will not share credentials with other requests for authentication. Shared credentials will not prompt multiple times for the same credentials in a certain time (the timeout, usually 300 seconds/5 minutes). More sensitive settings are usually not shared.

Exporting and importing privileges

Changing the rule is a straightforward and fairly safe way to change a right’s behavior. When a rule fits your requirements, you should probably use a rule.

However, sometimes you need more fine-grained control of a right. For this you can export a right to a property list file, modify this and re-import it.

For example, say you do not want to grant every user access to a certain right but just a certain group of users even though they are not administrators. Common examples for this would be developers, teachers or lab techs. So, in our example, we create a group named techs:

$ sudo dseditgroup -o create -n . -r "Lab Techs" techs

to be safe we will nest the admin group in the techs group so that members of admin also gain all the rights of techs:

$ sudo dseditgroup -o edit -a admin -t group techs

and add the example user beth

$ sudo dseditgroup -o edit -a beth techs

You can verify that everything worked with:

$ sudo dseditgroup -o read techs
dsAttrTypeStandard:GeneratedUID -
        F9EBB33D-8A71-45EE-A65D-4DBBFF421B49
dsAttrTypeStandard:RecordName -
        techs
dsAttrTypeStandard:AppleMetaNodeLocation -
        /Local/Default
dsAttrTypeStandard:GroupMembers -
        87EE7744-5872-47C1-9574-D247D3DD4D5C
dsAttrTypeStandard:PrimaryGroupID -
        501
dsAttrTypeStandard:NestedGroups -
        ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000050
dsAttrTypeStandard:RealName -
        Lab Techs
dsAttrTypeStandard:GroupMembership -
        beth
dsAttrTypeStandard:RecordType -
        dsRecTypeStandard:Groups

Now we can assign this group to a right. Our example will be the system.preferences.energysaver right. First export it to a property list file:

$ security authorizationdb read system.preferences.energysaver > energysaver.plist
YES (0)

Then change the value of the group key in the property list file to techs:

$ /usr/libexec/PlistBuddy -c "set group techs" energysaver.plist

If you want to learn more about working with property list files, I have written a book on it: ‘Property Lists, Preferences and Profiles for Apple Administrators’

And re-import the modified property list to the authorization database:

$ sudo security authorizationdb write system.preferences.energysaver < energysaver.plist

This alone is not sufficient to unlock the Energy Saver preference pane. When you look at the log with command from above, you can see that unlocking the energy saver pane requires the system.preferences right as well. You can modify this the same way:

$ security authorizationdb read system.preferences > system.preferences.plist
YES (0)
$ /usr/libexec/PlistBuddy -c "set group techs" system.preferences.plist
$ security authorizationdb write system.preferences < system.preferences.plist

Scripting

When scripting this setup you do not have to go through the export/import cycle but can directly import a prepared property list file or here doc:

Summary

There are many levels of access privileges in macOS. Most of them are controlled by different users and groups.

The super userroot exists on macOS like any other unix, but logging in as root is disabled by default as a security measure. The sudo command allows for interactive super user privileges in a shell. There are other ways administration scripts can be launched with super user privileges, such as LaunchDaemons, management systems etc.

The authorization database controls access to elevated rights in the macOS UI. You can modify it as an admin, but should do so with care.

Demystifying root on macOS: Conclusion

This ends my series on the super user in macOS. I hope it clarifies some confusing terms and configurations. As admins we have to use these privileges regularly. But, as the saying goes: “With great power comes great responsibility.”

Understanding how things work and how they affect the system will help you understand what to do when and how to avoid unexpected consequences.

Weekly News Summary for Admins — 2018-05-04

The conference registration season has begun! Three conferences started their registrations this week. There should be one for you. (The one for me is MacSysAdmin, where I will be presenting among many other great speakers this year.)

We got quite a few security related posts this week. Most important is a note from Twitter that they may have left your password unencrypted on their servers. So go change that right now, if you have not already.

In happier news, the iMac turns 20 this week!

Also in last week’s email I forgot set the subject and the email was sent out with tinyletter’s default subject line. My apologies for the confusion both for you, the readers and any email rules/filters you may have set up.

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

#! On Scripting OS X

🎤Conferences

📰News and Opinion

🐦MacAdmins on Twitter

🐞Bugs and Security

🔨Support and HowTos

🤖Scripting and Automation

♻️Updates and Releases

📺To Watch

🎧To Listen

📚Support

I do not have any ads on my webpage or this newsletter. However, if you want to support me and this website, then please consider buying one (or both) of my books. (Imagine it’s like a subscription fee, but you also get one or two useful books on top!)

If you have already bought and read the books, please leave a review on the iBooks Store. Reviews are important to help new potential readers make the purchase decision. Thank you (again)!

Demystifying `root` on macOS, Part 3 — `root` and Scripting

sudo is very useful when working interactively in the shell. However, when you are scripting workflows then you don’t want to encounter the interactive prompt for authentication.

sudo in Scripts

You will write scripts that require root privileges to perform their tasks. Many novice scripters will simply add the sudo command to their scripts. For example:

#!/bin/bash

timeserver="time.apple.com"

echo "Setting Time Server to: $timeserver"

# note: sudo is superfluous
sudo systemsetup -setnetworktimeserver "$timeserver"
sudo systemsetup -setusingnetworktime on

When you invoke this script from the command line, it will actually work as expected, since the first sudo will prompt the password and the second sudo will use the cached credentials.

In many cases where the script already has root privileges, it will work also, because sudo when run as root will not prompt for authorization again.

However, when this script is sent with Remote Desktop or run in a different context without user interaction to authorize sudo, the script will stall and eventually fail.

In most contexts, the scripts should already be running with root privileges so sudo in the script is not necessary.

#!/bin/bash

timeserver="time.apple.com"

echo "Setting Time Server to: $timeserver"

systemsetup -setnetworktimeserver "$timeserver"
systemsetup -setusingnetworktime on

You should not use sudo in your management scripts. When commands inside a script require root privileges, you should invoke the entire script with sudo:

$ sudo ./settimeserver.sh

or you deploy and execute the script through other methods that provide root privileges. (Remote Desktop: run as user root, installation scripts, LaunchDaemons, management systems, etc.)

Testing for root Privileges in Scripts

When you write scripts that require root privileges, you may want to test whether it is actually running as root early in the script or exit gracefully with an error or warning. As usual with Unix, there are many ways to achieve this, but the recommended one is to check the EUID (effective user id) environment variable. For the root user the EUID is 0.

#!/bin/bash

# test if root
if [[ $EUID -ne 0 ]]; then
    >&2 echo "script requires super user privileges, exiting..."
    exit 1
fi

# continue with important things here
echo "I am root"

Running a Process as Another User

Most administrator scripts are run in a context where they run with super user privileges. Often they require root privileges.

On the other hand, when you need to affect settings or processes in a user’s context or login session, you may need to run commands as a specific user from a script running as root. It’s the opposite problem of gaining root privileges.

You can use sudo -u user command or su user -c command to run a command as a different user. However, the launchd man page warns us:

On Darwin platforms, a user environment includes a specific Mach boot strap subset, audit session and other characteristics not recognized by POSIX. Therefore, making the appropriate setuid(2) and setgid(2) system calls is not sufficient to completely assume the identity for a given user. Running a service as a launchd agent or a per-user XPC service is the only way to run a process with a complete identity of that user.

So it is safest use the Darwin/macOS native mechanism to launch a process as another user. Enter launchctl. You can use the the launchctl asuser verb to execute a script or command as a different user.

uid=$(id -u "$username")
launchctl asuser "$uid" /path/to/command arguments

The launchctl command takes a user’s numerical ID or UID rather than the short name as an argument. You can get a user’s UID with the id -u username command.

Note that launchctl asuser does not launch the command in the context of a new shell environment. You cannot rely on environment variables being set in that context. This is especially relevant for the PATH.

Note also that the asuser verb of launchctl is listed among the deprecated functions of launchctl. However, there is no replacement for the functionality yet.

Getting the Current User

Most of the time you will not know which user you need to run as, when you write a script, but need to run as the ‘currently logged in user’. There are many unix-y ways of determining the current user. However, once again there are edge cases in macOS where some of the traditional methods fail. (Mainly concerning Fast User Switching)

The ‘official’, method is to use the SystemConfiguration framework, and from a script this is easiest from within python:

loggedInUser=$(/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");')

(Enduring thanks to ‘macmule’ who documented this years ago.)

This will return the currently active user, even when multiple users are logged in with Fast User Switching. When no user is logged and the system is logging in the value returned will be "". Your scripts have to cover this case as well.

You can use this code snippet as a template:

# get the current user
loggedInUser=$(/usr/bin/python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");')

# test if a user is logged in
if [[ $loggedInUser != "" ]]; then
    # get the uid
    uid=$(id -u "$loggedInUser")
    # do what you need to do
    launchctl asuser "$uid" /path/to/command arguments
fi

AppleScript

AppleScript has a special function when invoking shell commands for gaining super user privileges. When you run a shell command from AppleScript with the do shell script command you can add with administrator privileges to have the script prompt for admin user authentication and run the command as root:

do shell script "whoami"
do shell script "whoami" with administrator privileges

Will run like this:

    do shell script "whoami"
       --> "armin"
    do shell script "whoami" with administrator privileges
     --> "root"

Like with sudo the credentials for the first command run with administrator privileges will also be cached, so you will not get mulitple prompts, unless the script runs for a long time.

This is useful for providing tools and workflows from within AppleScript for interactive use. However, as with sudo you have to keep in mind that some contexts in which a script may be run does not allow for user interaction and then you have to find other means of elevating privileges.

AppleScript is often used to communicate with other applications and/or the user interface. However, when run with root privileges AppleScripts are often prohibited from connecting to other process or present user interface, such as dialogs. When you really need to do this, you have to use launchctl asuser to change the user the script is run as:

launchctl asuser "$uid" /usr/bin/osascript -e 'display dialog "Do you really want to do this?"

Beyond the Shell

sudo allows you to gain super user privileges from the interactive shell. LaunchDaemons, installer Packages, management systems and other tools will run scripts as root when required. This covers many cases where administrators need to influence the system on macOS.

However, for most users, macOS is exclusively the graphical interface. Users can authorize to perform certain tasks when they are administrator users, like unlocking a Preference Pane or running an installer package.

These tasks are not controlled by sudo but by a separate mechanism. The data for that mechanism is stored in the authorization database, which we will cover in the next post.