Archive

Posts Tagged ‘casper’

Collecting Data Using Plist Files

July 16, 2016 Leave a comment

At our recent Dallas area Casper User Group meeting, we got into a discussion around collecting data during a Casper recon. Specifically we were discussing the use of Extension Attributes to collect information about virtual machines.

Extension Attributes are a way to capture information from your systems. You can use scripts to pull information or drop downs or text boxes to store static information in the database. In the instance of collecting info about virtual machines, a script would be run on the systems during the recon to gather the information. Running a script on the system each time a recon happens can be processor heavy, depending on the data that is being gathered. For example, gathering home folder size by running “du” each time a recon happens can be taxing.

Rather than run the script each recon, you can use a policy to run the script once a week, once a month, or just one time, to gather the information you need and place it in a plist file somewhere. During the standard recon period, you can then use an Extension Attribute to read the information in that plist file. This is much less taxing on the systems than running the script during a recon.

Stash The Data

For our example, rather than run through grabbing info about virtual machines, let’s work on grabbing the home folder size for the logged on user. We will store the info in a plist file that we will stash in /Library/IT_Data.

First we need to find the logged in user name. There are plenty of ways to do this, but we’ll use the “Apple approved” method, using a Python one liner. Okay, it’s not really a one liner, it’s just built like one.

loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`
view rawcontents.sh
view raw gistfile1.txt hosted with ❤ by GitHub

Now that we have our logged in user, we just need to find the user’s home folder and use du to grab the data. We’ll use dscl to grab the home folder location and then du to get the home folder size.

homeDir=`dscl . read /Users/$loggedInUser NFSHomeDirectory | awk '{ print $2 }'`
homeSize=`du -hs ${homeDir}`
view raw gistfile1.txt hosted with ❤ by GitHub

The next thing we need to do is to store this information into our plist file. Using the defaults command, we can write as much data as we want into the plist file, We can use different keys to store whatever data you want, and then recall it during recon by asking for those specific keys.

defaults write /Library/IT_Data/com.mycompany.homesize.plist HomeFolderSize -string "${homeSize}"
view raw gistfile1.txt hosted with ❤ by GitHub

Retrieve The Data

Now that we have the data stashed away, we just need to grab it during the recon process. To do this, we’ll use the defaults command again, to grab the data. We’ll use some variables for the folder path and the plist name, that way we can re-use this code fairly easily. We also want to make sure the file actually exists before trying to read data from it, hence the If statement.

if [[ -e ${dataFile} ]]; then
homeSize=`defaults read ${dataFile} HomeFolderSize`
fi
view raw gistfile1.txt hosted with ❤ by GitHub

Once we’ve read the data, all that’s left is to echo it out into the EA.

if [[ ${homeSize} ]]
echo "<result>${homeSize}</result>"
else
echo "<result>No Results Found</result>"
fi
view raw gistfile1.txt hosted with ❤ by GitHub

That’s All Folks

That’s pretty much all there is. Now that we know how save data to a plist and then read it back, this method could be used for any data we only need to gather once, or gather at infrequent times.

The full script to write the data and to then read the data are below.

#!/bin/bash
loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`
homeDir=`dscl . read /Users/$loggedInUser NFSHomeDirectory | awk '{ print $2 }'`
homeSize=`du -hs ${homeDir}`
# check for our storage folder, and create if missing
if [[ ! -d "/Library/IT_Data" ]]; then
mkdir "/Library/IT_Data"
fi
defaults write /Library/IT_Data/com.mycompany.homesize.plist HomeFolderSize -string "${homeSize}"
#!/bin/bash
dataFolder="/Library/IT_Data"
dataFile="${dataFolder}/com.mycompany.homesize.plist"
if [[ -e ${dataFile} ]]; then
homeSize=`defaults read ${dataFile} HomeFolderSize`
fi
if [[ ${homeSize} ]]; then
echo "<result>${homeSize}</result>"
else
echo "<result>No Results Found</result>"
fi
Categories: Casper, Tech Tags: , , , ,

Custom CrashPlan Install With Casper

February 12, 2016 1 comment

I’m a fanboy. There, I said it and I’m proud of it. I’m a fanboy of JAMF Software’s Casper Suite. I’m also a fanboy of Code42 and their CrashPlan software. Put them together and it’s like when the two teens discovered peanut butter and chocolate as an amazing combination.

I am all about trying to minimize the amount of time my users need to be interrupted due to IT needs. That’s a large part of the reason we use Casper, so that my users do not have to be inconvenienced. Let’s face it, the more time I take performing IT tasks on their computer that cause them to not be able to work, the less money they are making for our agency. It’s one of my primary tenets of customer support: make every reasonable effort to not disturb the end user, period. So when I discovered several of my end user machines were not backing up via CrashPlan, I needed to find a way to deploy CrashPlan with as little interruption as possible. In steps Casper and CrashPlan together.

Our original setup of CrashPlan that has been running for several years, was setup using local logins. At the time when we first deployed, we were not on a single LDAP implementation, so I didn’t want to deploy an LDAP integrated CrashPlan. Fast forward to now, and we have a single LDAP (AD) and I want to take advantage of that implementation to provide “same password” logins for my users.

Fortunately JAMF has a technical paper outlining how to do this, titled Administering CrashPlan PROe with The Casper Suite. This paper was written back when CrashPlan PROe was still a thing. With the release of version 5 of CrashPlan, it has now become simply Code42 CrashPlan. This document still works for the newer version of the software.

Get The Template

The first step is to get ahold of CrashPlan custom template for the installer. Following the paper, you can download the custom template by navigating to this URL:

http://YourServerAddress:4280/download/CrashPlanPROe_Custom.zip

NOTE: If you are deploying version 5 or higher of CrashPlan, you can use this URL to download a newer version of the kit:

http://YourServerAddress:4280/download/Code42CrashPlan_Custom.zip

While there are two different URLs, you can use either one to customize your install.

Edit Away

After downloading and expanding the zip file, you will need to edit the userInfo.sh file to set some settings. First of which is to hide the application from your users during installation. Simply set the following line:

startDesktop=false
view raw gistfile1.txt hosted with ❤ by GitHub

The next thing you will want to edit are the user variables. CrashPlan uses these variables to grab the user’s short name and their home folder location. An assumption is made when it comes to the user’s home folder, and that is the assumption that the home folder lives in /Users. If your home folders do not live there, or you want to script the generation using dscl, you can. I’m lazy and so I simply went with the /Users setting.

Also, the method to grab the user short name is based on the user that is logged in currently. Now, we didn’t discuss before how you were deploying this via Casper (login, logout, Self Service, etc), but suffice it to say, it is preferable to deploy this when a user is logged in to the computer. There have been many discussions on JAMF Nation about CrashPlan and how to grab the user, I used the information found in this post to grab the info I needed:

user=`/usr/bin/defaults read /Library/Preferences/com.apple.loginwindow lastUserName`
CP_USER_HOME="/Users/$user"
userGroup=`id -gn "$user"`
CP_USER_NAME="$user"
view raw gistfile1.txt hosted with ❤ by GitHub

Now that you have the edits done, keep going through the technical paper, running the custom.sh script next to build the Custom folder we will need in a minute, and to download the installers. The custom.sh script will download the installers for Windows, Mac, and Linux, and slipstream the Custom folder into the installer package for us. In our case, since we are only concerned with the Mac installer, it places a hidden .Custom folder at the root of the DMG. We want that folder. So follow along in the tech paper to mount the Mac installer DMG and copy the .Custom folder out somewhere.

Package It All Up

We are going to need to deploy these custom settings alongside the CrashPlan installer. The tech paper has you using Composer (no surprise since it is their product), but I personally like to use Packages for my packaging fun. I’m not going to get into a discussion about what the best packaging method is, because that’s like debating which Star Trek movie was the best.

Using your method of packaging, create a package that drops that Custom folder (notice we are dropping the period so it is not hidden) into the following location:

/Library/Application Support/CrashPlan

Now that we’ve got our custom settings, we can move over to the JSS to work on our deployment. I’m going to skip discussing how to do this via Self Service, and instead stick with either a Login trigger or Recurring Check-In trigger. But first things first, go ahead and upload that custom settings package you just created into the JSS. Once it’s uploaded set the priority to something low, like 8:

 

Screen Shot 2016-02-12 at 12.05.44 PM

Create Your Policies

The tech paper discusses uploading the CrashPlan installer along with the custom properties, but I like the method that is discussed in this JAMF Nation post. It’s towards the bottom, and basically it uses curl to download the installer from the CrashPlan server. This method insures you have the latest version for your server. Of course, if you are trying to deploy to end users around the globe that may not have curl access to your CrashPlan server, uploading the installer to Casper may be your only option. For me, however, it was not.

First step is to create a new script in the JSS (or upload a script if your scripts are not stored in the database). The script itself is nothing special, it checks for the presence of the CrashPlan launch daemon, and if it is there unloads it and removes CrashPlan. Then the script continues on to install the custom properties (via a second policy) and finally installs CrashPlan:

Screen Shot 2016-02-12 at 12.14.24 PM.png

Screen_Shot_2016-02-12_at_12_28_13_PM.png

#!/bin/sh
# unload CrashPlan LaunchDaem if it exists
if [[ -e /Library/LaunchDaemons/com.crashplan.engine.plist ]]; then
launchctl unload /Library/LaunchDaemons/com.crashplan.engine.plist
/Library/Application\ Support/CrashPlan/Uninstall.app/Contents/Resources/uninstall.sh
rm -rf /Library/Application\ Support/CrashPlan
fi
# install the custom properties folder
jamf policy -event CrashInstall
# now install CrashPlan
curl http://yourserveraddress:4280/download/Code42CrashPlan_Mac.dmg > /var/tmp/CP.dmg
hdiutil attach /var/tmp/CP.dmg
installer -pkg /Volumes/Code42CrashPlan/Install\ Code42\ CrashPlan.pkg -target /
hdiutil detach /Volumes/Code42CrashPlan
rm -rf /var/tmp/CP.dmg
view raw gistfile1.txt hosted with ❤ by GitHub

As you can see, I’m using a second policy to install the custom properties. You could do everything with one policy and two scripts, or one policy and curl the custom properties from another location. The key point is that if you are removing an existing installation (like I was), you cannot install the custom properties until you are done removing the existing. Make sense?

Now that we have all of our pieces and parts up there, you will create your two policies, one to install the custom properties and the other to run the script.

To Trigger Or Not To Trigger

With your policies created, you now need to determine how you want to trigger these policies. Obviously you will need to trigger one from within the script, but what about the main policy that kicks it all off? Well, I would probably do this via a recurring check-in trigger. It keeps the user from having to wait for the policy to complete before their login completes.

Of course, you could use the login trigger and throw up a nice notification using jamfHelper, Notification Center, or CocoaDialog. That sounds like a nice post for another day.

I Didn’t Do It

I cannot take the credit for this process. It was people like Bob Gendler and Kevin Cecil on JAMF Nation, along with the folks at JAMF and Code42, that did the heavy lifting. I just put it all into one location for me to remember later.

What’s Your Extension

February 21, 2014 1 comment

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:

https://gist.github.com/anonymous/7346191

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:

https://gist.github.com/anonymous/7346262

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:

https://gist.github.com/anonymous/7346277

Keyboard or Mouse Battery Percentage

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

Keyboard:  https://gist.github.com/anonymous/9135830

Mouse:  https://gist.github.com/anonymous/9135844

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:

https://gist.github.com/anonymous/9135868

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.

Categories: Tech Tags: , ,