Skip to content

Commit

Permalink
tests: zfs: add native zfs encryption tests
Browse files Browse the repository at this point in the history
This primarily ensures that we correctly load the dataset keys when
importing a pool, and if we can't import the dataset that the storage
pool is correctly tagged as UNAVAILABLE.

Signed-off-by: Aleksa Sarai <[email protected]>
  • Loading branch information
cyphar committed Nov 22, 2024
1 parent 11831e9 commit de81870
Showing 1 changed file with 79 additions and 0 deletions.
79 changes: 79 additions & 0 deletions test/suites/storage_driver_zfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ test_storage_driver_zfs() {

do_zfs_cross_pool_copy
do_zfs_delegate
do_zfs_encryption
}

do_zfs_delegate() {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit de81870

Please sign in to comment.