Encrypting an existing Centos install (2)

In a previous post, I described how to encrypt an existing Centos install that approach was based on find out how LUKS worked and then creating a storage logical volume that was encrypted with then logical volumes on top of that to contain the original data. The main disadvantage of that approach was that it was not possible to encrypt the root partition, and thus still potentially leaking confidential data.

Therefore, I looked at how a standard fully encrypted Centos install worked and basically that is quite simple. The basic setup of an encrypted Centos install is to have a simple partitioning setup with one small physical partition (e.g. /dev/sda1) with /boot on it (using typically ext4), and a second partition /dev/sda2 which is encrypted. On top of the encrypted /dev/sda2 device (e.g. /dev/mapper/luks) the previous logical volumes are based. This approach requires no power managements hacks nor special mount options in /etc/fstab.

The setup requires the following:

  • supplying an rd_LUKS_UUID=luks-<UUID> parameter describing the UUID of the encrypted physical partition. The UUID can be easily ibtained using blkid
  • The encrypted physical partition as a physical volume of your volume group.

This will expose an encrypted device under /dev/mapper/luks-<UUID>, and allows a volume group to be created on that.

Migration from the unencrypted setup to an encrypted one is very easy. The starting point is a typical Centos setup with a single volume group. What you need is an additional hard disk with at least free disk partitions available that can contain all data of the original volume group. Then, move all data to the external disk by extending the volume group and using pvmove to move data off the local disk. Then, remove the local physical volumes from the local disk and repartition the local disk so it contains the two partitions. After that, setup the encrypted partition, turn the encrypted partition into a physical volume and it it to the volume group. Then move data back to the original disk using pvmove and remove the external physical partition from the volume group.  Now all data is local again and the external disk can be removed.

The details are described below. Below I am assuming there is only one local disk called /dev/sda and that there is one local volume group called vg_root.

Disclaimer: Use this procedure at your own risk and make sure you have a full backup of your hard disk (see previous post). In particular, the <code>pvmove</code> command is considered dangerous (even though I personally only have good experiences with it, even migrating virtual disks of virtual machines while they were running). Work at the lowest runlevel possible to avoid problems (init 1) and make sure your power adapter is connected to your laptop so the system doesn’t die suddenly whilst in the middle of copying data (as it did in my case).

Extending the volume group

Attach the external disk. Preferably use eSATA and check your BIOS to make sure external eSATA disks are recognized at boot. Verify the device name of the attached disk using dmesg. Let’s assume the external device name is /dev/sdb. Identify physical partitions on /dev/sdb of which the total disk space is sufficient to hold everything on the vg_root volume group.

pvcreate /dev/sdbX # create physiccal volume of partition on external disk

Now extend the volume group with the new physical partitions

vgextend vg_root /dev/sdbX... /dev/sdbY # extend the volume group.

Note that after this step, you can no longer boot your system without the external hard disk and your BIOS must recognize the external hard disk at boot.

Moving data to the external disk

Identify the physical volumes of the local disk using pvs. And move the data on them to the external disk

pvmove /dev/sdaX /# move data
vgreduce vg_root /dev/sdaX # remove physical volume from volume group

Create the encrypted device

Make sure you have the partitioning scheme as described before with /dev/sda1 as /boot and /dev/sda2 as free. Use the usual commands to create the encrypted disk using the cryptsetup commands as described in the previous post, replacing /dev/vg_storage/encrypted with /dev/sda2.

Add the kernel parameter rd_LUKS_UUID=luks-<UUID> to /boot/grub/menu.lst. The UUID is obtained from the output of blkid /dev/sda2. For testing you can also create a separate boot entry with this additional option. Create a backup copy of menu.lst before you start (and leave it on /boot to make rescue easier if needed from a rescue system).
Reboot the system and verify that the encrypted device /dev/mapper/luks-<UUID> is available.

Extend the volume group with the local storage

Create a physical volume of the encrypted device and extend the volume group.

pvcreate /dev/mapper/luks-<UUID>
vgextend vg_root /dev/mapper/luks-<UUID>

Now reboot the system again to verify it is still working.

Move data back to the local disk

Move data back using pvmove for each physical volume on the external disk.

pvmove /dev/sdbX # move data
vgreduce vg_root /dev/sdbX # remove external physical volume.

Cavaets

The approach works fine with one encrypted physical partition. If you would extend the volume group <code>vg_root</code> with an additional encrypted hard disk or other encrypted physical partition on the same disk, then the system will ask you for your password twice. There are imaginable workarounds using password files but these are not easy since the password file cannot be on the encrypted disks since you will need both disk to have a complete volume group to be able to read the file (chicken and egg problem).

A solution would be to have a special small encrypted physical partition with just the key file on it. Then somehow instruct dracut (the initrd implementation on Centos) to mount this partition by name and then use the keyfile to open all other encrypted partitions. The system would then only ask for your password for the single small encrypted partition with the key file on it.

Other solutions would be to have the key on an external USB stick. There are even ideas around to use a 2-factor scheme where the system would ask for a password to the key, then use the key to decrypt the partitions. This is 2-factor because you would have to have something (1, the USB key) and know something (2, the password). My personal challenge would at least be to get this functionality without requiring a custom initrd, but a dracut module would be acceptable of course.

This entry was posted in Devops/Linux. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *