mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
Added encryption support for zfs recv -o / -x
One small integration that was absent from b52563 was support for zfs recv -o / -x with regards to encryption parameters. The main use cases of this are as follows: * Receiving an unencrypted stream as encrypted without needing to create a "dummy" encrypted parent so that encryption can be inheritted. * Allowing users to change their keylocation on receive, so long as the receiving dataset is an encryption root. * Allowing users to explicitly exclude or override the encryption property from an unencrypted properties stream, allowing it to be received as encrypted. * Receiving a recursive heirarchy of unencrypted datasets, encrypting the top-level one and forcing all children to inherit the encryption. Reviewed-by: Jorgen Lundman <lundman@lundman.net> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Richard Elling <Richard.Elling@RichardElling.com> Signed-off-by: Tom Caputi <tcaputi@datto.com> Closes #7650
This commit is contained in:
committed by
Brian Behlendorf
parent
fe8a7982ca
commit
d9c460a0b6
@@ -455,7 +455,7 @@ tests = ['zdb_001_neg', 'zfs_001_neg', 'zfs_allow_001_neg',
|
||||
'zpool_offline_001_neg', 'zpool_online_001_neg', 'zpool_remove_001_neg',
|
||||
'zpool_replace_001_neg', 'zpool_scrub_001_neg', 'zpool_set_001_neg',
|
||||
'zpool_status_001_neg', 'zpool_upgrade_001_neg', 'arcstat_001_pos',
|
||||
'arc_summary_001_pos', 'arc_summary_002_neg',
|
||||
'arc_summary_001_pos', 'arc_summary_002_neg',
|
||||
'arc_summary3_001_pos', 'dbufstat_001_pos']
|
||||
user =
|
||||
tags = ['functional', 'cli_user', 'misc']
|
||||
@@ -743,7 +743,8 @@ tests = ['rsend_001_pos', 'rsend_002_pos', 'rsend_003_pos', 'rsend_004_pos',
|
||||
'send-c_mixed_compression', 'send-c_stream_size_estimate', 'send-cD',
|
||||
'send-c_embedded_blocks', 'send-c_resume', 'send-cpL_varied_recsize',
|
||||
'send-c_recv_dedup', 'send_encrypted_files', 'send_encrypted_heirarchy',
|
||||
'send_freeobjects', 'send_realloc_dnode_size', 'send_hole_birth']
|
||||
'send_encrypted_props', 'send_freeobjects', 'send_realloc_dnode_size',
|
||||
'send_hole_birth']
|
||||
tags = ['functional', 'rsend']
|
||||
|
||||
[tests/functional/scrub_mirror]
|
||||
|
||||
@@ -23,6 +23,7 @@ dist_pkgdata_SCRIPTS = \
|
||||
rsend_024_pos.ksh \
|
||||
send_encrypted_files.ksh \
|
||||
send_encrypted_heirarchy.ksh \
|
||||
send_encrypted_props.ksh \
|
||||
send-cD.ksh \
|
||||
send-c_embedded_blocks.ksh \
|
||||
send-c_incremental.ksh \
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2018 by Datto Inc. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/rsend/rsend.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify that zfs properly handles encryption properties when receiving
|
||||
# send streams.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a few unencrypted and encrypted test datasets with some data
|
||||
# 2. Take snapshots of these datasets in preparation for sending
|
||||
# 3. Verify that 'zfs recv -o keylocation=prompt' fails
|
||||
# 4. Verify that 'zfs recv -x <encryption prop>' fails on a raw send stream
|
||||
# 5. Verify that encryption properties cannot be changed on incrementals
|
||||
# 6. Verify that a simple send can be received as an encryption root
|
||||
# 7. Verify that an unencrypted props send can be received as an
|
||||
# encryption root
|
||||
# 8. Verify that an unencrypted recursive send can be received as an
|
||||
# encryption root
|
||||
# 9. Verify that an unencrypted props send can be received as an
|
||||
# encryption child
|
||||
# 10. Verify that an unencrypted recursive send can be received as an
|
||||
# encryption child
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
destroy_dataset $TESTPOOL/recv "-r"
|
||||
destroy_dataset $TESTPOOL/crypt "-r"
|
||||
destroy_dataset $TESTPOOL/ds "-r"
|
||||
[[ -f $sendfile ]] && log_must rm $sendfile
|
||||
[[ -f $keyfile ]] && log_must rm $keyfile
|
||||
}
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "'zfs recv' must properly handle encryption properties"
|
||||
|
||||
typeset keyfile=/$TESTPOOL/pkey
|
||||
typeset sendfile=/$TESTPOOL/sendfile
|
||||
typeset snap=$TESTPOOL/ds@snap
|
||||
typeset esnap=$TESTPOOL/crypt@snap1
|
||||
typeset esnap2=$TESTPOOL/crypt@snap2
|
||||
|
||||
log_must eval "echo 'password' > $keyfile"
|
||||
|
||||
log_must zfs create $TESTPOOL/ds
|
||||
log_must zfs create $TESTPOOL/ds/ds1
|
||||
|
||||
log_must zfs create -o encryption=on -o keyformat=passphrase \
|
||||
-o keylocation=file://$keyfile $TESTPOOL/crypt
|
||||
log_must zfs create $TESTPOOL/crypt/ds1
|
||||
log_must zfs create -o keyformat=passphrase -o keylocation=file://$keyfile \
|
||||
$TESTPOOL/crypt/ds2
|
||||
|
||||
log_must mkfile 1M /$TESTPOOL/ds/$TESTFILE0
|
||||
log_must cp /$TESTPOOL/ds/$TESTFILE0 /$TESTPOOL/crypt/$TESTFILE0
|
||||
typeset cksum=$(md5sum /$TESTPOOL/ds/$TESTFILE0 | awk '{ print $1 }')
|
||||
|
||||
log_must zfs snap -r $snap
|
||||
log_must zfs snap -r $esnap
|
||||
log_must zfs snap -r $esnap2
|
||||
|
||||
# Embedded data is incompatible with encrypted datasets, so we cannot
|
||||
# allow embedded streams to be received.
|
||||
log_note "Must not be able to receive an embedded stream as encrypted"
|
||||
log_mustnot eval "zfs send -e $TESTPOOL/crypt/ds1 | zfs recv $TESTPOOL/recv"
|
||||
|
||||
# We currently don't have an elegant and secure way to pass the passphrase
|
||||
# in via prompt because the send stream itself is using stdin.
|
||||
log_note "Must not be able to use 'keylocation=prompt' on receive"
|
||||
log_must eval "zfs send $snap > $sendfile"
|
||||
log_mustnot eval "zfs recv -o encryption=on -o keyformat=passphrase" \
|
||||
"$TESTPOOL/recv < $sendfile"
|
||||
log_mustnot eval "zfs recv -o encryption=on -o keyformat=passphrase" \
|
||||
"-o keylocation=prompt $TESTPOOL/recv < $sendfile"
|
||||
|
||||
# Raw sends do not have access to the decrypted data so we cannot override
|
||||
# the encryption settings without losing the data.
|
||||
log_note "Must not be able to disable encryption properties on raw send"
|
||||
log_must eval "zfs send -w $esnap > $sendfile"
|
||||
log_mustnot eval "zfs recv -x encryption $TESTPOOL/recv < $sendfile"
|
||||
log_mustnot eval "zfs recv -x keyformat $TESTPOOL/recv < $sendfile"
|
||||
log_mustnot eval "zfs recv -x pbkdf2iters $TESTPOOL/recv < $sendfile"
|
||||
|
||||
# Encryption properties are set upon creating the dataset. Changing them
|
||||
# afterwards requires using 'zfs change-key' or an update from a raw send.
|
||||
log_note "Must not be able to change encryption properties on incrementals"
|
||||
log_must eval "zfs send $esnap | zfs recv -o encryption=on" \
|
||||
"-o keyformat=passphrase -o keylocation=file://$keyfile $TESTPOOL/recv"
|
||||
log_mustnot eval "zfs send -i $esnap $esnap2 |" \
|
||||
"zfs recv -o encryption=aes-128-ccm $TESTPOOL/recv"
|
||||
log_mustnot eval "zfs send -i $esnap $esnap2 |" \
|
||||
"zfs recv -o keyformat=hex $TESTPOOL/recv"
|
||||
log_mustnot eval "zfs send -i $esnap $esnap2 |" \
|
||||
"zfs recv -o pbkdf2iters=100k $TESTPOOL/recv"
|
||||
log_must zfs destroy -r $TESTPOOL/recv
|
||||
|
||||
# Test that we can receive a simple stream as an encryption root.
|
||||
log_note "Must be able to receive stream as encryption root"
|
||||
ds=$TESTPOOL/recv
|
||||
log_must eval "zfs send $snap > $sendfile"
|
||||
log_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
|
||||
"-o keylocation=file://$keyfile $ds < $sendfile"
|
||||
log_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
|
||||
log_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
|
||||
log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
|
||||
log_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
|
||||
log_must test "$(get_prop 'mounted' $ds)" == "yes"
|
||||
recv_cksum=$(md5sum /$ds/$TESTFILE0 | awk '{ print $1 }')
|
||||
log_must test "$recv_cksum" == "$cksum"
|
||||
log_must zfs destroy -r $ds
|
||||
|
||||
# Test that we can override encryption properties on a properties stream
|
||||
# of an unencrypted dataset, turning it into an encryption root.
|
||||
log_note "Must be able to receive stream with props as encryption root"
|
||||
ds=$TESTPOOL/recv
|
||||
log_must eval "zfs send -p $snap > $sendfile"
|
||||
log_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
|
||||
"-o keylocation=file://$keyfile $ds < $sendfile"
|
||||
log_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
|
||||
log_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
|
||||
log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
|
||||
log_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
|
||||
log_must test "$(get_prop 'mounted' $ds)" == "yes"
|
||||
recv_cksum=$(md5sum /$ds/$TESTFILE0 | awk '{ print $1 }')
|
||||
log_must test "$recv_cksum" == "$cksum"
|
||||
log_must zfs destroy -r $ds
|
||||
|
||||
# Test that we can override encryption properties on a recursive stream
|
||||
# of an unencrypted dataset, turning it into an encryption root. The root
|
||||
# dataset of the stream should become an encryption root with all children
|
||||
# inheriting from it.
|
||||
log_note "Must be able to receive recursive stream as encryption root"
|
||||
ds=$TESTPOOL/recv
|
||||
log_must eval "zfs send -R $snap > $sendfile"
|
||||
log_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
|
||||
"-o keylocation=file://$keyfile $ds < $sendfile"
|
||||
log_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
|
||||
log_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
|
||||
log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
|
||||
log_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
|
||||
log_must test "$(get_prop 'mounted' $ds)" == "yes"
|
||||
recv_cksum=$(md5sum /$ds/$TESTFILE0 | awk '{ print $1 }')
|
||||
log_must test "$recv_cksum" == "$cksum"
|
||||
log_must zfs destroy -r $ds
|
||||
|
||||
# Test that we can override an unencrypted properties stream's encryption
|
||||
# settings, receiving it as an encrypted child.
|
||||
log_note "Must be able to receive stream with props to encrypted child"
|
||||
ds=$TESTPOOL/crypt/recv
|
||||
log_must eval "zfs send -p $snap > $sendfile"
|
||||
log_must eval "zfs recv -x encryption $ds < $sendfile"
|
||||
log_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
|
||||
log_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
|
||||
log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
|
||||
log_must test "$(get_prop 'mounted' $ds)" == "yes"
|
||||
recv_cksum=$(md5sum /$ds/$TESTFILE0 | awk '{ print $1 }')
|
||||
log_must test "$recv_cksum" == "$cksum"
|
||||
log_must zfs destroy -r $ds
|
||||
|
||||
# Test that we can override an unencrypted recursive stream's encryption
|
||||
# settings, receiving all datasets as encrypted children.
|
||||
log_note "Must be able to receive recursive stream to encrypted child"
|
||||
ds=$TESTPOOL/crypt/recv
|
||||
log_must eval "zfs send -R $snap > $sendfile"
|
||||
log_must eval "zfs recv -x encryption $ds < $sendfile"
|
||||
log_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
|
||||
log_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
|
||||
log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
|
||||
log_must test "$(get_prop 'mounted' $ds)" == "yes"
|
||||
recv_cksum=$(md5sum /$ds/$TESTFILE0 | awk '{ print $1 }')
|
||||
log_must test "$recv_cksum" == "$cksum"
|
||||
log_must zfs destroy -r $ds
|
||||
|
||||
# Check that we haven't printed the key to the zpool history log
|
||||
log_mustnot eval "zpool history -i | grep -q 'wkeydata'"
|
||||
|
||||
log_pass "'zfs recv' properly handles encryption properties"
|
||||
Reference in New Issue
Block a user