Skip to content

Commit

Permalink
Redo of implementation for feature request armbian#947 on current master
Browse files Browse the repository at this point in the history
This was already implemented with armbian#948,
before but never made it into the master branch yet. Probably because the
development branch has been abandoned in the meantime and it is to much effort
now to merge it into master.

It includes all the cleanup changes from commit 08743d3 and has been successfully
tested on an Odroid HC1.

In addition to what is currently in the `luks` branch the following improvments
where done/added:

1. update_initramfs() function in debbootstrap-ng.sh, which needs to be invoked
   after the partition layout and /etc/crypttab was created. Else `cryptroot-unlock`
   won't work and you'll run into:
   https://serverfault.com/questions/907254/cryproot-unlock-with-dropbear-timeout-while-waiting-for-askpass

   Apart from that it might be useful to always run `update-initramfs` at the end
   of the build process anyway, in case customize_image (userpatches) made some
   changes to the initramfs tools configs.

2. CRYPTROOT_SSH_UNLOCK=yes/no config option. It's by default set to yes, but it
   might be desired by some users to disable enable SSH/dropbear access while
   still having LUKS support. E.g. if they have a device that has a display
   and keyboard.

3. If no `authorized_keys` file is provided via userpatches, a new SSH key pair
   is generated and for convenience copied to the output directory along with
   the final image.
  • Loading branch information
zciendor committed Jul 31, 2018
1 parent fac4687 commit ddf0ed1
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 14 deletions.
3 changes: 2 additions & 1 deletion lib/build-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ for line in "${buildlist[@]}"; do
BOOTSCRIPT UBOOT_TARGET_MAP LOCALVERSION UBOOT_COMPILER KERNEL_COMPILER BOOTCONFIG BOOTCONFIG_VAR_NAME BOOTCONFIG_DEFAULT BOOTCONFIG_NEXT BOOTCONFIG_DEV \
MODULES MODULES_NEXT MODULES_DEV INITRD_ARCH BOOTENV_FILE BOOTDELAY MODULES_BLACKLIST MODULES_BLACKLIST_NEXT ATF_TOOLCHAIN2 \
MODULES_BLACKLIST_DEV MOUNT SDCARD BOOTPATCHDIR KERNELPATCHDIR buildtext RELEASE IMAGE_TYPE OVERLAY_PREFIX ASOUND_STATE \
ATF_COMPILER ATF_USE_GCC ATFSOURCE ATFDIR ATFBRANCH ATFSOURCEDIR PACKAGE_LIST_RM NM_IGNORE_DEVICES DISPLAY_MANAGER family_tweaks_bsp_s
ATF_COMPILER ATF_USE_GCC ATFSOURCE ATFDIR ATFBRANCH ATFSOURCEDIR PACKAGE_LIST_RM NM_IGNORE_DEVICES DISPLAY_MANAGER family_tweaks_bsp_s \
CRYPTROOT_ENABLE CRYPTROOT_PASSPHRASE CRYPTROOT_SSH_UNLOCK CRYPTROOT_SSH_UNLOCK_PORT CRYPTROOT_SSH_UNLOCK_KEY_NAME ROOT_MAPPER

read BOARD BRANCH RELEASE BUILD_DESKTOP <<< $line
n=$[$n+1]
Expand Down
18 changes: 18 additions & 0 deletions lib/configuration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ CHROOT_CACHE_VERSION=6
[[ -z $DISPLAY_MANAGER ]] && DISPLAY_MANAGER=nodm
ROOTFS_CACHE_MAX=16 # max number of rootfs cache, older ones will be cleaned up

# TODO: fixed name can't be used for parallel image building
ROOT_MAPPER="armbian-root"

[[ -z $ROOTFS_TYPE ]] && ROOTFS_TYPE=ext4 # default rootfs type is ext4
[[ "ext4 f2fs btrfs nfs fel" != *$ROOTFS_TYPE* ]] && exit_with_error "Unknown rootfs type" "$ROOTFS_TYPE"

Expand All @@ -31,6 +34,11 @@ ROOTFS_CACHE_MAX=16 # max number of rootfs cache, older ones will be cleaned up
# echo $(( $(blockdev --getsize64 /dev/sdX) / 1024 / 1024 ))
[[ "f2fs" == *$ROOTFS_TYPE* && -z $FIXED_IMAGE_SIZE ]] && exit_with_error "Please define FIXED_IMAGE_SIZE"

# a passphrase is mandatory if rootfs encryption is enabled
if [[ $CRYPTROOT_ENABLE == yes && -z $CRYPTROOT_PASSPHRASE ]]; then
exit_with_error "Root encryption is enabled but CRYPTROOT_PASSPHRASE is not set"
fi

# small SD card with kernel, boot script and .dtb/.bin files
[[ $ROOTFS_TYPE == nfs ]] && FIXED_IMAGE_SIZE=64

Expand All @@ -55,6 +63,9 @@ ARCH=armhf
KERNEL_IMAGE_TYPE=zImage
SERIALCON=ttyS0
CAN_BUILD_STRETCH=yes
[[ -z $CRYPTROOT_SSH_UNLOCK ]] && CRYPTROOT_SSH_UNLOCK=yes
[[ -z $CRYPTROOT_SSH_UNLOCK_PORT ]] && CRYPTROOT_SSH_UNLOCK_PORT=2022
CRYPTROOT_SSH_UNLOCK_KEY_NAME=id_ecdsa_cryptroot-unlock

# single ext4 partition is the default and preferred configuration
#BOOTFS_TYPE=''
Expand Down Expand Up @@ -142,6 +153,13 @@ PACKAGE_LIST_DESKTOP="xserver-xorg xserver-xorg-video-fbdev gvfs-backends gvfs-f
PACKAGE_LIST_DESKTOP_RECOMMENDS="mirage galculator hexchat xfce4-screenshooter network-manager-openvpn-gnome mpv fbi cups-pk-helper \
cups geany atril xarchiver leafpad"

# rootfs encryption related packages
if [[ $CRYPTROOT_ENABLE == yes ]]; then
PACKAGE_LIST="$PACKAGE_LIST cryptsetup"
if [[ $CRYPTROOT_SSH_UNLOCK == yes ]]; then
PACKAGE_LIST="$PACKAGE_LIST dropbear-initramfs"
fi
fi

case $DISPLAY_MANAGER in
nodm)
Expand Down
71 changes: 66 additions & 5 deletions lib/debootstrap-ng.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# debootstrap_ng
# create_rootfs_cache
# prepare_partitions
# update_initramfs
# create_image

# debootstrap_ng
Expand Down Expand Up @@ -74,6 +75,8 @@ debootstrap_ng()
source $SRC/lib/fel-load.sh
else
prepare_partitions
# update initramfs to reflect any configuration changes since kernel installation
update_initramfs
create_image
fi

Expand Down Expand Up @@ -325,6 +328,12 @@ prepare_partitions()
local bootfs=ext4
local bootpart=1
[[ -z $BOOTSIZE || $BOOTSIZE -le 8 ]] && BOOTSIZE=64 # MiB, For cleanup processing only
elif [[ $CRYPTROOT_ENABLE == yes ]]; then
# 2 partition setup for encrypted /root and non-encrypted /boot
local bootfs=ext4
local bootpart=1
local rootpart=2
[[ -z $BOOTSIZE || $BOOTSIZE -le 8 ]] && BOOTSIZE=64 # MiB
else
# single partition ext4 root
local rootpart=1
Expand Down Expand Up @@ -407,13 +416,30 @@ prepare_partitions()
rm -f $SDCARD/etc/fstab
if [[ -n $rootpart ]]; then
local rootdevice="${LOOP}p${rootpart}"
display_alert "Creating rootfs" "$ROOTFS_TYPE"

if [[ $CRYPTROOT_ENABLE == yes ]]; then
display_alert "Encrypting root partition with LUKS..." "cryptsetup luksFormat $rootdevice" ""
echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksFormat $rootdevice -
echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksOpen $rootdevice $ROOT_MAPPER -
display_alert "Root partition encryption complete." "" "ext"
# TODO: pass /dev/mapper to Docker
rootdevice=/dev/mapper/$ROOT_MAPPER # used by `mkfs` and `mount` commands
fi

check_loop_device "$rootdevice"
display_alert "Creating rootfs" "$ROOTFS_TYPE on $rootdevice"
mkfs.${mkfs[$ROOTFS_TYPE]} ${mkopts[$ROOTFS_TYPE]} $rootdevice
[[ $ROOTFS_TYPE == ext4 ]] && tune2fs -o journal_data_writeback $rootdevice > /dev/null
[[ $ROOTFS_TYPE == btrfs ]] && local fscreateopt="-o compress-force=zlib"
mount ${fscreateopt} $rootdevice $MOUNT/
local rootfs="UUID=$(blkid -s UUID -o value $rootdevice)"
# create fstab (and crypttab) entry
if [[ $CRYPTROOT_ENABLE == yes ]]; then
# map the LUKS container partition via its UUID to be the 'cryptroot' device
echo "$ROOT_MAPPER UUID=$(blkid -s UUID -o value ${LOOP}p${rootpart}) none luks" >> $SDCARD/etc/crypttab
local rootfs=$rootdevice # used in fstab
else
local rootfs="UUID=$(blkid -s UUID -o value $rootdevice)"
fi
echo "$rootfs / ${mkfs[$ROOTFS_TYPE]} defaults,noatime,nodiratime${mountopts[$ROOTFS_TYPE]} 0 1" >> $SDCARD/etc/fstab
fi
if [[ -n $bootpart ]]; then
Expand All @@ -429,8 +455,11 @@ prepare_partitions()

# stage: adjust boot script or boot environment
if [[ -f $SDCARD/boot/armbianEnv.txt ]]; then
echo "rootdev=$rootfs" >> $SDCARD/boot/armbianEnv.txt
echo "rootfstype=$ROOTFS_TYPE" >> $SDCARD/boot/armbianEnv.txt
if [[ $CRYPTROOT_ENABLE == yes ]]; then
echo "rootdev=$rootdevice cryptdevice=UUID=$(blkid -s UUID -o value ${LOOP}p${rootpart}):$ROOT_MAPPER" >> $SDCARD/boot/armbianEnv.txt
else
echo "rootdev=$rootfs" >> $SDCARD/boot/armbianEnv.txt
fi
elif [[ $rootpart != 1 ]]; then
local bootscript_dst=${BOOTSCRIPT##*:}
sed -i 's/mmcblk0p1/mmcblk0p2/' $SDCARD/boot/$bootscript_dst
Expand All @@ -441,7 +470,12 @@ prepare_partitions()
# if we have boot.ini = remove armbianEnv.txt and add UUID there if enabled
if [[ -f $SDCARD/boot/boot.ini ]]; then
sed -i -e "s/rootfstype \"ext4\"/rootfstype \"$ROOTFS_TYPE\"/" $SDCARD/boot/boot.ini
sed -i 's/^setenv rootdev .*/setenv rootdev "'$rootfs'"/' $SDCARD/boot/boot.ini
if [[ $CRYPTROOT_ENABLE == yes ]]; then
local rootpart="UUID=$(blkid -s UUID -o value ${LOOP}p${rootpart})"
sed -i 's/^setenv rootdev .*/setenv rootdev "\/dev\/mapper\/'$ROOT_MAPPER' cryptdevice='$rootpart':'$ROOT_MAPPER'"/' $SDCARD/boot/boot.ini
else
sed -i 's/^setenv rootdev .*/setenv rootdev "'$rootfs'"/' $SDCARD/boot/boot.ini
fi
[[ -f $SDCARD/boot/armbianEnv.txt ]] && rm $SDCARD/boot/armbianEnv.txt
fi

Expand All @@ -451,6 +485,31 @@ prepare_partitions()

} #############################################################################

# update_initramfs
#
# this should be invoked as late as possible for any modifications by
# customize_image (userpatches) and prepare_partitions to be reflected in the
# final initramfs
#
# especially, this needs to be invoked after /etc/crypttab has been created
# for cryptroot-unlock to work:
# https://serverfault.com/questions/907254/cryproot-unlock-with-dropbear-timeout-while-waiting-for-askpass
#
update_initramfs() {

update_initramfs_cmd="update-initramfs -uv -k ${VER}-${LINUXFAMILY}"
display_alert "Updating initramfs..." "$update_initramfs_cmd" ""
cp /usr/bin/$QEMU_BINARY $SDCARD/usr/bin/
mount_chroot "$SDCARD/"

chroot $SDCARD /bin/bash -c "$update_initramfs_cmd" >> $DEST/debug/debootstrap.log
display_alert "Updated initramfs." "for details see: $DEST/debug/debootstrap.log" "ext"

umount_chroot "$SDCARD/"
rm $SDCARD/usr/bin/$QEMU_BINARY

} #############################################################################

# create_image
#
# finishes creation of image from cached rootfs
Expand Down Expand Up @@ -493,6 +552,8 @@ create_image()
sync
[[ $BOOTSIZE != 0 ]] && umount -l $MOUNT/boot
[[ $ROOTFS_TYPE != nfs ]] && umount -l $MOUNT
[[ $CRYPTROOT_ENABLE == yes ]] && cryptsetup luksClose $ROOT_MAPPER

losetup -d $LOOP
rm -rf --one-file-system $DESTIMG $MOUNT
mkdir -p $DESTIMG
Expand Down
26 changes: 26 additions & 0 deletions lib/distributions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,32 @@ install_common()
echo "/dev/mmcblk0p1 / $ROOTFS_TYPE defaults 0 1" >> $SDCARD/etc/fstab
# required for initramfs-tools-core on Stretch since it ignores the / fstab entry
echo "/dev/mmcblk0p2 /usr $ROOTFS_TYPE defaults 0 2" >> $SDCARD/etc/fstab

# adjust initramfs dropbear configuration
# needs to be done before kernel installation, else it won't be in the initrd image
if [[ $CRYPTROOT_ENABLE == yes && $CRYPTROOT_SSH_UNLOCK == yes ]]; then
# Set the port of the dropbear ssh deamon in the initramfs to a different one if configured
# this avoids the typical 'host key changed warning' - `WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!`
[[ -f $SDCARD/etc/dropbear-initramfs/config ]] && sed -i 's/^#DROPBEAR_OPTIONS=/DROPBEAR_OPTIONS="-p '$CRYPTROOT_SSH_UNLOCK_PORT'"/' $SDCARD/etc/dropbear-initramfs/config

# setup dropbear authorized_keys, either provided by userpatches or generated
if [[ -f $SRC/userpatches/dropbear_authorized_keys ]]; then
cp $SRC/userpatches/dropbear_authorized_keys $SDCARD/etc/dropbear-initramfs/authorized_keys
else
# generate a default ssh key for login on dropbear in initramfs
# this key should be changed by the user on first login
display_alert "Generating a new SSH key pair for dropbear (initramfs)" "" ""
ssh-keygen -t ecdsa -f $SDCARD/etc/dropbear-initramfs/id_ecdsa -N '' -O force-command=cryptroot-unlock -C 'AUTOGENERATED_BY_ARMBIAN_BUILD'

# /usr/share/initramfs-tools/hooks/dropbear will automatically add 'id_ecdsa.pub' to authorized_keys file
# during mkinitramfs of update-initramfs
#cat $SDCARD/etc/dropbear-initramfs/id_ecdsa.pub > $SDCARD/etc/dropbear-initramfs/authorized_keys

# copy dropbear ssh key to image output dir for convenience
cp $SDCARD/etc/dropbear-initramfs/id_ecdsa $DEST/images/$CRYPTROOT_SSH_UNLOCK_KEY_NAME
display_alert "SSH private key for dropbear (initramfs) has been copied to:" "$DEST/images/$CRYPTROOT_SSH_UNLOCK_KEY_NAME" "info"
fi
fi

# create modules file
if [[ $BRANCH == dev && -n $MODULES_DEV ]]; then
Expand Down
2 changes: 1 addition & 1 deletion lib/general.sh
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ prepare_host()
nfs-kernel-server btrfs-tools ncurses-term p7zip-full kmod dosfstools libc6-dev-armhf-cross \
curl patchutils python liblz4-tool libpython2.7-dev linux-base swig libpython-dev aptly acl \
locales ncurses-base pixz dialog systemd-container udev lib32stdc++6 libc6-i386 lib32ncurses5 lib32tinfo5 \
bison libbison-dev flex libfl-dev"
bison libbison-dev flex libfl-dev cryptsetup"

local codename=$(lsb_release -sc)
display_alert "Build host OS release" "${codename:-(unknown)}" "info"
Expand Down
3 changes: 2 additions & 1 deletion lib/image-helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ unmount_on_exit()
umount -l $SDCARD >/dev/null 2>&1
umount -l $MOUNT/boot >/dev/null 2>&1
umount -l $MOUNT >/dev/null 2>&1
[[ $CRYPTROOT_ENABLE == yes ]] && cryptsetup luksClose $ROOT_MAPPER
losetup -d $LOOP >/dev/null 2>&1
rm -rf --one-file-system $SDCARD
exit_with_error "debootstrap-ng was interrupted"
Expand Down Expand Up @@ -124,4 +125,4 @@ install_deb_chroot()
display_alert "Installing" "$name"
chroot $SDCARD /bin/bash -c "dpkg -i /root/$name" >> $DEST/debug/install.log 2>&1
rm -f $SDCARD/root/$name
}
}
40 changes: 34 additions & 6 deletions packages/bsp/common/usr/lib/armbian/armbian-resize-filesystem
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,24 @@

do_expand_partition()
{
local rootpart=$(findmnt -n -o SOURCE /) # i.e. /dev/mmcblk0p1
local rootdevice=$(lsblk -n -o PKNAME $rootpart) # i.e. mmcblk0
# trim any btrfs subvolume identifier given in square brackets (e.g. /dev/mapper/armbian-root[/@])
local rootsource=$(findmnt -n -o SOURCE / | sed 's~\[.*\]~~') # i.e. /dev/mmcblk0p1 or /dev/mapper/armbian-root

# check for device type
local roottype=$(lsblk -n -o TYPE $rootsource) # crypt, part or disk
case ${roottype} in
crypt)
IS_CRYPTDEVICE=true
local cryptname=$(lsblk -n -o NAME $rootsource)
local parent_uuid=$(cat /etc/crypttab | awk '{if($1=="'$cryptname'"){print $2}}' | sed 's/UUID=//')
local rootpart=$(blkid -U $parent_uuid)
;;
part)
local rootpart=$rootsource # i.e. /dev/mmcblk0p1
;;
esac

local rootdevice=$(lsblk -n -o PKNAME $rootpart | head -1) # i.e. mmcblk0
local rootdevicepath="/dev/$rootdevice" # i.e. /dev/mmcblk0
# get count of partitions and their boundaries
local partitions=$(parted $rootdevicepath print -sm | tail -1 | awk -F ':' '{print $1}')
Expand Down Expand Up @@ -84,7 +100,7 @@ do_expand_partition()
fi

# Start resizing
echo -e "\n### [resize2fs] ${ResizeLog}. Start resizing partition $rootpart now:\n" >>${Log}
echo -e "\n### [resize2fs] ${ResizeLog}. Start resizing partition $rootsource now:\n" >>${Log}
cat /proc/partitions >>${Log}
echo -e "\nExecuting fdisk, fsck and partprobe:" >>${Log}
local fdisk_version=$(fdisk --version | awk '{print $NF}' | grep -oE "^[[:digit:]]\.[[:digit:]]+")
Expand All @@ -102,10 +118,16 @@ do_expand_partition()
partprobe $rootdevicepath >>${Log} 2>&1 || s=$?
echo -e "New partition table:\n" >>${Log}
cat /proc/partitions >>${Log}
echo -e "\nNow trying to resize $1 filesystem on $rootpart to the limits:\n" >>${Log}
echo -e "\nNow trying to resize $1 filesystem on $rootsource to the limits:\n" >>${Log}

# if crypt-device, resize LUKS container first
if [[ $IS_CRYPTDEVICE ]]; then
do_resize_crypt $cryptname
fi

case $1 in
ext4)
resize2fs $rootpart >>${Log} 2>&1
resize2fs $rootsource >>${Log} 2>&1
# check whether reboot is necessary for resize2fs to take effect
local freesize=$(( $(findmnt --target / -n -o AVAIL -b) / 1048576 )) # MiB
if [[ $s != 0 || $freesize -lt 512 ]]; then
Expand All @@ -119,6 +141,12 @@ do_expand_partition()
esac
}

do_resize_crypt()
{
echo -e "\n### [resize2fs] Start resizing LUKS container now\n" >> ${Log}
cryptsetup resize $1
}

do_expand_ext4()
{
echo -e "\n### [resize2fs] Start resizing ext4 partition $1 now\n" >> ${Log}
Expand Down Expand Up @@ -169,4 +197,4 @@ case "$1" in
echo "Usage: $0 start"
exit 0
;;
esac
esac

0 comments on commit ddf0ed1

Please sign in to comment.