1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
#!/bin/sh
# Copyright 2019 Johannes 'josch' Schauer <josch@debian.org>
# Copyright 2021 Guilhem Moulin <guilhem@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
PREREQ=""
prereqs() {
echo "$PREREQ"
}
case "$1" in
prereqs)
prereqs
exit 0
;;
esac
. /scripts/functions
set -eux
# drives available to the setup system
TARGET_DRIVE="/dev/vda"
CHROOT_TARBALL="/dev/vdb"
# we'll halt execution and hang until the timeout is reached (can't do better)
trap "panic \"couldn't prepare testbed\"" EXIT
# format the target disk with three partitions
GUID_TYPE_BIOS_boot="21686148-6449-6E6F-744E-656564454649" # BIOS boot partition
GUID_TYPE_Linux_FS="0FC63DAF-8483-4772-8E79-3D69D8477DE4" # Linux filesystem data
GUID_TYPE_LUKS="CA7D7CCB-63ED-4C53-861C-1742536059CC" # LUKS partition
sfdisk "$TARGET_DRIVE" <<-EOF
label: gpt
unit: sectors
${TARGET_DRIVE}1 : start=$((1024*2)), size=$((1024*2)), type=${GUID_TYPE_BIOS_boot}
${TARGET_DRIVE}2 : start=$(((1+1)*1024*2)), size=$((512*1024*2)), type=${GUID_TYPE_Linux_FS}
${TARGET_DRIVE}3 : start=$(((1+1+512)*1024*2)), size=$((16*1024*2))
${TARGET_DRIVE}4 : start=$(((1+1+512+16)*1024*2)), type=${GUID_TYPE_LUKS}
EOF
BOOT_DEV="${TARGET_DRIVE}2"
CRYPTSWAP_DEV="${TARGET_DRIVE}3"
CRYPTROOT_DEV="${TARGET_DRIVE}4"
CRYPTSWAP_DMNAME="swap_crypt"
CRYPTROOT_DMNAME="root_crypt"
HOSTNAME="debian"
# initialize a new LUKS partition and open it
cryptsetup luksFormat --batch-mode \
--key-file=/cryptroot/rootfs.key \
--type=luks2 \
--pbkdf=argon2id \
--pbkdf-force-iterations=4 \
--pbkdf-memory=32 \
-- "$CRYPTROOT_DEV"
cryptsetup luksOpen --key-file=/cryptroot/rootfs.key --allow-discards \
-- "$CRYPTROOT_DEV" "$CRYPTROOT_DMNAME"
# create ext2 resp. ext4 file system for /boot resp. the root FS
mke2fs -t ext2 -m0 "$BOOT_DEV"
mke2fs -t ext4 "/dev/mapper/$CRYPTROOT_DMNAME"
# extract the chroot tarball into the target's root FS (excluding /boot/* and special files)
mount -t ext4 "/dev/mapper/$CRYPTROOT_DMNAME" /root
tar -C /root -xf- --xattrs --xattrs-include="*" \
--exclude="./lost+found" \
--exclude="./boot/*" \
--exclude="./dev/*" \
--exclude="./proc/*" \
--exclude="./run/*" \
--exclude="./sys/*" \
--exclude="./tmp/*" \
<"$CHROOT_TARBALL"
# extract boot from the chroot tarball into the target's /boot partition
mount -t ext2 "$BOOT_DEV" /root/boot
tar -C /root -xf- --xattrs --xattrs-include="*" "./boot/" <"$CHROOT_TARBALL"
# setup fstab(5) and crypttab(5)
cat >/root/etc/fstab <<-EOF
/dev/mapper/$CRYPTROOT_DMNAME / auto errors=remount-ro 0 1
/dev/mapper/$CRYPTSWAP_DMNAME none swap sw 0 0
UUID=$(blkid -s UUID -o value "$BOOT_DEV") /boot auto defaults 0 2
EOF
cat >/root/etc/crypttab <<-EOF
$CRYPTROOT_DMNAME UUID=$(blkid -s UUID -o value "$CRYPTROOT_DEV") none luks,discard
$CRYPTSWAP_DMNAME $CRYPTSWAP_DEV /dev/urandom cipher=aes-xts-plain64,size=256,discard,swap
EOF
# setup the network
IFACE="eth0" # we can rely on that name since we set net.ifnames=0
cat >/root/etc/network/interfaces <<-EOF
auto lo
iface lo inet loopback
auto $IFACE
iface $IFACE inet static
address 10.0.2.129/24
EOF
echo "$HOSTNAME" >/root/etc/hostname
echo "127.0.0.1 localhost $HOSTNAME" >/root/etc/hosts
ln -s /dev/null /root/etc/systemd/system/systemd-firstboot.service
# instead of supplying the ip parameter to the kernel cmdline, we tell dropbear
# about it to test this functionality; we use a dedicated IP at initramfs stage
# to check that the network is re-configured as intended after pivoting
echo "IP=\"10.0.2.130:::255.255.255.0::$IFACE:off\"" >/root/etc/initramfs-tools/conf.d/dropbear
# start dropbear on a non-default port to also test this functionality
echo "DROPBEAR_OPTIONS=\"-p 2222\"" >>/root/etc/dropbear/initramfs/dropbear.conf
# copy dropbear's authorized_keys file to ~root/.ssh so we can login to the system's
# SSHd once it finished booting
mkdir -pm0700 /root/root/.ssh
cp -T /root/etc/dropbear/initramfs/authorized_keys /root/root/.ssh/authorized_keys
# add some restrictions to dropbear's authorized_keys file
sed -ri '/^\s*(#|$)/b; s#^#no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="/bin/cryptroot-unlock" #' \
/root/etc/dropbear/initramfs/authorized_keys
# mount pseudo- and temporary filesystems so we can chroot in the target system
mount -t devtmpfs none /root/dev
mount -t devpts none /root/dev/pts
mount -t proc none /root/proc
mount -t tmpfs none /root/run
mount -t sysfs none /root/sys
# update the initramfs image
echo RESUME=none >/root/etc/initramfs-tools/conf.d/resume
chroot /root update-initramfs -u
# configure and install GRUB
cat >/root/etc/default/grub <<-EOF
GRUB_DEFAULT=0
GRUB_TIMEOUT=0
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="net.ifnames=0 console=ttyS0"
GRUB_DISABLE_RECOVERY=true
EOF
chroot /root grub-install --no-floppy --modules=part_gpt "$TARGET_DRIVE"
chroot /root update-grub
# umount everything
for d in /boot /dev/pts /dev /proc /run /sys ""; do
umount "/root$d"
done
cryptsetup luksClose -- "$CRYPTROOT_DMNAME"
# we're done! power the setup system down so we can reboot into the
# target system
poweroff -f
|