Monthly Archives: August 2010

iPhone

Automating iPhone & iPad Deployment

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” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
<key>UniqueChipID</key>
<integer>0</integer>
<key>applicationDictionaries</key>
<array/>
<key>configurationProfiles</key>
<array/>
<key>deviceActivationState</key>
<string>WildcardActivated</string>
<key>deviceBuildVersion</key>
<string>7E18</string>
<key>deviceCapacityKey</key>
<integer>15333203968</integer>
<key>deviceIdentifier</key>
<string>12a0b688649cfe0ce5df2ab8b4f9eaaee0d000fc</string>
<key>deviceLastConnected</key>
<date>2010-05-27T00:17:17Z</date>
<key>deviceName</key>
<string>Charles Edge’s iPhone</string>
<key>devicePhoneNumber</key>
<string>1 (310) 555-1212</string>
<key>deviceProductVersion</key>
<string>3.1.3</string>
<key>deviceSerialNumber</key>
<string>12345678901</string>
<key>deviceType</key>
<string>iPhone</string>
<key>provisioningProfiles</key>
<array/>
</dict>
</plist>
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” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>FullScreen</key>
<false/>
<key>IsRemovable</key>
<true/>
<key>Label</key>
<string></string>
<key>PayloadDescription</key>
<string>Configures Web Clip</string>
<key>PayloadDisplayName</key>
<string>Web Clip</string>
<key>PayloadIdentifier</key>
<string></string>
<key>PayloadOrganization</key>
<string></string>
<key>PayloadType</key>
<string>com.apple.webClip.managed</string>
<key>PayloadUUID</key>
<string>80222944-B43C-4A43-AB93-2998CDCBE808</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>Precomposed</key>
<false/>
<key>URL</key>
<string></string>
</dict>
</array>
<key>PayloadDescription</key>
<string>Profile description.</string>
<key>PayloadDisplayName</key>
<string>Profile Name</string>
<key>PayloadOrganization</key>
<string></string>
<key>PayloadRemovalDisallowed</key>
<false/>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>5B0879F3-9BA9-41E7-AC8F-F4703D4400DB</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
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!
Network Infrastructure

Free Junos

For some time, Juniper has been agressively trying to win converts from Cisco. Not only in terms of sales, but also the hearts and minds of the engineers who influence purchasing decisions. Aggressively going after engineers has meant that for years, Juniper has made their certifications essentially free for those of us who were certified with Cisco. But now, they’re starting to cast their net a little wider and go after getting anyone and everyone certified for free, provided of course that you can pass the test.

Juniper’s Junos is being offered for free for a limited time. If you’re interested in beefing up your security and/or networking skills, this might not be a bad certification to look at (can’t beat the price and all):
http://f.netline.junipermarketing.com/juniper006e

Mac OS X Mac OS X Server Mass Deployment

Connect to Server Name

When connecting to a server from Mac OS X, what name will your system use when you bring up the Connect to Server dialog box? By default it shows the full name of the user authenticated to a client computer. But, not everyone wants this behavior. Therefore, you can change it by altering the /Library/Preferences/com.apple.NetworkAuthorization.plist file.

The first thing you can do is add a key called UseDefaultName, which will tell the system to use a static value to populate the user field. That static value is then put into a string for Default Name. To make the UseDefaultName field true:

defaults write /Library/Preferences/com.apple.NetworkAuthorization UseDefaultName -bool YES

To then set the string for that default name field:

defaults write /Library/Preferences/com.apple.NetworkAuthorization DefaultName “Charles”

Or if you wanted nothing to default into the field, you’d leave it static but give it nothing to put into the field (you do still need the key there though, so don’t skip this step):

defaults write /Library/Preferences/com.apple.NetworkAuthorization DefaultName “”

To have the field populated with the short name instead of long name, you would change UseDefaultName back to NO (after all, it isn’t a static setting, the short name):

defaults write /Library/Preferences/com.apple.NetworkAuthorization UseDefaultName -bool NO

And you would then add a key for UseShortName and set it to true:

defaults write /Library/Preferences/com.ap
ple.NetworkAuthorization UseShortName -bool YES

Or, if you wanted to To change everything back, just delete the keys we created earlier:

defaults delete /Library/Preferences/com.apple.NetworkAuthorization UseDefaultName

defaults delete /Library/Preferences/com.apple.NetworkAuthorization UseShortName

defaults delete /Library/Preferences/com.apple.NetworkAuthorization DefaultName

Mac OS X Server

Scrubbing Assets from Podcast Producer

At some point, you may find that you would like to remove all episodes from Podcast Producer that were brought in using a specific workflow, or based on a specific keyword, a string in the title, a date, or the user that created the episodes. All of these attributes are trapped in the db.sqlite3 database for Podcast Producer. This database is stored in the Server directory of your shared library. Within this database there is a table called episodes. Using that table you can locate all episodes that match the given pattern. To query, you will use the sqlite3 command and identify the database path. A very basic incantation of this command would be to show all of the data for a given table, which in our example would be “episodes”:

sqlite3 /Volumes/xsanVolume/Library/PodcastProducer/Shared/Server/db.sqlite3 ‘SELECT * FROM episodes’

You could then expand this to limit results based on a pattern match. Here, we will have sqlite3 return the uuid for episodes that have a workflow_uuid of AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE:

sqlite3 /Volumes/xsanVolume/Library/PodcastProducer/Shared/Server/db.sqlite3 ‘SELECT uuid FROM episodes WHERE workflow_uuid=”AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE”‘

We could also change it up slightly and look for episodes that were created by a user with a shortname of cedge:

sqlite3 /Volumes/xsanVolume/Library/PodcastProducer/Shared/Server/db.sqlite3 ‘SELECT uuid FROM episodes WHERE author_shortname=”cedge”‘

The sqlite3 commands will return a set of uuids. Once you have a list of uuids, you can go into the Content directory in your shared library and you will see each listed there based on the date they were created (inside of their date folders). Date is also a field in the sqlite3 database, but given the ease of recursively performing tasks I’m not sure it will be required. The uuids will have a .prb extension and you can then piped paths with the added extension out of your command, into an array or use them for some other action, thus allowing for archiving, removing and even performing further tasks to the assets that live within the actual bundle, including hooking into transmogrifier to link to Final Cut Server.

Mac OS X Server

Removing Feeds from Podcast Producer

Podcast Producer works by publishing video to an RSS feed known as the Podcast Library. There are feeds for workflows, Users, Keywords, Days (the podcasts are stored in day folders within Podcast Producer) and custom feeds. When you’re first getting started with and testing Podcast Producer you are likely to create a lot of test podcasts and feeds. Content is stored in the day folders in the Podcast Producer shared file system, and can be removed based on those days. To see the root of the shared file system (and therefore find the Content folder), you can use the following command (where VOLUMENAME is the name of the volume hosting:

serveradmin settings pcast:shared_filesystem

Within the Shared folder you will see Content and within Content you will see a directory for each day that an episode was created. Within the day folders you will see a long string (which is the generated ID of the episode) followed by a prb file extension. I call the prb a podcast resource bundle, although I’m not sure that’s official. Inside that bundle are all of the assets for the episode that the bundle represents, including property lists used to associate the corresponding podcast episode with various sorts of metadata and membership.

Removing the bundle for each episode alone does not remove it from the list in a feed. Therefore, to avoid broken links for episodes, you will then need to run

pcastconfig –sync_library

But if you leave the feed in place you can still see the feed itself, and even if you remove a workflow you will still see its corresponding feed listed in the Workflow Feeds, which can be pretty confusing. Feeds are defined in a pwf bundle, which I call a Podcast Workflow bundle. These can be found in the Server directory of your shared file system, within the Workflows directory. Here, you will see a number of long strings (the trend continues as these are the generated ID of the workflows) followed by the pwf extension indicating they are bundles.

These will correspond to the output of the following serveradmin command to show you which workflow is associated with which ID.

serveradmin settings pcast:workflows:_array_id:*:name

Or for a more robust albeit less human readable output, you can look at using the podcast command (a front end for many common Podcast Producer tasks) along with the –listfeeds option:

podcast –listfeeds

The feeds should not be removed directly from the file system. Instead, remove them using the –removefeed option, available with the podcast command. The following would remove a feed with an ID of AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE:

podcast –removefeed –feed_uuid AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE

Still working on a way to get all assets in a feed/workflow to tar or rm. I’m trying to use a curl against the atom feed at feed://SERVERNAME:8171/podcastproducer/atom_feeds/$FEEDGUID, where the $FEEDGUID is the output from –listfeeds.

sites WordPress

New Krypted.com

I just can’t help myself. Every now and then I get a bug up my butt to go messing around with Krypted.com. In this case, I was tired of looking at some broken elements from the page and the front end of the site in general (just felt like something I might have built in college). I also needed to upgrade the site to the latest and greatest WordPress and some of the plug-ins that I was using were broken in 3. And thus, the lightest version of the site that I think has ever gone up. The posts are all still there, so no change to the content, but a lot of stuff was removed and the site in general (I think) looks and navigates much better.

Hope you like, and thank you for continuing to come to the site and read my random meanderings!

Active Directory iPhone

Managing Active Directory from iPhone

AD HelpDesk is a tool that can be used to manage certain aspects of Active Directory user accounts. Using AD HelpDesk, you can configure an iOS based device to connect to Active Directory using an administrative account (or an account that has been delegated administrative access).

Using the tool, you can then find a user. Using the user pane, you can unlock accounts, reset their passwords, force the resetting of the password on the next authentication event and optionally send a user their new password via SMS (a really cool little feature, IMO).

There are a lot of useful ways to fit this tool into your service desk or network administration toolbox. Most notably, if you have field services engineers, they can reset passwords easily without needing to take computers with them to visit end users. Or, provided you have VPN access into your environment, you could also reset a password for the executive that calls the emergency line while you’re at the water park with the kids.

Overall, nice niche tool that does exactly what the description on the App store claims!

Note: In the interest of full disclosure, the developer essentially supplied me with a free copy of the application; however, as always if I didn’t think it worked well I wouldn’t be posting it either way.

personal

Minnebar-b-que

Regrettably, I’m on my way to the airport, but if you’re in Minneapolis today and looking for something fun to do, check out Minnebar-b-que down in Maple Grove. There is sure to be plenty of brats, some beer and maybe a tablet PC or 4:

http://anyvite.com/4atmfqaioc

Mac OS X VMware

Headless VMware Fusion

You can run VMware Fusion 2 in what is commonly referred to as headless mode. This option is not yet available in Fusion 3, but is handy when you do not want to authenticate at the loginwindow of Mac OS X in order to run virtual machines using the vmware-vmx process. To enable headless mode, first run the following command:

defaults write com.vmware.fusion fluxCapacitor -bool YES

You will then see a Headless option in the View menu. You can toggle it on and off there. If you wish to to then disable headless mode:
defaults write com.vmware.fusion fluxCapacitor -bool NO
While you are in headless mode, you will find it useful to have a way to see the guest OS. You can so so by editing the .vmx files and inserting the following lines in there, which then enable VNC for the virtual machine:
RemoteDisplay.vnc.enabled = “TRUE”
RemoteDisplay.vnc.port = “5901″
Mac OS X Mass Deployment

LANDesk Client In Image

LANDesk stores its data files in the /Library/Application Support/LANDesk/data directory. However, there is a uuid file for LANDesk that, if you put the LANDesk client in your image will need to be deleted. The uuid is in the /Library/Preferences/com.landesk.uuid.plist property list. If you rm this file as a postflight imaging task then your client can be deployed on your image:

rm /Library/Preferences/com.landesk.uuid.plist