Skip to content

Instantly share code, notes, and snippets.

@astoeckel
Last active December 25, 2019 04:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astoeckel/623c589f2ffa0f48609aca7759867e94 to your computer and use it in GitHub Desktop.
Save astoeckel/623c589f2ffa0f48609aca7759867e94 to your computer and use it in GitHub Desktop.
Mounts a LUKS encrypted QCOW2 image
#!/bin/bash
QCOW2_ACTION="$1"
QCOW2_FILENAME="$2"
QCOW2_MOUNTPOINT="$3"
if test -z "$QCOW2_ACTION" || test -z "$QCOW2_FILENAME" || test -z "$QCOW2_MOUNTPOINT"; then
echo "Usage: mount.qcow2 <mount|unmount> <FILENAME> <MOUNTPOINT>";
exit 1
fi
# Load the nbd device driver
modprobe nbd max_part=63 || exit 1
# Find the name of the nbdev associated with the QCOW2 image
QEMU_NBD_PIDS=$( pgrep qemu-nbd )
if test -n "$QEMU_NBD_PIDS"; then
NBD_DEV=$( \
ps --no-headers -o args -p $QEMU_NBD_PIDS | \
grep "$QCOW2_FILENAME" | tail -n 1 | sed -e 's/.*\s\(.*\)$/\1/' )
fi
# Find the name of the LUKS mapper associated with the NBD device
if test -n "$NBD_DEV"; then
for DEV in /dev/mapper/qcow2_*; do
DEV=$( basename "$DEV" )
if cryptsetup status "$DEV" | grep device | grep "$NBD_DEV" > /dev/null; then
CRYPT_DEVNAME="$DEV"
break;
fi
done
fi
if [ "$QCOW2_ACTION" = "mount" ]; then
# Find the next free nbd device number
if test -z "$NBD_DEV"; then
NBD_DEV_NO=$( lsblk -l | grep nbd | sort | sed -e 's/^nbd\([0-9]\+\).*$/\1/' | tail -n 1 )
if test -z "$NBD_DEV_NO"; then
NBD_DEV_NO=0
else
NBD_DEV_NO=$( expr "$NBD_DEV_NO" + 1 )
fi
NBD_DEV="/dev/nbd$NBD_DEV_NO"
# Export the device using qemu-nbd
qemu-nbd "$QCOW2_FILENAME" --cache=unsafe -c "$NBD_DEV" || exit 1
echo "Exported image to $NBD_DEV"
else
echo "Image already exported to $NBD_DEV"
fi
if test -z "$CRYPT_DEVNAME"; then
# Generate a random name for the device
CRYPT_DEVNAME=qcow2_$( head /dev/urandom | tr -dc A-Za-z | head -c 10 )
# Re-read the partition tables
partprobe
# Open the encrypted partition using LUKS
cat /etc/luks_passwd | cryptsetup open "${NBD_DEV}p1" "$CRYPT_DEVNAME" || exit 1
echo "Opened LUKS device $CRYPT_DEVNAME"
else
echo "Image already opened as LUKS device $CRYPT_DEVNAME"
fi
# Mount the file system at the specified mountpoint
if mount | grep "$QCOW2_MOUNTPOINT" > /dev/null; then
if mount | grep "$QCOW2_MOUNTPOINT" | grep "$CRYPT_DEVNAME" > /dev/null; then
echo "\"/dev/mapper/$CRYPT_DEVNAME\" is already mounted on \"$QCOW2_MOUNTPOINT\""
else
echo "Error: Mount point is already in use!"
fi
else
mount "/dev/mapper/$CRYPT_DEVNAME" "$QCOW2_MOUNTPOINT" || exit 1
echo "Mounted \"/dev/mapper/$CRYPT_DEVNAME\" on \"$QCOW2_MOUNTPOINT\""
fi
exit 0
elif [ "$QCOW2_ACTION" = "unmount" ]; then
# Unmount the file system from the specified mountpoint
if mount | grep "$QCOW2_MOUNTPOINT" > /dev/null; then
echo "Unmounting $QCOW2_MOUNTPOINT"
umount "$QCOW2_MOUNTPOINT" || exit 1
fi
# Close the LUKS device
if test -n "$CRYPT_DEVNAME"; then
echo "Closing LUKS device $CRYPT_DEVNAME"
cryptsetup close "$CRYPT_DEVNAME" || exit 1
fi
# Disconnect the NBD dev for the image
if test -n "$NBD_DEV"; then
echo "Disconnecting image from $NBD_DEV"
qemu-nbd -d "$NBD_DEV" || exit 1
fi
exit 0
else
echo "Invalid action \"$QCOW2_ACTION\"; must be \"mount\" or \"unmount\""
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment