diff --git a/.gitignore b/.gitignore index 8fb61aa7b..4c7656fcc 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/Makefile.am b/test-data/phony-guests/Makefile.am index 0114d10bb..0a41f168b 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/test-data/phony-guests/guests.xml.in b/test-data/phony-guests/guests.xml.in index 3af6b27af..dfcccc3d4 100644 --- a/test-data/phony-guests/guests.xml.in +++ b/test-data/phony-guests/guests.xml.in @@ -183,6 +183,24 @@ + + + fedora-luks-on-lvm + 1048576 + + hvm + + + + + + + + + + + fedora-lvm-on-luks diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl index 4cd6ef957..84d4742e9 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 <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/Makefile.am b/tests/Makefile.am index 911272675..9a2a2aab5 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/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 000000000..bf8aa3b1e --- /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