diff --git a/test/suites/storage_driver_zfs.sh b/test/suites/storage_driver_zfs.sh index 200160f0bbe..7adb81314c8 100644 --- a/test/suites/storage_driver_zfs.sh +++ b/test/suites/storage_driver_zfs.sh @@ -5,6 +5,7 @@ test_storage_driver_zfs() { do_zfs_cross_pool_copy do_zfs_delegate + do_zfs_encryption } do_zfs_delegate() { @@ -45,6 +46,84 @@ do_zfs_delegate() { incus delete -f c1 } +do_zfs_encryption() { + # shellcheck disable=2039,3043 + local INCUS_STORAGE_DIR incus_backend + + incus_backend=$(storage_backend "$INCUS_DIR") + if [ "$incus_backend" != "zfs" ]; then + return + fi + + if ! zfs --help | grep -q '^\s\+load-key\b'; then + echo "==> SKIP: Skipping ZFS encryption tests as installed version doesn't support it" + return + fi + + INCUS_STORAGE_DIR="$(mktemp -d -p "${TEST_DIR}" XXXXXXXXX)" + chmod +x "${INCUS_STORAGE_DIR}" + spawn_incus "${INCUS_STORAGE_DIR}" false + + # shellcheck disable=3043 + local zpool_name zpool_keyfile zpool_vdev + # Create a new pool. incus storage create doesn't support setting up + # encrypted datasets, so we need to create the pool ourselves. + configure_loop_device zpool_file zpool_vdev + zpool_name="$(mktemp -u incus-zpool-XXXXXXXXX)" + zpool_keyfile="$(mktemp -p "${TEST_DIR}" incus-zpool-keyfile.XXXXXXXXX)" + echo "dummy-passphrase" >"$zpool_keyfile" + + zpool create \ + -O encryption=on \ + -O keyformat=passphrase \ + -O keylocation="file://$zpool_keyfile" \ + "$zpool_name" "$zpool_vdev" + + incus storage create zpool_encrypted zfs source="$zpool_name" + + # Make sure that incus sees that the pool is imported. + zfs get -H -o name,property,value keystatus "$zpool_name" | grep -Eq "$zpool_name\s+keystatus\s+available" + incus storage list -f csv -c nDs | grep -q "zpool_encrypted,zfs,CREATED" + + # Shut down Incus to force the pool to get exported. The shutdown needs to be + # clean for this test to work, so we wait for it to finish. + incus admin shutdown + + # The pool should be exported now. + ! zpool status "$zpool_name" 2>/dev/null + + # Restart Incus. + incus admin waitready + + # The keys should've been re-imported automatically by Incus. + zfs get -H -o name,property,value keystatus "$zpool_name" | grep -Eq "$zpool_name\s+keystatus\s+available" + incus storage list -f csv -c nDs | grep -q "zpool_encrypted,zfs,CREATED" + + # Now we reconfigure the dataset so that the encryption key is provided via + # an interactive prompt. Incus cannot handle this, so we should expect the + # pool to remain unimported and the storage pool should be reported as + # UNAVAILABLE. + zfs set keylocation=prompt "$zpool_name" + + # Shut down Incus to force the pool to get exported. The shutdown needs to be + # clean for this test to work, so we wait for it to finish. + incus admin shutdown + + # The pool should be exported now. + ! zpool status "$zpool_name" 2>/dev/null + + # Restart Incus. + incus admin waitready + + # The pool should still not be imported, and Incus should report the storage + # pool as UNAVAILABLE. + ! zpool status "$zpool_name" 2>/dev/null + incus storage list -f csv -c nDs | grep -q "zpool_encrypted,zfs,UNAVAILABLE" + + # shellcheck disable=SC2031 + kill_incus "${INCUS_STORAGE_DIR}" +} + do_zfs_cross_pool_copy() { # shellcheck disable=2039,3043 local INCUS_STORAGE_DIR incus_backend