Wednesday, May 18, 2016

Xcode Applescript, Part II

The JSS Side - Reading that data in:
In the last article (http://tmhoule.blogspot.com/2015/10/empower-your-users-with-simple-xcode.html) we created a simple application which writes a flag to the computer specifying if we could run updates on the computer or not.  Your checkbox could be for other things.  And once we get this app working, you can add other information that may be relevant in your environment - perhaps what software a computer is licensed for? or the name of the person responsible for the computer?

Now that the data is saved on the computer, we need to see it in our JSS so we can work with it.  To do that, we create an Extension Attribute.  The JSS has lots of built in items it looks for when running Inventory, such as Operating System version and RAM.  To look for things that are not there, JAMF allows us to write scripts to collect that information.

Click Settings -> Computer Mangagement -> Extension Attributes.  From there, click the + to create a new one.  Extension Attributes are run every time the computer does an inventory (recon).

To continue our last project, lets create an EA that shows the status of the AllowUpdates setting we were playing with last time. 

Give the EA a name - perhaps AllowUpdates so it is consistent and a description that makes sense to you.  We are collecting a boolean, but lets set the Data Type to 'String'.  The Inventory Display controls what tab the EA shows up in when looking at a computer record.  The Input Type should be Script.  This is the fun part.

Enter the following script.

#!/bin/sh
setting=`defaults read /Library/Preferences/com.toddCo.manage.plist AllowUpdates`

if [ $setting == 1 ]; then
    answer="True"
elif [ $setting == 0 ]; then
    answer="False"
else
    answer="No data"
fi


echo "<result>$answer</result>"



Then click Save.  The setting line runs the defaults command to get the AllowUpdates value it is currently set to and saves it in a variable called 'setting'.   The different if lines turn that 1 or 0 into something more understandable when we look at it in our JSS. 

Now if you go to a computer and Update Inventory (type jamf recon in Terminal).  When you look at that computer in the JSS, you should see AllowUpdates and either True or False.  If you get No Data, then you haven't run the program on that computer yet. 

Smart Groups:

Now it's time to build a group of computer in the JSS that allow us to update their computers.  In your JSS, click Smart Computer Groups on the left and click the + to create a new group.  Give it a name that fits such as 'Software Updates OK' and click Criteria.  Under Criteria, click + sign.  At the bottom of the list click Choose next to All Criteria and look for your EA.  In the example, we named it AllowUUpdates.  Click Choose next to it.  Leave the Operator set to 'is' and in the Value enter "True".  


Then click Save.  Now you have a group of computers that have run your program and checked that box allowing you to update them.  

So create a policy set to run Software Updates and set the scope to your new group.  Go ahead and update them - you've got their permission!


Hopefully, now you see the value of saving data with a local application, then reading it into your JSS.  You can flag computers that are kiosks so they be rebooted at convenient times- or servers so they can be rebooted only when the right people have been notified.  You may want to put in the name of a person responsible for a shared computer, should it need some attention. 

Friday, May 13, 2016

Adobe CC local server and RUM

If you have any significant installation of Adobe Creative Cloud products in your environment, it may makes sense for you to run a local Adobe update server which is basically a copy of all Adobe CC updates hosted on your own machine and server with the web server of your choice.

There are two major benefits to running this server.  First, you're speeding up the update process on your workstations and saving bandwidth to the Internet.  Second, having a local server allows you to control what updates are available to your machines. I run three servers so that I can have DEV, TESTING, and PRODUCTION.

You can also invoke Adobe's command line tool called Remote Update Manager (RUM) to look for updates and apply them. 

This guide will go over setting up your Adobe server and running RUM on your workstations.  I'll reference Apple Mac computers, but RUM works on Mac and Windows computers.  Sadly, the tool to sync your local Adobe Update repository with Adobe's doesn't work under Linux; it's Mac or Windows only. 

Setting Up a Server
All you really need is a Mac or Windows computer with a web server on it. You may need to modify the mime types when running under IIS, but that's not really too hard.  Then run the sync tool when you're ready.

Setting up the Webserver
You Mac has a web server built in.  It called Apache and is the server used by the majority of websites in the world.  To start it up, open Terminal and type.
     sudo apachectl start
You can verify it is working by opening a web browser and visiting http://localhost/   You should see "It Works!" which is a basic web page that comes with Apache.  Those web pages are kept in /Library/WebServer/Documents folder.  Open that path and create a folder in there called AdobeUpdates (no spaces).

Setting up AUSST
Now you need Adobe's AUSST tool (Adobe Update Server Setup Tool).  On your Mac, assuming you've installed Adobe Creative Cloud software (such as Photoshop or Illustrator), you can find it in /Library/Application Support/Adobe/OOBE/PDApp/CCP/utilities/AUSST    If you have Adobe Creative Suite installed on a different computer, you can copy the AdobeUpdateServerSetupTool to your webserver now. 

Sync Updates with Adobe
Once you have a web server running and have the AdobeUpdateServerSetupTool, you can run it to get the data from Adobe.  It'll download anywhere from 50 to 100 GB of data so be prepared!  Run the command line tool and pass it the parameters 'fresh' and the path to store the updates. 

<AUSST> <--fresh> </path/to/updates>

Example:
sudo /Library/Application\ Support/Adobe/OOBE/PDApp/CCP/utilities/AUSST/AdobeUpdateServerSetupTool --fresh /Library/WebServer/Documents/AdobeUpdates

That will start updates downloading. In the future to get changes from Adobe, you just need to run AUSST with the --incremental flag. --fresh is only for the first time you run it.

sudo /Library/Application\ Support/Adobe/OOBE/PDApp/CCP/utilities/AUSST/AdobeUpdateServerSetupTool --incremental /Library/WebServer/Documents/AdobeUpdates

Testing your server
Now is a good time to make sure everything works.  From a different computer, open a web browser and make sure you can connect to your webserver.  Enter the computer name or IP address into that web browser and you should see the 'It Works' page you saw in the beginning.

You should also be able to type in
     http://yourserver.com/AdobeUpdates/webfeed/oobe/aam20/mac/updaterfeed.xml
You should either see the file which looks like XML text, or get a parsing message about XML.  As long as you don't get file not found or can't connect to server. 

Configuring Clients
The Adobe CC programs on your company's workstation need to know about your server and be directed to get updates from there instead of directly from Adobe. To do that, they need a configuration file.  You can either create that manually and deploy them (one Mac and one Windows), or have the AUSST tool create it for you.

To have AUSST create it for you, enter a command like the following
<AUSST> --genclientconf=<path to where to save configs> --root=<path to updates> --url=<Server URL>

If you've been following along at home, your command should look like

sudo /Library/Application\ Support/Adobe/OOBE/PDApp/CCP/utilities/AUSST/AdobeUpdateServerSetupTool 
    --genclientconf=/Library/WebServer/Documents/AdobeUpdates/configs   
    --root=/Library/WebServer/Documents/AdobeUpdates 
    --url=http://servername/AdobeUpdates

This should be on one line, but formatting limits it here.

So now in the path specified in the genclientconf line, you'll have a mac folder and win folder.  Each has a file called AdobeUpdater.Overrides.  That file, when in the correct location on a client machine, instructs Adobe applications to check your server for updates instead of going out to Adobe's servers.  Copy that file to:
   In Mac OS X:
   /Library/Application Support/Adobe/AAMUpdater/1.0/AdobeUpdater.Overrides
   In Windows XP:
   \Documents and Settings\All Users\Application Data\Adobe\AAMUpdater\1.0\AdobeUpdater.Overrides
   In Windows 7/Vista:
   \ProgramData\Adobe\AAMUpdater\1.0\AdobeUpdater.Overrides
Your favorite management tool comes in handy here.

Testing it all out

If you've gotten this far, it's time to give it a try.  Open your favorite Adobe application, then from the Help menu, choose Check for Updates.  It doesn't matter if any are available or not - you can still see if it worked by going back to your server.  Open /Applications/Utilities/Console.   On the left, look under /var/log for apache2.  If you expand that disclosure triangle, you'll see access_log.  Select that and you should see an entry from the machine you just checked from.  Do it again, and watch the log file.  If an update is available, you'll see lots of lines as updates are downloaded.

RemoteUpdateManager (RUM)
If you remotely manage your machines with a tool such as JAMF Casper, you can create a policy to update applications using the RemoteUpdateManager (RUM).  Create a policy in your JSS with a 'Files and Processes' section Execute Command set to "/usr/local/bin/RemoteUpdateManager --action=install"    If any Adobe applications are currently open, the install will fail and the user will not be interrupted. 



Ongoing Work
Now that you have your own server, you'll need to update it occasionally.  Use the --incremental line from above to re-sync with Adobe and make updates available to your clients.

Next Time
In the next article of this series,  we'll incorporate a TEST server so that updates can be tested before being released to your computers. 

Wednesday, May 11, 2016

Extending App Update Tool

Extension Attribute
The first Article was about the App Update Tool.  It's a suite of scripts to allow you to update applications on your Mac.  This article will describe the Extension Attribute included with those scripts.

I wanted to know if the App Update Tool was running properly on computers.  Perhaps the LaunchD was removed? Perhaps a user edited or deleted the script so it would stop interruption of other work? 

In the Download Package is the Extension Attribute (EA) called 'UpdateToolEA.sh'.  If you are unfamiliar with JAMF Extension Attributes, they are scripts which run on machines when the 'Run Inventory' once a day and return whatever result they are configured to return.

This EA returns "Running OK" if all looks good, else it'll return if something has been edited or not running.  I have a Smart Group of 'Not 'running ok'' and just reinstall the client package on those machines. 

If you edit any of the client side scripts, you'll need to generate the MD5 of that file and add that to the EA.  To do that,
Go to a client machine which has the client scripts as you want them (you done making any edits?).  Then type
myMac$ md5 -q /usr/local/updateTool/updateInstaller.sh
b28d74377f41a6994f521b422e21d56f
That MD5 value will change if the script is edited.  So copy/paste that into the Extension Attribute.  The three scripts are
/usr/local/updateTool/updateInstaller.sh
/usr/local/updateTool/updateKicker-overdue.sh
/usr/local/updateTool/updateKicker-popup.sh 

There are three LaunchDaemons to start each of those scripts. 
/Library/LaunchDaemons/edu.todd.ll.updateToolInstaller.plist
/Library/LaunchDaemons/edu.todd.ll.updateToolKickerGUI.plist
/Library/LaunchDaemons/edu.todd.ll.updateToolKickerOverDue.plist
type md5 -q for each of those to get the correct MD5 to enter into your EA.

You can find the Extension Attribute in the Download Package App Update Tool.  Edit the EA so the correct MD5 values are in it.

Wednesday, May 4, 2016

Finding your $PATH

Finding your $PATH
..And other Environment Variables


When scripting, many users will develop a script on their own computer and get it all sweet just right.  However, when deploying the script with a management tool, such as JAMF Casper, the script may fail.  One of the primary reasons is the path to a command may not be available in the environment used to run your script.

What does that mean?  It means that those different commands you type in Terminal are applications that are saved in different folders on your computer.  Sometimes, the computer knows where to look for them, sometimes not. 

When you open Terminal, your session starts with some settings in place.  Those settings are saved in Environment variables seen by typing printenv in Terminal. 

MyMac$ printenv
TERM_PROGRAM=Apple_Terminal
TERM=xterm-256color
SHELL=/bin/bash
TMPDIR=/var/folders/0t/l5h4xta2m30z8brekdsm3_cp0l/T/
TERM_PROGRAM_VERSION=361.1
EDITOR=emacs
USER=tman
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
PWD=/Users/tman/Documents/CODE/NewProject
LANG=en_US.UTF-8
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
HOME=/Users/tman
SHLVL=1


The PATH variable is the one we are interested in here.  We can see the defined path by running echo and the variable name. 

MyMac$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin


Here we have five different directories which can contain terminal commands.  Have you ever used diskutil or grep?  You can find out which directory a program is in by typing 'which' and the command name.

MyMac$ which grep
/usr/bin/grep
MyMac$ which diskutil
/usr/sbin/diskutil


which is actually a program itself.

MyMac$ which which
/usr/bin/which



So when you type a program to run, 'sudo' for example, the computer searches those directories in your PATH variable to find it.  Once it finds a program name that matches, it tries to run it for you.

Back to the original problem.  What happens when you run your nice script from an MDM?  Well, the PATH environment variable may not be set so the computer can't find the program you are referencing.  Say in your script, you are running

diskutil mount /tmp/Wonderapp.dmg
installer -pkg /Volumes/Wonderapp/Wonderapp.pkg -target / 

And that fails in your script when run through Casper or other MDM.  One possible reason is that when it runs from Casper, the Environment variables are not set so the computer can't find 'disktutil' or 'installer'. 

While you could define the path in the beginning of your script:

export PATH=$PATH:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

The more common solution is to simply specify the full path to the program you are using. 

/usr/sbin/diskutil mount /tmp/Wonderapp.dmg
/usr/sbin/installer -pkg /Volumes/Wonderapp/Wonderapp.pkg -target /

You can see from the export line above how we add to the PATH variable.   The $PATH variable in the command means 'everything that's in PATH now' and add this other stuff to it.  If you have a directory with a command line tool you use which is not in your PATH, you can add it so you don't always need to type the full path to the program.  For example, I have a directory on my computer with programs I've written.  It's in /Users/tman/Documents/CODE/   So instead of specifying that path when I want to run one, I can simply add that directory to my PATH variable.

export PATH=$PATH:/Users/tman/Documents/CODE

Now when I run my app, the computer (or BASH actually) will 'look' into my CODE directory for that program.

SECURITY HINT: Many GreyBeards (old linux guys with long grey beards) will type the full path to 'sudo' and other programs that require passwords when running.  It's possible that someone puts a malicious copy of 'sudo' on your computer so when you try to run it and enter your password, it actually emails a copy of your password to them.  So the GreyBeards will always type /usr/bin/sudo to make sure the right copy is run and nobody has a second copy to run in it's place. 

Changes to your PATH variable, or other environment variables are only valid in that terminal session and are reset each time you open Terminal.  If you'd like that setting to stay, you need to add it to your bash_profile file.  That file, if it doesn't already exist, can be saved in your home directory. 

nano ~/.bash_profile

Notice the period before bash.  Any file that starts with a period is hidden from normal view. Add that same text as above.  

export PATH=$PATH:/Users/tman/Documents/CODE

Nano is a simple text editor.  You could edit with TextWrangler or another app, but since we're in the command line anyways....    Follow the on screen instructions to save and edit.  That command will automatically add my CODE directory to my path each time I start Terminal.