Tiny Deathstars of Foulness

Hey look, there’s a new category on the Jamf Marketplace, available at,selecting the AppConfig category. The new AppConfig category gives administrators of any MDM that supports AppConfig access to a set of apps that support AppConfig. If you have an app that isn’t listed here, feel free to let me know. 

What does this mean? Well, AppConfig is a way of sending data into an app. App config allows a customer to deploy settings into applications on iOS devices in much the same way that settings can be sent into a Mac app via the defaults command. This means an end user could get an app installed on their device from the iOS App Store, a custom app, or a B2B app and that app would have any settings the user might need to connect to servers or configure the experience.

So what is Managed App Config? At it’s most basic, you identify a label and a value in XML and send it to an iOS device that’s running iOS 7 or later (e.g. via Jamf 9 and up). The vendor who makes the app has to basically define what those settings are. Which brings up an interesting problem never fully addressed with defaults domains: standardization and ease-of-use (although MCX was close).  is a consortium of MDM vendors and software vendors that maintain the emerging AppConfig standards around Managed App Config (within the confines of what Apple gives vendors) and then makes a feed of settings for apps that conform to those standards. Jamf is a founding member of, along with MobileIron and AirWatch. Examples of what you could put into the feed include 
  • Enabling certain features of apps
  • Server URLs
  • Logos (if they’re pulled dynamically)
  • Text labels
  • Language packs

To see a list of apps that are available, check out 

Managed App Config options are set by vendors at compile time within the code and then the XML sent with the app is parsed by the app at installation time. If you’re a software vendor who wants to get started with AppConfig, check out the Spec Creator from Jamf Research or get in touch with the developer relations team from any MDM vendor.

If you’re a customer of an app and would like to leverage Managed App Config and your vendor isn’t listed on the site, get in touch with them, as this is the future of app management and chances are that you won’t be the only organization looking to unlock this type of feature. 

Let’s look at how this actually works. The Managed App Config options per supported app are available on a feed. The feed is available at Here, as follows, you’ll see a list of all of the apps supported.

You can then copy the path for an app, such as com.adobe.Adobe-Reaser/1/appconfig.xml and append it to the end of the URL to get the feed for that specific app. You can test this using to see output as follows.

Here, note that most of these fields are key value pairs defined by Adobe (in this example at least). You can enable or disable features of Adobe Reader using these keys. The same is true with a tool like Box that might want a more granular collection of settings than a feature like Managed Open In. 

Once you have the XML, you can then copy it to the clipboard and paste it into the App Configuration tab of an app, as follows. 

Finally, Apple has sample code available at

March 13th, 2018

Posted In: iPhone, JAMF

Tags: , , , , , , ,

Given the increased reliance on XML in scripts and exchanging data, a number of different solutions leverage XML traversal options to get all the things done. We frequently use path to bring a file into a script or program, or accept input from STDIN. The most basic task that we then perform is simply selecting an item from that file or STDIN and then variabalizing it. One common tool that we use here is Path. XPath calls these objects nodes, and uses path expressions to select these nodes. A path expression is the path along the xml input that is followed to find a piece of data. There are some pretty standard wildcards the can be used with xpath, where node() watches any node, * matches any element node, @* matches any attribute node, helping to constrain output. Supported expressions include:
  • node: This is a text input that identifies the name of a node to start a relative search from – for example site would select all nodes in a structure with the name site
  • . Identifies the current node (kinda’ like pwd in a shell)
  • .. Starts at the parent of the current node – for example,
  • / Starts traversal from the root node – for example, /computer would select any nodes that falls underneath
  • /computer meaning that these are absolute paths
  • // Identifies the nodes in an XML structure that match a selection wherever they may be – for example
  • //computer would select all nodes that contain //computer and search for other expressions below those that you may identify such as: ‘xpath //computer/general/mac_address’
  • //* Selects everything
  • //computer/* Selects all the child element nodes of everything that starts with computer
  • @ Select an attribute in an XML structure – for example ‘xpath //computer/general/@’
  • [1] This predicate selects the first item (or whatever number is identified, so xpath
  • //computer[3]/general/mac_address would return with the mac address of the third computer
  • [@PATTERN] Constrains found sets, so ‘xpath //computer/general/[@mac_address]’ identifies all computers with an actual mac_address attribute
  • //[@PATTERN=VALUE] Constrains a found set to all items where the attribute contains the value, so ‘xpath //computer/general/[@mac_address=00]’ identifies all computers with an actual mac_address attribute that has the value of 00
  • //[@*] Selects only items with something in an attribute (non-null), so ‘xpath //computer/general/[@mac_address=@*] (btw, rather than use an =, you can use > or <)
  • | creates compound matches. So ‘xpath //computer/general/mac_address | //computer/general/name’ would grab the mac_address and name of every computer
  • [last()] Identifies the last item, so ‘xpath //computer[last()]/general/mac_address’ would return the last computer’s mac address
  • [last()-2] placing a negative number after the parenthesis identifies descending orders from the end of a found set – for example, //computer[last()-2] Selects the second to last computer
Overall, as you can see xpath really makes traversing XML structures simple. Other tools and languages have their own ways, but most are similar in syntax.

November 15th, 2016

Posted In: Mac OS X, Mac OS X Server, Ubuntu

Tags: , , , , ,

AppleTVs automatically update. They do so using a process similar to how iOS updates, but instead of looking at the feed I posted in, they look at The AppleTV feed is similar to that available for iOS updates, with each dictionary having roughly the same data:
<string>Apple Inc.</string>
To construct a URL to a zip, you would then simply merge the _BaseURL and the _RelativePath to the asset from the feed for a given model, in the above example, ending up with the following URL to manually download tvOS 9.2 for AppleTV 5,3:
BTW, Applednld is load balanced between and, both within Apple’s Class C.
You don’t need two / characters in the path, but if you take the same process from my earlier post, you end up with

April 27th, 2016

Posted In: Apple TV, Mac OS X, Mac OS X Server, Mac Security

Tags: , , , , , , , , ,

There are some new restriction payloads in iOS 9. These include the following:
allowNews Boolean Supervised only. If set to false, disables News. Defaults to true. Availability: Available in iOS 9.0 and later.
forceAirDropUnmanaged Boolean Optional. If set to true, causes AirDrop to be considered an unmanaged drop target. Defaults to false. Availability: Available in iOS 9.0 and later.
allowUIAppInstallation Boolean Supervised only. When false, the App Store is disabled and its icon is removed from the Home screen. However, users may continue to use Host apps (iTunes, Configurator) to install or update their apps. Defaults to true. Availability: Available in iOS 9.0 and later.
allowScreenShot Boolean Optional. If set to false, users can’t save a screenshot of the display and are prevented from capturing a screen recording as well. Defaults to true. Availability: Updated in iOS 9.0 to include screen recordings.
allowKeyboardShortcuts Boolean Supervised only. If set to false, keyboard shortcuts cannot be used. Defaults to true. Availability: Available in iOS 9.0 and later.
allowPairedWatch Boolean Supervised only. If set to false, disables pairing with an Apple Watch. Any currently paired Apple Watch is unpaired and erased. Defaults to true. Availability: Available in iOS 9.0 and later.
allowPasscodeModification Boolean Supervised only. If set to false, prevents device passcode from being added, changed, or removed. Defaults to true. Availability: Available in iOS 9.0 and later.
allowDeviceNameModification Boolean Supervised only. If set to false, prevents device name from being changed. Defaults to true. Availability: Available in iOS 9.0 and later.
allowWallpaperModification Boolean Supervised only. If set to false, prevents wallpaper from being changed. Defaults to true. Availability: Available in iOS 9.0 and later.
allowAutomaticAppDownloads Boolean Supervised only. If set to false, prevents automatic downloading of apps purchased on other devices. Does not affect updates to existing apps. Defaults to true. Availability: Available in iOS 9.0 and later.
allowEnterpriseAppTrust Boolean If set to false, prevents trusting enterprise apps. Defaults to true. Availability: Available in iOS 9.0 and later.
allowEnterpriseAppTrustModification Boolean Supervised only. If set to false, prevents the enterprise app trust settings from being changed. Defaults to true. Availability: Available in iOS 9.0 and later.
allowMusicService Boolean Supervised only. If set to false, Music service is disabled and the Music app reverts to classic mode. Defaults to true. Availability: Available in iOS 9.0 and later.
allowCloudPhotoLibrary Boolean If set to false, disables iCloud Photo Library. Any photos not fully downloaded from iCloud Photo Library to the device will be removed from local storage. Availability: Available in iOS 9.0 and later.

September 9th, 2015

Posted In: iPhone, Mac OS X, Mac OS X Server, Mac Security

Tags: , , ,

OS X Mavericks Server (Server 3) comes with the /usr/sbin/serverinfo command (introduced in Mountain Lion Server). The serverinfo command is useful when programmatically obtaining information about the very basic state of an Apple Server. The first option indicates whether the Server app has been downloaded from the app store, which is the –software option: serverinfo --software When used, this option reports the following if the can be found:
This system has server software installed.
Or if the software cannot be found, the following is indicated:
This system does NOT have server software installed.
The –productname option determines the name of the software app: serverinfo --productname If you change the name of the app from Server then the server info command won’t work any longer, so the output should always be the following: Server The –shortversion command returns the version of the Server app being used: serverinfo --shortversion The output will not indicate a build number, but instead the version of the app on the computer the command is run on:
To see the build number (which should iterate with each update to the Server app from the Mac App Store, use the –buildversion option: serverinfo --buildversion The output shows the build of server, which doesn’t necessarily match the OS X build number:
Just because the Server app has been downloaded doesn’t mean the Server setup assistant has been run. To see if it has, use the –configured option: serverinfo --configured The output indicates whether the system is running as a server or just has the app installed (e.g. if you’re using it to connect to another server:
This system has server software configured.
You can also output all of the information into a single, easy to script against property list using the –plist option: serverinfo --plist The output is a list of each of the other options used: IsOSXServerVolume IsOSXServerVolumeConfigured IsServerHardware LocalizedServerProductName Server ServerBuildVersion 13S411 ServerPerformanceModeEnabled ServerVersion 2.2.67 The Server Root can reside in a number of places. To see the path (useful when scripting commands that are relative to the ServerRoot: serverinfo --prefix By default, the output is as follows, which is basically like a dirname of the ServerRoot:
You can also see whether the system is running on actual hardware desgnated by Apple for servers using the --hardware option: serverinfo --hardware The output simply indicates if the hardware shipped with OS X Server on it from Apple:
This system is NOT running on server hardware.
The --perfmode option indicates whether or not the performance mode has been enabled, dedicating resources to binaries within the Server app: serverinfo --perfmode If the performance mode has not been enabled then the output will be as such:
Server performance mode is NOT enabled.
To enable performance mode, you can also use serverinfo. This is the only task that the command does that can make any changes to the system and as such is the only time you need to elevate privileges: sudo serverinfo —setperfmode 1 Or set the boolean value back to 0 to disable. sudo serverinfo —setperfmode 0

October 22nd, 2013

Posted In: Mac OS X Server

Tags: , , , , , , , , , , , , , , , , , , , , ,

You can obtain a pretty decent amount of information about leases your OS X computer gets just by looking in the Network System Preference pane, for each interface. Screen Shot 2013-10-02 at 10.16.16 PM However, you can get a little lot more information, as with most things, from the command line. First, we’re going to take a look at en0 on our host and see what the MAC address is: ifconfig en0 ether Now, we can look in the /var/db/dhcpclient/leases directory to see a list of all of the leases we have running on our system. Based on the MAC address of our computer, we should see a file there that starts with the name of our interface and finishes with our MAC address. Let’s cat this file: cat en0-1\,84\:38\:35\:63\:87\:2e The output is similar to the following (a standard plist): <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ""> <plist version="1.0"> <dict> <key>IPAddress</key> <string></string> <key>LeaseLength</key> <integer>86400</integer> <key>LeaseStartDate</key> <date>2013-10-03T02:43:36Z</date> <key>PacketData</key> <data> AgEGAPSEH9QAAAAAAAAAAMCo0pAAAAAAAAAAAIQ4NWOHLgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjglNjNQEFNgTAqNIBAQT///8A MwQAAVGAAwTAqNIBBggEAgICzg0cDP8= </data> <key>RouterHardwareAddress</key> <data> ABfFg9DO </data> <key>RouterIPAddress</key> <string></string> </dict> </plist> This shows us the amount of time our lease is valid for, when the lease what provided to us, what IP was provided and the IP of our router. We can then key off of that information as needed (e.g. for other scripts/tools).

October 7th, 2013

Posted In: Mac OS X, Mac Security, Mass Deployment

Tags: , , , , , , , , , ,

Since the early days, OS X Server has supported performing the serveradmin commands through a web interface. This interface was accessible at the address of the server followed by a colon and then 311 in a web browser. This feature was disabled by default in Mountain Lion. But fear causes hesitation, and hesitation will cause your worst fears to come true, so we’re going to turn it back on. To enable, use the following command: sudo defaults write /Library/Preferences/ requireUserAgent -bool false Once done, open in a web browser, or replace with the address of the server if accessing from another location. This is stimulating, but we’re out of here. So, authenticate to be greeted with a list of services.

Lawyers don’t surf.

At the Server Admin Modules page, each service output from `serveradmin list` appears. Clicking each produces the ability to run the commands you can supply using `serveradmin command` along with the service name. For example, to get a list of all of the connected AFP users in OS X Mountain Lion Server, run the following command: sudo serveradmin command afp:command = getConnectedUsers Now, to get the same list, click on the servermgr_afp.html link and then click on getConnectedUsers.

Life sure has a sick sense of humor, doesn’t it?

Click on Send Command to see the output.

Peace, through superior firepower.

You then see an XML output that shows who’s connected (since I’m on a flight right now, luckily no one is connected to mine). Now you also have a URL in the toolbar, which should look something like this:
Rad, unicode. I guess spaces aren’t really compliant in URLs. Before we look at that, let’s take a look at what we can do with these. If you follow what I write, you have probably noticed that I use curl for tinkering with URLs a lot. In many cases, this is not the right tool. But I usually start there and move on if need be. Six seconds. We’re going to be meat waffles. Because we’re going to assume the server is using a self-signed cert that we don’t yet trust, we’re gonna’ use a -k along with curl. Then we’re going to follow that with the link. However, since we need to auth, we’re going to also go ahead and embed the username (in this case johhny) followed by a : and then the password (in this example, bodhi), followed by an @ in between the https:// and the server address, as follows: curl -k https://johhny:bodhi@ The output includes the afp:usersArray which shows active connections. The most interesting options, other than those for services you run in your environment, ar those under servermgr_info. Here, you can get PIDs for processes, kill PIDs, view logs, check file sizes, delete data and even reboot servers. Overall, this option has some security concerns, but provides some good insight into how the Server Admin tool worked under the hood in Mac OS X Lion Server and below while also serving as a functional option as an API for the  product, especially given that output is in XML, similar to the output of most other modern APIs. Vaya con Dios, Brah.

August 20th, 2012

Posted In: Mac OS X Server

Tags: , , , , , , , , , , , , , , ,