Munki and Adobe CS5 deployment
This guide will look at one possible method to deploy CS5 applications/suites and updates using Munki and AAMEE packages, wherein the licensing information is kept separate from the original installer packages and applied with payload-free packages. This method is especially useful if you need to deploy multiple licenses of various CS5 packages.
Munki and Adobe CS5 deployment
Munki has out-of-the-box support for Adobe Creative Suite installers. To deploy CS5, the original installer must be installed using a package generated with AAMEE, Adobe's tool to convert the existing install media to an Apple installer pkg format.
For convenience you may serialize the installer with a volume license serial, so that it automatically licenses the install and no further actions are necessary. However, you may want to keep your installer as generic as possible if you are in the situation where you need to deploy different licenses to different groups or departments. Luckily, Adobe provides a command-line licensing tool to provision a license for an installed product. It is called APTEE (Adobe Provisioning Toolkit Enterprise Edition, a fancy name for a binary named "adobe_prtk"), and we'll look at how this can be used to provision the AAMEE installs as payload-free packages and the use of the 'requires' key in a pkginfo. APTEE is available here.
Note about AAMEE packages with updates: AAMEE also supports in recent versions the bundling of updates into the package, so that only one package needs to be deployed. However, makepkginfo will likely not generate a proper pkginfo if there are any updates included in the AAMEE installer. However, as Munki will handle all the updates just as it would any other application, they are not necessary.
Before going into this, it is worth first going through the effort of setting up a functional AAMEE install (optionally with updates) with Munki. The Munki Wiki has a page for CS5 and CS5 Updates and provides all the information necessary, and there are example pkginfo files along with the source code. To quickly summarize the basics:
- build an AAMEE package with no updates, whatever options you wish (EULA, updates, etc.)
- wrap it in a disk image
- run makepkginfo on the disk image, which should generate a completely functional pkginfo
- no editing of the installs keys are necessary for either the installer or updates
- you may still add them for the key applications installed if you wish (for sake of clarify or for other configuration needs you may have)
- it is *necessary* to add an update_for key for all the updates, such that you may specify which items an update is used for (and there is a very useful CS5 update dependency list on this wiki)
- you will want to make sure you pick useful names, because they will be referenced at a few levels in dependencies if you follow the next section on licensing with APTEE
- upload to munki repo, rebuild catalogs and test that it installs properly, even if not licensed
The basic workflow of setting up multiple licenses involves two extra pkginfos. One is the APTEE licensing tool itself, to make sure it is installed alongside any product install. The second is a payload-free package to simply license a particular install. This creates two dependencies around a CS5 installer item: that every product installer requires the APTEE tool, and that every payload-free licenser requires the appropriate product installer. The resulting installation order is something like this:
APTEE -> AAMEE installer -> (optional updates for product) -> Payload-free licenser
First let's set up the APTEE pkginfo. Since it's best to avoid re-packaging when possible, and APTEE is a single binary at the root of a .dmg, we can simply generate our pkginfo with all the parameters suitable for this executable. Since makepkginfo will generate a hash for the binary and check that the existing file matches this checksum, we don't worry about receipts or version strings for applications. We're going to put it in /usr/local/bin, but it could be just about anywhere. *note* This install will fail if /usr/local/bin doesn't already exist. copy_from_dmg won't automatically create target destinations for you, as it cannot assume what the correct ownerships/permissions should be.
Assuming we've got our repo mounted (for example, at /Volumes/munki_repo) and the distribution .dmg already in place in pkgs, we run:
makepkginfo -i adobe_prtk -d /usr/local/bin /Volumes/munki_repo/pkgs/apps/Adobe/Enterprise/adobe_prtk_15029.dmg
which specifies the path to the adobe_prtk item (-i), whose destination (-d) will be /usr/local/bin. It should generate:
<?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>autoremove</key> <false/> <key>catalogs</key> <array> <string>testing</string> </array> <key>installer_item_hash</key> <string>a5333f03dda6876469ba9d3b0b23b0762f0259f39f4de3ea6853d9ab068f146a</string> <key>installer_item_location</key> <string>apps/Adobe/Enterprise/adobe_prtk_15029.dmg</string> <key>installer_item_size</key> <integer>148</integer> <key>installer_type</key> <string>copy_from_dmg</string> <key>installs</key> <array> <dict> <key>md5checksum</key> <string>7606ede1a4b7697e31926d8974e16eb7</string> <key>path</key> <string>/usr/local/bin/adobe_prtk</string> <key>type</key> <string>file</string> </dict> </array> <key>items_to_copy</key> <array> <dict> <key>destination_path</key> <string>/usr/local/bin/</string> <key>source_item</key> <string>adobe_prtk</string> </dict> </array> <key>minimum_os_version</key> <string>10.4.0</string> <key>name</key> <string>adobe_prtk</string> <key>uninstall_method</key> <string>remove_copied_items</string> <key>uninstallable</key> <true/> <key>version</key> <string>0.0.0.0.0</string> </dict> </plist>
We can modify the name to something more meaningful:
and the version string to that which is reported by Get Info in Finder (Usually munki would find version strings from an Info.plist inside of an application bundle, but in this case it's just a single executable):
This way, if Adobe ever updates APTEE (for instance, to incorporate the inventory feature they advertise but don't actually have any evidence that it ever existed), the updated version will force Munki to ensure the binary matches the checksum in the pkginfo for the new version.
Next we've got to make sure APTEE is installed with any product installer. If, for example, we have a Design Premium CS5 install pkginfo with an item name AdobeDesignPremiumCS5, we specify that it requires the AdobeAPTEE item.
<key>name</key> <string>AdobeDesignPremiumCS5</string> <key>requires</key> <array> <string>AdobeAPTEE</string> </array>
Licensing postflight pkginfo
Next we want to apply the same logic to the licenser item, only it will depend on the entire product install. This licenser is the item we'll actually specify in a given client's manifest, rather than the product name itself.. but we'll specify that at the end.
To feed this pkginfo we can generate a simple payload-free package with a postflight by using Greg Neagle's payload-free package template.
#!/bin/sh /usr/local/bin/adobe_prtk --tool=ReplaceSN --serialize=DesignSuitePremium-CS5-Mac-GM --serial=THIS-WOUL-DBEY-OUR-SERI-ALNO exit 0
We can give the package name something to specify the product and whose license it is, for example "AdobeDesignPremiumCS5-License-DesignDept".
Once we've bundled the payload-free .pkg into a dmg and put it on the server, makepkginfo generates something like this:
<?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>autoremove</key> <false/> <key>catalogs</key> <array> <string>testing</string> </array> <key>description</key> <string>Licenses the suite.</string> <key>display_name</key> <string>Adobe Design Premium CS5 Design Dept License</string> <key>installer_item_hash</key> <string>170f1bab5c427257367eb2df79b1fa6be23789ce3a2cc36b5edbf7217a139d01</string> <key>installer_item_location</key> <string>apps/Adobe/CS5/Licenses/AdobeDesignPremiumCS5-License-DesignDept.dmg</string> <key>installer_item_size</key> <integer>17</integer> <key>minimum_os_version</key> <string>10.4.0</string> <key>name</key> <string>AdobeDesignPremiumCS5-License-DesignDept</string> <key>receipts</key> <array> <dict> <key>filename</key> <string>AdobeDesignPremiumCS5-License-DesignDept.pkg</string> <key>installed_size</key> <integer>0</integer> <key>packageid</key> <string>edu.org.AdobeDesignPremiumCS5-License-DesignDept</string> <key>version</key> <string>1</string> </dict> </array> <key>uninstall_method</key> <string>removepackages</string> <key>uninstallable</key> <true/> <key>version</key> <string>1</string> </dict> </plist>
And the only part we need to add is a requires key for the suite install.
<key>requires</key> <array> <string>AdobeDesignPremiumCS5</string> </array>
Tying it together
Since our licensing package depends on the main product install, which depends on APTEE, we only need to specify the licensing package as a managed_install in the client manifest. Because requires items are treated like any other managed_install item, we know that they will receive updates for the appropriate product.
<key>managed_installs</key> <array> <string>AdobeDesignPremiumCS5-License-DesignDept</string> </array>
Because Munki supports a script shoehorned via the uninstall_script key (see 0.7.0 release notes, a client could have its license removed by passing the "--unserialize" option to adobe_prtk, without needing to create another payload-free package.