I have seen several posts on MacAdmin Slack asking for help deploying only components of big packages that the business wants or needs. There are often several ways of handling this. For example, from the McAfee ePO console, your admin can give you a Threat Prevention only installer instead of the full Endpoint Security package. That is great if you can grab that yourself or the admin is helpful and able to get it for you. This isn’t always the case. Another route is to install the full package and then uninstall the pieces that you don’t want/need. The Cisco AnyConnect Secure Mobility client installer does put uninstall scripts for each piece of the package in /opt/cisco/anyconnect/bin. Both of these options can get your Macs to the end state you want, but they do have potential drawbacks/complications. Using the Apple provided installer command line tool, we can see what options are available in these packages and then create a file to set which pieces we want. This does take some work upfront, but we have all the tools we need.
To start we need an installer package that has choices. We will focus on 2, Cisco’s AnyConnect Secure Mobility Client 4.3.03086 and McAfee’s Endpoint Security for Mac 10.2.1. The choices show up in the GUI as selectable check boxes.
To see these choices from the command line and generate the information we need, we use the installer command with the
‑showChoicesXML option and pass it the package we are interested in. Depending on the package, we may also need to specify the target, so I generally always do. Be careful with the target. Some installers will behave differently if some or all of the software is already installed. Installing on a clean system (maybe a VM you can role back) is a good way to see the real default behavior. Notice in the Cisco installer picture above, VPN and WebSecurity are unchecked and grayed out. That is because my target already has those pieces installed on it.
Our command is:
installer ‑showChoicesXML ‑pkg /path/to/AnyConnect.pkg ‑target /
That will print a bunch of information to standard out (the terminal window), so I will often redirect it to a file for saving and easier reading/searching like so:
installer ‑showChoicesXML ‑pkg /path/to/AnyConnect.pkg ‑target / > ~/Desktop/anyconnect_choices.xml
That will output something like:
Notice the individual dictionaries:
This is one of the choices in the package (Umbrella). Notice that the choiceIsSelected key is set to 1. This means that by default on this volume (the target from the command), this choice will be installed. We want to tell the installer command to skip this choice so we want to set choiceIsSelected to 0. To do that we will create our own xml file that has the values we want. The keys that we need are the choiceIdentifier, choiceIsSelected, and whether we want the choice to install (set value to 1) or not install (set value to 0). Our file needs to be valid XML, so we need the appropriate file header. You can create a valid XML file with the built in defaults command but for this, we can just copy the skeleton of our choices.xml we output from installer.
Now we need to add a dictionary for each setting we want to set in this form:
We need to match the choiceIdentifier values to the those in the output of the installer command. This AnyConnect package is setup nicely for easy reading. Not all packages are (more on that later). Then we have our choiceAttribute key (the key we want to change from default) set to ‘selected’ and finally what we want to set that attribute to in the attributeSetting key (in this case we are setting it to 0 so this choice doesn’t install). We only need to add entries for things we want to change from the default. In this case the choices file specifies settings for all possible choices. Once we build up our file, we get something like: This file tells
installer to install VPN and skip the rest.
Now we are ready to test the package. To first verify that things look like they will work, we can use the
‑showChoicesAfterApplyingChangesXML option for installer and see what it will try to do.
installer ‑showChoicesAfterApplyingChangesXML /path/to/choicesForAnyConnect.xml ‑pkg /path/to/AnyConnect.pkg ‑target /
In this output we will see more than one entry for each choice. In this output I have 3, enabled, visible, and selected. Enabled means will the choice be allowed to be changed in the GUI and visible means will it even show up in the GUI. We are only worried about selected as we aren’t going to use the GUI. So confirm that the choices we want to install have selected set to 1 and the choices we want to skip have selected set to 0. Once that all looks correct, we can actually deploy with
‑applyChoiceChangesXML. That looks like
installer ‑applyChoiceChangesXML /path/to/choicesForAnyConnect.xml ‑pkg /path/to/AnyConnect.pkg ‑target /
This can be packaged up for deployment through a management tool pretty easily. Basically you want to put the default package and your choices.xml into the packages resources area and then have a post install script that runs the above command. There is a lot more detail possible, but that might be another blog post.
Cisco’s AnyConnect Secure Mobility installer is pretty friendly when it comes to repackaging/making choices. If we try to apply the above to the McAfee Endpoint Security 10.2.1 installer, we will see some additional complexity.
installer ‑showChoicesXML ‑pkg /path/to/McAfee_Endpoint_Security\ 10.2.1/1\ Source/McAfee-Endpoint-Security-for-Mac-10.2.1-RTW-standalone-2632.pkg ‑target /
Notice that the choiceIdentifier is the not so helpful installer_choice_5. We can still see what the choice is by the choiceTitle, but now when we create our choices.xml, we need to be very careful about which choices we are selecting and which we are not. Your end result will look something like:
In this file, installer_choice_5 is the Firewall and installer_choice_6 is Web Control. For this type of package it can be important to save the output of showChoicesXML as a reference for which choice is which. This is an example of only putting in dictionaries for the choices we want to change. I would say this is probably not a best practice as different systems can end up with different defaults, but it can work.