Monday, November 26, 2018

Automating Latest App Version Installation with Jamf using Payload-Free Packages

One of the most annoying tasks a Jamf administrator faces is dealing with the flood of updates constantly coming from Google Chrome, Mozilla Firefox, Adobe Flash Player, and other apps. Luckily, at least for those three, it is possible to create a special installation package that will automatically download and install the latest version of each, freeing you from the hassle of packaging updates manually, or the unreliability of the respective apps' auto-updaters.

The most important thing you need is either a stable download URL, or some other way to determine where to download the latest version of the application. Some apps, like Chrome and Firefox, offer a singe download URL; others, like Adobe Reader and Flash Player, make you work for it a little bit harder.

Google Chrome

I automated the Google Chrome download-and-install process using two scripts: a postinstall script, run as part of the installer .pkg, and a pkgbuild script, which creates the installer .pkg file. Here are the contents of each:

./scripts/postinstall

#!/bin/bash

echo Downloading and installing latest Google Chrome.
curl https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg > /tmp/googlechrome.dmg
hdiutil attach /tmp/googlechrome.dmg -nobrowse
ditto /Volumes/Google\ Chrome/Google\ Chrome.app /Applications/Google\ Chrome.app
hdiutil detach /Volumes/Google\ Chrome
rm /tmp/googlechrome.dmg

echo Creating First Run file in user profiles.
for user in `ls /Users`; do
mkdir -p /Users/$user/Library/Application\ Support/Google/Chrome
touch /Users/$user/Library/Application\ Support/Google/Chrome/First\ Run
chown -R $user /Users/$user/Library/Application\ Support/Google
done

echo Modifying user template with First Run file.
mkdir -p /System/Library/User\ Template/English.lproj/Library/Application\ Support/Google/Chrome
touch /System/Library/User\ Template/English.lproj/Library/Application\ Support/Google/Chrome/First\ Run
chown -R root:wheel /System/Library/User\ Template/English.lproj/Library/Application\ Support/Google
chmod -R 700 /System/Library/User\ Template/English.lproj/Library/Application\ Support/Google

echo Creating Master Preferences file.
mkdir /Library/Google
cat > /Library/Google/Google\ Chrome\ Master\ Preferences <<EOF
{
"browser" : {
"check_default_browser" : false,
"show_update_promotion_info_bar" : false
},
"distribution" : {
"skip_first_run_ui" : true,
"suppress_first_run_bubble" : true,
"suppress_first_run_default_browser_prompt" : true,
"make_chrome_default" : false
},
"sync_promo" : {
"show_on_first_run_allowed" : false
}
}
EOF
chmod -R 644 /Library/Google
chown -R root:wheel /Library/Google

echo Creating Chrome PLIST.
cat > /Library/Preferences/com.google.Chrome.plist <<EOF
<?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>HomepageLocation</key>
<string>https://www.google.com/</string>

<key>RestoreOnStartup</key>
<integer>4</integer>

<key>RestoreOnStartupURLs</key>
<array>
<string>https://www.google.com/</string>
</array>
</dict>
</plist>
EOF
chmod 644 /Library/Preferences/com.google.Chrome.plist
chown root:wheel /Library/Preferences/com.google.Chrome.plist

echo Done.
exit 0

./pkgbuild.sh

#!/bin/bash
pkgbuild --identifier com.company.install_chrome --nopayload --scripts scripts "Install Google Chrome.pkg"

As you can see, the postinstall script downloads the latest Google Chrome .dmg from Google, and extracts the .app file. Then, it creates a file in each existing users' profiles, and then in the profile templates, so that users don't see the first-run pages on each new computer they log into. Then, the script creates a master settings file in the Chrome .app to enforce some IT-specified settings, as well as a .plist for the same purpose. This script runs when the installer .pkg, created by the pkgbuild.sh script, is installed via Jamf policy, using Jamf Remote, or manually by double-clicking on it. Whenever an update is available from Google, you can either let automatic updates install it at its leisure, or re-push the installer via Jamf to force all computers to install the latest version.


Mozilla Firefox

The pkgbuild.sh script for Firefox is pretty much identical to the one used for Chrome, so I will not re-copy it here. Here is the postinstall script I use for Firefox:

./scripts/postinstall

#!/bin/bash


echo Downloading and installing latest Firefox ESR.

curl -L "https://download.mozilla.org/?product=firefox-esr-latest&os=osx&lang=en-US" > /tmp/firefox.dmg

hdiutil attach /tmp/firefox.dmg -nobrowse

ditto /Volumes/Firefox/Firefox.app /Applications/Firefox.app
hdiutil detach /Volumes/Firefox
rm /tmp/firefox.dmg

echo Creating firefox.cfg file.
cat > /Applications/Firefox.app/Contents/Resources/firefox.cfg <<EOF
//This line must be left as a comment. Do not place any prefs here.
//https://support.mozilla.org/en-US/kb/customizing-firefox-using-autoconfig

//Set the default browser to the Google website.
pref("browser.startup.homepage", "http://www.google.com");

//Skip first-run pages, default browser prompts, etc.
pref("browser.startup.firstrunSkipsHomepage", true);
pref("startup.homepage_welcome_url", "");
pref("datareporting.policy.firstRunURL", "");
pref("browser.defaultbrowser.notificationbar", false);
pref("browser.shell.checkDefaultBrowser", false);
pref("browser.shell.didSkipDefaultBrowserCheckOnFirstRun", true);
EOF

echo Creating prefs .js files in defaults/pref.
cat > /Applications/Firefox.app/Contents/Resources/defaults/pref/autoconfig.js <<EOF
pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);
EOF

cat > /Applications/Firefox.app/Contents/Resources/defaults/pref/channel-prefs.js <<EOF
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

pref("app.update.channel", "esr");
EOF

echo Setting permissions on Firefox.app.
chown -R root:wheel /Applications/Firefox.app

echo Done.
exit 0

Like the Google Chrome script, this downloads the latest version of Firefox, extracts the .app, and creates preferences/settings files to enforce IT-specified values. Updating can be done automatically, or by re-pushing the installer .pkg.


Adobe Reader

Adobe Reader's installation is pretty straightforward, since there are no preference files to install. It uses the usual pkgbuild.sh, and this postinstall script:

./scripts/postinstall

#!/bin/bash

# First, we need to figure out what the latest version of Adobe Reader is.
# We can do this by querying the Adobe FTP server.
# Since curl sorts FTP results by filename, which here are also dates, and since there's a folder called "misc" at the bottom of the list,
# we know that the next-to-last result is the latest version. If this package breaks, check the FTP URL below to see if Adobe has changed this.
echo Querying Adobe FTP server to find latest version.
latestversion=$( curl ftp://ftp.adobe.com/pub/adobe/reader/mac/AcrobatDC/ | tail -n 2 | head -n 1 | awk '{ print $NF }' )

# Then, download the installation package for the latest version.
echo Downloading version $latestversion installer package.
curl 'ftp://ftp.adobe.com/pub/adobe/reader/mac/AcrobatDC/'"$latestversion"'/AcroRdrDCUpd'"$latestversion"'_MUI.pkg' > /tmp/adobereader.pkg

# Finally, install the package.
echo Installing Adobe Acrobat Reader DC $latestversion.
installer -pkg /tmp/adobereader.pkg -target /

echo Cleaning up Adobe Reader installer package.
rm /tmp/adobereader.pkg

echo Done.
exit 0

Adobe doesn't provide a single URL to download the latest version of Reader (presumably, they would prefer you download it manually.) Luckily, the FTP server returns results in a sorted manner, so we can filter them using head, tail, and awk to find what we need. This downloads a .pkg file, which we can install directly without needing to mount a .dmg and extract a .app.


Adobe Flash Player

I was not actually able to find the correct download URL for Adobe Flash Player by myself. I found that Richard Trouton, on his GitHub, had already posted a ready-made script to download and install Flash Player. You can find his script here. I use this with a standard pkgbuild.sh, like those above, to create a package that can be pushed via Jamf.

Wednesday, November 7, 2018

In the news: SSD encryption weaknesses and Bitlocker

In an article posted late Monday evening on ZDNet, the results of research performed at Radboud University in the Netherlands reveal worrying weaknesses in full-disk encryption, particularly using Windows' built-in BitLocker, on several lines of solid-state drives produced by Crucial and Samsung. As someone who owns both Crucial and Samsung SSDs, and may plan to one day enable full-disk encryption, this was relevant to my interests.

Carlo Meijer and Bernard van Gastel, the researchers at Radboud University detail in their research paper the methods that various SSDs use to provide hardware-based encryption, and assess the vulnerabilities and possible attacks that each could offer to ne'er-do-wells. What follows is my summary of the research paper, though I encourage you to read it yourself, as it is illuminating on the current state of infosec in the computer hardware industry.

Encryption Overview

First, the researchers provide some background information on the different types of software and hardware encryption in use in today's computing environment.

Software-based encryption methods, like Windows' BitLocker, encrypt all of the data stored on the hard drive (or other media) with some cryptographic cipher, often AES with 128-bit or 256-bit-long keys. When the computer is off or the encryption is otherwise not being used, the key to this cipher is stored in a secure location, such as a Trusted Platform Module.

When the computer is on and encryption is in use, the key is loaded into RAM so that it can be used to encrypt/decrypt data. Therein lies the vulnerability, as the key itself cannot be encrypted, and could be stolen by a rogue program that accesses memory outside of its allowed range. Modern operating systems are very good at preventing simple attempts at such access, but more sophisticated attacks like RowhammerSpectre, and Meltdown can allow attackers to read private data even in different virtual machines running on the same physical hardware in co-hosted or cloud-based environments.

Hardware-based encryption methods use a dedicated AES co-processor and key storage outside of the main system RAM to provide a theoretically more secure encryption process. When hardware-based encryption is implemented directly in the drive itself, it is called a "self-encrypting drive", or SED. There are two main standards for SEDs: ATA Security and TCG Opal.

Self-Encrypting Drive Standards

The ATA Security standard defines a "security feature set" intended to ensure access control, mainly for drives that are powered off or not installed in a computer. The standard specifies that two passwords should be usable to lock or unlock the drive - a master password, usually set by the manufacturer, and a user password, set by the user of the drive. To prevent an attacker using the factory-set master password, the user can set the "Master Password Capability Bit" to 1, which prevents it from being used to unlock or decrypt a drive. (However, even with this set, the ATA Secure Erase command can be called with either the master or user password.)

While the ATA security feature set does not mandate that any encryption should be used to implement this access control, in practice most SEDs do use cryptography like AES-256 to encrypt data on the drive so that it cannot be retrieved without also capturing the encryption key.

TCG Opal ("Opal") is a newer specification that specifies a communication protocol that is used on top of the ATA or NVMe device interface protocols. Opal requires drives to encrypt data using either AES-128 or AES-256 , and that this encryption have the same bandwidth as the storage device itself to reduce the performance penalty normally associated with strong cryptography. Opal allows users to specify multiple passwords to the drive, and to assign different capabilities to each of those passwords, mirroring the usual access controls available in modern operating systems. Drives can be divided into different "locking ranges", each of which can be locked or unlocked independently of each other, and each of which is encrypted with a different cryptographic key. Secure erasure of data is implemented by generating a new cryptographic key for some or all of these locking ranges, and discarding the old key, effectively rendering the previously-encrypted data unreadable.

Besides these two industry standards, proprietary device encryption schemes are used by some manufacturers, either because their standards predate TCG Opal, or because they do not feel that the full complexity of Opal is warranted in their products' normal applications. Some of these proprietary standards include those used by Seagate's DriveTrust, Western Digital's MyPassport, and Samsung's portable SSDs.

Attack Models

Machine off, no awareness

In this attack model, which the researchers dub the "evil maid attack", the attacker has a small window of opportunity to access a system that is shut off without the owner knowing that the attack has happened. Since software-based methods cannot be used in this model, a hardware-based approach such as a keylogger might be used. The researchers note that, even with advanced security techniques like TPM sealing (where keys are locked to the specific hardware and software in use), no known mitigations exist to prevent such a hardware keylogger from capturing unencrypted data directly from the user's input device or unsecure RAM before it ever reaches the encrypted storage device. The only defense against the "evil maid attack" is to ensure the physical security of the device.

Machine on

When a computer is on, both hardware- and software-based encryption can be used to secure data on storage devices and in transit. Unfortunately, as described above, software-based encryption is often vulnerable to attacks that can directly read memory to capture the cryptographic key, including cold boot and DMA attacks. Some software-based encryption techniques store keys in CPU registers, rather than in RAM, which can help prevent these attacks.

Hardware-based encryption, like that used on SEDs, theoretically helps to protect sensitive data in this attack model by storing the encryption keys and performing the actual encryption and decryption in a secure hardware area separate from the rest of the computer. However, as the researchers describe, there are vulnerabilities in today's implementations that mean that hardware-based encryption on a running computer is effectively only as secure as software-based encryption:
  • In order for a computer to be able to suspend the session to RAM (essentially, to go into sleep mode), it must keep the device encryption key in memory so that it can be used to unlock the drive when it wakes back up. This means the key is vulnerable to cold boot and DMA attacks.
  • SSDs often keep the device encryption keys in the main memory of their controller chips, which are not specially protected from attacks. In fact, many SSDs have diagnostic ports or debugging interfaces that could allow attackers to directly read these keys out of the controller memory.
Here, again, the only way to mitigate attacks on running devices using hardware-based encryption is to ensure physical security of the protected device.

Machine off, awareness

This attack model differs from the "evil maid" scenario in that the owner of the device knows that it is being attacked, and so will obviously not enter the encryption key or other sensitive information into the device. Since the encryption key is not accessible anywhere in the computer's memory, and presumably is also not loaded into the SED's controller's memory, full-disk hardware-based encryption should completely secure all of the data on the drive. This is the attack model on which the researchers focus.

Attacks and Vulnerabilities

The attacks that the researchers describe center around the possibility of unsigned code execution on the SED's controller chip to get the drive itself to give up the encryption key or other sensitive information. The idea behind the attack is to load code that the attackers control in order to trick the SED into doing their bidding. The exact methodology used to inject unsigned code differs based on the design of the device, with some easier than others: some manufacturers implement undocumented commands that can be used to alter values in the controller chip's memory, which would allow an attacker to overwrite an function pointer or return address; other manufacturers' drives contain a NOR flash chip, accessible through the SPI protocol by attaching probes directly to the chip's pins, which holds executable code that can be modified for nefarious purposes; yet others are vulnerable to attacker-controllable glitches during a firmware update that result in unsigned firmware being loaded, totally compromising any security offered by the drive.

Once unsigned code is successfully loaded, the attacks may exploit one or more of the vulnerabilities that the researchers have identified in currently-available drives. These are:
  • Password and device encryption key not linked - A valid password must be required to retrieve the device encryption key. If this is not the case, the unprotected key must be stored on the drive itself in such a way that another security factor - in this case, the "something you know" of the password - is not required. As the researchers indicate, because TCG Opal specifies that multiple different passwords may be associated with multiple different device encryption keys, this is difficult to implement correctly.
  • Single device encryption key used for the entire disk - TCG Opal allows different keys to be used to encrypt different parts of the storage area. Some drives implement this by using one global key to encrypt the entire drive, then allowing different passwords to use this global key only on certain parts of the drive. While that should basically work, some popular encryption software that works with Opal - including BitLocker - does not protect the global range so that the drive's partition table is always accessible, meaning that it must store the device encryption key unprotected as well.
  • Lack of entropy in randomly generated device encryption keys - The ATA and TCG Opal standards do not provide a way for the user to create the device encryption keys (the 128- or 256-bit keys used in cryptography, not the user passwords), so these are generated randomly. Unfortunately, computers are not really capable of generating truly random numbers, so an algorithm called a pseudorandom number generator (PRNG) is used to create the keys. The better the PRNG, the less likely it is that an attacker will be able to guess the keys it generates; conversely, the weaker the PRNG, the more likely that keys can be guessed and checked via brute force.
    Some newer drives contain hardware-based random number generators, which use environmental factors like heat or electromagnetic noise to generate sufficient entropy, but these are not universal.
  • Wear leveling - Flash memory used in SSDs has a limited lifetime number of writes to each memory cell before the cell can no longer be used. To increase the lifetime of the overall drive, SSD controllers distribute writes evenly across all of the memory cells in the drive, keeping track of which cell holds which part of which file. This means that multiple cells may hold different versions of parts of files, with older copies marked free-for-use and normally inaccessible to applications. However, if unsigned code is loaded, it may be possible to retrieve these old copies - and, if one such old copy should contain the unencrypted device encryption key, the drive can be decrypted.
  • Power-saving mode: DEVSLP - SATA drives can be put into a low-power mode when sent the correct command, allowing computers to use less power while sleeping. However, the ATA standard does not specify how drives should implement this low-power mode. A drive may choose to save its internal state, including unprotected device encryption keys, to flash memory or other storage so that they can be quickly retrieved when it wakes back up; if the drive's controller does not explicitly erase that temporary storage after it wakes up, it may be possible for unsigned code to retrieve the device encryption key.
     

Case Studies

The researchers assessed several different brands and models of SSDs for the vulnerabilities described above, and laid out attacks that could be used to compromise the security of the encrypted data on each.

Crucial MX100 and MX200

The Crucial MX100 and MX200 SSDs support both ATA security and TCG Opal, and have an exposed JTAG hardware debugging interface that could potentially be used to read certain information from the drive. The researchers found that these SSDs use a password-checking algorithm with flaws that mean there is not a cryptographically-secure relationship between the user's password and the device encryption key, meaning that an attacker who can control the code running on the drive's controller could access the device encryption key without the password.

This is especially dangerous because of the vendor-specific debugging commands that are usable by sending specific values to specific addresses in the device's address space. Though these commands are initially locked from use, simply sending a special command (0xfd, feature code 0x55) to the drive, then setting the LBA value to 0x306775 with a block count of 0x65, unlocks these commands - a mere few lines of code. Once the commands are unlocked, an attacker can freely read and write to the NOR flash chip, which contains the code that the drive uses to boot itself, and can also read and write to any location in the controller's memory. The researchers describe an attack using the JTAG debug interface, coupled with the password-checking weaknesses, that allows an attacker to easily read any encrypted data on the drive in plaintext form. These drives do not provide any meaningful security through their encryption.


Crucial MX300

The Crucial MX300 SSD supports both ATA security and TCG Opal. Unlike the older versions, the controller chip's JTAG interface is not exposed, but there is a flash storage chip with an open SPI interface, from which the controller loads executable code during the boot process.

The researchers were able to analyze the drive's firmware and reverse-engineer the device encryption key generation scheme. While the MX300 uses a better password-checking scheme to associate user passwords with device encryption keys, the drive is not configured to use the controller chip's ability to cryptographically verify its boot-up code, and so an attacker can use the open SPI interface to load any program they wish to the drive. The researchers describe an attack, using this SPI interface, that could be used to load an attacker-created firmware to the drive, defeating any security measures on the drive and allowing complete access to its contents.

Samsung 840 EVO

The Samsung 840 EVO supports ATA security and TCG Opal (version 2 only), and claims to support hardware-based AES-256 encryption. Unlike the Crucial drives, which use a third-party (Marvell) controller, the 840 EVO uses Samsung's own triple-core ARM controller chip. This drive, like the Crucial MX100 and MX200, exposes a JTAG debugging interface.

The researchers were able to analyze the drive's firmware, and reverse-engineered the device encryption key generation scheme. They found that, using the JTAG interface, they could cripple the code used by the ATA security algorithm to check the user password, allowing any password to unlock the drive, and that a more complicated attack involving wear-leveling might be able to recover the TCG Opal device encryption key. It appears that the 840 EVO is marginally more secure than the Crucial drives in TCG Opal mode, but there are still significant vulnerabilities.


Samsung 850 EVO

The Samsung 850 EVO is similar to the 840 EVO, exposes the same JTAG debugging interface, and appears to use the same device encryption key derivation scheme as the older drive. Unlike the 840 EVO, the researchers were not able to identify any security issues with wear-leveling. They also discovered that no keys are stored to flash memory when the device is in DEVSLP, meaning that a drive that is not powered is not vulnerable to attacks through that mechanism. The only attack that appears to be usable, from this research, is the JTAG-based ATA security attack described above.


Samsung T3 Portable

The T3 Portable is essentially an 850 EVO drive connected to a USB-to-mSATA bridge, and exposes the same JTAG interface as that drive. The researchers found that this drive is vulnerable to the same ATA attack as the other Samsung drives.

Samsung T5 Portable

The T5 Portable, like the T3 Portable, is fundamentally an 850 EVO with a USB-to-mSATA bridge. This drive, though, has the JTAG interface disabled, and the researchers were unable to find a copy of the device's firmware for analysis.

However, they discovered that the T5 Portable supports vendor-specific commands, analogous to those found in the Crucial drives, that can be used to acquire the "cryptographic blob" that the drive uses to store (encrypted) device keys and other information. While the researchers were not able to determine a conclusive attack on this drive, they note that most of the same vulnerabilities affect the T5 as the T3, and so if a flaw is found that enables unsigned code execution these drives could be similarly compromised.

Conclusion

The researchers provide this table summarizing their findings:

While the Samsung 840 EVO and 850 EVO are harder to compromise, depending on the security mode use, none of the assessed drives provide a bulletproof hardware-based encryption scheme. Furthermore, when BitLocker is used with a drive claiming to support hardware-based encryption, it will by default rely on the drive's encryption rather than its own. Therefore, on these compromised drives, BitLocker is similarly compromised, and cannot be relied upon.

The researchers provided this information to Crucial and Samsung in May of this year, and both have addressed these vulnerabilities with firmware updates. However, as the researchers point out, hardware-based encryption in general currently forces us to rely on companies' proprietary schemes to be cryptographically-sound, and for drive controllers and firmware not to expose open or easily-unlockable debugging interfaces that allow attackers to compromise device security. They suggest that TCG should publish a reference implementation of Opal to aid developers in creating their own implementations, and to offer independent compliance testing to help verify the security of these implementations.

What does this mean to me?

If you have any sensitive information that you want to protect on one of the drives the researchers found to be exploitable, and even if you have an SSD that isn't tested, the best security is physical security. Make sure computers are in secure locations, preferably with Kensington locks, case locks, or any other measures that can be put in place. You can also use a software-based encryption technology, like VeraCrypt, to add another layer of security irrespective of any underlying OS- or hardware-level encryption.

Tuesday, October 23, 2018

Securely erasing a flash drive in Windows with cipher

From time to time, we are given student flash drives either to use or to dispose of. For drives we intend to use, we usually consider using diskpart to clean them good enough. For drives we dispose of, we want to make sure that all data is securely erased so that no potentially-confidential or FERPA-relevant student data is leaked in the event that an enterprising person at an electronics recycler decides to have a peek.

Tools like DBAN can be used from a bootable environment to accomplish this task. However, this only allows you to wipe one flash drive at a time, and you cannot use the computer for anything else while it is running. What if you want to wipe several drives at once, or to wipe just one while doing other work on the computer?

The cipher command-line tool, also useful for encrypting or decrypting drives, can be used to securely erase the free space on a given volume by writing various bytes over any data that may be present so that it is unrecoverable. To use cipher to wipe a flash drive, follow these steps:

1. Reformat the disk using diskpart or some other tool.
2. Open a Command Prompt with administrator rights.
3. Run cipher /w:<drive letter>:\

Formatting the drive will ensure that the cipher tool considers it all to be "free space", and so overwrites the data. cipher will run for a fairly long time, depending on the size of the drive being erased. Once it has finished, the drive will be as clean as if it were brand-new.

It is worth noting that, because of the way flash memory works, you probably don't want to do this all the time to a flash drive, as each write slightly shortens the life of the memory. This may also cause marginal drives to finally fail, so keep that in mind if you intend to reuse a drive you are wiping.

Upgrading Jamf Pro 10.7.1 to Jamf Pro 10.8

Overnight, Jamf released an even newer version of Jamf Pro, version 10.8. Since we're still in the testing phase, I figure that now is as good a time as any to give it a try. So, back to the Mini!

On the Jamf download page, you are warned to run a check on your database before upgrading to Jamf Pro 10.7.1 or 10.8, as there is an issue with a certain Smart Computer Group criteria that can cause infinite loops and other issues. Since I had already run this check before upgrading to 10.7.1, I did not need to do so this time, but anyone who hasn't run it yet should before going any further.

According to the Jamf Pro 10.8 installer, all of the prerequisites are the same as on 10.7.1, so this should be a fairly straight-forward update. Just like last time, it installed as a standard .pkg installer. This time, I didn't stop Tomcat beforehand, just to see what happened. Nothing of note occurred because of this omitted precaution.

After the installation is complete, I was prompted to go to https://127.0.0.1:8443 to complete the database portion of the upgrade, with a strong admonition not to restart Tomcat while this is in progress. The browser sat at a blank white page for a minute or so, then switched to the usual gray screen with the Jamf Pro progress bar. After fifteen or so further seconds, the login prompt appeared.

Upon logging in, I was presented with a Software License and Service Agreement page, which required me to scroll to the bottom (after having carefully read the terms and conditions, of course) before I could click the Agree button.

Once agreed, I was taken to the normal Jamf Pro interface. I confirmed that all of our computers, Policies, etc. were as they should be. Upgrade completed with no issues.

Monday, October 22, 2018

Upgrading Jamf 9.101 to Jamf Pro 10.7.1

We have finally reached the point where discussion about how we can upgrade our Jamf server, running an aging software version 9.101, to the latest, greatest Jamf Pro 10.7.1. I had the good fortune of being the one who got to set up a more-or-less identical testing environment, copy over the production database, and perform a test upgrade to see what might be broken, so that we can plan how to recover when we perform the upgrade to our production server.

Currently, our main Jamf server runs on a Windows Server 2012R2 VM hosted at our central office location. It was not considered worthwhile to spin up a similar VM to test the upgrade process, so I installed Jamf 9.101 on a Mac Mini we had on hand.

The first thing to mention is that, when setting up Jamf 9.101 for the first time, you need to carefully read the prerequisites presented by the installer, and you do need to read the documentation it links to on the Jamf Nation website. Before installing Jamf , you must install Java SE 8, the unlimited-strength Java Cryptography Extensions, and MySQL 5.7. Additionally, you need to manually create a database table and user for the JSS in the database. Once all of this is done, you can install the JSS like any other piece of software using the installation .pkg.

Now, my Mac Mini was running the Jamf 9.101 server software, but it was empty - no computers, no Policies, etc. The purpose of this testing was to determine what, if anything, would be broken by the upgrade process, so I needed to import a copy of our current Jamf database into this new instance.

The tool recommended to me on Jamf Nation, the Jamf Migrator, looked like a great place to start. This tool takes URLs and login credentials for two Jamf servers, a source and a destination, and uses the Jamf API to clone one server to another; alternatively, it can create an XML file from the source server that can later be uploaded to the destination server using the same tool. So, I downloaded this tool to my MacBook, gave it the information it needed, and clicked the "Go!" button. The tool reported that it was able to transfer some, but not all, of most of the things that it can transfer, but failed completely to move any Printers or Configuration Profiles. When I checked the Jamf instance on my Mini, I found that it had only actually moved over three computers. The same issue occurred after several more tries. I don't know what the issue was, but obviously, this tool wasn't going to work in my environment.

Luckily, Jamf provides a tool to back up and restore databases. I used the Jamf database tool to create a backup of our current database, then used it to restore that backup to the testing Jamf instance. This was much more successful than the migrator tool - all of our computers, Policies, Configuration Profiles, etc. were imported, and what's more, so were our VPP tokens and other system settings. I went into the JSS settings to change the JSS URL, turned off the SMTP server (so that my team members would not be inundated with emails from this testing environment), and made a few other changes to make sure that nothing funny would happen with the cloned instance running alongside the original. I enrolled a test Mac to this new JSS, and confirmed that everything was working.

I then set about installing the upgrade to Jamf Pro 10.7.1. No intermediate upgrades are required, so it is actually a very easy progress. The Jamf Pro 10 installer comes as a .pkg, just like the original Jamf 9.101 did, and all you need to do is to install it like any application. The Jamf Pro installer stops Tomcat (though I stopped it beforehand out of caution), installs the necessary updates, then restarts Tomcat. After the installation is complete, the web interface shows that Jamf Pro 10.7.1 is starting up, and eventually presents you with a login screen.

I logged in using the same credentials as I had before the upgrade. I was pleased to find that nothing appeared to have changed or broken - all of the computers appeared to be there, and their data appeared to be valid enough, and so did all of my Policies and Configuration Profiles. It appears that, at least in our case, the upgrade to Jamf Pro 10.7.1 will be painless. We'll see when we do it in production.

Friday, October 12, 2018

Mac Administration with JAMF, Part 4: Creating Packages with Composer

Previous updates have focused on the JAMF web interface, where most of the management capabilities are exposed through Policies and Configuration Profiles. This time, I will cover Composer, a tool in the Casper Suite that allows you to create software installation packages that you can deploy via Policy.

When you open Composer for the first time, you will be greeted by a dialog offering a choice of different ways to capture the sources that will be used to create a package:

One way that you can create a package using Composer is by taking a snapshot of your system before and after an installation. Once the before-and-after snapshots are made, Composer compares them to figure out which files were affected by the installation, then copies them into a .DMG or .PKG that you can deploy using JAMF. There are three snapshot "methods" that you can use with Composer:
  • Normal Snapshot - Composer creates a listing of all files that exist on the boot drive before and after the installation process, then compares them to find only the new files that have been created.
  • New & Modified Snapshot - Like a Normal Snapshot, Composer compares files that exist before and after the installation. In this mode, it also takes into account any files that were modified between the two snapshots (it's unclear whether it does this by checksum, modified date, etc.). This means that, for example, you can install one program and change some settings in another, and both of these actions will be captured. If you install the created package on a computer, both the new software and the changes made to the other program will be installed. 
  • Monitor File System Changes - Rather than creating a full-disk snapshot before and after an installation, Composer will listen for FSEvent events processed through the filesystem, and will use these to figure out which files need to be captured. Composer warns that, in cases where a lot of filesystem activity happens quickly, this may not capture everything correctly.
In most cases, you will want to use a Normal Snapshot. A New & Modified Snapshot is useful if you need to make changes to some files or programs related to the installation, but this can also cause problems, as it captures all files that change between the start and finish of the process, including browser history, login/logout records (if the computer locks itself, etc.), and, most importantly, any changes made to the Keychain on your Mac. Luckily, it's possible to selectively remove certain files from a Composer snapshot before building the package, but it's very important to be aware of what's actually being captured using the New & Modified Snapshot mode. To be absolutely safe, you can use a separate machine for Composer (I use an old Mac Mini), or a virtual machine, to make sure you build packages in a "clean" environment.

Another option Composer gives is Build OS Package, which is exactly what it sounds like. You can configure a Mac exactly the way that you want, then use Composer to capture an image of the disk that can be deployed to other Macs using JAMF as part of an Imaging Configuration. Effectively, this is analogous to capturing a base image from a PC, then using it in a Task Sequence in SCCM.


Unfortunately, as you can see in this screenshot, the version of Composer that I currently have access to does not support APFS disks, so going forward this will be a less viable tool for High Sierra, Mojave, etc. However, this isn't such a big deal, since Mac imaging is dead. For older, Sierra-based environments, though, this is a handy tool.

Composer also provides some pre-made "manifests", lists of files known to be changed by certain software installers, in the Pre-Installed Software section. You can use these to capture common software without having to wait the minute or two it takes to capture a snapshot.


This main section shows manifests that come with Composer, or that you have installed yourself. In the Not Installed sub-section, many more manifest files for other programs are available. All of the manifests available by default were created by JAMF themselves, but the JAMF Nation website also has a list of community-created manifests for almost any piece of software you could need to package.

Finally, Composer can also capture certain settings on the computer, which can be deployed in a package just as if they were an application. The available settings for capture can be found in the User Environment section.


These work similarly to the software manifests described above, in that Composer knows which files hold which settings. Unfortunately, this also means that if you are stuck with an older version of Composer, or if Apple decides to change where settings files are located, this portion of the tool may not be able to capture everything. Even if it does, because of the way Mac OS preferences work, it may not be desirable to do so - for example, the Dock settings you capture with Composer will completely overwrite users' Docks, including any customizations they may have made. For most of the settings here, a more appropriate method of management would be to use a Policy or Configuration Profile, which offer more fine-grained control over exactly what you want to change.

So, what is the process to create a package using a Snapshot? First, go back to the Snapshot section, and select Normal Snapshot. Then, click Next.


Enter the name of the package you want to create (usually, the name of the program, its version number, etc.), then click Next.


Composer will then begin to capture its pre-installation snapshot. You can see its progress as it indexes various parts of the operating system and user data directories.

Once the snapshot is complete, you will see this screen. This is your cue to perform the installation, make changes to files, and perform any other actions you want to capture. Once you have made your changes, click Create Package Source.


When you click the button to create the package source, Composer takes another snapshot, capturing any files that have been created since the first snapshot.


Once the "After" snapshot is created, Composer will present you with a list of the files it found to have been created. As you can see, I created a folder on my desktop called "test folder", and a text file within called "test.txt".


This is the main work area in Composer. Here, you can make changes to the files in the snapshot - you can delete them, change their owner/group/permissions using the handy dialog in the bottom-right, and even drag-and-drop them into different folders. In most cases, for software installations, you will want to leave things as they are.

When you have everything set up the way that you want it, you are ready to build the package using one of the two Build buttons in the toolbar at the top of the window. Composer offers a choice of two different kinds of package that you can build: .DMG or .PKG. These both perform the same basic task, but accomplish it in different ways:
  • .DMG packages are what they sound like. Composer creates a .DMG disk image file duplicating the structure and properties of the folders and files captured in the screenshot. When you deploy such a package via Policy or Casper Remote, the JAMF binary on the client Mac copies everything out of the DMG to the same location on the computer. .DMG packages are indexable in Casper Admin, which means that you can use JAMF to uninstall them as well.
  • .PKG packages are like "normal" installer packages that you might download from a vendor. You can deploy these packages via JAMF tools, or you can copy them to a flash drive and install them using the normal double-click method, even on a Mac not managed by JAMF. In addition, these packages can include preinstall and postinstall scripts (and a few other kinds, for non-flat packages) that allow you to perform pre-installation checks, post-installation cleanup, or any other scriptable actions that you might want to happen alongside the installation of files. However, .PKG packages cannot be indexed by Casper Admin, so they are not easily uninstallable without creating a separate uninstaller package.
Either of the Build options will let you choose where to save the created package, and will then build and save it there. Depending on the size of the installation you captured, it may take a long time (upwards of 45 minutes for OS captures or very large applications), but it is usually relatively quick.

If you have an installation that you know will not require much customization - for example, an application whose installation process is "drag me to the Applications folder", you can skip the normal snapshot-install-snapshot process, and create a package source with only the files you choose. For example, to create a package that just installs the Google Chrome app in the Applications folder, you can do this:

First, open Composer to the main package work area. Then, drag-and-drop the Google Chrome .app file to the left-hand pane, in the empty lower area.

Composer copies the files for the Chrome app to a temporary storage area, then creates a package source for it, just like it did using the snapshot method above.


You can now build a .DMG or .PKG package for this, and deploy it using whatever method you may choose to install Google Chrome. The disadvantage of this method is that you do not capture any settings changes made - with Chrome, for example, you may want to set a default homepage, etc. when capturing the package; in that case, the Snapshot method is more appropriate. 

More and more applications are moving to models where the Snapshot method does not work, whether because it writes changes to the system-wide Keychain, or other files that are not appropriate to copy from one user to the next, especially across different machines. Some of these, like Chrome and Firefox, allow you to embed special configuration files directly into the .app itself to change things like default homepages, etc. This is in keeping with Apple's changes to macOS installation, where direct captures and deployments will be less and less viable going forward. Therefore, this app-only package creation method will become more and more useful as time goes on.

Thursday, September 13, 2018

Automating Legacy Application Installation with Powershell and Startup Scripts

I recently had cause to install an old piece of software on 20 computers in a lab, and was looking for a way to automate this installation to reduce the tedium and opportunity for mistakes inherent in such a repetitive task.

Optimally, of course, the software would have come with a .MSI installer, and I would have just used wmic or Powershell to copy the the MSI and run it with the /quiet switch for a silent install. However, this application's installer was created with Clickteam Install Creator, so takes the form of a standard .EXE - and, what's more, it was created with the non-Pro version, so there is no silent installation switch. I tried all the standard tricks, including opening the installer in 7Zip to see if it simply hid an MSI (like some InstallShield installers), but it seemed like nothing was going to work. So, I got creative.

In the past, I have used AutoIt to script mouse movements and clicks. This would work in my use case, but I did not want to install the program just to install one other program, so it was out. Then, I realized that everything in the installer could be maneuvered with a combination of presses of the Tab, Enter, and arrow keys, and that if I could write a batch or Powershell script to send those keys to the installer application, I could do it with no additional software required. It wouldn't be a silent install, and would require logging in to the computer to start the script, but it would be more-or-less automated.

It turns out that, as of this writing, Powershell does not have a native cmdlet or other provision to send keys to another application. Luckily, there are two different methods to use Powershell for this: the Windows Script Host COM object, or a .NET assembly. In our case, because our other techs are more familiar with WSH scripting than with .NET, I chose to use that option.

The Windows Script Host COM component can provide a shell object that allows you to send keystrokes to a window, which behaves just as if a user had physically pressed the keys. To create the shell object and send a keystroke, you can use the following code:

$wshell = New-Object -ComObject wscript.shell
$wshell.AppActivate("name of window to send keystrokes to")
$wshell.SendKeys("keystrokes to send")

For the most part, I only needed to send Tab, Enter, and arrow key strokes, whose codes are, respectively, {TAB}, {ENTER}, {UP}, {DOWN}, {LEFT}, and {RIGHT}. Many other keycodes are available for other use cases. I found that several of the SendKeys commands in order were in fact going too fast for the installer to keep up, so I inserted some Powershell pauses between them:

Start-Sleep -s 1

to make sure that the installation proceeded correctly, as well as some longer pauses to allow the actual installations to take place before the final screen and "Finish" button keypresses.

Now, the installation was automated, but I would still need to log in to each computer, navigate to the script, right-click to Run as Administrator, and click "Allow." I wanted to automate this as much as possible, so I didn't stop there. I created a batch file that would run my installer script as an administrator user automatically:

powershell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process Powershell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""C:\install.ps1""' -Verb RunAs}"

and placed it in the Start Up folder so that it would run automatically on login:

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp

I then added a line to the installer script to delete this startup script when the installation was complete, so that it would not re-install the program on each login.

With this setup in place, the once-laborious install was reduced to:
1. Copy the installer application, install script, and startup script to the appropriate locations on the remote computer, using the \\computername\C$ share (also done via Powershell with a for loop).
2. Log in to each machine as an administrator user.
3. Click "Allow" on the UAC prompt.
4. Wait until the install finishes.
Before automation, installing this software on all 20 lab computers might have taken around 40 minutes; after automation, the whole-lab install took about 10 minutes, and considerably reduced the chances that an incorrect option may have been selected in the installer on some machines.

Tableau, TabPy, and the Case of No Input Rows

 I haven't scientifically confirmed this or anything, but it sure seems like if you pass an empty dataframe to a TabPy script, then no m...