Deploying Sophos Enterprise Anti-Virus for Mac 9.2.x
With the release of Sophos Enterprise Anti-Virus 9.2.x, Sophos changed how their enterprise antivirus solution for Macs was installed. While previous versions of Sophos Enterprise used an Apple installer metapackage, Sophos has now switched to using an application to install their enterprise antivirus software.
This switch was a problem for Mac admins who wanted to deploy Sophos Enterprise Anti-Virus 9.2.x, as the previously-available installer package had simplified the task of deployment. The new Sophos Enterprise Anti-Virus 9.2.x install application added further complexity by storing many of the installer’s files and other components outside the application in a separate Sophos Installer Components directory.
However, after doing some research and testing, it looks like it is possible to repackage Sophos Enterprise 9.2.x for deployment. For more details, see below the jump.
Sophos’ application can be run from the command line using the InstallationDeployer tool and include both install and remove switches. Here’s how to install and uninstall Sophos 9.x using the Sophos Enterprise Anti-Virus installer application:
Install:
/path/to/Sophos\ Installer.app/Contents/MacOS/tools/InstallationDeployer --install
Uninstall:
/Library/Application\ Support/Sophos/opm/Installer.app/Contents/MacOS/tools/InstallationDeployer --remove
With these commands, it’s possible to add the Sophos Installer application and the Sophos Installer Components directory to an installer package and run the needed commands with preinstall and postinstall scripts.
The other part of the puzzle is providing configuration and login credentials, to allow Sophos 9.2.x to communicate back with the Sophos Enterprise console following installation. After working on the problem in his own shop, Tim Kimpton figured out that both of the following files were needed:
/Library/Preferences/com.sophos.sau.plist
/Library/Sophos Anti-Virus/Sophos.keychain
Once I had this information and understood what was going on, here’s how I repackaged Sophos Enterprise Anti-Virus 9.2.x so that it could be deployed via an installer package.
Prerequisites:
A copy of the Sophos Installer application and the Sophos Installer Components directory from your Sophos Enterprise console server. The Sophos installer is available from the link below:
smb://your_sophos_enterprise_server_name_goes_here/SophosUpdate/CIDs/S000/ESCOSX/
A copy of the Sophos.keychain file, which will need to be taken from the following location on a Sophos Enterprise-managed machine: /Library/Sophos Anti-Virus/Sophos.keychain
A copy of the com.sophos.sau.plist file, which will need to be taken from the following location on a Sophos Enterprise-managed machine: /Library/Preferences/com.sophos.sau.plist
1. Set up a new Packages project and select Raw Package.
2. In this case, I’m naming the project Sophos Enterprise Anti-Virus 9.2.4
3. Once the Packages project opens, click on the Project tab. You’ll want to make sure that the your information is correctly set here (if you don’t know what to put in, check the Help menu for the Packages User Guide. The information you need is in Chapter 4 – Configuring a project.)
In this example, I’m not changing any of the options from what is set by default.
4. Next, click on the Settings tab. In the case of my project, I want to install with root privileges and not require a logout, restart or shutdown.
To accomplish this, I’m choosing the following options in the Settings section:
In the Post-Installation Behavior section, set On Success: to Do Nothing
In the Options section, check the box for Require admin password for installation.
5. Click on the Scripts tab in your Packages project.
6. Select the Sophos Installer application and the Sophos Installer Components directory and drag it into the Additional Resources section of your Packages project.
7. Select the Sophos.keychain file and drag it into the Additional Resources section of your Packages project.
8. The last piece is doing an automated uninstall of any existing Sophos installations, then installing a fresh copy of Sophos with the pre-configured autoupdate settings.
For this, you’ll need a preinstall script and postinstall script. Here are the ones I’m using:
Preinstall:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
LOGGER="/usr/bin/logger" | |
# Determine working directory | |
install_dir=`dirname $0` | |
# Uninstall existing copy of Sophos 8.x by checking for the | |
# Sophos Antivirus uninstaller package in /Library/Sophos Anti-Virus. | |
# If present, the uninstallation process is run. | |
if [ -d "$3/Library/Sophos Anti-Virus/Remove Sophos Anti-Virus.pkg" ]; then | |
${LOGGER} "Sophos AV present on Mac. Uninstalling before installing new copy." | |
/usr/sbin/installer -pkg "$3/Library/Sophos Anti-Virus/Remove Sophos Anti-Virus.pkg" -target "$3" | |
killall SophosUIServer | |
elif [ -d "$3/Library/Application Support/Sophos Anti-Virus/Remove Sophos Anti-Virus.pkg" ]; then | |
${LOGGER} "Sophos AV present on Mac. Uninstalling before installing new copy." | |
/usr/sbin/installer -pkg "$3/Library/Application Support/Sophos Anti-Virus/Remove Sophos Anti-Virus.pkg" -target "$3" | |
killall SophosUIServer | |
else | |
${LOGGER} "Sophos Anti-Virus 8.x Uninstaller Not Present" | |
fi | |
# Uninstall existing copy of Sophos 9.x by checking for the InstallationDeployer application | |
# in the following locations: | |
# | |
# Sophos AV Cloud | |
# /Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/ | |
# /Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/tools/ | |
# | |
# Sophos AV Home Edition | |
# /Library/Application Support/Sophos/he/Installer.app/Contents/MacOS | |
# /Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/tools | |
# | |
# Sophos AV Standalone | |
# /Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS | |
# /Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/tools | |
# | |
# Sophos AV Enterprise | |
# /Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS | |
# /Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/tools | |
# | |
# If the InstallationDeployer application is present in the Contents/MacOS/tools directory, the | |
# uninstallation process is run using the InstallationDeployer tool located there. | |
# | |
# If the InstallationDeployer application is present only in the Contents/MacOS directory, the | |
# uninstallation process is run using the InstallationDeployer tool located there. | |
# | |
# The reason for the directory-specific check is that running the InstallationDeployer application | |
# from Contents/MacOS on Sophos 9.1.x and later will cause the Sophos uninstaller application to | |
# launch in the dock and interfere with a normal installation via installer package. | |
# | |
# For more information, see the link below: | |
# http://www.sophos.com/en-us/support/knowledgebase/14179.aspx | |
if [[ -f "$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ ! -f "$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Home Edition present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/InstallationDeployer" –remove | |
elif [[ -f "$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Home Edition present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
elif [[ ! -f "$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Home Edition present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/he/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
else | |
${LOGGER} "Sophos Anti-Virus 9.x Home Edition Uninstaller Not Present" | |
fi | |
if [[ -f "$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ ! -f "$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Standalone present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/InstallationDeployer" –remove | |
elif [[ -f "$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Standalone present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
elif [[ ! -f "$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Standalone present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
else | |
${LOGGER} "Sophos Anti-Virus 9.x Standalone Uninstaller Not Present" | |
fi | |
if [[ -f "$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ ! -f "$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Enterprise present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/InstallationDeployer" –remove | |
elif [[ -f "$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Enterprise present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
elif [[ ! -f "$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Enterprise present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/opm/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
else | |
${LOGGER} "Sophos Anti-Virus 9.x Enterprise Uninstaller Not Present" | |
fi | |
if [[ -f "$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ ! -f "$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Cloud present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/InstallationDeployer" –remove | |
elif [[ -f "$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Cloud present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
elif [[ ! -f "$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/InstallationDeployer" ]] && [[ -f "$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/tools/InstallationDeployer" ]]; then | |
${LOGGER} "Sophos AV Cloud present on Mac. Uninstalling before installing new copy." | |
"$3/Library/Application Support/Sophos/saas/Installer.app/Contents/MacOS/tools/InstallationDeployer" –remove | |
else | |
${LOGGER} "Sophos Anti-Virus 9.x Cloud Uninstaller Not Present" | |
fi | |
exit 0 |
Postinstall:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
LOGGER="/usr/bin/logger" | |
FILE_DATE=`date +%Y%m%d%H%M%S` | |
# Determine working directory | |
install_dir=`dirname $0` | |
# Location of Sophos keychain file | |
sophos_keychain="$3/Library/Sophos Anti-Virus/Sophos.keychain" | |
# Install Sophos Anti-Virus | |
$install_dir/"Sophos Installer.app/Contents/MacOS/tools/InstallationDeployer" –install | |
# Remove existing Sophos autoupdate configuration file | |
/bin/mv "/Library/Preferences/com.sophos.sau.plist" /tmp/com.sophos.sau."$FILE_DATE".plist | |
# Remove and replace existing Sophos keychain file | |
if [[ -f "$sophos_keychain" ]]; then | |
mv "$sophos_keychain" /tmp/Sophos-"$FILE_DATE".keychain | |
cp "$install_dir/Sophos.keychain" "$sophos_keychain" | |
fi | |
# Write Sophos autoupdate configuration file | |
# | |
# Note: Plist file here is only an example. You will | |
# need to provide your own plist settings between the | |
# following lines: | |
# | |
# /bin/cat > "/Library/Sophos Anti-Virus/com.sophos.sau.plist" << 'SOPHOS_CONFIG' | |
# | |
# ….plist data goes here…. | |
# | |
# SOPHOS_CONFIG | |
# | |
/bin/cat > "/Library/Preferences/com.sophos.sau.plist" << 'SOPHOS_CONFIG' | |
<?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"> | |
<dict> | |
<key>LastUpdated</key> | |
<string>February 25, 2015 at 9:17:42 AM EST</string> | |
<key>OverrideCredentialsForSaas</key> | |
<integer>0</integer> | |
<key>PrimaryServerProxy</key> | |
<integer>0</integer> | |
<key>PrimaryServerProxyPort</key> | |
<integer>0</integer> | |
<key>PrimaryServerProxyURL</key> | |
<string></string> | |
<key>PrimaryServerType</key> | |
<integer>2</integer> | |
<key>PrimaryServerURL</key> | |
<string>smb://sophos_enterprise_server_name_goes_here/SophosUpdate/CIDs/S000/ESCOSX</string> | |
<key>SecondaryServer</key> | |
<true/> | |
<key>SecondaryServerProxy</key> | |
<integer>0</integer> | |
<key>SecondaryServerProxyPort</key> | |
<integer>0</integer> | |
<key>SecondaryServerProxyURL</key> | |
<string></string> | |
<key>SecondaryServerType</key> | |
<integer>0</integer> | |
<key>SecondaryServerURL</key> | |
<string></string> | |
<key>UpdateFrequency</key> | |
<integer>1</integer> | |
<key>UpdateInterval</key> | |
<integer>10</integer> | |
<key>UpdateLogIntoFile</key> | |
<true/> | |
<key>UpdateLogIntoSyslog</key> | |
<false/> | |
<key>UpdateOnConnection</key> | |
<false/> | |
<key>UpdateUnits</key> | |
<integer>1</integer> | |
</dict> | |
</plist> | |
SOPHOS_CONFIG | |
# Force Sophos to reload its configuration | |
/usr/bin/killall -HUP SophosConfigD | |
exit 0 |
9. Once you’ve got the preinstall and postinstall scripts built, run the following command to make the script executable:
sudo chmod a+x /path/to/preinstall
sudo chmod a+x /path/to/postinstall
10. Once completed, add the preinstall and postinstall scripts to your Packages project.
11. Last step, go ahead and build the package. (If you don’t know to build, check the Help menu for the Packages User Guide. The information you need is in Chapter 3 – Creating a raw package project and Chapter 10 – Building a project.)
Testing the installer
Once the package has been built, test it by taking it to a test machine that does not have Sophos and install it. The end result should be that Sophos Anti-Virus installs properly and has the pre-configured settings for your Sophos Enterprise server included automatically.
Thanks will come in handy and damn you Sophos thats really enterprise friendly, smh !
Shouldn’t have to go through that crap….anyone using Sophos needs to complain until they change it back to a package. Great article though for us all!!
I can give you the email address of one of their program managers. I tried and failed to impress upon him how bullshit this is for business users
* via DM in IRC, I won’t post this online.
If it was me I’d post it on the macenterprise mailing list and let him get hammered for making a moronic installer over a package!
You can avoid creating the XML script part if you just use the internal build command by (Assuming you have the sops installer.app in your Desktop) opening Terminal.app and navigate to /Users/yourusername/Desktop/Sophos\ Installer.app/Contents/MacOS then type sudo -s and authenticate then type:
./CreateOnAccessPreconfig -AutoLaunch “YES” -InArchives “NO” && sudo ./CreateUpdatePreconfig -PrimaryServerType 1 -PrimaryServerUserName SophosSvcAccount -PrimaryServerPassword \!changeme -PrimaryServerURL http://avupdate.yourdomaingoeshere.com:8195/sophosupdate/CIDs/S000/ESCOSX -SecondaryServerType 0 -SecondaryServerUserName username -SecondaryServerPassword \!changeme
That way the pkg installer will have the info built into it.
Thanks Rich! Works like a charm! Totally agree about the installer app. Way to make life more difficult, Sophos!
Just FYI for everyone who’s creating packages:
using /usr/bin/logger don’t work for me as it never shows up in Console. But what worked for me and helped a lot while creating other packages was to redirect the debug output of the script to a file:
set -x
exec 2>/var/log/sophosinstall.log
So I could find syntax errors, etc. as well. In production, of course, I disable it.
Hey Rich,
I’m trying to understand this part of the postinstall script:
/bin/cat > “/Library/Preferences/com.sophos.sau.plist” << 'SOPHOS_CONFIG'
##plist content
SOPHOS_CONFIG
The "<<" tells me that you are appending content to com.sophos.sau.plist. However, wouldn't it be better to just overwrite it altogether using just "<" ?
Also, what is 'SOPHOS_CONFIG' ? And why do you have SOPHOS_CONFIG after the plist content again?
I’m writing the plist file with cat redirects. I have a better explained example of how that works as part of this post: https://derflounder.wordpress.com/2011/09/23/setting-multiple-network-time-servers-from-the-command-line/
I just worked on a similar approach, but the two Library-Files were not necessary. The URL of the Update-Server are specified in the ESCOSX/Sophos Installer Component/rms/mrinit.conf File. Everything else comes from the Settings off the Sophos Console. So my install-Script just checks if previous Sophos-Installations were around, uninstalls them, then calls the install-binary…….
But the it occured to me that we had to repackage it because installing a .pkg from a share doesn’t work. Now changing that to the .app gives us direct access to the install routine actually makes life easier for us instead of harder. No need for repackaging, just mount the share, install sophos, enjoy a free afternoon.
here goes:
#!/bin/sh
sudo mkdir -p /mnt/sophos
sudo mount -t smbfs //UserName:PassWord@your.sophos.server.url/SophosUpdate /mnt/sophos/
sudo “/mnt/sophos/CIDs/S000/ESCOSX/Sophos Installer.app/Contents/MacOS/tools/InstallationDeployer” –install
exit 0
Just to add that I have tested this with DeployStudio and Absolute Manage on fresh installs. One might want to add the uninstall-routines for a more universally usable script
I’m curious why we wouldn’t just use the command line installer Sophos built in for Enterprise deployment? http://www.sophos.com/en-us/support/knowledgebase/14179.aspx
Feel free to use Sophos’ published method. This is how I was able to package it for deployment in my own shop.
The above procedure is unsupported and unnecessary. Sophos has published articles to apply configuration data to the package and even preload Group Path (so clients don’t flounder in the Unassigned container). Follow: https://sophos.com/kb/119744 for updating and scanning settings. Follow https://sophos.com/kb/119791.aspx for setting Group Path for managed clients.
This no longer seems to work, Sophos AV 9.2.4. Packages builds a pkg, but when installing, gets to Validating Packages and rushes through it and says “Installation Successful”, but nothing is installed?
I second this, as of 9.2.4 my package is broken and not being able to deploy it… and of course sophos has no clue…
Excellence tutorial, if you add the mac to the right container which has update server configured, there is no need to add keychain and com.sophos.sau.plist. Here is the URL show you how to add it a particular group/container:
https://www.sophos.com/en-us/support/knowledgebase/119791.aspx
Copying across the keychain and pref file caused Sophos to crash spectacularly.
Using CreateUpdatePreconfig and CreateOnAccessPreconfig worked a treat as per:
https://www.sophos.com/support/knowledgebase/119744.aspx
This Package doesn’t work properly anymore on OS X El Capitan.
You have to manually Disable System Integrity Protection, otherwise you’ll get en error while creating the needed file under /Library/LaunchAgents
SIP does not block the creation of files in /Library/LaunchAgents/, it would however for /System/Library/LaunchAgents. You need to be root to write to /Lib/LA, but again SIP would not interfere with this. See another of Rich’s posts: https://derflounder.wordpress.com/2015/10/01/system-integrity-protection-adding-another-layer-to-apples-security-model/
I noticed that when i’m running the package with SIP enabled the package says that it was installed successfully, but sophos isn’t installed. When i’m running this package with SIP disabled, everything work’s well and sophos is installed and running.
I’m running the package as admin user.
In the system.log i noticed a line like:
/Library/LaunchAgents/com.sophos.uiserver.plist no such file or directory.
i’ll try to reproduce this problem.
The exact error in the system.log is the following:
Jan 5 08:40:51 000109 com.apple.xpc.launchd[1] (com.apple.xpc.launchd.domain.system): Could not read path: path = /Library/LaunchDaemons/com.sophos.devicecontrol.plist, error = 2: No such file or directory\
the same error with some other plist files in /LIbrary/LaunchDaemons
This files aren’t created during installation with SIP enabled.
I got the similar issue. my previously created SAV 9.2.8 pkg can deploy and install on client. but i tried to create a new one with SAV version of 9.4.3, the pkg can show installation succuesfully but actually nothing installed. i tried both with and without SIP, all failed to install in real. i m wondering what has been changed on SAV.
This is working great for me thanks. I needed a .pkg as this was easiest to use with my DeployStudio workflow and I don’t want Sophos baked into our base image. Our Enterprise version is 9.2.10, running on OS X 10.11.3.
Thank you sir.
Looks like the keychain is now called “SophosSecure.keychain”
I was wondering if there are updated instructions for Sophos AV v.9.6.x? They have changed the name of the Sophos keychain, the path for silent install, and also some internal workings of the install that I cannot figure out.
I’ve followed the instructions on this page before to create a 9.4.x package with great success. But, something with 9.6.x has changed…
Any help would be greatly appreciated.