Skip to content

Commit

Permalink
F 1345: Allow using LUKS volumes for KVM (#808)
Browse files Browse the repository at this point in the history
* F #1345: KVM support for persistent luks volmes

Support for attaching a persistent qemu luks encrypted disk, created as
per the libvirt/qemu documentation.

Private secret must be defined on the hypervisor for decryption and the
image should contain "LUKS_SECRET" attribute.

1) Create the image and import into datastore:

 # qemu-img create --object secret,id=sec0,data=secretphrase -o key-secret=sec0 -f luks volume 1G

2) Create the secret on the hypervisor:

 # virsh secret-define volume-secret.xml
 # MYSECRET=`printf %s "secretphrase" | base64`
 # virsh secret-set-value $MYUUID $MYSECRET

 # virsh secret-dumpxml $MYUUID
 <secret ephemeral='no' private='yes'>
   <uuid>$MYUUID</uuid>
   <description>luks key</description>
   <usage type='volume'>
     <volume>rbd:one/one-123</volume>
   </usage>
 </secret>

3) Set the UUID in the image attributes, ie:

 # oneimage show 123 |grep LUKS
 LUKS_SECRET="$MYUUID"

This should allow the disk attach to decryt the luks image and
use as a normal disk within the VM.

Co-authored-by: Laurence <laurencegill@users.noreply.github.com>
  • Loading branch information
xorel and laurencegill committed Feb 18, 2021
1 parent f6e3c4e commit 73c27a9
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 5 deletions.
1 change: 1 addition & 0 deletions share/etc/oned.conf
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,7 @@ INHERIT_IMAGE_ATTR = "ISCSI_USER"
INHERIT_IMAGE_ATTR = "ISCSI_USAGE"
INHERIT_IMAGE_ATTR = "ISCSI_HOST"
INHERIT_IMAGE_ATTR = "ISCSI_IQN"
INHERIT_IMAGE_ATTR = "LUKS_SECRET"

INHERIT_DATASTORE_ATTR = "GLUSTER_HOST"
INHERIT_DATASTORE_ATTR = "GLUSTER_VOLUME"
Expand Down
2 changes: 2 additions & 0 deletions src/datastore_mad/remotes/fs/cp
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,6 @@ else
FORMAT=$($QEMU_IMG info $DST | grep "^file format:" | awk '{print $3}' || :)
fi

[[ "$FORMAT" = "luks" ]] && FORMAT="raw"

echo "$DST $FORMAT"
14 changes: 9 additions & 5 deletions src/datastore_mad/remotes/libfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,13 @@ function image_size_required {

OUT=$($QEMU_IMG info "${1}" 2>&1)
if [ $? -ne 0 ]; then
REQUIRED=$(echo "${OUT}" | \
grep 'expecting at least [0-9]* bytes' | \
sed -e 's/.*expecting at least \([0-9]*\) bytes.*/\1/')
if file "${1}" | grep -q 'LUKS encrypted file'; then
REQUIRED="$(du -sb ${2} | cut -f1)"
else
REQUIRED=$(echo "${OUT}" | \
grep 'expecting at least [0-9]* bytes' | \
sed -e 's/.*expecting at least \([0-9]*\) bytes.*/\1/')
fi
fi

echo "${REQUIRED:-65536}"
Expand Down Expand Up @@ -292,7 +296,7 @@ function fs_size {
# if unknown image type, maybe we haven't downloaded
# enough bytes; check if qemu-img info doesn't complain
# on least than expected bytes and redownload more bytes
NEW_HEAD_SIZE=$(image_size_required "${IMAGE}")
NEW_HEAD_SIZE=$(image_size_required "${IMAGE}" "${SRC}")
if [ -n "${NEW_HEAD_SIZE}" ] && [ "${NEW_HEAD_SIZE}" != "${HEAD_SIZE}" ]; then
continue # redownload more bytes
else
Expand All @@ -305,7 +309,7 @@ function fs_size {
# raw images requires special handling, as there is no image header
# with size available and we can't predict image virtual size just
# from a part of the file
if [ "${TYPE}" = 'raw' ]; then
if [ "${TYPE}" = 'raw' ] || "${TYPE}" = 'luks' ]; then
$UTILS_PATH/downloader.sh ${DOWNLOADER_ARGS} --nodecomp -c "${HEAD_SIZE}" "${SRC}" - >"${IMAGE}" 2>/dev/null
error=$?
if [ $error -ne 0 ]; then
Expand Down
9 changes: 9 additions & 0 deletions src/mad/sh/scripts_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ function get_source_xml {
# * CEPH_HOST
# * CEPH_SECRET
# * CEPH_USER
# * LUKS_SECRET
# * ISCSI_HOST
# * ISCSI_USAGE
# * ISCSI_USER
Expand Down Expand Up @@ -872,6 +873,7 @@ function get_disk_information {
$DISK_XPATH/CEPH_HOST \
$DISK_XPATH/CEPH_SECRET \
$DISK_XPATH/CEPH_USER \
$DISK_XPATH/LUKS_SECRET \
$DISK_XPATH/ISCSI_HOST \
$DISK_XPATH/ISCSI_USAGE \
$DISK_XPATH/ISCSI_USER \
Expand Down Expand Up @@ -916,6 +918,7 @@ function get_disk_information {
CEPH_HOST="${XPATH_ELEMENTS[j++]}"
CEPH_SECRET="${XPATH_ELEMENTS[j++]}"
CEPH_USER="${XPATH_ELEMENTS[j++]}"
LUKS_SECRET="${XPATH_ELEMENTS[j++]}"
ISCSI_HOST="${XPATH_ELEMENTS[j++]}"
ISCSI_USAGE="${XPATH_ELEMENTS[j++]}"
ISCSI_USER="${XPATH_ELEMENTS[j++]}"
Expand Down Expand Up @@ -953,6 +956,12 @@ function get_disk_information {
NAME="$SOURCE"
if [ -n "$LUKS_SECRET" ]; then
LUKS="<encryption format='luks'>
<secret type='passphrase' uuid='$LUKS_SECRET'/>\
</encryption>"
fi
case "$TYPE" in
block)
TYPE_SOURCE="dev"
Expand Down
11 changes: 11 additions & 0 deletions src/vmm/LibVirtDriverKVM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ int LibVirtDriver::deployment_description_kvm(
string sheepdog_host = "";
string gluster_host = "";
string gluster_volume = "";
string luks_secret = "";

string total_bytes_sec = "";
string total_bytes_sec_max_length = "";
Expand Down Expand Up @@ -906,6 +907,8 @@ int LibVirtDriver::deployment_description_kvm(
gluster_host = disk[i]->vector_value("GLUSTER_HOST");
gluster_volume = disk[i]->vector_value("GLUSTER_VOLUME");

luks_secret = disk[i]->vector_value("LUKS_SECRET");

sheepdog_host = disk[i]->vector_value("SHEEPDOG_HOST");
total_bytes_sec = disk[i]->vector_value("TOTAL_BYTES_SEC");

Expand Down Expand Up @@ -1161,6 +1164,14 @@ int LibVirtDriver::deployment_description_kvm(

file <<"/>\n";

// ---- luks secret for target ----
if ( !luks_secret.empty())
{
file << "\t\t\t<encryption format='luks'>\n"
<< "\t\t\t\t<secret type='passphrase' uuid="
<< one_util::escape_xml_attr(luks_secret) <<"/>\n"
<< "\t\t\t</encryption>\n";
}

// ---- boot order for this device ----

Expand Down
1 change: 1 addition & 0 deletions src/vmm_mad/remotes/kvm/attach_disk
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ XML+="</source>"
XML+="<target dev='$(xml_esc "${TARGET}")'/>"
[ -n "${ORDER}" ] && XML+=" <boot order='$(xml_esc "${ORDER}")'/>"
[ "${READONLY}" = 'yes' ] && XML+="<readonly/>"
[ -n "${LUKS}" ] && XML+="${LUKS}"

if [ -n "${TOTAL_BYTES_SEC}${READ_BYTES_SEC}${WRITE_BYTES_SEC}" ] || \
[ -n "${TOTAL_BYTES_SEC_MAX}${READ_BYTES_SEC_MAX}${WRITE_BYTES_SEC_MAX}" ] || \
Expand Down

0 comments on commit 73c27a9

Please sign in to comment.