Recently on JAMF Nation there was a discussion about the Adobe Flash Player Distribution site going away. This site is where admins can go to get a copy of Flash that can then be legally distributed to their fleet of machines. The discussion started out to be about the change Adobe recently made to the URL for this site, but quickly turned to a discussion around distribution of Flash via Casper.

While I have signed up for the Adobe distribution site, I currently utilize a PKG file that comes from AutoPKGr (I replaced my Jenkins install with AutoPKGr last year sometime). Utilizing AutoPKGr makes my life easier, because I do not have to do anything except update my policy to replace the actual PKG file. I’m not going to go into setting up AutoPKGr for use with Casper, there have been plenty of discussions on that, but rather I am going to list out my procedures for processing Flash upgrades.

It’s Upgrade Day

I typically find out that there is a Flash upgrade from JAMF Nation. Someone typically posts that there is a Flash update almost immediately upon release. Once I’ve verified that the update has been uploaded to my JSS by AutoPKGr, I will go update my policy, changing out the PKG file.

As you will see, the policy is set to trigger on “Recurring Check-In” because I don’t care if a web browser is open or not. Flash can be installed while browsers are open, the users just have to restart the browsers that are open after the update. We’ll handle letting them know via a CocoaDialog script.

There are a few pre-requisite items we need to have in place for this process to work. First, we need to have a way to grab the Flash version off of the machines in our fleet. Second, we need to have a Smart Group that will capture all of the machines that are out of spec. This will allow us to scope our policy to those machines.

Grab the Version

I utilize an Extension Attribute to grab the version of Flash and store it in the database. While it can be argued that utilizing an EA to grab the version is not efficient, since the EA will run every time a Recon runs, there really isn’t another reliable method for grabbing the version.

So, setup an EA to grab the version of Flash. My EA is named “AdobeFlashVersion” and utilizes the following BASH script:

That’s pretty straight forward. Now that we have the version, we can build our Smart Group.

Screen Shot 2015-12-18 at 5.38.04 PM.png

As you can see, just pick your EA name out of the list of criteria to search for, and enter the version you are searching for using the “is not” operator.

Policy Time

Now that we’ve got our Smart Group collecting machines that are out of date, we can build our policy to install the update. We will name our policy “Update Flash Player” and place it in whichever category makes sense to your deployment of Casper.

I have my update policy set to run at “Recurring Check-in”, which means that machines will update as soon as they contact the JSS. The frequency is set to “Once per computer”, since we only need it to run one time.


We’ll click on Packages next so that we can add our Flash package. Click on Configure to get a list of all packages in the JSS:


Screen Shot 2015-12-18 at 5.32.24 PM.png

We should now have a list of all packages that the JSS knows about. Locate our latest Flash Player package and click Add to add it to the policy:


I utilize a script that runs after Flash has been installed to notify end users to restart any open web browsers. My script uses CocoaDialog to make these notifications, but you can use the built in notification process that Casper has. The script I utilize is below:

Now that we’ve added that script to our policy, we will add a line to the Files & Processes tab to set Flash to not auto update.


That line of information in the Execute Command box simply adds a line to a file called mms.cfg to tell Flash Player to not try to auto update. The line is:

The final thing for us to do is to add our Scope. Just click on the Scope tab at the top and add our Update Flash Smart Group:

Screen Shot 2015-12-18 at 6.01.26 PM.png


That’s all there is. Now that we have our update policy in place, each time there’s a new version we just have a few simple steps to update our end users:

  1. Get the new Flash package into the JSS
  2. Change our Smart Group to look for the new version number
  3. Change our policy to remove the old version and add the new version
  4. Finally, Flush All on the policy logs so everyone in the Smart Group gets the update.


I have been utilizing this method for updating Flash for well over a year now, and I have not had any troubles at all.

I hope this quick article has helped you out.


Here are the links to resources that were mentioned tonight at the meeting:

Rich Trouton’s blog:

Ben Tom’s blog:

Shea Craig’s blog:

Univ Utah rc.netboot fix:

JAMF Support GitHub:

Bryson Tyrell:

Mike Morales GitHub:

JAMF Nation JNUC 2014 Playlist:

My GitHub Repo:

IRC – there is a #jamfnation channel on the Freenode IRC server. A lot of great minds hang out on that channel during the day. While it is not a JAMF sponsored place, even a few JAMFers hang out in there occasionally. It’s a great way to get help in real time.  If you’ve never used IRC before, or it’s been a while, IRC Cloud is a great IRC app:

Some Tools:

AutoDMG – tool for creating never before booted OS X DMG files for use in Casper or AutoCasperNBI

AutoCasperNBI – tool for creating NetBoot images

CreateUserPKG – tool for creating a package that will “install” a user on a system

AutoPKG – tool for downloading applications and updates. Utilizes recipes from the community. Can be coupled with Jenkins for automation. See my series of posts about it, starting with this one.

AutoPKGr – AutoPKG with a GUI front end, and integeration into the JSS. This tool eliminates the need to implement Jenkins

vfuse – tool for creating VMware Fusion VMs from DMG files

The presentation from tonight, minus the movies, can be downloaded from here:

Music tonight was courtesy of the JNUC 2014 playlist on Spotify, put together by Mike Paul:

Wells Fargo BuildingEvery year as October gets closer, I get anxious. I know that at some point, usually toward the end of the month, I will be traveling up to Minneapolis for the JAMF Nation User Conference, JNUC. The conference is located at the Guthrie Theater in downtown, in the Mill district of Minneapolis, right on the Mississippi river. It’s one of my favorite locations to go to.

The JNUC is one of my favorite conferences to attend. Not just for the great content, but for the relationships that get formed and strengthened there. There are friends at JNUC that I’ve known for well over 10 years now, just from attending different conferences in the past. It’s great to catch up with these friends.IMG_0839

This year was also special because I was presenting there. I had the opportunity to present on imaging in a session titled “Unwrap the Imaging Enigma”.  It was a wonderful experience, and one that I will repeat again. Giving back to the community by presenting is important for any admin. If you’re interested in the slides, you can find them on my GitHub repository.

Now that I’ve called more attention to this blog, and to myself, I will try to post more relevant content regularly. If there is a topic you’d like to see, just post it in the comments and I’ll see if I can come up with something. Or reach out to me on Twitter: @stevewood_tx

To say that I’m a huge fan of JAMF Software‘s Casper Suite is probably putting it lightly.  I love it, and one of the features I love is the ability to use Extension Attributes for gather information. In the old days of Casper we had no real way of gathering things like Flash version and storing it in an easy to get to place.  Along came Extension Attributes and we were now able to store that version information right in the

As I work on upgrading to 9.2, I am doing a clean installation of the JSS and not importing my previous database.  In the process I am only taking over packages, policies, scripts, etc, that I want on the new server.  So I thought I would do a quick post on some of my favorite Extension Attributes and what I use them for.

“X” Plug-in Version

It seems like about once every two or three months a question comes across the JAMF Nation list about how to grab the version of Flash, or Silverlight, or name your application or plug-in.  Here’s how I grab those versions:

From that script we can start to swap out different plug ins.  The magic is the “defaults read” statement that grabs the version information from the Info.plist file in each plug-in.  For example, if we wanted Silverlight, we’d use:

And so on.  Pretty easy to use this to grab version information from different apps.

Display Serial Number

I used to hate having to inventory Apple Cinema Displays because you’d have to tip them up or lay them flat to read the barcode.  With this EA you can have Casper do the work for you:

Keyboard or Mouse Battery Percentage

Do you want to know when the batteries are getting low on your Apple keyboard or mouse:



Warranty Status

I can’t take credit for this one, but it is in the script.  Need to grab the warranty status of your equipment:

These are only a few of the Extension Attributes I’ve moved over to the new server.  JAMF did a good job of including a lot of pre-built EAs in version 9 of Casper.  Make sure to check them out and implement the ones that you need.

In my two previous posts, I talked about deploying AutoPkg and Jenkins.  AutoPkg allows us to build packages from common apps, like Adobe Flash or VLC, using recipes.  This allows for all of the guess work to be done through automation.  Then with Jenkins, we deployed a Continuous Integration server that allows for the scheduling of tasks, thus getting us closer to full automation.

Jenkins & AutoPKG Together

Now that we’ve got AutoPkg and Jenkins installed, it’s time to configure them to work together and get some automation going.  Hopefully you’ve installed both AutoPkg and Jenkins on the same machine.

When installing Jenkins, the software creates a new user aptly named “jenkins” on your system.  When Jenkins is running tasks, it will run these tasks as the jenkins user.  In order for us to run AutoPkg as Jenkins, we will need to configure things like the CACHE_DIR and the repositories for Jenkins to use.

First thing we need to do is reset the Jenkins user’s password.  So login to your Mac as the admin user (or ssh in if you’d like).  Open a Terminal window and issue the following command:

sudo passwd jenkins

You will then be prompted to enter a password for the jenkins account.  Go ahead and enter whatever password you want, just make sure it’s one you will remember.  Once you’ve done that, go ahead and logout of the admin account.

Now login to the machine as the Jenkins user and open the Terminal.  We need to set the CACHE_DIR for the jenkins user, just like we did in our AutoPkg post.  From the command line in Terminal, enter the following:

defaults write com.github.autopkg CACHE_DIR /path/to/cache/dir

In our previous post, we said “/paht/to/cache/dir” was a path to a local directory on your system.  In our example we used /Autopkg_done.  So our command was:

defaults write com.github.autopkg CACHE_DIR /Autopkg_Done

Now that we’ve set the CACHE_DIR, we need to set the locations for the repositories we’re going to use:

autopkg repo-add
 autopkg repo-add
 autopkg repo-add
 autopkg repo-add

The Jenkins user should now be set to utilize autopkg.  Now we need to figure out which recipes we want Jenkins to build for us, and how often we want this to happen.

Given the frequency at which Adobe Flash is updated, this is probably a good one to have in Jenkins.  So we’ll use that recipe as our example.  Go ahead and pull up the Jenkins dashboard (http://localhost:8080).

Click on the New Job link to the left side of the dashboard.  On the page that comes up, enter a name for this new job, and choose to “Build a free-style software project”.  In our example, I’m creating a job named “Flash Player”.


The next page that we are presented with asks for a bunch of different information about the job (project) we are creating.  You can give a description, set it to discard old builds, use source code management, and plenty of other things.

For this example, we’ll give the job a description and then we’ll tell Jenkins what to actually do using the Build drop down box (Add build step).  We will be using the build step “Execute Shell”.

Our shell command that we will have Jenkins execute is the command line commands to run the autopkg recipe for Flash.


Once we’ve set our configuration, simply click on the Save button to save the job into Jenkins list of jobs.

Now that our job is built, we will need to schedule it to run.  We can do this in two ways:

1)  We can schedule each job to run individually on its own schedule, or

2)  We can create a job in Jenkins that triggers the jobs we want to run.

We’re going to focus on the second option, triggering all builds via a single job.

Start a new job, and this time give a name like “Daily AutoPkg Builds” and the type of job is “Build multi-configuration project”.


On the configuration page that comes up, go ahead and set a job description if you’d like, but the first area we’ll be really concerned with is the Build Triggers.  IN here we want to select the Build Periodically check box.  This will give us a new box to enter a schedule in using the standard UNIX cron parameters:

BuildTriggersIf you’re not familiar with cron parameters, click on the blue question mark to the right of the Build Periodically line.  This will give you a great explanation of the parameters you want.  In the screen shot above, we are set to run this everyday of every month at 6 am.

Next up, we need to tell this project what to do.  Under the Post-Build Actions section towards the bottom, you want to select Build Other Projects.  In the field that opens up, you want to then type the names of each of the projects you want to build.  Don’t worry if you cannot remember the exact names, as you type the names of projects will appear just below the box.  Just choose the ones you want.

PostBuildThat’s it.  Just click on the Save button at the bottom of the page, and you’ve now created a system for building these software packages each morning.  Each morning you can come in and check the Autopkg_Done directory to find your packages already built:

AutoPKG_DoneAs you can see, each of those folders was updated this morning.  This provides me with the latest versions of those apps/plug-ins for me to then import into whatever management app I’m using, whether it’s Casper, Absolute Manage, or something else.

NOTE:  Since AutoPKG was developed by Greg Neagle and Tim Sutton, there are built-in recipes for importing directly into Munki.  I have reached out to JAMF for the possibility of having the same feature made available for Casper.  It may be some time before we are there, but at least we can get our packages built automatically.

This is just the tip of the iceberg when it comes to using Jenkins.  You can configure Jenkins to send out RSS updates or emails when packages are built or when they fail.  Dig into the documentation and start to tweak it to your needs.

Don’t be afraid to roll up your sleeves.

Continuing with my posts on automation, or at least the automation of package building, I’d like to introduce you to my new assistant, Jenkins.  Jenkins is a continuous integration server.  Continuous Integration, or CI, is defined by Wikipedia as:

Continuous integration (CI) is the practice, in software engineering, of merging all developer working copies with a shared mainline several times a day.

To put it plainly, or to put it into the perspective of a Mac sysadmin, Jenkins can be used to run shell commands at a given interval, or to run several commands in series.  We can then use CRON like scheduling within Jenkins to run these commands at a given time each day, each week, or whatever interval you give.

Jenkins will require the use of the Java 6 JRE on the machine you run it on.  You can go out to the Jenkins CI web site ( to download the installer for Mac.  Once you have downloaded the software, while logged in as an admin on the machine, run the Jenkins installer PKG.  After the installation has completed, either restart the computer, or open a Terminal window and load the LaunchDaemon:

launchctl load /Library/LaunchDaemon/org.jenkins-ci.plist

If Java is not installed you may be prompted to load Java.  After completing these steps, open a web browser and navigate to the home page for Jenkins:


You should hopefully see the Jenkins dashboard, which looks similar to this:


NOTE:  If you receive an error about the home folder, try restarting the computer.

You can also check this web site for more info:

If you successfully loaded the Jenkins dashboard, then you are all set to start using the power of a CI server.  I utilize Jenkins to work with my AutoPkg installation (on the same machine) so that I can build packages while I sleep.

Next up we’ll look at integrating Jenkins and AutoPkg.

There’s been a lot of talk in the Mac admin community recently about AutoPkg (  This tool, currently being developed by Greg Neagle and Tim Sutton, allows for the use of “recipes” to download and package different software found on the Internet.  This ability takes a lot of the work out of locating software, downloading it, and then packaging it, something a Mac admin may do multiple times a week.  AutoPkg automates all of that.  And, if you are a user of Munki, there are even recipes in AutoPkg that will import directly into Munki and update the catalogs.

As a prerequisite for AutoPKG to work, you need to have the command line version of git installed.  If you’ve installed XCode, then you have git.  If not, you can get git by downloading either a GUI GitHub tool like this one here, or download the command line version of git here.

Once you have git installed, go ahead and download the AutoPkg installer file from this location.  Now that it is downloaded, go ahead and run the AutoPkg installer.  This will install the AutoPkg software in the proper  locations on the machine.  Once completed, fire up Terminal and you can verify the software is properly installed by running the following command:

autopkg version

That will give you the current version installed on the system.  Now that AutoPkg is installed, you may want to create a directory in a common location, like the root of the drive or in the /Users/Shared folder, to hold the output from AutoPKG.  By default AutoPkg stores it’s output inside the user’s Library folder at ~/Library/AutoPkg/Cache.  This location can be changed by adjusting the CACHE_DIR in the preferences.  I like to store it at the root of the drive in a folder named Autopkg_Done.

mkdir /Autopkg_Done
chmod 777 /Autopkg_Done

Now that you have the CACHE_DIR created, you’ll need to tell AutoPkg about it.  This is done with the following command:

defaults write com.github.autopkg CACHE_DIR /path/to/cache/dir

So, in our example, the command we’d use is this:

defaults write com.github.autopkg CACHE_DIR /Autopkg_Done
NOTE:  AutoPKG stores its preferences in the user’s Preferences folder (~/Library/Preferences/com.github.autopkg.plist).  Because of this, any new user on the machine that will need to use AutoPKG will need to have the CACHE_DIR set and will need to download the recipe repositories (more on this in a minute).

With AutoPkg installed, and the CACHE_DIR set, all we have left is to tell it about some recipe repositories.  AutoPkg utilizes git repositories that hold recipes for building different packages.  Like using a recipe to bake a cake, AutoPkg uses these recipes to build the different files.

As of this writing, there are four repositories that I am aware of.  They are:
We need to tell AutoPkg about these repositories.  This is accomplished with the following command line:

autopkg repo-add <repoURL>

So for the four repositories above, we would use the following:

autopkg repo-add
autopkg repo-add
autopkg repo-add
autopkg repo-add

Now that we have our repositories in AutoPkg, we are free to run one of the recipes.  We can see what recipes we have access to with the following:

autopkg list-recipes

If all went right, you should see a list of the recipes that your AutoPkg installation knows about.  To run one, simply use the following:

autopkg run <recipe>

For example, to run Adobe Flash Player:

autopkg run AdobeFlashPlayer.pkg

That will download the Flash Player and create a PKG file for deployment inside of our CACHE_DIR (/Autopkg_Done in our case).  We can navigate through the folders there to find a pristine Flash installer package that we can now deploy to our machines.
There’s plenty more to know about AutoPkg, including how to import directly into Munki during a build.  Check out the wiki for more information on Munki integration, or if you want help with installation and config, go here.

Next up, we’ll setup Jenkins, a continuous integration server that will eventually allow us to build packages while we sleep