Building a Jamf Self Service policy for Homebrew

Homebrew, the open-source UNIX package manager tool for macOS, got a new installation option last year: a macOS installer package. This is an exciting change for Mac Admins looking to deploy Homebrew for software developers, sys admins, and refugee Linux nerds in their organizations.

That said, the Homebrew package appears built to be installed by humans, not in an unattended fashion as a management framework, or even Installomator, would. The package has two prerequisites:

  1. Command Line Tools for Xcode (CLT)
  2. A logged-in user1

Opening the package without CLT installed results in the following alert:

Therefore, any policy that attempts to install Homebrew must resolve this requirement. Either, one could scope the policy in such a way as to require that CLT are installed before the Mac falls into scope, or one could install CLT if it’s missing. I chose the latter approach.

Self Service is run in the macOS GUI and as such a user is logged-in. This meets the other requirement. The package’s postinstall script will grant ownership of the Homebrew to the logged-in user.

A further indication that the package is designed for humans is that a set of “Next steps” are presented when installation is complete. These can be addressed either by scripting or in the Self Service description.

Self Service Policy

The Homebrew policy I created has a single script payload and the Maintenance payload to update inventory. It is only triggered by Self Service and has an Ongoing execution frequency. It is scoped to a smart group, which I’ll cover later.

InstallHomebrewPackage.bash script

The script to install Homebrew takes a single parameter which is the name of a policy event trigger to install CLT. I have an existing policy to install CLT based on Rich Trouton’s script.

The download and install portion is modeled heavily on Installomator’s process. (Full credit to Armin Briegel and team for their inspiration here.)

The order of operation in the script:

  1. Check that /Library/Developer/CommandLineTools/usr/bin/git exists. If not, call the policy to install CLT. (This is same check performed by the Homebrew package.)
  2. If /Library/Developer/CommandLineTools/usr/bin/git still doesn’t exist, exit with an error.
  3. Call the GitHub API2 and fetch information about the last 10 releases of Homebrew looking for a package download. (Why not the latest release? Not all releases have a package download and when they do, it may not be available immediately after a release is created.)
  4. If no package download URLs are found, exit with an error.
  5. Download the latest package found to a temporary directory.
  6. Verify the code signature on the package and that the Team ID matches the expected ID. If not, exit with an error.
  7. Install the package.
  8. Verify that the receipt for the package and the brew executable exist. If not, exit with an error.
  9. Update the logged-in user’s .zshrc and .bash_profile for Homebrew’s shell environment

Self Service parameters

Self Service Display Name: Homebrew

Button Name Before Initiation: Install

Button Name After Initiation: Install

Description:

Homebrew is the easiest and most flexible way to install the UNIX tools Apple didn’t include with macOS.

#### Notes

• The Homebrew installation will be owned by the logged-in user
• The logged-in user's Bash and Z shells will be updated to add Homebrew to PATH
• Command Line Developer Tools will be installed if needed
• Once installed, open a new shell to use the **brew** command
• For help, run **brew help** or read [docs.brew.sh](https://docs.brew.sh/)

Icon: download from here

Ensure that users view the description: checked

Homebrew smart group and extension attribute

The POL- Homebrew smart group, to which the policy is scoped, matches a value of “Not installed” for an extension attribute named Homebrew, that searches for the brew executable:

#!/bin/bash

result="Not installed"

export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"

if /usr/bin/which -s brew; then
  result=$(/usr/bin/which -a brew | sort | uniq)
fi

echo "<result>${result}</result>"

Completed Policy

Once completed, the policy appears in Self Service:


  1. This requirement can be met (and overridden) by populating a plist at /var/tmp/.homebrew_pkg_user.plist, setting the key HOMEBREW_PKG_USER to the username of an extant local user. ↩︎
  2. Unauthenticated calls to the GitHub API are rate-limited to 60/hour. ↩︎

Leave a comment

Website Powered by WordPress.com.