A strange thing happened last Friday: while I was putting together last week’s news summary, HP printer connections on Macs all over started showing strange error messages. First suspicions were on the Xprotect update published a day before, but then HP had to admit that they had ‘accidentally’ revoked a certificate that was still very much in active use. As usual, Howard Oakley and Mr Macintosh covered the issue in much detail.
macOS Big Sur is still in beta did a surprising step from “11.0 beta 10” to “11.0.1 beta 1.” This probably means that there will be new Mac hardware soon that ships with a version of 11.0, and immediately prompt for an update when they are run for the first time.
Even though the 2020 conference season is not over yet—you can register for Everyworld here—Jamf has gone ahead and announced that JNUC 2021 will also be virtual. This will planning uncertainty for the organizers, speakers, attendees. Virtual JNUC 2020 was already a great event, but there were many aspects that can be improved on and I am happy that Jamf is taking the time necessary to take that on.
Alexander Blach: “TIL: you can use a Lightning to USB3 Camera Adapter to migrate data to a new iPhone using a wired connection (no Wi-Fi) while also charging both iPhones from a single power adapter.”
Tim Perfitt: “Yes, this is probably from Xcode, but Xcode isn’t running nor is an iOS simulator. I have no idea what to answer here and I am an Apple developer since before Swift! How would I know if I should trust this? If I deny it, there could be issues with development” (Thread)
Mr. Macintosh: “As to why we are getting 11.0.1 This could mean that 11.0 is GM for Apple Silicon Macs currently in production. When they arrive in customers hands, 11.0.1 will show as an available update. Doing it this way hides the AS installer data so we can’t look at the new DeviceIDs.”
Erik Gomez: “I think it’s less to hide things and more that Big Sur just isn’t ready.”
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
Bit of a lull in the news between the previous iOS 14 and forthcoming macOS 11 releases. Apple is shipping the iPhone 12, iPhone 12 Pro, and iPad Air 4 this week and the devices look good in the reviews.
No reason to be bored, though. You probably haven’t caught up with the sessions from Virtual JNUC and MacSysAdmin Online, yet! (To be honest, there are some Campfire sessions I have not gotten around to watch yet.)
Patrick Wardle: “Previously, a comprehensive macOS firewall could be implemented via a Network Kernel Extension (kext) Apple deprecated kexts, giving us Network Extensions….but apparently (many of) their apps / daemons bypass this filtering mechanism. Are we ok with this!?” (Thread, Michael Tsai)
Joel Rennich: “Let’s talk attestation and boxes and what that means for generating keys on an iOS device. For a while folks, myself included, have been really interested in getting Apple to provide attestation statements about a key being in the Secure Enclave.” (Thread)
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
In one of the recent betas for macOS 11.0 Big Sur, the xpath command line tool changed. Big Sur uses the 5.28 version of the tool, while Catalina defaults to the 5.18 version.
These aren’t version numbers for xpath but actually version numbers for perl. When you look at all the xpath executables you will see that they are actually perl scripts.
The perl environment will choose the xpath script ending in the version number matching the perl version automatically. The plain xpath script with no version number serves as fallback.
Either way, Catalina runs perl 5.18 and xpath5.18 and Big Sur runs perl 5.28 and the newer xpath5.28 script.
The problem here is that the newer xpath script has a different syntax:
Either version will use stdin when there is no file name, but the newer xpath requires the query string to be labeled with a -e argument.
So, your scripts that are using the xpath tool to parse XML data, will fail in Big Sur!
The easiest fix is to change the script to use the new syntax, i.e. insert the -e at the right place and if necessary re-arrange the arguments. But then the script will fail on older versions of macOS. Many of us will have to write our scripts to be able to support the latest and older versions of macOS for a transition time. For some MacAdmins the transition time can be several years.
Since Big Sur still includes xpath5.18, another solution is to just hardcode the version whenever you use xpath. But this will only defer the problem to a future version of macOS, when the 5.18 version of the script is removed.
A better solution is to check the version of macOS that is being used and to call xpath with the proper for each version:
if [[ $(sw_vers -buildVersion) > "20A" ]]; then
xpath -e "//query" "/path/to/file"
else
xpath "/path/to/file" "//query"
fi
This will call xpath with the new syntax on Big Sur (20A) and higher and use the older syntax otherwise. (Why I use the build version.)
If you are using xpath in multiple locations in a script, using this code everywhere will become tedious. In the Installomator script, we often use xpath to parse the download URL out of an XML file. As of now, there are nine occurences of xpath, but as more people contribute to Installomator, this is likely to go up.
There is a nice sleight-of-hand trick you can use to make the script resilient to change in Big Sur, without having to touch every use of xpath in the code.
At the beginning of the script (before the first use of xpath) insert this function:
xpath() {
# the xpath tool changes in Big Sur
if [[ $(sw_vers -buildVersion) > "20A" ]]; then
/usr/bin/xpath -e "$@"
else
/usr/bin/xpath "$@"
fi
}
Since the shell interpreter (bash or zsh) will prefer a local function over an external executable, this function will now be used for all uses of xpath in the remaining code. We don’t need to touch them at all.
Within the function, we tell the interpreter to use the executable by using its full path.
In Installomator, we pipe data into xpath, so there are no files involved and the above works fine.
When you use xpath with files, it gets a bit more complicated, because the order of the arguments changed between the versions.
With the assumption that the current use is xpath [filename] query we can use the following:
xpath() { # [filename] query
# xpath in Big Sur changes syntax
if [[ -n $2 ]]; then
local query=$2
local filename=$1
else
local query=$1
local filename=""
fi
if [[ $(sw_vers -buildVersion) > "20A" ]]; then
/usr/bin/xpath -e "$query" "$filename"
else
/usr/bin/xpath "$filename" "$query"
fi
}
You will want to make a note for some point in the future, when you finally can drop Catalina support, to revisit these scripts and clean them up for the new syntax.
I have not yet encountered other command line tools that change in a similar way in Big Sur. If you do, you should be able to use a similar function to simplify the transtition.
I had been fairly busy with both the JNUC and MacSysAdmin presentations, but work on Installomator has continued.
I also did an overview of what Installomator does in my MacSysAdmin Online presentation: “Practical Scripting”.
Many of these new features have been provided from others, either through GitHub issues, pull requests, or through comments in the #installomator channel on MacAdmins Slack. Thanks to all who contributed.
What’s new in v0.4:
you can now set script variables as an argument in the form VARIABLE=value. More detail on this in the README file, ‘Configuration from Arguments.’
change downloadFromGit to match file types better
implemented a workaround for changed behavior of xpath in Big Sur
added an option prompt_user_the_kill to BLOCKING_PROCESS_ACTION which will kill the process after the third unsuccessful attempt to quit
added several new labels for total of 116
Get the script and find the instructions on the GitHub repo.
If you have any feedback or questions, please join us in the #installomatorchannel on MacAdmins Slack.
We got the expected new iPhones 12 this week, all four models, and a new HomePod mini. I am actually looking forward to a smaller iPhone 12 mini to replace my iPhone X.
In other (some would say good) news, macOS 11 Big Sur was not released this week, but we got beta 10 instead. There is an expectation for another Apple event introducing the first Apple Silicon based Macs in the upcoming weeks and that would be an obvious time to release Big Sur to everyone.
William Smith: “Tomorrow (October 13, 2020): Support for Microsoft Office 2016 for Mac — any version 16.16.x and lower— ends. No more software updates to fix: • Bugs • Compatibility problems • Security vulnerabilities – No macOS Big Sur support”
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
For now this has been a quiet week. Since Apple announced another event next week, possibly a calm before the storm. After Apple announced iOS 14 with 24 hours notice, MacAdmins are understandably a bit nervous. Also, no new betas this week (so far).
On the other hand, after JNUC last week, we had MacSysAdmin this week. I have not been able to watch all presentations yet, but those that I have seen have been worth it and I am looking forward to the rest.
In other news, this newsletter just passed the 1000 email subscribers number! Thank you all for reading, and on to the next thousand!
Eliz: “Please don’t say just “Hello” in a chat #NoHello” (Read thread and links for background. I find myself doing that a lot, too, and have resvoled to do better.)
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
Virtual JNUC 2020 was on and had some great sessions. If you have registered you can (re-)view the sessions in the portal for three more weeks and then they will be moved to the Jamf YouTube channel. Thanks to everyone who presented a session, I have not been to watch the all (not even close) but will try to over the next few weeks. Thanks also, to everyone who watched my session live and for all the kind feedback I have already gotten. You can find the slides, notes and links for my session here.
Steve Hayman: “Your grep one-liner du jour. Count how many words of each length appear in the /usr/share/dict/words dictionary. for n in $(jot 25); do printf "%2d letter words: " $n; grep -E "^.{$n}\$" /usr/share/dict/words | wc -l; done” (Thread)
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
The session should be available “on demand” in the JNUC2020 portal within an hour or so. I believe all sessions will be available on YouTube eventually and will update the links then!
I hope you enjoyed the session, and if you have any more questions or comments, then I am @scriptingosx on the MacAdmins Slack and Twitter.
AppleScript on macOS is a useful tool for pro users and administrators alike. Even though it probably is not (and shouldn’t be) the first tool of choice for many tasks, there are some tasks that AppleScript makes very simple. Because of this it should be a part of your ‘MacAdmin Toolbelt.’
AppleScript’s strength lies in inter-application communication. With AppleEvents (or AppleScript commands) you can often retrieve valuable information from other applications that would be difficult or even impossible, to get any other way. With AppleScript, you may even be able to create and change data in the target applications.
If you are in any way security and privacy minded this should raise your hairs. Up to macOS 10.13 High Sierra, any non-sandboxed app could use AppleScript and AppleEvents to gather all kinds of personal and private data from various script-enabled apps and services. It could even use script-enabled apps like Mail to create and send email in your name.
Since macOS Mojave, the Security and Privacy controls restricts sending and receiving AppleEvents. A given process can only send events to a different process with user approval. Users can manage the inter-application approvals in the Privacy tab of the Security & Privacy preference pane.
MacAdmins have the option of pre-approving inter-application events with a PPPC (Privacy Preferences Policy Control) configuration profile that is pushed from a DEP-enrolled or user-approved MDM.
Privacy approval
You can trigger the security approval from Terminal when you send an event from the shell to another process with osascript:
> osascript -e 'tell application "Finder" to get POSIX path of ((target of Finder window 1) as alias)'
When you run this command from Terminal, you will likely get this prompt:
You will not get this prompt when you have approved or rejected the Terminal app to send events to this particular target application before. You can check the permissions granted by the user in the Automation section of Privacy tab in the Security & Privacy pane of System Preferences.
For any given source/target application combination, the prompt will only be shown once. When the user approves the privilege (“OK” button), future events will just be allowed.
When the user rejects the connection (“Don’t Allow” button), this event and future events will be rejected without further prompts. The osascript will fail and the AppleScript will return an error –1743.
> osascript -e 'tell application "Finder" to get POSIX path of ((target of Finder window 1) as alias)'
79:84: execution error: Not authorized to send Apple events to Finder. (-1743)
If you want to get the approval dialogs again, you can reset the state of the source application (Terminal) with the tccutil command:
> tccutil reset AppleEvents com.apple.Terminal
This will remove the Terminal application and all target applications for it from the Automation (AppleEvents) area in the Privacy pane and show dialogs for every new request going forward. This can be very useful during testing.
Dealing with rejection
You should write your code in a ways that it fails gracefully when access is not granted. in this case osascript will return an error:
if ! osascript -e ' tell app "Finder" to return POSIX path of ((target of Finder window 1) as alias)'
then
echo "osascript encountered an error"
exit 1
fi
However, osascript will return errors for all kind of failures with no easy way to distinguish between them. As an example, the above will also fail when there are no Finder windows open.
If you want to distinguish AppleScript errors, you need to do so in the the AppleScript code:
if ! osascript -s o <<EndOfScript
tell application "Finder"
try
set c to (count of Finder windows)
on error message number -1743
error "Privacy settings prevent access to Finder"
end try
if c is 0 then
return POSIX path of (desktop as alias)
else
return POSIX path of ((target of Finder window 1) as alias)
end if
end tell
EndOfScript
then
echo "osascript failed"
fi
Note: the -s o option of osascript makes it print AppleScript errors to standard out rather than standard error, which can be useful to find the errors in logs of management systems.
Note 2: when you are running osascript from management and installation scripts (which run as the root user) you need to run them as the current user to avoid problems.
Avoiding Privacy prompts
So, we know of one way to deal with the privacy prompts. Ideally, you would want to avoid them entirely. While this is not always possible, there are a few strategies that can work.
Don’t send to other Processes
In past versions of Mac OS X (I use this name intentionally, it’s that long ago.), scripts that showed dialogs might not display on the highest window layer. In other words, the dialog was lost behind the currently active windows. To avoid “lost” dialogs, it became best practice to send the display dialog command (and similar) to a process that had just received an activate command as well:
tell application "Finder"
activate
display dialog "Hello, World!"
end tell
As an alternative for Finder, the System Events process is often used as well. Jamf MacAdmins often used “Self Service.” This had the added bonus, that the dialog looks as if it comes from the Finder or Self Service, including the bouncing dock icon.
Over time, even though the underlying problem with hidden dialog has been fixed, this practice has persisted. You often even see AppleScript code use this with commands other than user interaction, where it wouldn’t have made sense in the first place. With the privacy restrictions in macOS Mojave, this practice has become actively trouble some, as you are sending the display dialog (or other) command to a separate process. The process running this script will require approval to send events to “System Events.”
In current versions of macOS, you can just use display dialog and may other commands without an enclosing tell block. Since your AppleScript code isn’t sending events to another process, no privacy approval is provided. This code has the same effect as above, but does not trigger an approval request.
To determine whether an AppleScript command requires a tell block, you have to check where it is coming from. Many AppleScript commands that are useful to MacAdmins are contained in the ‘StandardAdditions’ scripting extension. Scripting extensions, as the name implies, extend the functionality of AppleScript without requiring their own process.
The useful commands in the Standard Additions extension include:
user interaction: choose file/folder/from list, display dialog/alert/notification
file commands: mount volume
clipboard commands: get the clipboard, set the clipboard to
sound control: set volume, get volume settings
system info
When your script uses only these commands, make sure they are not contained in tell blocks. This will avoid unnecessary prompts for access approval.
Exempt AppleScript commands
Some AppleScript commands are treated differently and will not trigger privacy approval:
activate: launch application and/or bring to front
open: open a file
open location: open a URL
quit: quit the application
For example, this will work without requiring approval:
osascript <<EndOfScript
tell application "Firefox"
open location "https://scriptingosx.com"
end
EndOfScript
Use non-AppleScript alternatives
Sometimes, similar effects to an AppleScript can be achieved through other means. This can be difficult to figure out and implement.
As an example, I used this AppleScript command frequently for setup before Mojave:
tell application "Finder" to set desktop picture to POSIX file "/Library/Desktop Pictures/BoringBlueDesktop.png"
While Mojave was in the beta and it wasn’t really clear if or how the PPPC exemptions could be managed, I looked for a different means. I discovered Cocoa functions to read and change the desktop picture without triggering PPPC, and built a small command line tool out of that: desktoppr.
The downside of this approach is that you know have to install and/or manage a command line tool on the clients where you want to use it. There are different strategies for this, but it is extra effort compared to “just” running an AppleScript.
Build PPPC profiles to pre-approve AppleEvents
Even after you have considered the above options to avoid sending AppleEvents to another process, there will still be several situations where it is necessary. For situations where a MacAdmin needs to run a script on several dozens, hundreds, or even thousands of Macs, user-approval is simply not a feasible option.
MacAdmins can pre-approve AppleEvents (and most other privacy areas) between certain processes with a Privacy Preferences Policy Control (PPPC) configuration profile. PPPC profiles can only be managed when pushed from a user-approved or automatically enrolled MDM.
You can build such a profile manually, but it is much easier to use a tool to build these:
Your MDM solution might have a specific tool or web interface for this, consult the documentation or ask you vendor.
There is one big requirement here, though: only applications and tools that are signed with a valid Apple Developer ID can be pre-approved this way, as the signature is used to identify and verify the binary.
Determining the process that needs approval
While you can sign shell scripts and other scripts this is often not necessary. As we have seen earlier, when we ran our script from Terminal, it wasn’t the script that requested approval but the Terminal application. When your scripts run from a management system or another tool, it may not be easy to determine which process exactly needs approval.
The most practical approach to determine this, is to log the output of the ’Transparency, Consent, and Control” system (tcc) and look which process is sending the requests.
First, either use a clean test system, or reset the approvals for the processes that you suspect may be involved with tccutil.
Then open a separate Terminal window and run this command which will show a stream of log entries from the tcc process:
Then run the script in question, the way you are planning to run it during deployment. If you are planning to run the script from a management system, then do that right now. You will get a lot output in the stream above.
Even when you don’t have a good idea what the parent process is going to be, you can filter the output for osascript since this is usually the intermediary tool used.
In my example I found several entries similar to this:
The important information here is the responsible path which give me the binary and the enclosing application that tcc considers ‘responsible.’ This is the application you need to approve.
When you are running your scripts from a management system, your MDM vendor/provider should already have documentation for this, to save you all this hassle.
With all this information, you can build the PPPC profile with one of the above tools, upload it to your MDM and push it to the clients before the deployment scripts run.
Conclusion
While the added privacy around AppleEvents is welcome, it does add several hurdles to automated administration workflows.
There are some strategies you can use to avoid AppleScripts triggering the privacy controls. When these are not sufficient, you have to build a PPPC profile to pre-approve the parent process.