[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

GELI encrypted ZVOL backed image-jails



Hi,

I had to implement encrypted jails with ZFS for a customer. As complete
encryption with GELI below the zpool was not an option, ZFS still
doesn't support encryption by itself and the customer didn't like large
image files and wanted ZFS snapshot support, I used ZVOLs as a backend.

Basically the patch creates a zfs ZVOL which creates a geom-device below
/dev/zvol, attaches a GELI ontop of that geom-device and creates/mounts
a UFS filesystem on/from the the GELI-device.

The filesystem inside the ZVOLs is still UFS as ZFS ontop of ZFS is
somewhat ugly.

This will definitly not go into 3.1, maybe into 3.2 if it turns out to
be useful and someone else likes to test it and produces some feedback.

greetings,
philipp
Index: ezjail-admin
===================================================================
RCS file: /home/cvsroot/ezjail/ezjail-admin,v
retrieving revision 1.252
diff -u -r1.252 ezjail-admin
--- ezjail-admin	16 Feb 2010 22:33:52 -0000	1.252
+++ ezjail-admin	7 Mar 2010 17:46:03 -0000
@@ -42,9 +42,9 @@
 case `uname -p` in amd64) ezjail_dirlist="${ezjail_dirlist} usr/lib32"; ezjail_basesystem="${ezjail_basesystem} lib32";; esac
 
 # Synopsis messages
-ezjail_usage_ezjailadmin="${ezjail_admin} v3.0\nUsage: ${ezjail_admin} [archive|config|console|create|delete|install|list|restore|update] {params}"
+ezjail_usage_ezjailadmin="${ezjail_admin} v3.2\nUsage: ${ezjail_admin} [archive|config|console|create|delete|install|list|restore|update] {params}"
 ezjail_usage_install="Usage: ${ezjail_admin} install [-mMpPsS] [-h host] [-r release]"
-ezjail_usage_create="Usage: ${ezjail_admin} create [-xbi] [-f flavour] [-r jailroot] [-s size] [-c bde|eli|zfs] [-C args] [-a archive] jailname jailip"
+ezjail_usage_create="Usage: ${ezjail_admin} create [-xbi] [-f flavour] [-r jailroot] [-s size] [-c bde|eli|zfs|zvol-eli] [-C args] [-a archive] jailname jailip"
 ezjail_usage_delete="Usage: ${ezjail_admin} delete [-w] jailname"
 ezjail_usage_update="Usage: ${ezjail_admin} update [-s sourcetree] [-p] (-b|-i|-u|-P)"
 ezjail_usage_config="Usage: ${ezjail_admin} config [-r run|norun] [-n newname] [-c cpuset] [-z zfs-datasets] [-f fib] [-i attach|detach|fsck] jailname"
@@ -63,7 +63,14 @@
 # generic attach routine for image jails
 attach_images () {
   # Create a memory disc from jail image
-  ezjail_imagedevice=`mdconfig -a -t vnode -f ${ezjail_image}` || exerr "Error: Could not attach memory disc."
+  case ${ezjail_imagetype} in
+  zvol-eli)
+    ezjail_imagedevice="zvol/${ezjail_jailzfs}/${ezjail_hostname}"
+  ;;
+  *)
+    ezjail_imagedevice=`mdconfig -a -t vnode -f ${ezjail_image}` || exerr "Error: Could not attach memory disc."
+  ;;
+  esac
 
   # If this is a crypto jail, try to mount it, remind user, which jail
   # this is. In this case, the device to mount is 
@@ -75,7 +82,7 @@
     # Device to mount is not md anymore
     ezjail_device="${ezjail_imagedevice}.bde"
     ;;
-  eli)
+  eli|zvol-eli)
     echo "Attaching eli device for image jail ${ezjail}..."
     echo geli attach ${ezjail_attachparams} "/dev/${ezjail_imagedevice}" | /bin/sh
     [ $? -eq 0 ] || detach_images keep || exerr "Error: Attaching eli device failed."
@@ -113,14 +120,23 @@
     umount "${ezjail_rootdir}" > /dev/null 2> /dev/null
     case ${ezjail_imagetype} in
       bde) gbde detach "/dev/${ezjail_imagedevice}" > /dev/null;;
-      eli) geli detach "/dev/${ezjail_imagedevice}" > /dev/null;;
+      eli|zvol-eli) geli detach "/dev/${ezjail_imagedevice}" > /dev/null;;
+    esac
+    
+    case ${ezjail_imagetype} in
+    zvol-eli)
+      [ "$1" = "keep" ] || /sbin/zfs destroy -r ${ezjail_jailzfs}/${ezjail_hostname}
+      rm -f "${ezjail_devicelink}"
+    ;;
+    *)
+      mdconfig -d -u "${ezjail_imagedevice}" > /dev/null
+      [ "$1" = "keep" ] || rm -f "${ezjail_image}"
+      # Remove soft link (which acts as a lock)
+      [ -e "/dev/${ezjail_imagedevice}" ] || rm -f "${ezjail_devicelink}"
+    ;;
     esac
-    mdconfig -d -u "${ezjail_imagedevice}" > /dev/null
-    [ "$1" = "keep" ] || rm -f "${ezjail_image}"
   fi
 
-  # Remove soft link (which acts as a lock)
-  [ -e "/dev/${ezjail_imagedevice}" ] || rm -f "${ezjail_devicelink}"
 
   # This function is being called in case of error. Keep $? bad
   return 1
@@ -235,7 +251,7 @@
     # Add this device to the list of devices to be unmounted
     case ${ezjail_imagetype} in
       crypto|bde) ezjail_imagedevice=${ezjail_device_geom%.bde} ;;
-      eli)        ezjail_imagedevice=${ezjail_device_geom%.eli} ;;
+      eli|zvol-eli)        ezjail_imagedevice=${ezjail_device_geom%.eli} ;;
       zfs)        ezjail_imagedevice='' ;;
       *)          ezjail_imagedevice=${ezjail_device_geom} ;;
     esac
@@ -275,9 +291,9 @@
   # Try to remove the old template jail
   if [ "${ezjail_use_zfs}" = "YES" ]; then
     echo "ZFS: cleanup old template jail"
-    [ -d "${ezjail_jailtemplate}" ] && zfs destroy -R ${ezjail_jailzfs}/newjail && rm -rf "${ezjail_jailtemplate}"
+    [ -d "${ezjail_jailtemplate}" ] && /sbin/zfs destroy -R ${ezjail_jailzfs}/newjail && rm -rf "${ezjail_jailtemplate}"
     cd ${ezjail_jaildir}
-    zfs rename ${ezjail_jailzfs}/fulljail ${ezjail_jailzfs}/newjail
+    /sbin/zfs rename ${ezjail_jailzfs}/fulljail ${ezjail_jailzfs}/newjail
   else
     [ -d "${ezjail_jailtemplate}" ] && chflags -R noschg "${ezjail_jailtemplate}" && rm -rf "${ezjail_jailtemplate}"
     mv "${ezjail_jailfull}" "${ezjail_jailtemplate}"
@@ -444,15 +460,15 @@
   [ "${ezjail_name}" -a "${ezjail_ips}" -a $# -eq 2 ] || exerr ${ezjail_usage_create}
 
   # check for an active ZFS zpool
-  [ "${ezjail_imagetype}" = "zfs" ] && check_for_zpool
-
+  [ "${ezjail_imagetype}" = "zfs" -o "${ezjail_imagetype}" = "zvol-eli" ] && check_for_zpool
+  
   # check for sanity of settings concerning the image feature
   if [ "${ezjail_imagetype}" != "zfs" ]; then
     [ -z "${ezjail_imagetype}" -o "${ezjail_exists}" -o "${ezjail_imagesize}" ] || exerr "Error: Image jails need an image size."
   fi
 
   # check for a sane image type
-  case ${ezjail_imagetype} in ""|simple|bde|eli|zfs) ;; *) exerr ${ezjail_usage_create};; esac
+  case ${ezjail_imagetype} in ""|simple|bde|eli|zfs|zvol-eli) ;; *) exerr ${ezjail_usage_create};; esac
 
   # check for a sane image size and split it up in blocks
   if [ "${ezjail_imagesize}" ]; then
@@ -534,13 +550,15 @@
 
     # zfs does not use image files
     [ "${ezjail_imagetype}" = "zfs" ] && unset ezjail_image
+    # zvol backed have no image files
+    [ "${ezjail_imagetype}" = "zvol-eli" ] && ezjail_image="zvol/${ezjail_jailzfs}/${ezjail_hostname}"
 
     # Prepare crypto jail so that an attacker cannot guess which blocks
     # have been written
     case ${ezjail_imagetype} in bde|eli) ezjail_sourcedevice="/dev/random";; simple) ezjail_sourcedevice="/dev/zero";; esac
 
     # If NOT exist and imagetype not ZFS, create image
-    if [ -z "${ezjail_exists}" -a ${ezjail_imagetype} != "zfs" ]; then
+    if [ -z "${ezjail_exists}" -a ${ezjail_imagetype} != "zfs" -a ${ezjail_imagetype} != "zvol-eli" ]; then
       [ -e "${ezjail_image}" ] && exerr "Error: A file exists at ${ezjail_image}.\n  Won't overwrite an existing image."
 
       # Now create jail disc image
@@ -558,6 +576,13 @@
       ezjail_devicelink="${ezjail_rootdir}.device"
 
       [ $? -eq 0 ] || detach_images || exerr "Error: Could not attach image device.\n  Command failed was 'mdconfig -a -t vnode -f ${ezjail_image}'."
+    elif [ -z "${ezjail_exists}" -a ${ezjail_imagetype} = "zvol-eli" ]; then
+      [ -e "/dev/zvol/${ezjail_jailzfs}/${ezjail_hostname}" ] && exerr "Error: A file exists at ${ezjail_jailzfs}/${ezjail_hostname}.\n  Won't overwrite an existing image."
+      /sbin/zfs create -V ${ezjail_imagesize} ${ezjail_jailzfs}/${ezjail_hostname}
+      ezjail_imagedevice="zvol/${ezjail_jailzfs}/${ezjail_hostname}"
+      ezjail_devicelink="${ezjail_rootdir}.device"
+      
+      [ $? -eq 0 ] || detach_images || exerr "Error: Could not attach image device.\n  Command failed was '/sbin/zfs create -V ${ezjail_imagesize} ${ezjail_jailzfs}/${ezjail_hostname}'."
     fi
 
     case ${ezjail_imagetype} in
@@ -570,7 +595,7 @@
       case ${ezjail_imagetype} in
       bde) init_cmd="gbde init /dev/${ezjail_imagedevice} ${ezjail_imageparams}"
            attach_cmd="gbde attach /dev/${ezjail_imagedevice} ${ezjail_attachparams}";;
-      eli) init_cmd="geli init ${ezjail_imageparams} /dev/${ezjail_imagedevice}"
+      eli|zvol-eli) init_cmd="geli init ${ezjail_imageparams} /dev/${ezjail_imagedevice}"
            attach_cmd="geli attach ${ezjail_attachparams} /dev/${ezjail_imagedevice}";;
       esac
 
@@ -584,6 +609,26 @@
 
       ezjail_device="${ezjail_imagedevice}.${ezjail_imagetype}"
       ;;
+    zvol-eli)
+      # parse imageparams, generate attachparams
+      ezjail_attachblocking="YES"
+      if [ "${ezjail_imageparams}" ]; then
+        ezjail_attachparams=`eval parse_g${ezjail_imagetype}_attach_args ${ezjail_imageparams}` || unset ezjail_attachblocking
+      fi
+      
+      init_cmd="geli init ${ezjail_imageparams} /dev/${ezjail_imagedevice}"
+      attach_cmd="geli attach ${ezjail_attachparams} /dev/${ezjail_imagedevice}"
+
+      if [ -z "${ezjail_exists}" ]; then
+        [ "${ezjail_attachblocking}" ] && echo "Initialising crypto device. You will be asked to enter a new passphrase twice... "
+        ( echo ${init_cmd} | /bin/sh ) || detach_images || exerr "Error: Could not initialise crypto image."
+
+        [ "${ezjail_attachblocking}" ] && echo "Attaching crypto device. You will be asked to enter the new passphrase... "
+        ( echo ${attach_cmd} | /bin/sh ) || detach_images || exerr "Error: Could not attach crypto image."
+      fi
+
+      ezjail_device="${ezjail_imagedevice}.eli"
+      ;;
     simple)
       ezjail_device=${ezjail_imagedevice}
       ;;
@@ -628,7 +673,7 @@
     if [ "${ezjail_imagetype}" = "zfs" -a "${ezjail_use_zfs}" = "YES" ]; then
       # create ZFS filesystem first when using ZFS
       /sbin/zfs snapshot ${ezjail_jailzfs}/newjail@_createnewjailtmp
-      /sbin/zfs send ${ezjail_jailzfs}/newjail@_createnewjailtmp | zfs receive -F ${ezjail_jailzfs}/${ezjail_hostname}
+      /sbin/zfs send ${ezjail_jailzfs}/newjail@_createnewjailtmp | /sbin/zfs receive -F ${ezjail_jailzfs}/${ezjail_hostname}
       /sbin/zfs destroy ${ezjail_jailzfs}/${ezjail_hostname}@_createnewjailtmp
       /sbin/zfs destroy ${ezjail_jailzfs}/newjail@_createnewjailtmp
     else
@@ -776,7 +821,7 @@
     simple|bde|eli)
      [ "${ezjail_image}" ] && rm -f "${ezjail_image}" "${ezjail_image%.img}.device"
     ;;
-    zfs)
+    zfs|zvol-eli)
       echo "ZFS: delete the jails ZFS"
       /sbin/zfs destroy -r ${ezjail_jailzfs}/${ezjail_hostname}
     ;;
@@ -839,7 +884,7 @@
 
   if [ "${ezjail_use_zfs}" = "YES" ]; then
     check_for_zpool
-    zfs create -p -o mountpoint=${ezjail_jaildir} ${ezjail_jailzfs}
+    /sbin/zfs create -p -o mountpoint=${ezjail_jaildir} ${ezjail_jailzfs}
   fi
 
   if [ "${ezjail_installaction}" = "none" ]; then
@@ -851,7 +896,7 @@
 
     # If ran from cron be kind to freebsds update servers and sleep first
     [ -z "$TERM" -o "$TERM" = "dumb" ] && ezjail_urgency="cron" || ezjail_urgency="fetch"
-    [ "${ezjail_use_zfs}" = "YES" ] && zfs snapshot ${ezjail_jailzfs}/basejail@`date -v -7d +"%C%y%m%d_%H:%M:%S"`
+    [ "${ezjail_use_zfs}" = "YES" ] && /sbin/zfs snapshot ${ezjail_jailzfs}/basejail@`date -v -7d +"%C%y%m%d_%H:%M:%S"`
     freebsd-update -b ${ezjail_jailbase} ${ezjail_urgency} install
   else
     # Bump the user for some of the most common errors
Index: ezjail.sh
===================================================================
RCS file: /home/cvsroot/ezjail/ezjail.sh,v
retrieving revision 1.58
diff -u -r1.58 ezjail.sh
--- ezjail.sh	18 Feb 2010 12:22:26 -0000	1.58
+++ ezjail.sh	7 Mar 2010 17:46:03 -0000
@@ -18,6 +18,7 @@
 ezjail_prefix=EZJAIL_PREFIX
 
 . /etc/rc.subr
+. /usr/local/etc/ezjail.conf
 
 name=ezjail
 rcvar=`set_rcvar`
@@ -147,8 +148,11 @@
     fi
 
     # Create a memory disc from jail image
-    ezjail_device=`mdconfig -a -t vnode -f ${ezjail_image}` || return 1
-
+    case ${ezjail_imagetype} in
+    zvol-eli) ezjail_device="zvol/${ezjail_jailzfs}/${ezjail}";;
+    *) ezjail_device=`mdconfig -a -t vnode -f ${ezjail_image}` || return 1;;
+    esac
+    
     # If this is a crypto jail, try to mount it, remind user, which jail
     # this is. In this case, the device to mount is 
     case ${ezjail_imagetype} in
@@ -172,6 +176,12 @@
       # Device to mount is not md anymore
       ezjail_device="${ezjail_device}.eli"
       ;;
+    zvol-eli)
+      echo "Attaching eli device for image jail ${ezjail}..."
+      echo geli attach ${ezjail_attachparams} "/dev/${ezjail_device}" | /bin/sh
+      # Device to mount is not md anymore
+      ezjail_device="${ezjail_device}.eli"
+      ;;
     esac
 
     # Clean image
@@ -195,7 +205,7 @@
     # Add this device to the list of devices to be unmounted
     case ${ezjail_imagetype} in
       crypto|bde) ezjail_mds="${ezjail_mds} ${ezjail_device%.bde}" ;;
-      eli) ezjail_mds="${ezjail_mds} ${ezjail_device%.eli}" ;;
+      eli|zvol-eli) ezjail_mds="${ezjail_mds} ${ezjail_device%.eli}" ;;
       simple) ezjail_mds="${ezjail_mds} ${ezjail_device}" ;;
     esac
 
@@ -210,7 +220,7 @@
   for md in ${ezjail_mds}; do
     [ -e "${md}.bde" ] && gbde detach "${md}"
     [ -e "${md}.eli" ] && geli detach "${md}"
-    mdconfig -d -u "${md#/dev/}"
+    [ "${ezjail_imagetype}" != "zvol-eli" ] && mdconfig -d -u "${md#/dev/}"
   done
 }