Staging Casper policies with an Opt-In Early Access group

Being able to test policies and updates on a smaller group of computers can be quite useful to identify potential problems before all hell breaks loose.
That’s why a lot of folks have adopted a Dev-Test-Release strategy when it comes to deployments.
While Dev is IT-internal only, our Test users are some (more or less) tech-savvy powerusers.
Here’s a way to allow users to Opt-In to (und out of) the testing stage of this process through Self Service.

All we need are two Self Service policies, two Smart Groups and an Extension Attribute.

To determine if a computer is opted in to our “Early Access Program”
(you need to sell that stuff!!), we’ll use an EA:
EA
/Library/Application Support/MyCompany/ is where i store all my helper-tool cruft,
adapt the path as you wish but make sure the directory exists.
We’ll create the com.mycompany.earlyaccess.plist later on.

Next up are our Smart Groups which determine if a client is a member of our testgroup:
Smart Group NO
Smart Group YES
You can enable “Send email notification on membership change” if you wish to be notified when someone joins your testgroup.

And finally the two Self Service policies to modify our com.mycompany.earlyaccess.plist

The first one is to opt in, it is scoped to the “Early Access Opt-in NO” Smart Group:
Opt-In General
Opt-In Processes
Opt-In Self Service

Under “Files and Processes”, enter this in the “Execute Command” field:

defaults write "/Library/Application Support/MyCompany/com.mycompany.earlyaccess.plist" OptIn YES; jamf recon

I’ve added a recon to the command rather than checking the “Update Inventory” box in the policy because Casper delays the Inventory run until after the policy has finished.
In this case i want it to update immediately so the change is immediately reflected in the Self Service app.

The opt-out policy is pretty much the same, except our command is now

defaults write "/Library/Application Support/MyCompany/com.mycompany.earlyaccess.plist" OptIn NO; jamf recon

Scope it to the the “Early Access Opt-in YES” Smart Group.
Opt-Out GeneralOpt-Out Processes
Opt-Out Self Service

And that’s it!
Your users can now Opt-In or Out of your testgroup.

Self Service Icon Self Service Info
To scope a test-policy to your testgroup, simply add the Opt-In status as a criteria to the Smart Group that you scope your test-policy to:

Early Access Smart GroupAnother great use-case for this is if you have Reposado (or NetSUS) set up with Dev-, Test- and Release-Branches.

Reading Casper Extension Attributes with a shell script via the API

I recently had a need to get the value of Casper EAs in a script.
Bryson Tyrrell has two great articles about working with the API here and here which helped me getting started.

Let’s look at what the Extension Attributes look like on our JSS:

https://your.jss.org:8443/JSSResource/computers/macaddress/aa.bb.cc.dd.ee.ff/subset/extensionattributes

(Replace your.jss.org with your JSS URL and aa.bb.cc.dd.ee.ff with the MAC address of a managed client).

Depending on which EAs you have set up, it will look something like this:

JSS Extension AttributesNote that all child-nodes of “extension_attributes” are called “attribute“.
Therefor we have to look for the “name” of the EA we want and get the corresponding “value“.

Bryson already described how to use the Xpath command-line tool,
so we just have to tell Xpath to look for a certainĀ “name” in the child nodes of all occurrences of “attribute“.

Here’s the script i came up with:

#!/bin/sh

apiURL="https://your.jss.org:8443/JSSResource/computers/macaddress/"  #replace your.jss.org with your JSS URL
apiUser="casperapiuser"  #JSS-user with API read privileges
apiPass="casperapipass"  #password of the JSS-user
MacAdd=$(networksetup -getmacaddress en0 | awk '{ print $3 }' | sed 's/:/./g')
extAttName="\"EA Name\"" #name of the EA you're looking for

value=$(curl -s -u $apiUser:$apiPass $apiURL$MacAdd/subset/extension_attributes | xpath "//attribute[name=$extAttName]" 2>&1 | awk -F'<value>|</value>' '{print $2}')


echo $value

Firefox AutoConfig creation & deployment with CCK2

Mike Kaply recently released a new version of the Firefox Client Customization Kit, CCK2.
Head over to his blog to read all about it!

One cool new feature of the new version is that it can create AutoConfig files.
This allows you to disable the annoying “Import Wizard”, among lots of other options.

Get started by downloading CCK2 and starting it from the Firefox menubar.

Check mike.kaply.com for details on how to use CCK2.
When you’re done with your config, select “Use AutoConfig” from the “Finish”-tab:

You’ll end up with a ZIP file and a folder in the location you specified:

The ZIP has the same content as the “firefox” folder:

(Your folder’s content may vary depending on which options you set in your config)

Now, to make Firefox use your AutoConfig, we need to move contents of the newly created “firefox” folder into the Firefox binary directory, which is typically

/Applications/Firefox.app/Contents/MacOS

After copying the AutoConfig files it should look something like this:

Now start Firefox and check if your config was activated.Your changes should have taken effect, and the “About Firefox” window should show the name of your config.

When deploying your customized version of Firefox, it might be a smart idea to package the AutoConfig files separately, so you can easily update Firefox without having to integrate your config over and over again.

If you’re using Composer, your AutoConfig package would look similar to this:

Now we can just push a standard copy of Firefox to our clients, drop the configuration package on top, and be done.

Of course you can keep lots of different configuration packages if you have the need for it and just switch between them by uninstalling one and installing the other.

Enabling Accessibility for ADPassMon in Mavericks

I’m a fan of ADPassMon.

It’s especially useful for FileVault 2 encrypted Macs, where the user will never see the
“Your password will expire in X days” notification at the loginwindow, since they are directly taken to their Desktop from the pre-boot authentication.

Now, Mavericks (10.9.”0″) appears to have a bug where it will not show the password expiry notification even if you’re not using FileVault 2. Another reason to use ADPassMon.

ADPassMon has a built in shortcut to change the user’s password

Screen Shot 2013-11-14 at 16.31.19For this to work, you need to grant it access to “control your computer” in the Accessibility options in System Preferences.

Now these options have changed a bit in Mavericks.
In Mountain Lion it used to look like this:

Accessiblity 10.8It was sufficient for ADPassMon the check the “Enable access for assistive devices” checkbox, which could be done simply by running

sudo touch /private/var/db/.AccessibilityAPIEnabled

In Mavericks however, the option to allow ADPassMon to do it’s thing has moved to
System Preferences -> Security & Privacy -> Privacy:

Accessibility 10.9These settings are stored in
/Library/Application Support/com.apple.TCC/TCC.db
which is another SQLite3 database.

Chances are, you want to enable this programmatically.
Otherwise your users get presented with this message:

Screen Shot 2013-11-14 at 4.29.48 PMSelecting “Open System Preferences” will take them here:

Screen Shot 2013-11-14 at 4.29.55 PMSee the closed lock?
Now you might give your users access to the Security & Privacy settings by messing with the

security authorizationdb

command, but is that really a good idea?

 

The alternative is to modify the /Library/Application Support/com.apple.TCC/TCC.db database before installing ADPassMon.

When packaging up ADPassMon, add a preinstall script with these two commands:

sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "delete from access where client='org.pmbuko.ADPassMon';"

sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "INSERT INTO access VALUES('kTCCServiceAccessibility','org.pmbuko.ADPassMon',0,1,1,NULL);"

If you’re using Composer to build your package, it might look like this:

Screen Shot 2013-11-14 at 16.42.10

Thanks to spikehed for finding this trick here, and of course Peter Bukowinski for creating ADPassMon!

Deploying Mavericks via Casper Self Service

Disclaimer: All credit for this method goes to
Greg Neagle for creating the amazing createOSXinstallPkg
and Rich Trouton for his First Boot Package Install.pkg.

Check the linked pages (if you don’t know them yet) to get an understanding of how we’re putting the pieces together.

Of course it would be possible to deploy the Mavericks installer as it is from the App Store.
However, as we learned, upgrading to Mavericks removed Java from your Mac, and the user would be greeted with the iCloud sign-in dialogue once the upgrade is completed.

Maybe you don’t want that. And maybe you want to add a “postupgrade” script to the installer to make Mavericks fit your environment. Maybe you want to tweak the authorization database since /etc/authorization is deprecated in Mavericks…

Lots of reasons not to go with the standard installer.
I’ll try to explain how to do this.

Requirements:

 

Building a payload-free package with Composer

We need our postupgrade configuration script to be wrapped in a pkg.
Launch Composer and create a new empty package.
Click the triangle next to your package in the sidebar, then right-click on “Scripts”, select “Add Shell Script” -> “Postinstall” or “Postflight”.

Composer1Then paste your script contents into the script editor and save it.

Composer2Select “Build as PKG” to finish the build process.

 

Preparing First Boot Package Install.pkg

Right-click the package you downloaded, select “Show Package Contents” and navigate to
/Contents/Resources/fb_installers
You will find six numbered folders in there.
Each pkg we want to install on first boot goes into one folder.

Payload-free package to run the configuration script:

FBPI1Java for OS X installer:

FBPI2

Of course you don’t need to have exactly six pkgs, however you can add additional folders as needed. Remember the 350MB size limit!

 

Building the Mavericks installer pkg

Here’s where createOSXinstallPkg comes into play.
We’re going to bake our prepared First Boot Package Install.pkg into the Mavericks installer.
To do that, fire up Terminal and run

sudo /path/to/createOSXinstallPkg --source /path/to/Install\ OS\ X\ Mavericks.app --pkg /path/to/First\ Boot\ Package\ Install.pkg --output /path/to/Output.pkg

createOSXinstallPkg1Grab a coffee while it does its thing.

 

Deploying the Mavericks installer via Self Service

Once your package is ready, upload it to Casper Admin.
We’re almost done!

Now we’ll create a policy to cache the installer on our clients.

Create a new policy:

Policy1Add the Mavericks installer package we just uploaded:Policy2 Choose “Cache” from the Options

Policy3Scope it to a group or single computersPolicy4Choose a triggerPolicy5And set it to “Once per computer”Policy6Give it a name and a categoryPolicy7Now we need to know which clients are done caching the installer.
Therefor we need a create smart group:

SmartGroupIn order to make the Mavericks installer available in Self Service, we create another policy.

Upgrade1Scope it to the smart group we created:Upgrade2Make it available in Self Service, upload an icon and add a description:Upgrade3Install the cached installer:Upgrade4Add “shutdown -r now” in the “Run Command” field to trigger a rebootUpgrade5Our policy should now show up on the clients on which we cached the installer!

SelfService1 SelfService2When the user selects “Install”, the Mavericks will run for 5-10 minutes and reboot the computer afterwards.
It will then boot into the actual OS X installation environment and upgrade the OS which takes about 45 minutes, depending on the machine you run it on.
When the upgrade is done, the computer reboots again.
Now the First Boot Package Install.pkg kicks in and runs our script & installs Java,
plus whatever else you set it up to install.
During this, the end user will see the grey Apple bootscreen with the spinning circle.

Once all packages are installed, the Mac will reboot one last time and is then ready for the user to log in.

So far this method has worked very well for me, however
I’m sure there are smarter/better ways to achieve the same result and if you know one,
please let me know!
Same goes for any errors/mistakes you find in my posts.

Thanks to Mr Greg Neagle and Mr Rich Trouton for their amazing work,
and for sharing it with the Mac admin community.