How to Customize and Silently Deploy Cisco AnyConnect 4.x

If you’re an existing 3.x consumer of Cisco AnyConnect you may be surprised when you load up the 4.x installer and find your users have a plethora of additional features; like Web Security, System Scan, Roaming Security and AMP Enabler.ciscoanyconnect-all

If these are features you’re planning on using, great, you’re all set.  If you were just hoping to leverage the VPN, well, all is not lost.  You can easily customize the installer, providing it a set of instructions indicating what modules you want installed and what modules you want blocked – and it’s all done via a simple PLIST file.

I’ve included the entire example PLIST I used to block everything but the VPN as well as the installer script for LANDESK on my GitHub site here.

Let’s discuss the PLIST first.  Here is an example of one of the dictionary objects found in the PLIST file, in this case it is for the VPN feature.

 <dict>
    <key>attributeSetting</key>
    <integer>1</integer>
    <key>choiceAttribute</key>
    <string>selected</string>
    <key>choiceIdentifier</key>
    <string>choice_vpn</string>
 </dict>

Basically we have a dictionary of values that define the module and tell the installer of whether it should be installed by setting the Integer value to 1.  If you want to block the given module, set the integer value to 0.  Look at the string value to figure out what module you’re enabling or disabling.

You shouldn’t need to adjust any of the other settings.  So go ahead and download the example PLIST file I have on my GitHub site and finish customizing it for your environment.  My PLIST file has everything disabled  outside of the VPN.  If you were to manually install the application, you’d see the window below.  manualinstallciscooptions

Now that you have your PLIST ready to go, you need to save it as ‘ChoiceChangesCiscoAnyConnect.plist’ so it can be properly referenced in our installer script.  If you save it as something else, just make sure you make the appropriate change in your installer script.

OK, we’re now ready to create the installer script.  For simplicity, I’m going to build my installer script to do both the downloading of the AnyConnect package file, the PLIST file we just created and then it’ll kick off the installer – all using SDClient so I can take advantage of the bandwidth and throttling settings.

The entire installer script is pasted below.  In your environment, you’ll likely only need to change the plistFilePath and packageFilePath variables.  The script copies everything to a folder titled CiscoAnyConnect inside of sdcache.  I  purposely chose to put everything in the sdcache folder as the script doesn’t purge anything when finished, letting the standard sdcache cleanup process take care of that at the appropriate time.

Once you have your paths set, you should be ready to go.  You’ll notice that SDClient is used, with several arguments, to download the files.  The -noinstall argument is quite obvious, it tells SDClient to just download and not do anything else.  The -package is telling SDClient where to obtain the file and the -destdir argument is telling SDClient where to copy the file to.

/Library/Application\ Support/LANDesk/bin/sdclient -noinstall -package "$packageToCopy" -destdir "$destinationLocation"

As mentioned before, the script copies down the PLIST file and the Cisco installer.  If you have a DMG version of the Cisco Installer, just mount it on a Mac and copy out the AnyConnect.pkg from the DMG.  I copied mine directly to my standard SWD file share.

Then the scripts wraps up by executing the AnyConnect.pkg installer with a few arguments as well.  We tell macOS we want it to run a pkg intsaller and point to where that file is.  In my example, it’s in the /Library/Application Support/LANDesk/sdcache/CiscoAnyConnect folder.  I leave the -target path empty, basically letting the installer put where it’s designed to.  I then add the flag -applyChoiceChangesXML so that it knows customization is to be performed and I supply the path to that name/file.

installer -pkg "$destinationLocation"/"$packageName" -target / -applyChoiceChangesXML "$destinationLocation"/"$plistName"

And that’s it.  You now have everything you need to deploy your package.  Save out your installer script, I named mine ciscoAnyConnect4.3Deploy.sh but you can name yours whatever you want.

As always, once saved, make sure you give the script the execution permissions by opening Terminal and running:

sudo chmod +x /path/to/script.sh

Now copy your installer script to your LANDESK SWD file share.  I used the same path for my script, PLIST file and AnyConnect.pkg installer.

Once you’ve copied up your script, you just need to create your LANDESK Mac package so you can target and silently deploy Cisco AnyConnect with all of your customizations.

Creating LANDESK Management Suite Mac Packages

  1. Open the LANDESK Console
  2. Navigate to the top menu bar, select Tools > Distribution > Distribution Packages.
  3. In the lower left menu tree, highlight My Packages or Public Packages from within the Distribution Packages window
  4. On the Distribution menu bar, press the New Package button and select New Macintosh Agent package.
  5. Give the package a name
  6. Provide a description as well as any metadata information desired
  7. Set the primary file to the script file you previously transferred to your package share
  8. Fill out the Metadata details if desired, specifically supplying a logo so it shows up properly in the portal
  9. Save the package

Creating a Scheduled Mac Software Distribution Task

  1. Right click on the Mac software distribution package created and select Create Scheduled Task
  2. From the network view, select and drag the desired machine(s), user(s) or query(ies) and drop them onto the task
  3. Now, right click on the task and select properties
  4. Set the desired Task type under Task Settings as to whether you want a push, a policy or a hybrid of the two types in a policy-supported push
  5. Set the radio button in the Portal Settings to either Recommended or Optional if you desire to put the package into Workspaces.  If you’d like to automatically deploy the app, select Run automatically
  6. Change the Reboot Settings or Distribution and Patch settings if desired
  7. Set the schedule task settings with the appropriate start time

PLIST File

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
 <dict>
 <key>attributeSetting</key>
 <integer>1</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_vpn</string>
 </dict>
 <dict>
 <key>attributeSetting</key>
 <integer>0</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_websecurity</string>
 </dict>
 <dict>
 <key>attributeSetting</key>
 <integer>0</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_fireamp</string>
 </dict>
 <dict>
 <key>attributeSetting</key>
 <integer>0</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_dart</string>
 </dict>
 <dict>
 <key>attributeSetting</key>
 <integer>0</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_posture</string>
 </dict>
 <dict>
 <key>attributeSetting</key>
 <integer>0</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_iseposture</string>
 </dict>
 <dict>
 <key>attributeSetting</key>
 <integer>0</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_nvm</string>
 </dict>
 <dict>
 <key>attributeSetting</key>
 <integer>0</integer>
 <key>choiceAttribute</key>
 <string>selected</string>
 <key>choiceIdentifier</key>
 <string>choice_umbrella</string>
 </dict>
</array>
</plist>

Installer Script

#!/bin/sh

# ciscoAnyConnect4.3Deploy.sh
# Created by Bennett Norton on 11/30/16.


#File to copy
#change this to match your hosted path, it needs to be http
plistName="ChoiceChangesCiscoAnyConnect.plist"
packageName="AnyConnect.pkg"
plistFilePath="http://yourFileShareServer/Path/To/PLIST"
packageFilePath="http://yourFileShareServer/Path/To/CiscoAnyConnect"
packageToCopy="$packageFilePath"/"$packageName"
plistToCopy="$plistFilePath"/"$plistName"

#Location to copy file to
#change this to match your destination path
destinationLocation='/Library/Application\ Support/LANDesk/sdcache/CiscoAnyConnect'

#Check to see if destination exists and if not, create it
if [ ! -d "$destinationLocation" ]; then
echo "Location doesn't exist. Creating directory"
mkdir $destinationLocation
echo "$destinationLocation created"
fi

#Download and execute command
#You shouldn't need to make any changes here
#-noinstall ensure the package does not get executed when downloaded
#-package is the source url path
#-destdir is the destination url path
/Library/Application\ Support/LANDesk/bin/sdclient -noinstall -package "$packageToCopy" -destdir "$destinationLocation"
/Library/Application\ Support/LANDesk/bin/sdclient -noinstall -package "$plistToCopy" -destdir "$destinationLocation"
installer -pkg "$destinationLocation"/"$packageName" -target / -applyChoiceChangesXML "$destinationLocation"/"$plistName"

7 thoughts on “How to Customize and Silently Deploy Cisco AnyConnect 4.x

  1. Hi Bennett. This is very helpful but I’m having an issue. The package fails but it does download the .pkg, the .plist and the .sh file to the target machine. It just doesn’t install it.

    I ran the .sh manually on the machine and I get this: installer: choices file ‘/Library/Application Support/LANDesk/sdcache/CiscoAnyConnect/ChoiceChangesCiscoAnyConnect.plist’ either could not be found or was malformed.

    I verified the path and that the plist could be opened and even changed the permissions on it. Still doesn’t work though.

    Any thoughts? Thanks!

    Like

  2. Thanks for the reply. I built it in Xcode. I tested using your method and it checks out fine. I couldn’t figure out how to actually download the one on your GitHub site so I copied it.

    Like

    1. OK, it may be a syntax error then in your shell script path. Try adding a backslash after Application\. Example /Library/Application\ Support/LANDesk/sdcache/CiscoAnyConnect/ChoiceChangesCiscoAnyConnect.plist. If that doesn’t work, email me your plist and scripts and I’ll take a look.

      Like

  3. So I had to change that line because is was creating a new folder called “Application\ Support” in the Library folder with the \ in at the end of Application instead of just putting it into the regular “Application Support” folder (the package failed that time too). Once I changed the script to ‘/Library/Application Support/LANDesk/sdcache/CiscoAnyConnect’ it put them into the normal directory. I’m happy to email you my shell script and plist file if you can provide your email address. Thanks again! I appreciate the help!

    Like

  4. OK, looks like the PLIST being used had some extra tags, something the Cisco installer wasn’t expecting and causing it to fail. These tags may have been caused by Xcode when generating the file.

    Like

Leave a comment