Microsoft Office 2016 Preview and OneDrive for Business Beta don’t play together, yet

As a Mac SysAdmin in a dominantly Microsoft leaning organisation, I’m led to test new MS offerings with a view to rolling them out to Mac users once they reach their production stage. Sometimes, as in the case of OneDrive for Business, the need to use it is so great that we have to offer to deploy the Beta version.

However, there appears to be a problem if you have both Office for Mac 2016 Preview and OneDrive for Business (Beta) installed. Every time you start your computer, or restart OneDrive for Business (Beta), an alert is displayed:

Screen Shot 2015-05-20 at 09.45.18

Pressing “Yes” opens “Microsoft Upload Centre” – not very informative. Opening the Microsoft Upload Centre Preferences and clicking “Delete Files” to empty the Office Document Cache apparently solved the problem for some, but not for me.

The official word from Microsoft came in the following thread of the Office365 community forum: http://community.office365.com/en-us/f/153/t/298682.aspx

  • Close OneDrive for Business Mac (Beta)
  • Open a terminal window and delete the OfficeFileCache as follows:
$ rm -rf ~/Library/Group Containers/UBF8T346G9.Office/Microsoft/AppData/Microsoft/Office/15.0/OfficeFileCache
  • Reopen OneDrive for Business Mac (Beta)

Microsoft stated that this would need to be done everytime the OneDrive for Business process is started. Their alternative is “Choose to install either Office 2016 Mac Preview OR OneDrive for Business Mac Preview on your system.” So I guess these Beta programs are not ready to play with each other, yet.

Docker: Use Cases presentation – 19/3/2015 London Apple Admins @ ThoughtWorks London

Back on 19th March 2015 I gave a short informal presentation at the second London Apple Admins meeting at ThoughtWorks London, about how I’ve been using Docker to setup some Mac administration tools, with the examples of Crypt, Munki-Trello and Munki-enroll. Here’s my segment:

The excellent hosts Ben Toms (@macmuleblog), Steve Quirke (@Steve2CV) and Graham Gilbert (@grahamgilbert) also gave presentations about Bushel, Docker and Sal respectively.

A test Docker-BSDPy environment

Some Mac Admins have recently blogged about testing BSDPy using Docker:

I decided to try it out in a setup that suited me. Here’s how it went.

What is BSDPy?

Put simply, BSDPy is an alternative to Apple’s NetBoot/NetInstall. The premise is to provide a NetBoot/NetInstall service from a Linux host, removing another necessity for an OS X Server. Since Apple stopped providing server-grade hardware, this has been on Mac Admins’ agendas.

The posts above details all the reasons for trying this. This post is not intended to replace those posts, simply to document the set up I used to get this working.

Pre-requisites

My set up is a MacBook Air, with 8GB RAM, and the following programs installed:

  • VirtualBox
  • VMWare Fusion (version 6). Version 7 will work. Note this isn’t a free program, but is required to test NetBooting an OS X VM. If you have a spare physical Mac on your network, you can use this instead.
  • DeployStudio
  • Vagrant
  • TextWrangler with Command Line Tools – this enables the edit command. You can substitute nano or vi or another editor.

Side note: I use AutoPkg to install TextWrangler, VirtualBox and Vagrant.

1. Setup VMWare Fusion

My setup was based on instructions on Der Flounder’s blog: https://derflounder.wordpress.com/2013/01/23/building-mac-test-environments-with-vmware-fusion-netboot-and-deploystudio/

  • Open VMWare Fusion, click on File > New
  • Drag “Install OS X Yosemite.app” (you already got this from the App Store, right?) into the “Install from Disk or Image” window
  • Allow the standard setup for OS X 10.10, but press “Customise” before launching.
  • In the “Startup Disk” pane, set the VM to boot to the “Network Adapter NAT”.
  • Leave VMWare Fusion open (but don’t start the VM) while you perform the remaining tasks – you need the virtual network interface to be active.

2. Setup Vagrant

I used a CentOS VM to better emulate my shop’s configuration.

If you wish, you can just clone the Vagrantfile and startup.sh shown below using git, and move on to Step 4:

$ mkdir -p ~/vagrant/docker-bsdpy
$ git clone https://github.com/grahampugh/docker-bsdpy-vagrant.git ~/vagrant/docker-bsdpy

Otherwise, carry on reading to create the files yourself:

$ mkdir -p ~/vagrant/docker-bsdpy/nbi
$ cd ~/vagrant/docker-bsdpy
$ vagrant init chef/centos-7.0
$ edit Vagrantfile

Vagrantfile should have the following contents:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.box = "chef/centos-7.0"

  config.vm.network "public_network"
  config.vm.synced_folder '.', '/vagrant', disabled: true
  config.vm.synced_folder '.', '/usr/local/docker', {:mount_options => ['dmode=777','fmode=777']}

end

This config allows us to populate ~/vagrant/docker-bsdpy with scripts, and ~/vagrant/docker-bsdpy/nbi with our NetBoot Images, so we don’t need to manually copy them into the VM.

3. Create a Startup script which will be used to setup the Docker BSDPy environment

$ cd ~/vagrant/docker-bsdpy
$ edit startup.sh

The contents of startup.sh. The ETH variable is the network interface you are going to use. In my case, the virtual interface created by my VMware Fusion installation (enp0s8) worked best. You may get away with eth0 or eth1. Experiment!:

#!/bin/bash

# Set this to match the valid interface
ETH="enp0s8"

# Setup machine
yum update -y
yum install -y nano docker-io
service docker restart
chkconfig docker on

# Pull
docker pull hunty1/bsdpydocker

# Clean up
docker stop bsdpy
docker rm bsdpy

# Run
chmod -R 777 /usr/local/docker/nbi
IP=`ifconfig $ETH | awk '/inet / {print $2}' | sed 's/ //'`
echo $IP

docker run -d \
  -p 0.0.0.0:69:69/udp \
  -p 0.0.0.0:67:67/udp \
  -p 0.0.0.0:80:80 \
  -v /usr/local/docker/nbi:/nbi \
  -e DOCKER_BSDPY_IFACE=$ETH \
  -e DOCKER_BSDPY_IP=$IP \
  -e DOCKER_BSDPY_NBI_URL=http://$IP \
  --name bsdpy \
  --restart=always \
  hunty1/bsdpydocker

4. Make a DeployStudio NetBoot Image

Or use an existing one. I won’t go through GUI snapshots. Just make sure Python is enabled, and it’s set to HTTP type (not NFS). Once created, you need to move or copy it to the nbi folder and make some tweaks:

$ cp /Library/NetBoot/LibrarySP0/OSX-NETBOOT.nbi ~/vagrant/docker-bsdpy/nbi/
$ cd ~/vagrant/bsdpy/nbi/OSX-NETBOOT.nbi
$ rm NetInstall.dmg
$ mv NetInstall.sparseimage NetInstall.dmg
$ edit NBImageInfo.plist

You may wish to remove the entries from the DisabledSystemIdentifiers array. You should also ensure the following keys are set as follows:

...
<key>DisabledSystemIdentifiers</key>
<array/>
<key>IsDefault</key>
<true/>
<key>IsEnabled</key>
<true/>
<key>Type</key>
<string>HTTP</string>
...

5. Vagrant up!

It’s time to start up your virtual Linux server.

$ chmod 755 startup.sh
$ vagrant up

You will be asked to select a network interface. On my tests, vmnet8 was the correct choice.

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'chef/centos-7.0' is up to date...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Available bridged network interfaces:
1) en1: Wi-Fi (AirPort)
2) en0: Ethernet
3) p2p0
4) vmnet1
5) vmnet8
==> default: When choosing an interface, it is usually the one that is
==> default: being used to connect to the internet.
    default: Which interface should the network bridge to? 5

Now, we are ready to run the startup script. If all goes well, you should be able to netboot to your NBI!

$ vagrant ssh -c 'sudo /usr/local/docker/startup.sh'

My setup encountered problems with a VirtualBox Guest Additions mismatch. YMMV. This is why I haven’t set startup.sh to run in the Vagrantfile. You can uncomment it from the Vagrantfile if you want to try this out, and can certainly uncomment for subsequent vagrant ups. These commands fixed it:

$ vagrant ssh -c 'sudo yum update -y'
$ vagrant ssh -c 'sudo /etc/init.d/vboxadd setup’

If you encountered this too, you’ll get an error about needing to install a new kernel-devel-3.* package. Copy the version into the command:

$ vagrant ssh -c 'sudo yum install gcc yum install kernel-devel-3.*' ### copy the full path from the error message
$ vagrant ssh -c 'sudo /etc/init.d/vboxadd setup’
$ vagrant reload

6. Boot your VMWare Fusion VM

Boot up your VMWare Fusion OS X VM. If all goes well, you’ll see the VMWare boot screen, attempting to boot from EFI Network, and then the OS X boot screen with spinning globe:
Screen Shot 2015-04-29 at 22.25.04

Screen Shot 2015-04-29 at 22.25.08

To check what’s going on, you can monitor the log:

$ vagrant ssh -c 'sudo docker logs -f bsdpy'

Screen Shot 2015-04-29 at 22.29.11

Here’s my very first virtual DeployStudio workflow window!

Screen Shot 2015-04-29 at 19.54.01

Munki: How to remove cruft

An issue with Munki, especially if using AutoPkg, is that you can quickly amass many versions of software packages, which can fill up your repository volume. There are no automated ways of clearing out old versions of software, but in many cases there is no reason to keep them.

Removing a package involves the following process:

  1. Locate the imported package and delete it
  2. Locate the associated pkginfo file and delete it
  3. makecatalogs

If you’re organised, you’ll know exactly where every package is in the subdirectory structure of your Munki repository. But the repository can get hard to navigate. In which folder does Autopkg put Java 8? To where did your colleague import SPSS?

Use a GUI!

One way of removing packages is using the MunkiAdmin application. Simply right- or ctrl-click on an item in the Packages list, and select Delete Package. MunkiAdmin offers to delete the package and associated pkginfo file, and potentially the icon.

Screen Shot 2015-04-24 at 00.09.34

Command-line alternative?

If you don’t wish to use MunkiAdmin, for instance if you are working remotely on a server via ssh, you may wish for an easy way to find and remove old packages using the command line. The munkitools don’t include a tool for this task. So I wrote a script to find items in the Munki repository that match an input, list the items in order of filename (so that associated .pkg and .plist files are adjacent in the list), and offer to delete each one in term.

Pressing ‘y’ deletes the item and moves on to the next item in the list. Pressing ‘n’ or any other character (except ‘q’) skips the item and moves on to the next. Pressing ‘q’ skips to the end of the list. After the end of the list has been reached, if anything has been deleted, ‘makecatalogs’ is run (for this to work, this script needs to be run on a Mac with munkitools installed and configured to point to your munki repository).

Make the script executable:

$ chmod +x /path/to/munkirm

To run the script:

$ /path/to/munkirm -d java

Example output:

$ /path/to/munkirm -d chrome

----------------------------
  MUNKI FILE REMOVAL TOOL
----------------------------
Usage:   munkirm -d 
 is case-insensitive
part strings OK, e.g. goog

Found these files:

/Volumes/munki_repo/pkgs/apps/GoogleChrome-40.0.2214.115.dmg
/Volumes/munki_repo/pkgsinfo/apps/GoogleChrome-40.0.2214.115.plist
/Volumes/munki_repo/pkgs/apps/GoogleChrome-41.0.2272.118.dmg
/Volumes/munki_repo/pkgsinfo/apps/GoogleChrome-41.0.2272.118.plist
/Volumes/munki_repo/pkgs/apps/GoogleChrome-42.0.2311.90.dmg
/Volumes/munki_repo/pkgsinfo/apps/GoogleChrome-42.0.2311.90.plist
/Volumes/munki_repo/icons/GoogleChrome.png

Delete /Volumes/munki_repo/pkgs/apps/GoogleChrome-40.0.2214.115.dmg (y/n/q)? y
/Volumes/munki_repo/pkgs/apps/GoogleChrome-40.0.2214.115.dmg Deleted!

Delete /Volumes/munki_repo/pkgsinfo/apps/GoogleChrome-40.0.2214.115.plist (y/n/q)? y
/Volumes/munki_repo/pkgsinfo/apps/GoogleChrome-40.0.2214.115.plist Deleted!

Delete /Volumes/munki_repo/pkgs/apps/GoogleChrome-41.0.2272.118.dmg (y/n/q)? n
skipped

Delete /Volumes/munki_repo/pkgsinfo/apps/GoogleChrome-41.0.2272.118.plist (y/n/q)? q
skipped to end

### Catalogs have changed - running makecatalogs

Hashing Adobe Acrobat XI Pro_3.png...
Hashing Adobe-Premiere.png...
... [makecatalogs output] ...
Created catalog /Volumes/munki_repo/catalogs/standard...

If you want to run this tool from any directory without requiring a path, copy it into /usr/local/munki/:

sudo cp /path/to/munkirm /usr/local/munki/

Munki: find out in which manifests a package is available

I sometimes need to know which manifests would be affected by an update to a Munki package, or need to know which manifests another manifest is included within. There are no tools to do this, so I wrote a script to do it. I suspect that someone could write it much more efficiently – it takes some time to iterate through all the manifests.

Make the script executable:

$ chmod +x /path/to/manifest-find.sh

To run the script:

$ /path/to/manifest-find.sh -f package-name

Example output, showing all manifests in which Xcode is made available (either as managed_install or optional_install):

./manifest-find.sh -f Xcode

==== MANIFESTS CONTAINING "Xcode" ====
Included: Xcode
_sw_testing_group
client-it021669
_cg_testing_group
client-it000492
client-it000912
client-it011313
client-it005896
client-IT029452
client-it015180
client-IT006319
client-it006319
client-it031540
client-it000545
client-it013465
client-it015172
client-it000516
client-it031455
client-it013544

Results outputted to manifests.txt

Creating a pre-configured Junos Pulse VPN client on OS X with The Luggage

Rich Trouton’s Der Flounder blog recently described how to create a pre-configured Junos Pulse VPN client on OS X: https://derflounder.wordpress.com/2015/03/13/deploying-a-pre-configured-junos-pulse-vpn-client-on-os-x/

I prefer to use Unixorn’s The Luggage rather than a GUI package creator, so here I adapt Rich’s instructions for The Luggage users.

Installing the Luggage

If you don’t already have The Luggage, install it as follows (as per the instructions on Graham Gilbert’s blog post about The Luggage):

$ cd
$ git clone https://github.com/unixorn/luggage.git

At this point, if you don’t already have git installed, you will be prompted to do so. If that happens, install git and rerun the last command. Then continue:

$ cd luggage
$ make bootstrap_files

Creating the package

Now The Luggage is installed, copy your Junos Pulse installer and config file into a new folder:

$ mkdir -p ~/luggage-packages/junos
$ cp /path/to/JunosPulse.dmg /path/to/Default.jnprpreconfig ~/luggage-packages/junos/

Create a new file named Makefile in the same folder using whatever editor you use, and populate as follows:

USE_PKGBUILD=1
include /usr/local/share/luggage/luggage.make

TITLE=Junos-Pulse
PACKAGE_NAME=${TITLE}
REVERSE_DOMAIN=net.juniper
MANAGEMENT_DIR = "junos"
INSTALLER_PATH = "."
INSTALLER = "JunosPulse.dmg"
CONFIG = "Default.jnprpreconfig"
PAYLOAD=\
pack-server \
pack-script-postinstall

pack-server:
    @sudo mkdir -p ${WORK_D}/Library/Management/$(MANAGEMENT_DIR)
    @sudo cp $(INSTALLER_PATH)/$(INSTALLER) $(INSTALLER_PATH)/$(CONFIG) ${WORK_D}/Library/Management/$(MANAGEMENT_DIR)
    @sudo chown -R root:wheel ${WORK_D}/Library/Management/$(MANAGEMENT_DIR)

You may wish to sign the package with a developer ID if you are intending to make the installer available to your users for self-install, so that Gatekeeper doesn’t prevent installation. You will need an Apple Mac OS X Developer Account to do this, and have your Developer ID Certificate installed on the machine you are building the package. Then, add the following line as the third line of the Makefile, changing “Your Name” to the name of your certificate in your Keychain:

PB_EXTRA_ARGS+= --sign "Your Name"

Create a new file named postinstall in the same folder using whatever editor you use, and populate as follows (this is exactly the same as Rich Trouton’s postinstall file except for the install_dir):

#!/bin/bash
# Determine working directory
install_dir="/Library/Management/junos"

#
# Installing Junos Pulse
#

# Specify location of the Junos Pulse disk image
TOOLS=$install_dir/"JunosPulse.dmg"

# Specify location of the Junos Pulse configuration file
VPN_CONFIG_FILE=$install_dir/"Default.jnprpreconfig"

# Specify a /tmp/junospulse.XXXX mountpoint for the disk image
TMPMOUNT=`/usr/bin/mktemp -d /tmp/junospulse.XXXX`

# Mount the latest Junos Pulse disk image to the /tmp/junospulse.XXXX mountpoint
hdiutil attach "$TOOLS" -mountpoint "$TMPMOUNT" -nobrowse -noverify -noautoopen

# Install Junos Pulse
/usr/sbin/installer -dumplog -verbose -pkg "$(/usr/bin/find $TMPMOUNT -maxdepth 1 \( -iname \*\.pkg -o -iname \*\.mpkg \))" -target "$3"

#
# Applying Janelia VPN configuration file
#

if [[ -d "$3/Applications/Junos Pulse.app" ]]; then
    echo "Junos Pulse VPN Client Installed"
    "$3/Applications/Junos Pulse.app/Contents/Plugins/JamUI/jamCommand" -importFile "$VPN_CONFIG_FILE"
    echo "VPN Configuration Installed"
else
    echo "Pulse Client Not Installed"
fi

#
# Clean-up
#

# Unmount the Junos Pulse disk image
/usr/bin/hdiutil detach "$TMPMOUNT"

# Remove the /tmp/junospulse.XXXX mountpoint
/bin/rm -rf "$TMPMOUNT"

exit 0

To create the package, run the following command:

$ make pkg

You should now have a package named Junos-Pulse.pkg which you can import into your software distribution system (Munki, Casper etc).

Making a DMG for manual distribution

For any package that you wish to make available for distribution via the web or fileshare, you may wish to enclose it in a DMG. I’ve created a script that automates the process of creating a dmg for any pkg file in the same folder. the output includes a visual check to see if the package is signed.

$ nano dmg-it.sh

Contents of dmg-it.sh:

#!/bin/bash

# Run this script after "make pkg" to create a DMG
# if you have already signed your pkg in the Makefile
# or if you dont want to sign it.
#
# This version of the script will create a DMG for each pkg in the folder it is in.

mkdir tmp
ls ./*.pkg | while read script
do
    output_Name="${script%.pkg}.dmg"
    echo "PKG->DMG maker. Checking for signed packages..."
    pkgutil --check-signature "${script}"
    cp $script tmp/
    hdiutil create \
        -volname "${script}" \
        -srcfolder ./tmp \
        -ov \
        $output_Name
    rm tmp/*
done
rm -rf tmp
exit 0

Make it executable, then run it:

$ chmod o+x dmg-it.sh
$ ./dmg-it.sh

You should now have Junos-Pulse.dmg in your folder.

DeployStudio 1.6.12 with Late-2012 Mac minis and Early-2015 MacBook Pros

UPDATE: DeployStudio have now released version 1.6.13 which addresses the kernel cache issue that was present in 1.6.12.

UPDATE 2: OS X is no longer forked as of 10.10.3

DeployStudio hasn’t been updated for a while: version 1.6.12 came out 21 October 2014.  Since then we’ve had new Mac minis and MacBook Pros released that won’t boot to NetBoot images or USB boot sticks built using version 1.6.12.

What’s worse, Early-2015 MacBook Pros (the ones with the new force-touch, taptic TrackPad), are using a forked version of OS X 10.10.2 (14C2513) (regular Macs are still on 14C1514).

Late-2014 Mac minis

DeployStudio USB sticks

UPDATE: This is no longer required if you upgrade your DeployStudio USB stick using version 1.6.13 of DeployStudio Assistant.

You can fix your existing DeployStudio USB boot stick so that it will work on the Late-2014 Mac minis by plugging it into a fully up-to-date 10.10.2 Mac and running the following command to patch it:

$ sudo kextcache -update-volume /Volumes/DeployStudioRuntimeHD -Installer

Reference: http://www.deploystudio.com/Forums/viewtopic.php?id=7102

NetBoot images

UPDATE: This is no longer required if you upgrade your DeployStudio NetBoot image using version 1.6.13 of DeployStudio Assistant.

You can also fix your NetBoot image in a similar way (please note, I haven’t tried booting to this yet as my network does not allow it):

  • Browse into the NetBoot image, which is normally in the folder /Library/NetBootSP0, and double-click NetInstall.dmg.
  • Run the following command to patch it:
$ sudo kextcache -update-volume /Volumes/DeployStudioRuntime -Installer
  • Unmount the DMG

Early-2015 MacBook Pros

The method for Mac minis won’t fix your existing USB stick or NetBoot image to make it work on Early-2015 MacBook Pros. You must install DeployStudio on one of these new Macs, and then run DeployStudio Assistant to create your NetBoot image or DeployStudio USB boot stick. You will then have to run the commands as above to patch the images.

Bear in mind that your existing DeployStudio master images or AutoDMG OS X installers won’t work on these Macs either. Additionally, you cannot download OS X Yosemite from the App Store on these Macs, as the forked version is not available. So if you need to rebuild one of these Macs, you will have to use Internet Recovery, or obtain InstallESD.dmg from the recovery partition, e.g. using this method.