PRE-READ DISCLAIMER
2017-03-16 - There's been a lot of discussion regarding this post pertaining to security - and rightfully so!
That being said, I can not gauge or assign a value to your own internal risk assessment methodology. In other words, I take no responsibility for when and how you use this script should you decide to do so. This is entirely up to you. For myself and my DevOps and SecOps teams, this workflow warrants "low risk". You and your team may see this differently. YMMV.
Now, onto the post at hand...
INTRODUCTION
Hey everyone! It's me... AGAIN!
One of the things that I love to do is to automate things. I once had a college instructor who said, "If you're working and not automating, then you're not doing your job correctly." I took those words to heart and they have served me well in my career!
On the heels of automation is the idea of DIY - In other words, automation for me equals DIY for my user-base.
For those of us who use JAMF Pro (formerly know as Casper Suite) day in and day out, we are well aware of how powerful Self Service can be in giving us this level of automation.
But at times, even Self Service, when left to its own devices, falls short.
So let's automate the automation!
In my workplace, our user community relies upon RingCentral, a VOIP provider. RingCentral provides various apps for desktop and mobile, etc.
My users who need the RingCentral for Mac desktop app can easily log into the RIngCentral Portal, go to the correct location, download and install the latest version of the app. That's great. But...
What if there was a way to make it even easier for my user community, especially for new hires or for those users in a hurry?
As the admin, we could certainly log into RingCentral ourselves and download the DMG file, unarchive the PKG file and upload said PKG to our JAMF Distribution Server.
As the admin, we would also be held accountable for maintaining that software's upkeep in a timely manner, whenever the vendor releases software updates, etc.
Well my friends... Ain't nobody got time for dat!
Since the vendor is already doing the heavy lifting with regards to updates, why not leverage that to your own benefit!
Many vendors make their software available to download on their web sites or FTP sites, etc. So here is a way to tie that into your existing Self Service infrastructure...
This particular workflow was designed for use with RingCentral's "RingCentral for Mac" application, but it can be tweaked and hacked to meet your needs with other vendors (i.e. Google Chrome comes to mind).
There's also the additional benefit of not hosting the software on your own server and having a slight reduction in bandwidth utilization.
Let's get started...
PART 1 - BUILD A SCRIPT
We are going to need a script that does the bulk of the work for us.
- Log into your JSS and navigate to Settings > Computer Management > Scripts
- Click the "+" button to create a new script
- Under the "General" tab, set these values:
Display Name: RingCentral.sh Category: Software (NOTE: If you don't have a Software Category, you can create one in Settings > Global Management > Categories) - Under the "Script" tab, copy and paste this script into the "Script Contents" field:
#!/bin/sh
####################################################################################################
#
# RingCentral for Mac.app Installation Script
#
####################################################################################################
#
# DESCRIPTION
#
# Automatically download and install or upgrade the latest version of the
# RingCentral for Mac.app VOIP application
#
####################################################################################################
#
# HISTORY
#
# Created by Caine Hörr on 2017-03-14
#
# v1.2 - 2017-03-16 - Caine Hörr
# Set all URLs to use https (SSL)
# Added the following line: echo "Downloading from:" ${VendorURL}${VendorRelativeFilenamePath} for logging purposes
#
# v1.1 - 2017-03-15 - Caine Hörr
# Added -i flag to VendorRelativeFilenamePath="$( curl -sI $VendorDownloadURL | grep -i "location" | awk '{ print $2 }' )"
# Added sudo to sudo rm -rf /Applications/RingCentral for Mac.app
#
# v1.0 - 2017-03-14 - Caine Hörr
# Initial RingCentral for Mac.app Installation Script
#
#
# THESE VALUES ARE EDITABLE...
#
# Vendor URL
VendorURL="https://downloads.ringcentral.com"
# Vendor Download URL
VendorDownloadURL="https://downloads.ringcentral.com/sp/RingCentralForMac"
# Local directory to save to...
LocalSaveDirectory="/tmp/"
# DMG Mount Point
DMGMountPoint="/Volumes/RingCentral for Mac"
#
# DO NOT EDIT BELOW THIS LINE
#
# Check to see if RingCentral for Mac already exists in /Applications
CheckForRingCentralApp="$(ls /Applications/ | grep "RingCentral for Mac")"
if [ "$CheckForRingCentralApp" = "RingCentral for Mac.app" ]; then
echo "RingCentral for Mac.app currently installed..."
# Check to see if RingCentral for Mac is running
RingCentralRunning="$(ps aux | grep "/Applications/RingCentral for Mac.app/Contents/MacOS/Softphone" | awk '{ print $11 }' | grep "/Applications/RingCentral")"
if [ "$RingCentralRunning" = "/Applications/RingCentral" ]; then
echo "RingCentral for Map.app is running..."
echo "Quitting RingCentral for Mac.app..."
# Gracefully Quit RingCentral for Mac.app
osascript -e 'quit app "RingCentral for Mac"'
else
echo "RingCentral for Map.app is not running..."
fi
echo "Deleting /Applications/RingCentral for Mac.app..."
rm -rf /Applications/RingCentral for Mac.app
else
echo "RingCentral for Mac.app not currently installed..."
fi
echo "Installing latest version of RingCentral for Mac.app..."
echo ""
# Vendor Relative Path to File
VendorRelativeFilenamePath="$( curl -sI $VendorDownloadURL | grep Location | awk '{ print $2 }' )"
echo "Downloading from:" ${VendorURL}${VendorRelativeFilenamePath}
echo
# Remove
(CR) at the end ( 0d )
VendorRelativeFilenamePath=${VendorRelativeFilenamePath%$'
'}
# Vendor Dynamic Filename as Downloaded
VendorDynamicFilename="${VendorRelativeFilenamePath##*/}"
# Vendor Full Download URL
VendorFullDownloadURL=${VendorURL}${VendorRelativeFilenamePath}
# Download vendor supplied DMG file to local save directory
curl ${VendorFullDownloadURL} -o ${LocalSaveDirectory}${VendorDynamicFilename}
# Mount vendor supplied DMG File
echo "Mounting" ${LocalSaveDirectory}${VendorDynamicFilename} "..."
hdiutil attach ${LocalSaveDirectory}${VendorDynamicFilename} -nobrowse
# Copy contents of vendor supplied DMG file to /Applications/
# Preserve all file attributes and ACLs
echo "Copying RingCentral for Mac.app into the /Applications/ folder..."
cp -pPR /Volumes/RingCentral for Mac/RingCentral for Mac.app /Applications/
# Identify the exact mount point for the DMG file
ProperDMGMountPoint="$(hdiutil info | grep "$DMGMountPoint" | awk '{ print $1 }')"
# Unmount the vendor supplied DMG file
echo "Unmounting" ${ProperDMGMountPoint}"..."
hdiutil detach $ProperDMGMountPoint
# Remove the downloaded vendor supplied DMG file
echo "Removing" ${LocalSaveDirectory}${VendorDynamicFilename}"..."
rm -f $LocalSaveDirectory$VendorDynamicFilename
# Launch RingCentral for Mac.app
open /Applications/RingCentral for Mac.app
echo "Installation complete!"
- Click the "Save" button
PART 2 - BUILD A COMPUTER POLICY
Now that the script building part is done, let's build a policy that interfaces with Self Service.
- Navigate to Computers > Policies
- Click the "+" button to create a new policy
- Under the "Options" tab, set these values:
General Display Name: RingCentral for Mac (Latest Version) Enabled: Checked Category: Software Execution Frequency: Ongoing Make Available Offline: Checked Scripts RingCentral.sh Priority: Before - Under the "Scope" tab, set these values:
Targets Target Computers: All Computers Target Users: All Users - Under the "Self Service" tab, set these values:
Make the policy available in Self Service: Checked Button Name: Install Description: Install the latest version of the RingCentral for Mac softphone application. Ensure that users view the description: Checked Icon:
(Right-click the icon image and save as "RingCentral_icon_128x128.png") - Click the "Save" button
PART 3 - MANUALLY UPDATE SELF SERVICE
To quickly test your configuration, run these commands to update Self Service.
sudo jamf manage -verbose
NOTE: Either close Self Service before running the aforementioned command or if you leave Self Service open, right click on Self Service and click on "Reload".
DEVELOPER NOTES
You're probably wondering why I have so many "echo" commands in my scripts since the end user will never actually see the output from within Self Service. As it turns out, when you use "echo", the output is reflected within the associated Policy log. Here is a sample output after the script has been run...
[STEP 1 of 4]
Executing Policy RingCentral for Mac (Latest Version)
[STEP 2 of 4]
Running script RingCentral.sh...
Script exit code: 0
Script result: RingCentral for Mac.app currently installed...
RingCentral for Map.app is running...
Quitting RingCentral for Mac.app...
Deleting /Applications/RingCentral for Mac.app...
Installing latest version of RingCentral for Mac.app...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
1 89.4M 1 1399k 0 0 2249k 0 0:00:40 --:--:-- 0:00:40 2247k
9 89.4M 9 8555k 0 0 5317k 0 0:00:17 0:00:01 0:00:16 5317k
18 89.4M 18 16.8M 0 0 6611k 0 0:00:13 0:00:02 0:00:11 6609k
27 89.4M 27 24.3M 0 0 6925k 0 0:00:13 0:00:03 0:00:10 6923k
38 89.4M 38 34.4M 0 0 7660k 0 0:00:11 0:00:04 0:00:07 7658k
48 89.4M 48 43.2M 0 0 7891k 0 0:00:11 0:00:05 0:00:06 8595k
58 89.4M 58 52.6M 0 0 8162k 0 0:00:11 0:00:06 0:00:05 9076k
69 89.4M 69 62.2M 0 0 8356k 0 0:00:10 0:00:07 0:00:03 9264k
80 89.4M 80 72.0M 0 0 8573k 0 0:00:10 0:00:08 0:00:02 9762k
90 89.4M 90 81.0M 0 0 8637k 0 0:00:10 0:00:09 0:00:01 9539k
99 89.4M 99 89.0M 0 0 8596k 0 0:00:10 0:00:10 --:--:-- 9386k
100 89.4M 100 89.4M 0 0 8605k 0 0:00:10 0:00:10 --:--:-- 9332k
Mounting /tmp/RingCentralForMac-8.4.5.dmg ...
Checksumming whole disk (Apple_HFS : 0)…
whole disk (Apple_HFS : 0): verified CRC32 $21478FE1
verified CRC32 $2709DA68
/dev/disk3 /Volumes/RingCentral for Mac
Copying RingCentral for Mac.app into the /Applications/ folder...
Unmounting /dev/disk3...
"disk3" unmounted.
"disk3" ejected.
Removing /tmp/RingCentralForMac-8.4.5.dmg...
Installation complete!
[STEP 3 of 4]
[STEP 4 of 4]
Now, isn't that nice?! Great for troubleshooting failed installs!
USING THE SCRIPT FROM WITHIN SELF SERVICE
When the user clicks on the "Install" button, this little gem of a script will bypass RingCentral's log in page, find the latest version of the installer, download the installer, check to see if the user already has a version of the app already installed, gracefully quit the app if it's running, install the new app, and launch it so the user can log into the app and get to work.
DISCLAIMER
I have tested this script fairly thoroughly in my own environment with a user-base of ~500 people and we have yet to experience any adverse side effects.
Keep in mind, your environment and requirements may be different. You should always test out before deploying into production.
MORE TO COME
If you know of any ways to make this script better, let me know!
I would like to add functionality that adds the application's icon to the dock as well. I toyed with that a bit but couldn't' get it to work to my satisfaction.
I also wanted to use string variables with the cp (copy) command, but cp was giving me grief so I hard coded everything just to make cp happy. Perhaps I'll revisit.
Anyway, hope you enjoy!
