Laszlo Ersek
2022-Feb-23 16:21 UTC
[Libguestfs] [libguestfs PATCH 0/3] tests: add LUKS-on-LVM test
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1658126 Laszlo Ersek (3): tests: rename "luks" to "lvm-on-luks" tests: add LUKS-on-LVM test TODO: remove "Better support for encrypted devices" .gitignore | 3 +- TODO | 10 -- test-data/phony-guests/Makefile.am | 15 ++- test-data/phony-guests/guests.xml.in | 22 ++++- test-data/phony-guests/make-fedora-img.pl | 62 +++++++++++- tests/Makefile.am | 6 +- tests/luks/test-key-option-inspect-luks-on-lvm.sh | 103 ++++++++++++++++++++ tests/luks/{test-key-option-inspect.sh => test-key-option-inspect-lvm-on-luks.sh} | 4 +- 8 files changed, 200 insertions(+), 25 deletions(-) create mode 100755 tests/luks/test-key-option-inspect-luks-on-lvm.sh rename tests/luks/{test-key-option-inspect.sh => test-key-option-inspect-lvm-on-luks.sh} (94%) -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Feb-23 16:21 UTC
[Libguestfs] [libguestfs PATCH 1/3] tests: rename "luks" to "lvm-on-luks"
Clarify that our current usage of "luks" stands for "lvm-on-luks" (IOW, that the decrypted LUKS devices are Physical Volumes for LVM). Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1658126 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- test-data/phony-guests/Makefile.am | 8 ++++---- tests/Makefile.am | 4 ++-- .gitignore | 2 +- test-data/phony-guests/guests.xml.in | 4 ++-- test-data/phony-guests/make-fedora-img.pl | 8 ++++---- tests/luks/{test-key-option-inspect.sh => test-key-option-inspect-lvm-on-luks.sh} | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test-data/phony-guests/Makefile.am b/test-data/phony-guests/Makefile.am index 60313548af32..0114d10bb170 100644 --- a/test-data/phony-guests/Makefile.am +++ b/test-data/phony-guests/Makefile.am @@ -49,7 +49,7 @@ disk_images = \ fedora-md1.img \ fedora-md2.img \ fedora-btrfs.img \ - fedora-luks.img \ + fedora-lvm-on-luks.img \ ubuntu.img \ archlinux.img \ coreos.img \ @@ -96,11 +96,11 @@ fedora-btrfs.img: make-fedora-img.pl \ fedora.db SRCDIR=$(srcdir) LAYOUT=btrfs $(top_builddir)/run --test ./$< -# Make a (dummy) Fedora image with LVM encrypted with LUKS. -fedora-luks.img: make-fedora-img.pl \ +# Make a (dummy) Fedora image with LVM-on-LUKS. +fedora-lvm-on-luks.img: make-fedora-img.pl \ fedora-journal.tar.xz \ fedora.db - SRCDIR=$(srcdir) LAYOUT=lvm-luks $(top_builddir)/run --test ./$< + SRCDIR=$(srcdir) LAYOUT=lvm-on-luks $(top_builddir)/run --test ./$< # Make a (dummy) Debian image. debian.img: make-debian-img.sh diff --git a/tests/Makefile.am b/tests/Makefile.am index 690e09b5e603..9112726750a7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -464,12 +464,12 @@ TESTS += \ luks/test-luks.sh \ luks/test-luks-list.sh \ luks/test-key-option.sh \ - luks/test-key-option-inspect.sh + luks/test-key-option-inspect-lvm-on-luks.sh EXTRA_DIST += \ luks/test-luks.sh \ luks/test-luks-list.sh \ luks/test-key-option.sh \ - luks/test-key-option-inspect.sh + luks/test-key-option-inspect-lvm-on-luks.sh TESTS += \ lvm/test-lvm-filtering.sh \ diff --git a/.gitignore b/.gitignore index ebb67850c6c6..8fb61aa7bb66 100644 --- a/.gitignore +++ b/.gitignore @@ -452,7 +452,7 @@ Makefile.in /test-data/phony-guests/debian.img /test-data/phony-guests/fedora.img /test-data/phony-guests/fedora-btrfs.img -/test-data/phony-guests/fedora-luks.img +/test-data/phony-guests/fedora-lvm-on-luks.img /test-data/phony-guests/fedora-md1.img /test-data/phony-guests/fedora-md2.img /test-data/phony-guests/fedora.db diff --git a/test-data/phony-guests/guests.xml.in b/test-data/phony-guests/guests.xml.in index 4139d04f689f..3af6b27af073 100644 --- a/test-data/phony-guests/guests.xml.in +++ b/test-data/phony-guests/guests.xml.in @@ -185,7 +185,7 @@ <!-- LUKS password is 'FEDORA' --> <domain type='test'> - <name>fedora-luks</name> + <name>fedora-lvm-on-luks</name> <memory>1048576</memory> <os> <type>hvm</type> @@ -194,7 +194,7 @@ <devices> <disk type='file' device='disk'> <driver name='qemu' type='raw'/> - <source file='@abs_builddir@/fedora-luks.img'/> + <source file='@abs_builddir@/fedora-lvm-on-luks.img'/> <target dev='vda' bus='virtio'/> </disk> </devices> diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl index 27b154f9d71d..4cd6ef9575eb 100755 --- a/test-data/phony-guests/make-fedora-img.pl +++ b/test-data/phony-guests/make-fedora-img.pl @@ -171,8 +171,8 @@ EOF } } -elsif ($ENV{LAYOUT} eq 'lvm-luks') { - push (@images, "fedora-luks.img-t"); +elsif ($ENV{LAYOUT} eq 'lvm-on-luks') { + push (@images, "fedora-lvm-on-luks.img-t"); open (my $fstab, '>', "fedora.fstab") or die; print $fstab <<EOF; @@ -183,9 +183,9 @@ EOF $bootdev = '/dev/sda1'; - $g->disk_create ("fedora-luks.img-t", "raw", $IMAGE_SIZE); + $g->disk_create ("fedora-lvm-on-luks.img-t", "raw", $IMAGE_SIZE); - $g->add_drive ("fedora-luks.img-t", format => "raw"); + $g->add_drive ("fedora-lvm-on-luks.img-t", format => "raw"); $g->launch (); $g->part_init ('/dev/sda', 'mbr'); diff --git a/tests/luks/test-key-option-inspect.sh b/tests/luks/test-key-option-inspect-lvm-on-luks.sh similarity index 94% rename from tests/luks/test-key-option-inspect.sh rename to tests/luks/test-key-option-inspect-lvm-on-luks.sh index 78128db84b52..3d2bb9e6c843 100755 --- a/tests/luks/test-key-option-inspect.sh +++ b/tests/luks/test-key-option-inspect-lvm-on-luks.sh @@ -24,9 +24,9 @@ set -e $TEST_FUNCTIONS skip_if_skipped skip_unless_feature_available luks -skip_unless_phony_guest fedora-luks.img +skip_unless_phony_guest fedora-lvm-on-luks.img -disk=../test-data/phony-guests/fedora-luks.img +disk=../test-data/phony-guests/fedora-lvm-on-luks.img device=/dev/sda2 # Get the UUID of the LUKS device. -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Feb-23 16:21 UTC
[Libguestfs] [libguestfs PATCH 2/3] tests: add LUKS-on-LVM test
Create a new (fake) Fedora disk image with two partitions. /dev/sda1 is the boot partition as usual, /dev/sda2 is used as an LVM PV. The VG has four LVs, Root and LV1 through LV3. Each LV holds a LUKS device (with a different key). Each decrypted LUKS device holds an ext2 filesystem, with "/dev/mapper/Root-luks" holding the root filesystem. Each filesystem has a dedicated label (ROOT, LV1, LV2, LV3). In the test case, run guestfish in inspector mode, twice. In the first invocation, provide the LUKS passphrases by LV name. Also specific to the first invocation, fetch the LUKS UUIDs by LV name. In the second invocation, provide the LUKS passphrases by UUID. In both invocations, after decryption, check the filesystem labels, the /dev/mapper/* names generated for the decrypted LUKS block devices, and the existence of "/etc/fedora-release" on the root filesystem. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1658126 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- test-data/phony-guests/Makefile.am | 7 ++ tests/Makefile.am | 2 + .gitignore | 1 + test-data/phony-guests/guests.xml.in | 18 ++++ test-data/phony-guests/make-fedora-img.pl | 54 ++++++++++ tests/luks/test-key-option-inspect-luks-on-lvm.sh | 103 ++++++++++++++++++++ 6 files changed, 185 insertions(+) diff --git a/test-data/phony-guests/Makefile.am b/test-data/phony-guests/Makefile.am index 0114d10bb170..0a41f168bdfc 100644 --- a/test-data/phony-guests/Makefile.am +++ b/test-data/phony-guests/Makefile.am @@ -49,6 +49,7 @@ disk_images = \ fedora-md1.img \ fedora-md2.img \ fedora-btrfs.img \ + fedora-luks-on-lvm.img \ fedora-lvm-on-luks.img \ ubuntu.img \ archlinux.img \ @@ -96,6 +97,12 @@ fedora-btrfs.img: make-fedora-img.pl \ fedora.db SRCDIR=$(srcdir) LAYOUT=btrfs $(top_builddir)/run --test ./$< +# Make a (dummy) Fedora image with LUKS-on-LVM. +fedora-luks-on-lvm.img: make-fedora-img.pl \ + fedora-journal.tar.xz \ + fedora.db + SRCDIR=$(srcdir) LAYOUT=luks-on-lvm $(top_builddir)/run --test ./$< + # Make a (dummy) Fedora image with LVM-on-LUKS. fedora-lvm-on-luks.img: make-fedora-img.pl \ fedora-journal.tar.xz \ diff --git a/tests/Makefile.am b/tests/Makefile.am index 9112726750a7..9a2a2aab59a5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -464,11 +464,13 @@ TESTS += \ luks/test-luks.sh \ luks/test-luks-list.sh \ luks/test-key-option.sh \ + luks/test-key-option-inspect-luks-on-lvm.sh \ luks/test-key-option-inspect-lvm-on-luks.sh EXTRA_DIST += \ luks/test-luks.sh \ luks/test-luks-list.sh \ luks/test-key-option.sh \ + luks/test-key-option-inspect-luks-on-lvm.sh \ luks/test-key-option-inspect-lvm-on-luks.sh TESTS += \ diff --git a/.gitignore b/.gitignore index 8fb61aa7bb66..4c7656fccd6e 100644 --- a/.gitignore +++ b/.gitignore @@ -452,6 +452,7 @@ Makefile.in /test-data/phony-guests/debian.img /test-data/phony-guests/fedora.img /test-data/phony-guests/fedora-btrfs.img +/test-data/phony-guests/fedora-luks-on-lvm.img /test-data/phony-guests/fedora-lvm-on-luks.img /test-data/phony-guests/fedora-md1.img /test-data/phony-guests/fedora-md2.img diff --git a/test-data/phony-guests/guests.xml.in b/test-data/phony-guests/guests.xml.in index 3af6b27af073..dfcccc3d4cff 100644 --- a/test-data/phony-guests/guests.xml.in +++ b/test-data/phony-guests/guests.xml.in @@ -183,6 +183,24 @@ </devices> </domain> + <!-- LUKS passwords are 'FEDORA-Root', 'FEDORA-LV1', 'FEDORA-LV2', + 'FEDORA-LV3' --> + <domain type='test'> + <name>fedora-luks-on-lvm</name> + <memory>1048576</memory> + <os> + <type>hvm</type> + <boot dev='hd'/> + </os> + <devices> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='@abs_builddir@/fedora-luks-on-lvm.img'/> + <target dev='vda' bus='virtio'/> + </disk> + </devices> + </domain> + <!-- LUKS password is 'FEDORA' --> <domain type='test'> <name>fedora-lvm-on-luks</name> diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl index 4cd6ef9575eb..84d4742e9000 100755 --- a/test-data/phony-guests/make-fedora-img.pl +++ b/test-data/phony-guests/make-fedora-img.pl @@ -200,6 +200,60 @@ EOF init_lvm_root ('/dev/mapper/luks'); } +elsif ($ENV{LAYOUT} eq 'luks-on-lvm') { + push (@images, "fedora-luks-on-lvm.img-t"); + + open (my $fstab, '>', "fedora.fstab") or die; + print $fstab <<EOF; +LABEL=BOOT /boot ext2 default 0 0 +LABEL=ROOT / ext2 default 0 0 +EOF + close ($fstab) or die; + + $bootdev = '/dev/sda1'; + + $g->disk_create ("fedora-luks-on-lvm.img-t", "raw", $IMAGE_SIZE); + + $g->add_drive ("fedora-luks-on-lvm.img-t", format => "raw"); + $g->launch (); + + $g->part_init ('/dev/sda', 'mbr'); + foreach my $p (@PARTITIONS) { + $g->part_add('/dev/sda', @$p); + } + + # Create the Volume Group on /dev/sda2. + $g->pvcreate ('/dev/sda2'); + $g->vgcreate ('VG', ['/dev/sda2']); + $g->lvcreate ('Root', 'VG', 32); + $g->lvcreate ('LV1', 'VG', 32); + $g->lvcreate ('LV2', 'VG', 32); + $g->lvcreate ('LV3', 'VG', 64); + + # Format each Logical Group as a LUKS device, with a different password. + $g->luks_format ('/dev/VG/Root', 'FEDORA-Root', 0); + $g->luks_format ('/dev/VG/LV1', 'FEDORA-LV1', 0); + $g->luks_format ('/dev/VG/LV2', 'FEDORA-LV2', 0); + $g->luks_format ('/dev/VG/LV3', 'FEDORA-LV3', 0); + + # Open the LUKS devices. This creates nodes like /dev/mapper/*-luks. + $g->cryptsetup_open ('/dev/VG/Root', 'FEDORA-Root', 'Root-luks'); + $g->cryptsetup_open ('/dev/VG/LV1', 'FEDORA-LV1', 'LV1-luks'); + $g->cryptsetup_open ('/dev/VG/LV2', 'FEDORA-LV2', 'LV2-luks'); + $g->cryptsetup_open ('/dev/VG/LV3', 'FEDORA-LV3', 'LV3-luks'); + + # Phony root filesystem. + $g->mkfs ('ext2', '/dev/mapper/Root-luks', blocksize => 4096, label => 'ROOT'); + $g->set_uuid ('/dev/mapper/Root-luks', '01234567-0123-0123-0123-012345678902'); + + # Other filesystems, just for testing findfs-label. + $g->mkfs ('ext2', '/dev/mapper/LV1-luks', blocksize => 4096, label => 'LV1'); + $g->mkfs ('ext2', '/dev/mapper/LV2-luks', blocksize => 1024, label => 'LV2'); + $g->mkfs ('ext2', '/dev/mapper/LV3-luks', blocksize => 2048, label => 'LV3'); + + $g->mount ('/dev/mapper/Root-luks', '/'); +} + else { print STDERR "$0: Unknown LAYOUT: ",$ENV{LAYOUT},"\n"; exit 1; diff --git a/tests/luks/test-key-option-inspect-luks-on-lvm.sh b/tests/luks/test-key-option-inspect-luks-on-lvm.sh new file mode 100755 index 000000000000..bf8aa3b1ee6e --- /dev/null +++ b/tests/luks/test-key-option-inspect-luks-on-lvm.sh @@ -0,0 +1,103 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2019-2022 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Test the --key option. It is handled by common code so we only need +# to test one tool (guestfish). + +set -e + +$TEST_FUNCTIONS +skip_if_skipped +skip_unless_feature_available luks +skip_unless_phony_guest fedora-luks-on-lvm.img + +# Start a background guestfish instance to check key specification by Logical +# Volume names. +guestfish=(guestfish --listen --ro --inspector + --add ../test-data/phony-guests/fedora-luks-on-lvm.img) +keys_by_lvname=(--key /dev/VG/Root:key:FEDORA-Root + --key /dev/VG/LV1:key:FEDORA-LV1 + --key /dev/VG/LV2:key:FEDORA-LV2 + --key /dev/VG/LV3:key:FEDORA-LV3) + +# The variable assignment below will fail, and abort the script, if guestfish +# refuses to start up. +fish_ref=$("${guestfish[@]}" "${keys_by_lvname[@]}") + +# Set GUESTFISH_PID as necessary for the remote access. +eval "$fish_ref" + +# From this point on, if any remote guestfish command fails, that will cause +# *both* the guestfish server *and* this script to exit, with an error. +# However, we also want the background guestfish process to exit if (a) this +# script exits cleanly, or (b) this script exits with a failure due to a reason +# that's different from a failed remote command. +function cleanup_guestfish +{ + if [ -n "$GUESTFISH_PID" ]; then + guestfish --remote -- exit >/dev/null 2>&1 || : + fi +} +trap cleanup_guestfish EXIT + +# Get the UUIDs of the LUKS devices. +uuid_root=$(guestfish --remote -- luks-uuid /dev/VG/Root) +uuid_lv1=$( guestfish --remote -- luks-uuid /dev/VG/LV1) +uuid_lv2=$( guestfish --remote -- luks-uuid /dev/VG/LV2) +uuid_lv3=$( guestfish --remote -- luks-uuid /dev/VG/LV3) + +# The actual test. +function check_filesystems +{ + local decrypted_root decrypted_lv1 decrypted_lv2 decrypted_lv3 exists + + # Get the names of the decrypted LUKS block devices that host the filesystems + # with the labels listed below. + decrypted_root=$(guestfish --remote -- findfs-label ROOT) + decrypted_lv1=$( guestfish --remote -- findfs-label LV1) + decrypted_lv2=$( guestfish --remote -- findfs-label LV2) + decrypted_lv3=$( guestfish --remote -- findfs-label LV3) + + # Verify the device names. These come from decrypt_mountables() in + # "common/options/decrypt.c". + test /dev/mapper/luks-"$uuid_root" = "$decrypted_root" + test /dev/mapper/luks-"$uuid_lv1" = "$decrypted_lv1" + test /dev/mapper/luks-"$uuid_lv2" = "$decrypted_lv2" + test /dev/mapper/luks-"$uuid_lv3" = "$decrypted_lv3" + + # Check "/etc/fedora-release" on the root fs. + exists=$(guestfish --remote -- exists /etc/fedora-release) + test true = "$exists" +} +check_filesystems + +# Exit the current guestfish background process. +guestfish --remote -- exit +GUESTFISH_PID+ +# Start up a similar guestfish background process, but specify the keys by +# UUID. +keys_by_uuid=(--key "$uuid_root":key:FEDORA-Root + --key "$uuid_lv1":key:FEDORA-LV1 + --key "$uuid_lv2":key:FEDORA-LV2 + --key "$uuid_lv3":key:FEDORA-LV3) +fish_ref=$("${guestfish[@]}" "${keys_by_uuid[@]}") +eval "$fish_ref" + +# Repeat the test. +check_filesystems -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Feb-23 16:21 UTC
[Libguestfs] [libguestfs PATCH 3/3] TODO: remove "Better support for encrypted devices"
LUKS support used to work best if the LUKS device resided on a partition, and contained a Physical Volume for an LVM Volume Group. This scheme, also called LVM-on-LUKS, is commonly created by installers of various Linux distributions. (See RHBZ#1451665.) Libguestfs now also supports the scheme wherein the LUKS device resides on an LVM Logical Volume, and contains a filesystem. This is called LUKS-on-LVM, it is the inverse of the above scheme, and is created by installers of other Linux distributions. (See RHBZ#1658126.) Both schemes are now decrypted by libguestfs-based utilities when inspection is enabled (such as in "guestfish -i", virt-inspector, virt-v2v), through the inspect_mount() function in utilities written in C, and through the "inspect_decrypt" function in ones written in OCaml. We don't seem to need an API like "list-luks-devices", as "list-dm-devices" returns decrypted (i.e., opened) LUKS devices too; for example, in the LUKS-on-LVM case:> ><fs> list-dm-devices > /dev/mapper/luks-0d619854-ccd5-43b1-8883-991fec5ef713 > /dev/mapper/luks-4e9e7a6f-a68c-42fd-92b4-8f4f2579a389Thus, the subject TODO section is now out of date, and it's unclear what remains "to do" there; let's just remove the section. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1658126 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- TODO | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/TODO b/TODO index 064386ac2dce..6fb11d5ecdd4 100644 --- a/TODO +++ b/TODO @@ -161,16 +161,6 @@ Could we make guestfish interactive if commands are used without params? Image name? disk.img Size of image? 10M -Better support for encrypted devices ------------------------------------- - -Currently LUKS support only works if the device contains volume -groups. If it contains, eg., partitions, you cannot access them. -We would like to add: - - - Direct access to the /dev/mapper device (eg. if it contains - anything apart from VGs). - Display image as PS ------------------- -- 2.19.1.3.g30247aa5d201