TweetFollow Us on Twitter

MacEnterprise: Sparseimage Conversion

Volume Number: 26
Issue Number: 04
Column Tag: MacEnterprise

MacEnterprise: Sparseimage Conversion

Scripting the conversion of a Filevault sparseimage to a sparsebundle

By Greg Neagle, MacEnterprise.org

Introduction

Back in 2008, I wrote a series of MacEnterprise columns on managing FileVault in an enterprise environment. We covered preparation steps, including setting up an enterprise-wide FileVault Master Password, using MCX to automate the creation of FileVault-protected home directories for new mobile and local accounts, and how to recover from lost user passwords. In the last of three columns, I discussed how to move a FileVault-protected account and home directory from one machine to another.

These past columns can be found in the MacTech archives:

http://www.mactech.com/articles/mactech/Vol.24/24.07/2407MacEnterprise-FileVaultintheEnterprisePart1/index.html

http://www.mactech.com/articles/mactech/Vol.24/24.09/2409MacEnterprise-FileVaultintheEnterprisePart2/index.html

http://www.mactech.com/articles/mactech/Vol.24/24.10/2410MacEnterprise-MigratingFileVault/index.html

This month, we're going to look at another aspect of managing FileVault-encrypted home directories. The format of such directories in Tiger was an encrypted sparsebundle disk image. In this type of image, the entire contents of the disk image are stored in a single file. If the file became corrupted, the entire disk image could be lost. This is why I recommend that you do not implement FileVault unless you either have a backup strategy or are using portable home directories—where the local home directory is kept in sync with a network copy. But if you are backing up the disk image, any change requires backing up the entire disk image file. Another downside of the sparseimage format is as items are changed in the mounted disk image, the disk image file grows in size, even if you delete items within the image. To shrink the disk image file, on logout users are asked if they want to reclaim unused space. This process can take a long time if a lot of changes have been made since the last recovery operation, as the entire disk image file may need to be rewritten.

To address some of these issues, Apple changed the FileVault disk image format in Leopard. Starting with OS X 10.5, newly created FileVault home directories use the "sparse bundle" format. With this format, instead of storing the disk image contents in a single file, the contents are divided among files inside a directory. Think of the enclosing directory as a physical hard drive, and the files within (called "bands") correspond to sectors on a physical disk. This solves several problems. First, the corruption/failure of a single file within the sparsebundle won't render the entire disk image useless; as with a physical disk, only the data in a specific part of the virtual disk is affected. Backups can be faster since only the changed "band" files need to be backed up, instead of the entire image. Finally, recovering unused space in the image is much, much faster, as the OS can just remove the unused band files.

FileVault migration issues

So a big problem with my technique for migrating FileVault-protected accounts from one machine to another is that if you migrate a FileVault-protected home directory from a Tiger machine to a Leopard (or Snow Leopard) machine, the disk image says in the old sparseimage format. This is not a showstopper, as Leopard and Snow Leopard will still happily use sparseimage FileVault home directories. As we moved users from Tiger to Leopard, we saw this issue, but we thought we'd just go back and manually convert the images to the new format. Apple's recommended technique for the conversion? Turn FileVault off, wait for the image to decrypt, then turn FileVault back on and re-encrypt the image. This can take a long time.

A few years passed, and we have started moving users to Snow Leopard. To our chagrin, we're encountering a not-insignificant number of users that still have sparseimage FileVault homes! We could just take the same approach as before, but I knew that if after two years on Leopard we haven't manually converted most of the sparseimages, we're not going to do it now.

So I decided to script the conversion, with the initial goal of streamlining and standardizing the conversion process, and the eventual goal of automating it entirely. I think I've accomplished the first goal, and I will share my solution with you.

Language choices

If you are going to script a system administration task, the first choice you need to make is what language to use as the scripting language. Normally I am a big fan of Python, but I decided against it this time around. Why? It's really overkill for the simple series of operations needed. I developed the procedures I needed by using the shell, so a simple shell script seemed to fit the bill. It was extremely convenient to test a little bit by just typing stuff into the shell and making sure it worked as expected, then adding that to the shell script. So even if the specific task at hand is not relevant to you, you may learn something about shell scripting by following along.

The script, bit by bit

The script is very linear - there are no functions or subroutines or even any loops! It just starts at the beginning and works its way to the end, bailing at various spots if it runs into an error. This makes it easy to present the script in bite-sized chunks. I'll talk about what each bit does, then move to the next. Here goes!

#!/bin/bash
# convertsparseimage
#
# Copyright 2010 by Greg Neagle
# converts FileVault sparseimages to sparsebundles
# free to use, but no suitability for any purpose implied.
# use at your own risk! data loss is a possibility.
WHOAMI=`/usr/bin/id -u`
if [ "$WHOAMI" -ne 0 ]; then
    echo "You must run this as root!"
    exit -1
fi

We start with the familiar "she-bang" line: #!/bin/bash. This tells the OS to use the bash interpreter for this script. Then follow a few comments absolving me of any responsibility if this script causes you or your users to lose data. I don't think it will, but it never hurts to be careful. Test this script carefully before using it on actual user data!

First we check to make sure the effective user ID is that of the root user. In order to convert a user's data we need to run with root privileges. Running this script with 'sudo' is fine. If the current user doesn't have root privileges, we print an error and exit with an error code.

USER=$1
if [ "$USER" == "" ]; then
    echo "Need to specify a user to convert:"
    echo "$0 shortusername"
    exit -1
fi

When we run this script, we need to pass the short name of a user to convert, like so:

/path/to/convertsparseimage gneagle

The username is made available to the script in the $1 variable, and we copy it to a new variable named "$USER". If $USER is empty, we print an error and exit with an error code.

USERLOGGEDIN=`/usr/bin/who | 
              /usr/bin/grep console | 
              /usr/bin/grep $USER`
if [ "$USERLOGGEDIN" != "" ]; then
    echo "$USER is currently logged in!"
    exit -1
fi

Next, we check to see if the user we want to convert is logged in via to GUI. This is done by piping the output of /usr/bin/who to /usr/bin/grep, which will output only lines containing "console", then piping these lines to grep again, this time looking only for lines with our user's name. If $USER is logged in via the console, $USERLOGGEDIN will have something in it; otherwise it will be empty. If it's not empty, we print an error message and exit with an error code.

Note that this simple code could return a false positive. If the user you are looking for has a shortname of "sjohn" and "sjohnson" is logged in, grep will return a match. You can do more sophisticated matches with grep to avoid this issue.

SPARSEIMAGE="/Users/$USER/$USER.sparseimage"
if [ ! -e "$SPARSEIMAGE" ]; then
    echo "Sparseimage $SPARSEIMAGE does not exist!"
    exit -1
fi

Now we check to make sure there actually is a sparseimage to convert. Again, this code is a little simplistic, because the user's home directory and sparseimage name do not technically have to match the user shortname. In 99% or more of cases, though, they do, so this code will work. If you have users with home directories in places other than "/Users" or with alternate names, you'll have to get more clever; perhaps by reading the output of

 `dscl . read /Users/$USER HomeDirectory`.
SPARSEBUNDLE="/Users/$USER/$USER.sparsebundle"
if [ -e "$SPARSEBUNDLE" ]; then
    echo "Sparsebundle $SPARSEBUNDLE already exists!"
    exit -1
fi

This time we check to make sure a sparsebundle doesn't exist. We probably don't want to write over an existing sparsebundle in the user's home directory path.

# get the size of the sparseimage in megabytes
IMAGESIZE=`/usr/bin/du -m "$SPARSEIMAGE" |
           /usr/bin/cut -f1`
# add some breathing room; 100 MB
SPACENEEDED=$((IMAGESIZE+100))
# get the free space on the disk in megabytes
DISKSPACE=`/bin/df -m / | /usr/bin/awk 'NR>1 { print $4 }'`
if [ $DISKSPACE -lt $SPACENEEDED ]; then
    echo "Not enough free space on disk:" 
    echo "$DISKSPACE MB available; want $SPACENEEDED MB."
    exit -1
fi
echo "Need $SPACENEEDED MB to convert; found $DISKSPACE MB"

For our next subtask, we figure out the size of the sparseimage in megabytes and add another 100MB to guess at how much space we'll need to do the conversion. We then figure out the amount of free space on the startup disk, also in megabytes. If the free space on the disk is less than the space we need to convert the image, we print an error message and exit with an error code.

This bit makes use of the du (disk usage) and df (disk freespace) commands. To parse the output of these commands, we use cut and awk. awk is somewhat arcane - in fact, it is another language all to itself, but very useful when it comes to parsing text output from another shell command.

echo "Unlocking FileVaultMaster keychain..."
FVMASTER="/Library/Keychains/FileVaultMaster.keychain"
# /usr/bin/security will prompt the for the password
/usr/bin/security unlock-keychain "$FVMASTER"
if [ $? -ne 0 ]; then
    echo "Error unlocking FileVaultMaster keychain"
    exit -2
fi

All the preliminary checks are done. We can finally start with the actual task. Since this script is eventually destined for automation, we can't count on having the user's password. Fortunately, we've created all our FileVault-protected home directories along with a FileVault Master Password, and so we can use the FileVaultMaster keychain to decrypt the sparseimage. (If, in the name of security, you've moved (or removed!) the FileVaultMater keychain, you'll need to modify the script to use the new location or retrieve the keychain from wherever you've stashed it. If you aren't using a FileVault Master password, then this script would have to be modified to require and use the user's login password.

We're using the security command to unlock the FileVaultMaster keychain. It will prompt for a password for this keychain. That's a pretty significant barrier to completely automating this process. The security command does take a -p parameter, which allows you to pass the keychain password, but including the password in a script like this immediately compromises the security of all the FileVault-protected accounts in your organization, so I do not recommend it. For now, we're just going to have to type in the password.

echo "Mounting sparseimage $SPARSEIMAGE..."
/usr/bin/hdiutil attach "$SPARSEIMAGE" -recover "$FVMASTER" -nobrowse -mountpoint /tmp/fvimage
if [ $? -ne 0 ]; then
    echo "Error mounting FileVault-protected sparseimage"
    exit -3
fi

(In the above code block, the /usr/bin/hdiutil line should all be one single line through "/tmp/fvimage")

Now we use the FileVaultMaster keychain to mount the encrypted disk image even though we don't have the user's password. We also specify the -nobrowse option so it does not appear in the Finder (which would be bad if another user was logged in). We also specify a custom mountpoint in /tmp, so the volume is not accessible via the normal /Volumes mountpoints. Both of these options improve security somewhat. If we get an error while trying to mount the image, we exit with an error.

echo "Creating encrypted sparsebundle with contents from"
echo "sparseimage..."
PASSWORD="LetMeIn!\\0000"
echo -e "$PASSWORD" | /usr/bin/hdiutil create -srcfolder /tmp/fvimage -format UDSB -o "$SPARSEBUNDLE" -volname $USER -encryption -stdinpass -certificate /Library/Keychains/FileVaultMaster.cer
if [ $? -ne 0 ]; then
    echo "Error creating sparsebundle"
    rm -r $SPARSEBUNDLE
    echo "Unmounting sparseimage"
    /usr/bin/hdiutil eject /tmp/fvimage
    exit -4
fi

(In the above code block, the section starting with 'echo -e "$PASSWORD" ' and ending with '/Library/Keychains/FileVaultMaster.cer ' is all one long line.)

The actual image conversion happens here at long last. Since we don't have the user's password, we have to create this sparsebundle with a default password, which we'll need to provide to the user to use on the first login. Change this password as you wish, but leave the "\\0000" at the end - this is a null-character, which is needed by hdiutil at the end of a password passed in via STDIN.

Let's tear apart the rather complicated line with hdiutil:

echo -e "$PASSWORD" | 

- send the password via STDIN to hdiutil

/usr/bin/hdiutil create -srcfolder /tmp/fvimage 

- create a new disk image from the contents of the folder /tmp/fvimage, which is where we've mounted the sparseimage.

-format UDSB 

- the new disk image should be formatted as a sparsebundle.

-o "$SPARSEBUNDLE" 

- write the new disk image to the path described by $SPARSEBUNDLE, which we've previously set to "/Users/$USER/$USER.sparesbundle".

-volname $USER 

- make sure the volume has the same name as the user

-encryption 

- use the standard encryption

-stdinpass 

- read the password from STDIN.

-certificate /Library/Keychains/FileVaultMaster.cer

- use the certificate given as the alternate unlock key. This allows us to decrypt an image with the FileVaultMaster keychain.

hdiutil create may take a while to do its job. The larger the original sparseimage, the longer creating the sparsebundle will take. It does print some progress info as it works. If an error is encountered, we delete the sparesbundle, eject the sparseimage, and exit with an error message.

echo "Unmounting sparseimage $SPARSEIMAGE"

/usr/bin/hdiutil eject /tmp/fvimage
echo "Moving $SPARSEIMAGE to /Users/Shared/..."
/bin/mv "$SPARSEIMAGE" "/Users/Shared/$USER.sparseimage"
echo "Updating DirectoryService HomeDirectory to point to" 
echo "new sparsebundle"
/usr/bin/dscl . -create /Users/$USER HomeDirectory "<home_dir><url>file://localhost$SPARSEBUNDLE</url></home_dir>"

Finally, some cleanup and housekeeping: We eject the sparseimage and move it to /Users/Shared for safekeeping—I'm still not confident enough to delete it outright. After a day or so, assuming the converted sparsebundle works as expected, you could then go back and delete the old sparseimage.

Lastly, we update the HomeDirectory attribute in the local directory service to point to the sparsebundle instead of the old sparseimage. Note that the section starting with "/usr/bin/dscl" and ending with "</home_dir>" should all be a single line. This of course assumes the account information is local, but for mobile account or local users, the account info will be in the local directory service.

Now what?

So you've implemented and tested this script on some test accounts and you want to try it on a user's data. It's important to remember that the new sparsebundle does not have the user's login password, since we don't have that password anywhere in the script. Instead, we've created the disk image with a generic password that we'll provide to the user.

The first time the user tries to login after the conversion, they will see a dialog like the one in Figure 1.


Figure 1 - FileVault password warning

What is happening here is that the user has successfully authenticated against the directory service, but the current password isn't working to unlock the encrypted disk image. Since this is typically caused by network users changing their password, Mac OS X helpfully suggests that the user try their previous password to unlock the FileVault image.

In this case, you don't want the user to try their previous password. Instead, you want them to use the generic password that was used to encrypt the sparsebundle during the conversion. Once they provide that password, the sparsebundle will be unlocked and its password updated to the current user password.

Conclusion

In this month's MacEnterprise column, we stepped through a BASH script that converts FileVault sparseimages into FileVault sparsebundles for better performance and compatibility with Leopard and Snow Leopard. If you haven't done much shell scripting, I hope the examples in this script inspire you to learn more. Good luck!


Greg Neagle is a member of the steering committee of the Mac OS X Enterprise Project (macenterprise.org) and is a senior systems engineer at a large animation studio. Greg has been working with the Mac since 1984, and with OS X since its release. He can be reached at gregneagle@mac.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Bartender 3.0.32 - Organize your menu-ba...
Bartender lets you organize your menu-bar apps by hiding them, rearranging them, or moving them to Bartender's Bar. You can display the full menu bar, set options to have menu-bar items show in the... Read more
Adobe Animate CC 2018 18.0.1.115 - Anima...
Animate CC 2018 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous Flash Professional customer). Animate CC 2018 (was Flash CC) lets you... Read more
Adobe Lightroom Classic CC 7.1 - Import,...
Adobe Lightroom is available as part of Adobe Creative Cloud for as little as $9.99/month bundled with Photoshop CC as part of the photography package. Lightroom 6 is also available for purchase as a... Read more
ExpanDrive 6.1.8 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
ExpanDrive 6.1.8 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
DiskCatalogMaker 7.2.7 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
DiskCatalogMaker 7.2.7 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
Iridient Developer 3.2.1 - Powerful imag...
Iridient Developer (was RAW Developer) is a powerful image-conversion application designed specifically for OS X. Iridient Developer gives advanced photographers total control over every aspect of... Read more
BusyContacts 1.2.7 - Fast, efficient con...
BusyContacts is a contact manager for OS X that makes creating, finding, and managing contacts faster and more efficient. It brings to contact management the same power, flexibility, and sharing... Read more
MegaSeg 6.0.5 - Professional DJ and radi...
MegaSeg is a complete solution for pro audio/video DJ mixing, radio automation, and music scheduling with rock-solid performance and an easy-to-use design. Mix with visual waveforms and Magic... Read more

Latest Forum Discussions

See All

The best deals on the App Store this wee...
A new week means new discounts on the App Store. This week's deals run the gamut of action-adventure titles, puzzle games, and one of the best narrative adventure series out there. If you're looking to fill out your mobile gaming library on a... | Read more »
What you need to know about Animal Cross...
We hope you've been hard at work on collecting all of those holiday items in Animal Crossing: Pocket Camp, because you're about to get a whole new list of fun things to do as the game receives its first big update sometime soon. There are a lot of... | Read more »
Reigns: Her Majesty guide - how to use e...
Ruling a kingdom isn't easy--doubly so for a queen whose every decision is questioned by the other factions seeking a slice of power. Reigns: Her Majesty builds on the original game's swipey tactics, adding items that you can use to move the story... | Read more »
The best new games we played this week -...
Friday has crept up on us once again, so it's time to honor the best new games we've played over the past few days. This past week was a pretty exciting one, with the debut of lots of beautiful new indies and some familiar faces returning to the... | Read more »
Portal Knights guide- beginner tips and...
Portal Knights is finally making the jump to iOS and Android, and it's already climbing the ranks to become the next big MMO experience on mobile. This sprawling sandbox game will let you pursue any adventure you wish, whether you want to sling... | Read more »
Reigns: Her Majesty guide - how to swipe...
Reigns: Her Majesty is storming the App Store this week, bringing more tinder-esque kingdom building to eager players everywhere. If you've played the original Reigns, you'll know that leading a kingdom is never easy. It's a careful balancing act... | Read more »
Getting Over It (Games)
Getting Over It 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: A game I madeFor a certain kind of person To hurt them. • Climb up an enormous mountain with nothing but a hammer and a pot.•... | Read more »
Reigns: Her Majesty (Games)
Reigns: Her Majesty 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: | Read more »
Pocket Legends Adventures guide - how to...
Pocket Legends Adventures is a fun action adventure RPG that takes control when you want it to, but also opens itself for player input, too, if you're looking to tkae a more active role in combat. Regardless of play style, the game can be quite... | Read more »
Portal Knights (Games)
Portal Knights 1.2.4 Device: iOS Universal Category: Games Price: $4.99, Version: 1.2.4 (iTunes) Description: Craft your adventure. Forge your hero. Become the ultimate Portal Knight! | Read more »

Price Scanner via MacPrices.net

Apple Watch Series 2, Certified Refurbished,...
Apple has Certified Refurbished Apple Watch Nike+ Series 2s, 42mm Space Gray Aluminum Case with Anthracite/Black Nike Sport Bands, available for $249 (38mm) or $279 (42mm). The 38mm model was out of... Read more
Apple offers Certified Refurbished 2016 12″ R...
Apple has Certified Refurbished 2016 12″ Retina MacBooks available starting at $949. Apple will include a standard one-year warranty with each MacBook, and shipping is free. The following... Read more
B&H drops price on 13″ 256GB MacBook Air...
B&H has the 13″ 1.8GHz/256GB Apple MacBook Air (MQD42LL/A) now on sale for $1079 including free shipping plus NY & NJ sales tax only. Their price is $120 off MSRP, and it’s the lowest price... Read more
Holiday sale: 9″ iPads starting at $299, take...
MacMall has 9″ WiFi iPads on sale for $30 off including free shipping: – 9″ 32GB WiFi iPad: $299 – 9″ 128GB WiFi iPad: $399 Read more
Green Monday deal: 15″ 2.8GHz MacBook Pro on...
B&H Photo has the 15″ 2.8GHz Space Gray MacBook Pro on sale for $250 off MSRP for today only as part of their Green Monday/Holiday sale. Shipping is free, and B&H charges sales tax for NY... Read more
Green Monday sale: B&H offers 12″ Apple i...
B&H Photo has 12″ iPad Pros on sale for up to $150 off MSRP as part of their Green Monday/Holiday sale. Shipping is free, and B&H charges sales tax in NY & NJ only: – 12″ 64GB WiFi iPad... Read more
Holiday deal: 21″ and 27″ Apple iMacs on sale...
MacMall has 2017 21″ and 27″ Apple iMacs on sale for up to $200 off MSRP. Shipping is free: – 21″ 2.3GHz iMac: $999 $100 off MSRP – 21″ 3.0GHz iMac: $1199 $100 off MSRP – 21″ 3.4GHz iMac: $1379 $120... Read more
Holiday deal: Apple Mac minis for up to $150...
MacMall has Mac minis on sale for up to $100 off MSRP, each including free shipping: – 1.4GHz Mac mini: $399 $100 off MSRP – 2.6GHz Mac mini: $599 $100 off MSRP – 2.8GHz Mac mini: $949 $50 off MSRP... Read more
Beats by Dr. Dre – BeatsX Earphones on sale f...
Best Buy has BeatsX Earphones on sale for $109, $40 off, on their online store. Sale price for online orders only. Choose free store pickup, if available, or choose free shipping. Read more
10″ 64GB WiFi Apple iPad Pros on sale for $59...
MacMall has 10.5″ 64GB Apple iPad Pros on sale for $599 including free shipping. That’s $50 off MSRP and among the lowest prices available for these iPads from any Apple reseller. Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Information Security - Security Data...
# Apple Information Security - Security Data Analyst Job Number: 113119545 Austin, Texas, United States Posted: 10-Nov-2017 Weekly Hours: 40.00 **Job Summary** This Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.