Tiny Deathstars of Foulness

Apple has released version 1.0.1 of the Apple Configurator tool. To install the first update to Apple’s new tool, go to the App Store on a computer that has Apple Configurator installed, click on Updates and then click on the Update button for Apple Configurator.

The update has a number of new features and fixes. The first is that Enterprise Apps can be installed. Previously, when you went to install internally developed applications, you would get an error that the installation could not proceed. Another great fix is that commas are now escaped when importing application codes from the VPP spreadsheets (a comma in a CSV/comma separated value would kill the ability to import VPP codes before). Another fix is to let you pull redemption codes from unsupervised device (this makes me very happy).

The redemption codes that you buy an app with can also now be used in Configurator, according to the release notes. This worked for me anyway, but I’ve read reports that people had to burn an additional code to use them with Configurator. The remaining redemption codes are now listed properly, as well. Another fix is that Notes and Bookmarks pushed into iBooks and iTunes U are restored properly when supervising devices. The WPA2 passwords had been wonky (according to the content of that payload), so that’s been fixed as well.

Also, a bug I hadn’t noticed, the capacity of an 8GB iPod Touch is now displaying properly…

April 18th, 2012

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

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

I have been added as a speaker at MacTech InDepth in New York. If you haven’t signed up yet, and you work with Mac OS X Server then you should really check out the sessions that have been planned:

  • The Elephant in the Room: The New Lion OS X is out, now what? There are a lot of differences to contend with between Lion and Snow Leopard. Now with the new Mountain Lion update, what changes can we expect to see? We discuss the differences in advanced services, GUI simplicity, and Apache management GUI’s. We help you understand the updates in the new OS and make the transition easier. We go over the new updates of Lion over the Snow Leopard server.
  • Setting solid foundations: To truly grasp the power of Lion, you need to set up solid foundations. We go over minimum requirements for internet DNS, and tackle router tricks. We discuss open directory and what it was used for.
  • Mobile Device Management 101: Apple’s IPCU/Apple Configurator: Mobile Device Management is vital to businesses, large or small. We have an extensive overview of profile manager and how you can use mobile device management on OS X. For those still using Snow Leopard, we go over your options and discuss the possibility of using third parties as a solution.
  • DNS, Ahh, run away, run away: In this session, we tackle DNS and break it down and show how simple it is to work with. We go over how DNS works and cover different components such as internet DNS and internal DNS.
  • Administering a Server with just We show you how to use and control administrative programs. For the services, we go over Address Book, iCal, iChat, and Mail.
  • Web Administration of OS X Server : Web Admin on Lion Server versus Snow Leopard is covered, dealing with the differences and how to use each system effectively. On Lion server, we cover using FTP without a GUI.
  • Going old school, using the old tools: After getting used to Snow Leopard we go over the major differences between Snow and Lion and how you can handle the transition. We go over server admin and what is still left in the program and why it has been left.
  • Deployment Part I: Tools & Concepts: In tools and concepts we learn that there aren’t stark differences between Lion server and Snow Leopard. NetBoot, NetRestore and third party tools are covered; we talk about how NetBoot works and what the differences between NetBoot and NetRestore are. Along with this we cover Network configuration requirements and using software update server.
  • Deployment Part II: DeployStudio: DeployStudio is covered in-depth; we cover creation techniques and management techniques.

Overall, this represents a nice, fast way to update your skills to allow for managing Lion Server and to get up to speed with those new to the platform. One thing I like about the session list is that it goes beyond the stock server implementation and looks at DeployStudio, MDM and other important topics not purely server oriented. I hope to see you all there!

These vagabond shoes, are longing to stray
Right through the very heart of it – New York, New York

April 5th, 2012

Posted In: public speaking

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

Apple Configurator has now been in my grubby hands long enough for me to start looking at it a little deeper than I did in the introductory article I did awhile back. Architecturally, Apple Configurator keeps its data in ~/Library/Application Support/ Here, you’ll find a directory called IPSWs, another called Resources, file called AppleConfigurator.storedata and another called Users.storedata.

The IPSWs directory is where operating system versions, per model of iOS are stored. These look something like iPad2,1_5.1_9B176_Restore.ipsw, which is iOS 5.1 for a standard iPad 2. iPad 1, the retina display iPad, as well as each iPod Touch and iPhone 4 each have their own entry as well. The IPSWs are automatically downloaded here when you initially perform a restore using Apple Configurator for each model of iOS device. You can copy each model’s ipsw into this directory proactively to keep Apple Configurator from downloading updates. You can also populate this directory manually with older copies of iOS if you are running them or if you are a developer, with developer releases of ipsw files.

The Resources directory is going to house applications and documents/content that you’ll be pushing to devices if you use the Assign options to assign content (and possibly other assets, although thus far I seem to only be getting apps and documents in here). They don’t look like applications or documents though. Each entry in this directory is assigned a generated identifier. The size of each and date/time stamp should match the size of the object and when it was added to Apple Configurator, respectively. When you delete an application or document from Apple Configurator then you should see the entries here disappear. Running strings against the entries that are applications, you should be able to identify which is which pretty quickly. Running such commands against documents (or other assigned content) can net much spottier results due to the fact that there aren’t always references to what you’re looking at inside of what you’re looking at… Either way, just looking at the raw data that comprises these application and content objects isn’t the only way to grab the name of the file. We’ll take a look at that a little later.

In addition to these two directories, Apple Configurator can throw data almost anywhere because it allows users to do so when creating backups of devices. These backups are in the form of files ending with .iosdevicebackup and by default getting placed into ~/Documents. When these are created, they can be saved to any location you choose. Deleting them from the file system automatically causes Apple Configurator to forget about them (although I have had to restart the application after removing the .iosdevicebackup file).

And then there’s the databases. As I mentioned, there are two, AppleConfigurator.storedata and Users.storedata. These are both sqlite databases and are both accessible through standard sqlite3 commands/queries. I haven’t been able to find any documentation of what each table is used for, but I’ve run devices through a number of regressions and think I’ve mostly pieced it together, which I’m in some cases able to back up with writing directly to the SQL table. Each database consists of the following tables (although not all are used and in some cases they are used for different purposes in each database), which I show followed by a description of what I think each is doing along with the more important columns of each table:

  • ZAPPINSTALL: In AppleConfigurator.storedata keeps track of applications that have been deployed via Configurator. Each application has a ZAPPLICATION column, which is a numeric identifier for each application. The ZCODE is a human readable column that shows what kind of application was deployed and the ZDEVICERECORD indicates which device that Apple Configurator placed the application on. This table does not appear to be used in Users.storedata.
  • ZMOBILEAPPLICATIONICON: In the AppleConfigurator.storedata, the Z_PK column in this table should match the ZDEVICERECORD column in ZAPPINSTALL. Other than that, thus far the columns appear to be the same for each row. This table does not appear to be used in the Users.storedata.
  • ZDEVICEPROPERTIES: Not used in Users.storedata, the table in AppleConfigurator.storedata is used to track information about devices under supervision. The Z_PK column does not match the Z_PK column in the ZMOBILEAPPLICATIONICON but the ZECID, ZDISKCAPACITY, ZENABLEWIFICONNECTIONS, ZBLUETOOTHADDRESS, ZBUILDVERSION, ZDEVICECLASS, ZNAME, ZPRODUCTVERSION, ZSERIALNUMBER, ZTYPE and ZUDID match what their names imply if you de-prefix the Z from the column names.
  • ZPROFILE – Each profile created is tracked in this table. Given that a profile is just a property list, the ZDATA column consists of text data that we’ll look at a little more in a bit. The ZPAYLOADUUID column is a unique identifier for the payload, which appears in the payload as well. The ZNAME column tracks the user-enterable name for each profile you create.
  • Z_19MEMBERS: Not used in AppleConfigurator.storedata, this table is used to track manual group membership in the Users.storedata database.
  • Z_15SUPERVISIONRECORDS: Table used to track supervision with manually created groups.
  • ZDEVICERECORD: Each iOS device that has been docked into Apple Configurator is tracked using this table. Here, the name of the iOS device is trapped in the ZNAME column, the serial number in the ZSERIALNUMBER column and the UDID of the device in the ZUDID column.
  • ZSUPERVISIONRECORD: AppleConfigurator.storedata uses this table to attach UUIDs for users (in the ZPOLICYUSERUUID column and ZUSERUUID columns) to devices (ZUDID and ZDEVICESERIALNUMBER columns)
  • Z_METADATA: Used in both .storedata databases, appears to link a UUID to a property list.
  • ZIPSWPACKAGE: Doesn’t appear to be used. Based on the column headers, I think this table is supposed to link the IPSW path to the build version and device types. This seems to be getting derived from elsewhere though (e.g. the metadata directly on IPSWs). Given that you can drop an IPSW into the directory and it will just use it I, I think that Configurator is just getting the data directly from the bundleID and skipping this altogether, which given the relatively small number of IPSWs that people will use doesn’t seem to be very costly in terms of runtime/efficiency… For me the jury is still out on this as I haven’t made it do anything yet.
  • ZSUPERVISIONRECORDGROUP: Stores information about manually created device groups (as opposed to user groups). The ZNAME column is where the name you enter for the group is kept, so you can direct queries here to see the rest of the contents for each row. Used by AppleConfigurator.storedata, not Users.storedata.
  • Z_PRIMARYKEY: The Z_NAME row in this table is the same in both Users.storedata and AppleConfigurator.storedata as is the Z_SUPER column. However, the Z_MAX is different, as it indicates the highest number of entries (in terms of IDs) in the column for the corresponding object (e.g. the highest Z_PK entry in the ZMOBILEAPPLICATION table).
  • ZMANAGEDFILEOBJECT: The users.storedata table uses this directory to track data that has been assigned to each user. The ZURLSTRING column indicates the path to the file, the ZAPPLICATION IDENTIFIER indicates the application the file is bound for in the iOS filesystem and the ZNAME1 column indicates the name of the object. This table is also used in the AppleConfigurator.storedata database, but there it simply lists the instance of each application, the generated ID for the application and the location on the filesystem.
  • ZUSER: Show’s the UUID of the user in the ZUUID column, which matches with the ZUSERUUID in column in the ZSUPERVISIONRECORD table, (assigned in Configurator), whether there is an image for the user from the directory service (ZIMAGEISFROMDIRECTORY column, boolean), the hash of the image if there is one (ZOPENDIRECTORYIMAGEHASH column), the device the user has checked out (ZDEVICESERIALNUMBER), the last device the user checked out (ZLASTDEVICESERIALNUMBER), the Open Directory GUID (ZOPENDIRECTORYGUID) for the user, the short name (ZOPENDIRECTORYSHORTNAME) and the directory domain (ZOPENDIRECTORYNODEPATH). This data is, as you can imagine, in Users.storedata and the AppleConfigurator.storedata for this table is empty.
  • ZMOBILEAPPLICATION: Empty for Users.storedata, but keeps all the fun info on apps for AppleConfigurator.storedata. It keeps the name the app should have (ZNAME), the version of the app (ZVERSION), the identifier for the app (ZIDENTIFIER), the genre (ZGENRE), the author (ZAUTHOR) the price paid for the app (ZORIGINALPURCHASEPRICE), the app image (the ZMOBILEAPPLICATIONICON Z_PK column matches the ZDATA and ZIMAGES columns here), whether you can push content to the app (using the ZSUPPORTFILESHARING column), whether the app is an enterprise app (ZISENTERPRISEAPP). The app has told Apple Configurator all of this information (notice when you add an app you have to have an internet connection) and so if you try and change it the app won’t deploy.
  • ZUSERGROUP: Empty for AppleConfigurator.storedata, lists the name (in the ZNAME column) of groups, the Open Directory GUID if it’s an Open Directory group (ZOPENDIRECTORYGUID). You could do an export from dscl and then import it here if you wanted to pop a whole lot of groups into Apple Configurator.
Note: Again, these are my initial ideas of what these are. I’ll change them if I discover they’re something different or link to official documentation of the table map if it’s released.

Now that we know roughly what’s where, let’s put that to use. Let’s start with just getting some information on what profiles are installed in Apple Configurator. Here, we can run a SQL select to look at all the rows in the ZPROFILE table, by calling the sqlite3 command (in /usr/bin), using the SQL table as our first position and then putting our select query in quotes, which in this case is to select all (*) information from the ZPROFILE table:

sqlite3 ~/Library/Application Support/ 'SELECT * FROM ZPROFILE'

To export a profile from Apple Configurator’s database using sqlite3 (which means you can do this from a centralized location), use the sqlite3 command, selecting the database and then run a select for the ZPROFILE table, selecting the ZNAME record called Pretendco Deployment and then send the output to a file called test.mobileconfig:

sqlite3 ~/Library/Application Support/ 'SELECT * FROM ZPROFILE WHERE ZNAME = "Pretendco Deployment"' > test.mobileconfig

Strip the first line of that file out and you’ve got yourself a mobileconfig file.

To see all of your applications:

sqlite3 ~/Library/Application Support/ 'SELECT * FROM ZMOBILEAPPLICATION'

Or if that’s too much output (it is), then just look at the names of the apps:

sqlite3 ~/Library/Application Support/ 'SELECT ZNAME FROM ZMOBILEAPPLICATION'

These are just a few light queries. You could easily expand on this to export all of the profiles as mobileconfigs, dump a list of each iOS device that has each app installed, a list of which users have which devices, which users have which apps, which devices are running low on disk space, etc. Overall, the sqlite queries are similar in nature (or can be) to what we were doing in the scripting iPhone Configuration Utility article I did awhile back; however, there are a lot more options here.

March 28th, 2012

Posted In: iPhone, Mac OS X Server, Mass Deployment

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

My traditional interpretation of Apple’s vision on how iOS devices are used is that everyone has an AppleID. That AppleID enables them to access their apps from any iOS device they own or Mac that they own. That AppleID enables them to access mail, contacts, calendars and even files through iCloud. That AppleID also allows users to remotely wipe their device through Find iPhone and track their friends iOS devices (as in social networking via breadcrumb tracking) through Find Friends. All of this “Just Works” in a consumer sense. And it even allows for a little sharing of content across devices you own. However, larger organizations need more. They need centralized management, content distribution and most other things you find that you rely on traditional desktop computers for.

Over the years, Apple has added tools for centralized control of devices. This started with ActiveSync compatibility and early forms of Mobile Device Management and has grown into a pretty robust, albeit disconnected, set of tools. Of these, Apple Configurator is the latest. Apple Configurator was released about a week ago and since, I’ve been trying to figure where it fits into the solutions architecture that surrounds iOS integrations. There are a number of other tools already available that can aid in the deployment and management of iOS devices, and Configurator is a great addition.

To me, there are 3 classes of management tools for iOS. These were roughly broken up into Over the Air (OTA), cradled (USB) and content management. Apple Configurator ends up fitting into all of these scenarios in some way. Let’s start by looking at the traditional uses of these three and then look at how they are impacted by Apple Configurator.

Mobile Device Management

Over the Air tools, such as Profile Manager, allow for Mobile Device Management (MDM) without cradling, or syncing a devices. These tools allow you to configure policies via profiles. There is also a bit of App pushing built into most MDM solutions. Apple’s Profile Manager can push applications written in-house, but no content from the App Store. 3rd party solutions, such as JAMF’s Casper Suite, Absolute Manage MDM, AirWatch and about 15 others are able to push apps from the App Store as well, leveraging the Volume Purchasing Program (VPP) to issue apps to devices. However, when an app is pushed through one of these tools, the app becomes associated with the AppleID for the user who owns the device.

Note: While we use the term push, the user has to accept all App installations on the device.

For large environments, MDM is a must as it allows for centralized command and control. Pushing apps is one aspect of such control. Policies enforceable through MDM include disabling cameras, configuring passcode policies on devices (not pushing passcodes), disabling YouTube, silencing Siri, unstreaming photos, disabling iCloud Backup, forcing encrypted backups, disabling location services, controlling certificates, blocking pop-ups, controlling cookies, disabling access to the iTunes and App Stores,  and controlling what kind of media can be accessed on devices.

Additionally, MDM can be used to push SSIDs for wireless networks (and their passwords/802.1x configuration information), setup mail, setup Exchange ActiveSync, configure VPN connections, configure access shared calendars (iCal shared files, CalDAV and Exchange), configure access to shared contacts (LDAP, CardDAV, Exchange and Exchange Global Address Lists), deploy Web Clips and manage certificates (either with cert files or via SCEP). In short, whether you’re using the practically free Profile Manager from Apple, Mobile Iron, Casper, AirWatch, FileWave or one of the many other tools, there are a lot of things that MDM can configure on devices.

Reporting can also play a major role in how MDM tools are used. iOS Apps are owned by AppleIDs, not devices. MDM does not manage AppleIDs, but you can trigger fields in MDM databases to report back unauthorized AppleIDs being used. Reporting can also identify when devices join non-approved wireless networks (which cannot be blocked through MDM), identify devices that have been jailbroken (a major security concern for many organizations) and report on device use.

Because devices can fall outside of our control, MDM also plays an important role in being able to wipe and lock devices. While some of these types of features are available via Exchange, not all people use ActiveSync. Users and administrators alike can wipe, lock and de-enroll devices at will, potentially crippling what any device with an Enrollment Profile can do.

There are really 3 kinds of MDM tools: those that can push apps, those that can’t and Apple’s Profile Manager. The reason I put Profile Manager into its own class, is that it can push some kinds of apps, it’s cheap ($49.99 one time as opposed to per device per month or per device per year billing) and it’s great for some things. But Profile Manager should be used in very specific environments unless the price is the only decision making factor behind a tool. In larger environments, choosing a MDM solution is one of the most important aspects of managing mobile devices and the iOS platform is no different in that manner than other mobile platforms.

MDM has some limitations, though. A good MDM solution can manage the infrastructure side of device configuration. However, content requires a completely separate tool. Additonally, MDM is a completely opt-in experience. If a user wants, they can remove their device from the MDM solution at any time. Rather than a limitation, think about the opt-in experience this way: if a user removes themselves from MDM then all content that was given to them via MDM is then taken away, except that which they have moved to the local device. Therefore, if an administrator pushes an Exchange configuration then all content from that Exchange profile is forbidden fruit, removed alongside the de-enrollment.

MDM also works with Lion. Policies, centralized management, etc can be integrated with Lion. You can’t do app distribution per se, but you can push out a policy to change where the dock is on the screen, add a printer to a Mac and configure a login hook through a Profile Manager-based policy. Many of the MDM providers have begun adding functionality to their tools to allow for Mac management as well as iOS and I would expect that to become the standard in years to come. iOS is a single-user device and OS X is a multi-user device, which completes that paradigm, but Apple has made it no secret that policy-based management for Mac OS X is moving to the realm MDM (even if that is enforced through a traditional lens of directory services based policy-based management).

Content Management

One of the unique aspects of the iOS platform is that it doesn’t have a file system that is exposed to users. There’s no /Volumes, no C: drive and no home folders. The devices don’t log into a server, because there’s no way to interpret a server connection. The file system that is exposed to iOS devices is through the lens of each application. Sandbox is a technology that limits each application’s access in terms of memory, hard drive, etc. Each application can only communicate with resources outside of itself if there is an API to do so, APIs mostly reserved for Apple (e.g. photos, contacts, etc). Therefore, when you discuss content management from the perspective of building a large iOS solution, you’re talking about apps.

The apps used for content management come in a few flavors. There are those that allow you to edit content and then there are those that allow you to read content. One way to look at this is through Safari. Sharepoint, WebDAV and various document management portals allow users to access data through the Safari browser on an iOS device. Safari will let you view various file types. But to edit the data, you would need to send it to an app, or copy it to the clipboard and access it in an app. Pages is an example of an app that can browse a file tree via WebDAV and edit content. However, planning how each type of file is accessed and what type of editing can be done on each file type or what type of resources need to be accessible can be difficult (e.g. there are a number of transitions in Keynote presentations that do not work in iOS).

Cradling Devices

Then there’s iTunes. iTunes allows you to backup and restore devices, update devices, etc. iTunes allows you to drop content into each application. If you look into the ~/Library/Mobile Documents, you can drop content, edit default documents and other tasks that can be done through a command line, then perform a cradled sync to an app. If networking is built into an app then you don’t have to plug a device into a computer. If an app can leverage iCloud, SMB or AFP then you can access data over the air. If you are trying to replace computers with iOS devices (a la post-PC) then you would need to plan each business task that needs to be performed and make sure not only that there is an app for that (or an app you build for that) but also make sure that you can round trip data from a shared repository and back to the network storage that the data resides on.

You can also access many of the benefits of MDM without having an OTA element. This can be done with iPhone Configuration Utility. iPhone Configuration Utility can configure the same policies available through Profile Manager but relies on either a cradled or email/web server/manual way of getting policies onto devices and updating. MDM automates this, but iPhone Configuration Utility is free and can be used as well. Additionally, profiles can be exported from Profile Manager and installed in the email/web server/manual way that iPhone Configuration Utility profiles are installed.

This is all probably starting to seem terribly complicated. Let’s simplify it:

  • OTA policies and custom app deployment: MDM
  • OTA content distribution: Apps
  • Cradled policies and custom app deployment: iPhone Configuration Utility (free)
  • Cradled content and app distribution: iTunes (free)
  • OTA App distribution: AppleID/iCloud
  • Backup and restore: iCloud or iTunes

Basically, there’s a few holes here. First, AppleIDs cannot be centrally managed. Second, you need to use gift cards or the Volume Purchasing Program (VPP) to distribute apps, and Third, even when you push an app to an AppleID, the app follows the AppleID to their next organization (which causes many organizations to treat apps like consumables). Fourth, synchronizing content is done primarily through iTunes, which only syncs a device at a time, making preparation of large numbers of systems terribly complicated.

Apple Configurator

Enter Apple Configurator, a free tool on the Mac App Store. This tool basically fixes all of the problems that we reference, but does so over USB. This means that Apple Configurator is not necessarily a replacement for MDM. In fact, you can deploy Trust and Entrollment profiles for MDM and automate the MDM enrollment for a device through Configurator. Instead, Apple Configurator is a tool that can either Prepare or Supervise an iOS deployment and do so in a manner that is easy enough that you don’t need a firm background in IT to manage devices on a day-to-day basis.

Here is what Apple Configurator can do:

  • Update iOS devices to the latest version of iOS.
  • Rename devices using a numbered scheme (e.g. iPad 1, iPad 2, etc).
  • Erase (wipe) iOS devices.
  • Backup and Restore iOS devices.
  • Deploy profiles/policies (e.g. no Siri for you, disable cameras, setup wireless, etc) to iOS devices.
  • Export profiles.
  • Activate devices (after all a restore of a freshly activated device is an activation).
  • Push any kind of app to devices.
  • Track Volume Purchase Program (VPP) codes used on devices.
  • Revoke VPP codes used on “Supervised” devices (more on supervision later).
  • Assign users from directory services to devices.
  • Load non-DRM’d content to apps on devices.
  • Can work with up to 30 devices simultaneously (think big USB hubs or carts on wheels here).

Apple Configurator has some caveats:

  • Paid apps need to use VPP codes to DRM apps. These VPP codes are purchased through a centralized program for an entire organization. To enter the VPP, you need to be a business with a DUNS number or an educational institution. You also basically need to be in the United States.
  • Free apps can be deployed but the AppleID is in the IPA, meaning that to do an OTA update through App Store requires entering the password for the Apple ID the app was purchased with.
  • In order to push apps through Apple Configurator, the system running Configurator needs access to Apple’s servers and Apple Configurator needs an AppleID associated with it that is not the VPP facilitator if you are leveraging any paid apps.
  • You can use Apple Configurator “off-line” or without an AppleID to Prepare devices with Profiles, just not to
  • If you push Trust and Enrollment profiles to automatically join Profile Manager (or another MDM vendor) the device isn’t associated with a user unless the MDM has been prepped to designate each UDID or Serial Number to a given user.
  • Apple Configurator doesn’t work with Video or Music due to different DRM limitations.
  • If you accidentally plug in your iPhone to a machine you’re using Apple Configurator on it and you’ve chosen to Erase in the application, then it will wipe your phone along with the 30 iPads you’re wiping. It’s awesome and scary like that (yes, I’ve accidentally wiped my phone).

I see a number of uses for Apple Configurator. Some of these use cases include:

  • Company and education labs: manage devices end-to-end (no MDM, iTunes iPhone Configuration Utility or other tools needed), managed by the lab manager.
  • One-to-One environments (schools): Manage the distribution of infrastructure settings (mail, wireless networks, etc) for devices as well as Trust Profiles to make it faster to enroll in MDM environments and Web Clips to manage the links for enrollment.
  • Device distribution: Pre-load applications (that can’t be updated unless they’re cradled again), renaming, profiles, activation, iOS software updates, etc.
  • Backup and Restore only stations where you don’t interfere with later iTunes use.

These can enhance practically every environment I’ve worked with. But unless it’s a small environment (e.g. the labs), Apple Configurator isn’t a replacement for the tools already in use in most cases. Instead, it just makes things better. Overall, Apple Configurator is a welcome addition to the bat belt that we all have for iOS management and deployment. Now that we’ve looked at the when/where of using it, let’s look at the how.

There are two ways to use Apple Configurator. The first is to Prepare Devices. You would use this mode when you’re going to perform the initial setup and configuration of devices but not when the devices won’t be checking back into the computer running Apple Configurator routinely. Preparation settings do not persist. And while applications can be pushed through Preparation, updates for those applications will be tied to the AppleID that purchased the app.

The second is Supervise.  Supervising devices is an option when preparing and allows you to have persistent changes to devices, to layer new settings the next time devices are plugged in, to add applications and the most intriguing aspect of iOS management here is reallocating VPP codes to new devices when a user or device is retired. Supervising devices also allows for assigning a given user to a device and thus pushing data into an application.

Setting Up Apple Configurator

Apple Configurator is installed through the Mac App Store. When installed, you are presented with three options. The first (going from left to right) is to Prepare Devices.

Apple Configurator

Apple Configurator

Before we get started, we’re going to add our AppleID. The computer running Apple Configurator needs to be able to connect to the App Store and it needs to have an AppleID associated with it if you’re going to use VPP codes. So let’s set that up before moving on. To do so, from Apple Configurator, click on the Apple Configurator menu and click on Preferences… From the Preferences menu, click on Set for the Apple ID and provide an AppleID (not the VPP Program Facilitator).

Configuring AppleIDs with Apple Configurator

Configuring AppleIDs with Apple Configurator

Then, when prompted, provide the credentials for your AppleID. If you have any problems with this, try Authorizing the computer in iTunes, if you can’t do one it stands to reason you can’t do the other and it’s either an invalid AppleID or that the computer cannot communicate with Apple’s servers (ports, DNS, Internet connectivity, etc might be the issue).

Configuring AppleIDs with Apple Configurator

Configuring AppleIDs with Apple Configurator

Also, let’s configure the Lock Screen settings, which is what’s displayed to users when you’re supervising devices. If you have user pictures in Open Directory, this will show each user’s photo at the lock screen (we will discuss device supervision later).

Configuring Lock Screen Settings In Apple Configurator

Configuring Lock Screen Settings In Apple Configurator

Using Apple Configurator to Prepare Devices

In this example, we’re going to prepare some devices for deployment. Before we do anything, we’re going to do a backup of the iOS device to use for testing. To do so, simply click Prepare Devices to bring up the main Apple Configurator screen and then click in the Restore field.

Apple Configurator's Prepare Devices Screen

At the Restore menu, click Back Up…

Then choose the device to backup and click on Create Backup… to bring up the screen to select where to save your backup to (by default it should be your Documents but you can save them anywhere, like /iOSBackups). Click Save to make the first backup.

Saving Backups in Apple Configurator

Saving Backups in Apple Configurator

Notice how fast that went (assuming you didn’t load it up with 10 Gigs of crap)? The reason is that we’re not backing up iOS, just the data. This will become a little more obvious the first time we go to restore a device. In the meantime, if you look at your target directory, you’ll see a file with the name you provided followed by .iosdevicebackup. If you aren’t supervising you would need to delete these from the filesystem to remove them from the menu of available backups. If you are supervising then you’ll have a menu to manage the backups. You can also use the Other option in the selection menu to browse to another location and select another backup (e.g. you’re pulling them from other machines, etc.

Now that we have a backup, let’s do some stuff to the device. Let’s join the wireless network, change the wallpaper, create some contacts, make some notes and in general do some of those things that you might do on a base image of a computer, aside from of course configuring local admin (it’s not a multi-user device), installing anti-virus (to date, AV companies for iOS are snake oil salesmen) and other things you might not do. But as with imaging, if you can do something in Profile Manager or Apple Configurator, let’s reserve doing it there. In fact, I would probably try to set everything in Profile Manager or your MDM provider that you can (if you have one) and use Apple Configurator for as little as possible. That goes with imaging as well, do as much in directory services/managed preferences/profiles as you can and keep the image as simple as possible…

Anyway, once you have the device as you want it, make another backup. This is akin to baking an image with DeployStudio or System Image Utility. We can’t asr them out yet, but we’re in a much better place than we were.

Once you have a good backup, let’s leverage Apple Configurator to tell the device erase, update to the latest version of iOS, restore our image, join the SSID of our enrollment network (let’s consider this similar to a supplicant network in 802.1x). Then, let’s add a profile that will throw a Web Clip to our MDM solution and even add a Trust Profile to cut down on the number of taps to enroll (and the confusion of tap here, tap there, etc). From the Prepare screen in Apple Configurator, click on Settings and type the naming convention for your devices (in this case we’re going to call them krypted 1 and up) in the Name field. Then check the box for Number sequentially starting at 1 so it’s going to name them from 1 to 1,000,000 (which is how many iPads my krypted company is going to end up writing off at the testing rate I’m on now). Leave Supervision set to OFF (we’ll look at that later) and set the iOS field to Latest. Then, check the box for Erase all contents and settings and choose your image from the Restore menu.

Preparing Devices in Apple Configurator

Preparing Devices in Apple Configurator

Now for something that users of iPhone Configuration Utility, Profile Manager and Casper MDM will find familiar, click on the plus sign in the Profiles field and select Create New Profile. Here, we see what is the standard policy sheet (apologies to HIG if that’s not what those are officially called but I’ve not been able to find the right term) and give it a name in the Name field. This is how it will appear in the Profiles section of Apple Configurator. Because you can deploy multiple profiles, I’m just going to configure the SSID and Web Clip and call it MDM Enrollment. Optionally, give it some notes, organization name, etc.

Naming Your Profile in Apple Configurator

Naming Your Profile in Apple Configurator

Click on Wi-Fi and then click on the Configure button. Here, enter the SSID of the deployment network (MDMEnroll in this example). We’ll use the Hidden Network field to indicate the SSID is suppressed and we’ll use the network type of WEP and throw the password into the Password field as well. Now, before we move on, notice that there’s a plus and minus sign in the top right of the screen? You can deploy multiple of each, so if you have 10 wireless networks, 4 Email accounts, 9 VPN connections, 29 SSL Certs etc, you could deploy them all easily with multiple entries of each.

Adding Wireless Networks with Apple Configurator

Adding Wireless Networks with Apple Configurator

Scroll down in the sidebar a little and then click on Web Clips. Click on the Configure button. The Label is how the web clip’s name will appear on the device. We’re going to enter Enroll Here. In the URL field, provide the URL for your MDM server (e.g. When using a Profile Manager server called the URL would be Not to get off topic, but did anyone else notice that Profile Manager in 10.7.3 now requires SSL certs? Anyway, you’ll also choose whether the web clip should be Removable (I think it should if it’s to enroll) and optionally choose an Icon. We’ll skip that (if we were using a 3rd party tool, I’d throw their logo in here; otherwise I usually like to use the company logo. I also like enrollment links to be Full Screen.

Go ahead and click Save and you’ll see MDM Enrollment listed in the Settings. If you notice, you can also click on the profile and then click on the export menu to export the profile or under the plus sign (“+”) you can Import Profile…, which is how we’ll bring in our Trust Profile from Profile Manager. From Profile Manager we already downloaded the Trust Profile. Now we’re going to click on Import Profile… and browse to it on the desktop, clicking on Trust profile.mobileconfig (or whatever name yours may have). Click Open.

Importing a Trust Profile Into Apple Configurator

Importing a Trust Profile Into Apple Configurator

We could go a step further and actually enroll the device by exporting the enrollment profile as well, but again, I want each user to provide their username and password so I as an administrator don’t have to go through and attach each device to a user in this scenario. I’ve been looking at importing devices and associating them with users via postgres, but that’s going to be another 3am article, on another night…

Next, check the box for each profile and click on Apps. This is where things start getting kinda’ cool. For this you’re going to need some app ipas. Each app in iTunes is stored as an .ipa file. We’re going to look at two different kinds of apps. The first is a free one and the second is a paid for app, both we’ll pull from iTunes. To do so, open iTunes and click on an app (iBooks in our example) and click on Show in Finder.

Show Apps in iTunes

Show Apps in iTunes

Note: Not all app .ipas are called the same thing as the filename. If you Show in Finder from the contextual menu of an app in iTunes it will automatically highlight the correct app in the Finder when it opens a Finder screen.

From the Finder you can either copy the app to the machine running Apple Configurator or if you’re using iTunes on that machine, you can go ahead and drag it to the Apple Configurator apps list. We’re also going to add an App that we used a purchase code from the VPP store to buy. You’ll get an error when you drag the paid app in (or browse to it if you so choose) that indicates the app is paid and in order to deploy it you’ll need to use VPP codes. Once added, you’ll notice it has an error indicator and the number 0 beside it.

Install Apps in Apple Configurator

Install Apps in Apple Configurator

Click on the numerical indicator beside the app name and you’ll be able to import redemption codes. These are emailed to you when you buy apps through the Volume Purchasing Program. BTW, no drag and drop in this screen, use the Important Redemption Codes button to browse to the XLS files.

Adding VPP Codes in Apple Configurator

Adding VPP Codes in Apple Configurator

Once the codes are imported, you’re ready to configure a device.
App Indicator Counts

App Indicator Counts In Apple Configurator

When you import an application, you are creating a file with a GUID in /Users/admin/Library/Application Support/ These files represent applications that have been prepared for distribution. When importing, it will take as long as it takes to copy from the source to that directory. The entry in that directory is roughly the same size as the app. Therefore, you likely don’t want to copy every app you have in there, just the ones you plan to distribute.
Now for the dangerous part. Make sure you don’t have any devices plugged into the computer. I love to start with a device at the activation screen. That thing requires so many taps I jump at any 0 touch deploy type of options I can get my hands on to skip it (not that you’re going to get 0 touch if you have profiles). The reason we want to make sure there aren’t any devices plugged in is that they’ll be wiped if they are… Provided there aren’t any, click on the Prepare button and any devices plugged in wills tart configuring immediately. The application count will go down for VPP apps as each device is configured. It can do 30 in parallel.
Imaging Devices in Apple Configurator

Imaging Devices in Apple Configurator

You’ll see a green checkmark when each device is done. When you’re ready to stop configuring devices, click on Stop. The only other way to do any in parallel is through Xcode Organizer’s restore feature, but that was never very stable for this type of purpose and this is a much more object oriented approach to device imaging. The caveat for these apps is that the password for the AppleID is needed to update them, so this is not a means to deploy paid apps to BYOD or self-managed types of devices (IMHO). Also, the iOS version for devices is downloaded at this point from Apple. If you notice that the first time each type of device is imaged that it takes awhile, this is why. The second time this step is skipped (another reason we need Internet access on our Apple Configurator computer). These are located in /Users/admin/Library/Application Support/ and if you need to run a beta version of iOS you can do so by dropping their ipsw versions in here manually, but I haven’t gotten device supervision to work when doing so.

Using Apple Configurator to Supervise Devices

Now, supervising devices may seem more complicated, but it isn’t. Back at the Prepare screen, we set Supervision to OFF. Change the iOS field to No Change. Now, let’s turn it ON. When you do so, the iOS field automatically switches to Latest. This means that supervision is going to require updates (which is fine in my book as updates have yet to break a single app for me). Get all the same settings the same as they were previously.

Supervising Devices in Apple Configurator

Supervising Devices in Apple Configurator

Once you enable Supervision, click on Prepare in Apple Configurator and connect a device again. The device will then be imaged as with the same settings that you’ve given it from before. However, once it’s done, you’ll be able to click on the Supervise tab and see devices (Note: You supervise devices rather than users).

Device Supervision in Apple Configurator

Device Supervision in Apple Configurator

The subsequent Starts and Stops will now allow you to enable and disable profiles and apps on the fly, as well as restore backups, update devices and as you can see in this screen, reclaim those valuable VPP codes!

Do a Get Info on a device and you’ll also see a bevy of information about that device.

Get Info on Devices in Apple Configurator

Get Info on Devices in Apple Configurator

You can also click on Assign, once you’ve enabled Supervision. Assigning devices requires directory services. When you click on Assign, click on the plus sign (“+”) to add the first user. Type the first few letters of the users name and they should appear in the list. Click on them and they’ll be added. You can then use the right panel to assign content to the apps that you assign to that user’s devices.

Pushing Content in Apple Configuration Utility

Pushing Content in Apple Configuration Utility

Once added, the user will by default have no device. To assign a device to a user, use the Check Out box at the bottom of the screen and then match the users with the devices you want them to have.

Checking Devices Out To Users

Checking Devices Out To Users

The final piece of this application is to assign content to users. As I mentioned earlier in this article, the file system of an iOS device is through the lens of the applications that the device has installed. Therefore, we’ll be associating files to applications. DRMd content is not distributed through Apple Configurator. So iBooks, etc, aren’t applicable. The various third party applications can open and therefore host file types that they support, as with iTunes. From the Assign pane of Apple Configurator, click on a user and then click on the plus sign (“+”) to add documents. At the Choose A Target Application screen, choose the application you’ll be loading content into.

Choosing An App For Content

Choosing An App For Content

When you click Choose, you’ll then be able to select files to use with that application.

Selecting Content

Selecting Content

Then just dock the iOS device, sync and viola you’ve got content distribution over USB all handled. You can also add groups of devices and groups of users and distribute content to groups of users rather than to one at a time.


Apple Configurator is really a great tool when used in the right scenarios. In learning how it works and interacts I actually learned a lot about both iOS and Mac OS X that I didn’t know before. I hope I did the tool justice with how easy it is to use. This is a fairly long article and it’s probably more complicated than it needs to be in parts, but that’s more my method of trying to figure out what it’s doing than the tool being complicated. It’s not hard to figure out at all. I am sure I could teach any non-technical iOS admin to use it in less than an hour.

My wish list includes logs and OTA. You can’t use iPhone Configuration Utility while you’re using Apple Configurator and therefore, you can’s see up-to-the second logs about things like key bags to figure out why this isn’t working or that. This makes it kinda’ difficult to figure out why a profile doesn’t get installed with an image if you’re not using an AppleID with the tool or other weird little things like that. I’d love to see a little more logging. Obviously, if you could run this thing Over the Air then it would be nerd nirvana. I guess the OTA isn’t as much as wish list for this tool, but features that could be imported into Profile Manager and other tools.

One of the more important aspects is the impact on AppleID use and app ownership. I started this off by saying “My traditional interpretation of Apple’s vision on how iOS devices are used is that everyone has an AppleID.” Well, when using this tool an AppleID is no longer necessary for app deployment.

Overall, we have a new, powerful tool in our arsenal that makes up the iOS administration ecosystem. I hope that I’ve managed to dispel a few rumors with this article and look at some great uses for where this tool should and should not be used. I also hope that no matter what, if you manage iOS devices, that you’ll take a look at it. I expect you’ll find it useful in some part of your management toolkit!

March 15th, 2012

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

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

In a previous post I looked at automating iPhone and iPad deployment. There, we looked at the iPhone Configuration Utility. Now that Profile Manager is built into Mac OS X Server in Lion, and with the number of 3rd party MDM solutions on the market, many users of iPhone Configuration Utility are looking to extract information from it and move it into other places. Many of these places can import property lists.

If you look at the file header for .mobileconfig and .deviceinfo files you’ll notice that they begin with the familiar:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0"><dict>

Given that .mobileconfig and .deviceinfo files are property lists with different extensions, if you want to turn them into property lists, simply rename them. Given that many people will have 100s or 1000s of devices, this is something that most will want to automate. So, let’s use a basic for loop to do so. The following will convert .mobileconfig files into plist:

for x in ~/Library/MobileDevice/Configuration Profiles/*.mobileconfig; do mv $x `basename $x .mobileconfig`.plist; done;

This will put them back:

for x in ~/Library/MobileDevice/Configuration Profiles/*.plist; do mv $x `basename $x .plist`.mobileconfig; done;

Or to convert the device information to property lists:

for x in ~/Library/MobileDevice/Devices/*.deviceinfo; do mv $x `basename $x .deviceinfo`.plist; done;

Or property lists to device information:

for x in ~/Library/MobileDevice/Devices/*.plist; do mv $x `basename $x .plist`.deviceinfo; done;

Once files are converted then you can also automate crawling through them to obtain information. For example, to pull the information from the two fields in iPhone Configuration Utility that are user editable, ownerName and ownerEmail as well as the serial number of a device with a deviceIdentifier of 26c2d1b2a68c7862bd4c6bfbe708517964733cf3:

defaults read ~/Library/MobileDevice/Devices/26c2d1b2a68c7862bd4c6bfbe708517964733cf3 ownerEmail

defaults read ~/Library/MobileDevice/Devices/26c2d1b2a68c7862bd4c6bfbe708517964733cf3 ownerName

You could then redirect this output into a csv file, perhaps grabbing other information such as:

  • UniqueChipID
  • deviceActivationState
  • deviceBluetoothMACAddress
  • deviceBuildVersion
  • deviceCapacityKey
  • deviceClass
  • deviceIdentifier (also the basename of the file)
  • deviceLastConnected
  • deviceName
  • deviceProductVersion
  • deviceType
  • deviceWiFiMACAddress

And then there are 3 arrays that wouldn’t likely look great in a csv, but could easily be brought out automatically:

  • provisioningProfiles: useful if you are duplicating provisioning profile information into an mdm solution
  • configurationProfiles: useful if you are duplicating configuration profile information from devices into an mdm solution
  • applicationDictionaries: great for pulling off what apps are where

You can get all of this without moving the files to plist as well, but in this example I am making an assumption that you will be importing these devices via plist and so you would be converting them anyway. The ability to dump information into a csv for reporting or other types of imports is ancillary. Having said this, I’ve taken it all and wrapped it into a shell script:

echo deviceIdentifier,deviceSerialNumber,ownerName,ownerEmail,UniqueChipID,deviceActivationState,deviceBluetoothMACAddress,deviceBuildVersion,deviceCapacityKey,deviceClass,deviceLastConnected,deviceName,deviceProductVersion,deviceWiFiMACAddress,deviceType > ~/mydevices.csv
for deviceID in *.deviceinfo; do mv "$deviceID" "`basename "$deviceID" .deviceinfo`.plist";
deviceserialnumber=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceSerialNumber`
ownerName=`defaults read ~/Library/MobileDevice/Devices/$deviceID ownerName`
ownerEmail=`defaults read ~/Library/MobileDevice/Devices/$deviceID ownerEmail`
UniqueChipID=`defaults read ~/Library/MobileDevice/Devices/$deviceID UniqueChipID`
deviceActivationState=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceActivationState`
deviceBluetoothMACAddress=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceBluetoothMACAddress`
deviceBuildVersion=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceBuildVersion`
deviceCapacityKey=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceCapacityKey`
deviceClass=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceClass`
deviceLastConnected=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceLastConnected`
deviceName=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceName`
deviceProductVersion=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceProductVersion`
deviceType=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceType`
deviceWiFiMACAddress=`defaults read ~/Library/MobileDevice/Devices/$deviceID deviceWiFiMACAddress`
echo $deviceID,$deviceserialnumber,$ownerName,$ownerEmail,$UniqueChipID,$deviceActivationState,$deviceBluetoothMACAddress,$deviceBuildVersion,$deviceCapacityKey,$deviceClass,$deviceLastConnected,$deviceName,$deviceProductVersion,$deviceWiFiMACAddress,$deviceType >> ~/mydevices.csv

This script (which should have a bit more logic put into it for defining things, etc) should convert all of your .deviceinfo files to property list while building a csv of their contents (minus the arrays, which I didn’t think prudent to put into csv but which could be thrown in there pretty easily) in ~/mydevices.csv (or my devices.csv in your home directory). ProfileManager can definitely import device holders, which you should be able to do with a couple of columns of this output…

And to undo the conversion to plist (if you didn’t actually mean to do that part):

for x in ~/Library/MobileDevice/Devices/*.plist; do mv $x `basename $x .plist`.deviceinfo; done;

August 1st, 2011

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

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

The iPhone Configuration Utility is used to “image” iPhone, iPad and iPod Touch. The reason I quoted image was because you aren’t laying bits down as you would in a traditional imaging scenario. Instead, you are sending a profile and possibly some applications to the device. This is done through a configuration profile, which is a property list, prefixed with a .mobileconfig extension.

The iPhone Configuration Utility stores its data in the ~/Library/MobileDevice directory. Here, you will find two directories:

  • Devices – Contains the Device data for each device that has been docked to the iPhone Configuration Utility.
  • Configuration Profiles – Contains the profiles that you will assign to devices in the form of .mobileconfig plists.

Both of these can be managed from the command line and therefore generated en masse. First, let’s look at creating Devices. If you go into the Devices directory you will see a .deviceinfo file for each device that you have interacted with through iPhone Configuration Utility, prefixed by the UDID of the device. Here, you can view one as a standard property list, which appears in a very simplistic fashion as follows:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “”>
<plist version=”1.0″>
<string>Charles Edge’s iPhone</string>
<string>1 (310) 555-1212</string>
To find a UDID, you can plug a device into iTunes, select the device from the Devices list and then click on the Summary tab. Here, you can click on the bold Software Version to see the Build version, the bold Phone Number to see the IMEI (first click) or ICCID (second click) and the bolded Serial Number to see the Identifier (or UDID).
The serial number can also be obtained from a bar code on the box that came with the device, although the UDID cannot at this time. The serial though can then be brought into a database that has both, to correlate them (assuming you are programmatically going to wrangle this data at a later time) and assign profiles based on, for example, Open Directory or Active Directory group membership of the primary user.
You can copy a template file without unique identifiers and then use defaults to put the unique data into the file. Or you can use a series of defaults commands with plistbuddy to create a file from scratch. The data can then be viewed in somewhat of a 2d fashion up to this point. The problem is then come in the arrays, which in conjunction with the fact that they reference data from the mobileconfig files we’ll look at in a moment, mean that you are using localized plists to form a relational context to data.
You can then look at a .mobileconfig file, which appears in a very simplistic form as follows:
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “”>
<plist version=”1.0″>
<string>Configures Web Clip</string>
<string>Web Clip</string>
<string>Profile description.</string>
<string>Profile Name</string>
You can then create a single ,mobileconfig, make it a template and make it exactly like you want things to match up as your lowest common denominator, or template, user. Those .mobileconfig files then get applied to each device, which you could do in batches. You can also dynamically copy them to a web server and send an SMS/email to the user to click on them to apply them, or dock the device.
You can also add applications using a pre-existing array and copying it down, although if there are licensing concerns surrounding doing so it would be wise to investigate the ramifications of doing so first. Keys and such are defined in the iPhone Enterprise Deployment Guide, along with sample AppleScript for creation of files.
You can also copy the database by copying the property list files between machines. When iPhone Configuration Utility is opened it will automatically read in the new property lists and display the information. Overall, it is going to be as much work as it is to dynamically generate provisioning on the fly using the ruby sample code provided by Apple. It is still going to be the fastest path to market (and support) to go the 3rd party route, using a tool where they’ve built all of this out. The options in the iPhone Configuration Utility, along with the .mobileconfig files becomes the baseline that most 3rd party packages use, but overall they’ve done the work to build out the wrappers and if you want to roll your own you’ll essentially end up building something similar to what is currently on the market, without support (which for some environments is required).
Good luck!

August 31st, 2010

Posted In: iPhone

Tags: , , ,