Category Archives: Casper

This is our Firehouse

Firehouse is a OS X application to help manage sites within our Casper environment at Indiana University. We manage a central service for other IT departments across the University, currently around 30 sites and growing. In Casper, there are resource areas that are not site specific, so if you give Site Admins access to scripts, they could possibly use, edit, or delete another site scripts.

We wanted to prevent this from happening and shut down Site administrators access to shared areas. We would then upload and transfer scripts, packages, and printers for the Site Admins. As the service grows, we know this level of support is unsustainable for our small department. Wanting to keep the same restrictions in place, but also give our Site Admins the ability to manage their own resources we developed Firehouse.

First the name…I’m a huge Ghostbusters fan. Casper…Ghostbusters…perfect.

Poster“This place is great! You gotta try this pole!”

How it works (in a nutshell)

Firehouse manages which resources the admins can see, edit, and post. Here’s how it works.



Screen Shot 2016 05 25 at 10 32 45 AM

The first step in the login process is to check for any updates to the Firehouse application itself. This happens through a appCast mechanism.

Next the user logs in and Firehouse authenticates the user to sites by looking at which sites are available via the Casper API and then authenticates the user to their sites via Active Directory.



Screen Shot 2016 05 25 at 10 33 22 AM

We enforce a strict naming scheme in our shared environment. This is what allows Firehouse to parse out the objects and allow access to site admins. It also enforces the naming convention, you cannot upload anything not prefixed with your site name.

Here you can see admins can quickly upload and delete their scripts without the ability to effect anything but their own objects.



In the packages tab, you are presented with a list of all your sites installers. Delete will remove the package.

Screen Shot 2016 05 25 at 10 46 48 AM

Adding a packaged presents a screen that lets you configure your installers settings. The same naming conventions are enforced here. Upon clicking done, the installer is uploaded to the Root JDS via WebDav and the Installer information is posted to the JSS via the api. The installer will then replicate out to the JDS children which happens on a recurring schedule.

Screen Shot 2016 05 25 at 11 05 03 AM


In its current version, Firehouse can only upload printers that use generic ppd’s. I am currently working on updating this so fully customizable printers can be uploaded.

There are 2 primary ways to setup a printer here. You can manually enter all the information or you can import a local printer and all its detail will be entered for you.

Screen Shot 2016 05 25 at 11 12 45 AM

Casper Site Management Enhancement with the API

I work in a Casper environment that relies heavily on the Sites feature to deploy a unified Apple management solution across the enterprise.   Out of the box, JAMFs Casper has been a great solution for us.  There are a few things we would like to see Site admins to be able to do, amongst them, managed their own scripts and printers.  We have leveraged Caspers REST based API to give the site admins additional access and control.

Enter The Ghostbusters

The in-house tools (named after Ghostbusters) give the Site Admins the ability to manage items not normally available to that user level.  These applications were development for OS X with Cocoa and Obj-C / Swift as the primary languages. (See my SwiftJSS example) The architecture would also work with other languages,such as Ruby or Java.  

So how does this work and what does it really do?  Here’s a logic quick graph of what’s happening behind the scenes. 

My Diagram


The Site Admins belong to a Active Directory Organizational Unit associated with their site.   In this case, I use the OpenDirectory Framework to authenticate and lookup users Site credentials. It’s then cross referenced with the API by correlating the OU information with the proper Sites. 

 Middleman API / Behind the Scenes

Once we have the user authenticated to the proper site, a middleman API only account is used to get and push content to/from the JSS.  You could just give the user the API permissions and use that account for the API calls.  I opted for a 3rd Party account that I control that can be deactivated and cut off all application access. This also allows me to control their API access and force them to use my tool which enforces our naming rules.

The application then goes out and gathers the information needed for the user.  This is usually categories and whatever object the app is designed to edit, like Scripts. 

 Matching Objects to Sites

We enforce a strict naming scheme in the shared areas of Casper.  SITENAME-LABEL.  Since the scripts and printers specific for each site is prefaced with the site name, we are able to parse only the objects belonging to the users site. On the posting side, the script name is auto-magically prefaced with the site name before posting.

 XML Generation

A easy to use UI is presented to the user.  They enter the information and the application generates the proper XML for posting. Easy peasy. 


Here’s a look at what the completed Script management app looks like, called Egon. 


Screen Shot 2015 03 17 at 1 17 03 PM


That’s it in a nutshell.


Use JAMFs Casper API with Swift

I have updated JAMFs Cocoa example with a Swift version I am using internally at work.  The code is up on GitHub for anyone to use.  This example counts and displays the number of managed machines in a JSS. Pretty simple.

I have been slow to get on the Swift train.  Now that I’m here….full steam ahead.  I am really enjoying it.  I had been so stubborn to code outside of Objective-C.  

Just one important code note.  The JSS will sometimes return JSON instead of XML.  You can always force XML with this code.  This was not part of the original SDK example. 

  let theRequest = NSMutableURLRequest(URL : NSURL(string:urlWithPath)!)

        theRequest.timeoutInterval = 60;

        theRequest.addValue(“application/xml”, forHTTPHeaderField:“Accept”)