Last active
December 30, 2017 12:01
-
-
Save hashbrowncipher/1dae932af83b58b51655a88ddad0ee4a to your computer and use it in GitHub Desktop.
An imager based on s3gof3r, for reimaging EC2 nodes without losing their instance store
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -x | |
set -o errexit | |
set -o nounset | |
set -o pipefail | |
#------- end of header (relevant for root/kernel.sh, below) | |
readonly INITRD_DIR=initrd | |
readonly SSH_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIyK5qcNzv65trF8pdiLZbnBS6NLJqiHhGSQo6veOswH" | |
readonly KERNEL_VERSION="4.13.0-21-generic" | |
readonly SCRIPT_LOCATION="$(readlink -f "${BASH_SOURCE}")" | |
base() { | |
cp -a ../"${INITRD_DIR}.bak" "${INITRD_DIR}" || | |
debootstrap \ | |
--include "openssh-server less vim-tiny iproute2 kmod udev ca-certificates" \ | |
--variant=minbase \ | |
xenial "${INITRD_DIR}" | |
cd "${INITRD_DIR}" | |
cat << EOF > etc/apt/sources.list | |
deb http://archive.ubuntu.com/ubuntu xenial main universe | |
deb http://archive.ubuntu.com/ubuntu xenial-security main universe | |
EOF | |
head -n6 "${SCRIPT_LOCATION}" > root/kernel.sh | |
cat >> root/kernel.sh <<EOF | |
cd /root | |
apt update | |
apt install liblz4-tool | |
apt download "linux-image-${KERNEL_VERSION}" | |
dpkg -x *.deb / | |
depmod "${KERNEL_VERSION}" | |
systemctl enable systemd-networkd.service | |
systemctl enable systemd-resolved.service | |
systemctl enable systemd-networkd-wait-online.service | |
sed -ie 's/^root:\*:/root::/' /etc/shadow | |
EOF | |
chmod +x root/kernel.sh | |
chroot . /root/kernel.sh | |
cp boot/vmlinuz* ../vmlinuz | |
cat <<EOF > etc/systemd/network/all.network | |
[Network] | |
DHCP=yes | |
EOF | |
mkdir root/.ssh | |
echo "${SSH_KEY}" > root/.ssh/authorized_keys | |
cat <<EOF > etc/systemd/system/generate_ssh_keys.service | |
[Unit] | |
Description=Generate SSH keys | |
Before=ssh.service | |
[Service] | |
Type=oneshot | |
ExecStart=/usr/local/bin/generate_ssh_host_keys | |
EOF | |
cat <<EOF > etc/systemd/system/install_from_s3.service | |
[Unit] | |
Description=Install an image from S3 | |
After=network-online.target | |
Wants=network-online.target | |
[Service] | |
ExecStart=/usr/local/bin/install_from_s3 | |
Restart=always | |
RestartSec=60 | |
StandardOutput=journal+console | |
EOF | |
ln -s "/etc/systemd/system/install_from_s3.service" "etc/systemd/system/multi-user.target.wants" | |
ln -s "/etc/systemd/system/generate_ssh_keys.service" "etc/systemd/system/multi-user.target.wants" | |
cat <<EOF > usr/local/bin/generate_ssh_host_keys | |
#!/bin/bash | |
ssh-keygen -q -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa | |
ssh-keygen -q -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa | |
ssh-keygen -q -f /etc/ssh/ssh_host_ecdsa_key -N '' -t ecdsa | |
ssh-keygen -q -f /etc/ssh/ssh_host_ed25519_key -N '' -t ed25519 | |
EOF | |
chmod +x usr/local/bin/generate_ssh_host_keys | |
ln -sf /run/systemd/resolve/resolv.conf etc/resolv.conf | |
rm -rf -- \ | |
boot/vmlinuz* \ | |
etc/ssh/ssh_host_*_key* \ | |
etc/hostname \ | |
root/* \ | |
usr/share/doc \ | |
usr/share/i18n \ | |
usr/share/locale \ | |
var/cache/apt \ | |
var/lib/dpkg/info \ | |
var/lib/apt \ | |
var/log | |
cat "${SCRIPT_LOCATION}" > root/build.sh | |
chmod +x root/build.sh | |
mkdir var/lib/dpkg/info | |
cd .. | |
} | |
installer() { | |
GOF3R_FILENAME="gof3r_0.5.0_linux_amd64.tar.gz" | |
curl -LO "https://github.com/rlmcpherson/s3gof3r/releases/download/v0.5.0/${GOF3R_FILENAME}" | |
echo "d88f199d1580d8c8cac26ba39e15dc6e2126d20e56c3894bd37a226e8b3e665c ${GOF3R_FILENAME}" | sha256sum -c | |
cd "${INITRD_DIR}" | |
ln -s /sbin/init init | |
tar -C usr/bin --strip-components=1 -xzvf "../${GOF3R_FILENAME}" | |
rm "../${GOF3R_FILENAME}" | |
cat > usr/local/bin/install_from_s3 <<"EOF" | |
#!/bin/bash -x | |
set -o errexit | |
set -o nounset | |
set -o pipefail | |
read -a cmdline < /proc/cmdline | |
for arg in "${cmdline[@]}"; do | |
case "${arg}" in | |
root=UUID=*) | |
root="/dev/disk/by-uuid/${arg#root=UUID=}" | |
;; | |
root=*) | |
root="${arg#root=}" | |
;; | |
source=*) | |
IFS=/ read -r bucket key <<< "${arg#source=}" | |
;; | |
esac | |
done | |
echo "Bucket: ${bucket}" | |
echo "Key: ${key}" | |
echo "Root: ${root}" | |
gof3r get -b "${bucket}" -k "${key}" | lz4 -d > "${root}" | |
exec reboot -f | |
EOF | |
chmod +x usr/local/bin/install_from_s3 | |
find . -print0 | cpio -o -H newc -R 0:0 --null | gzip > ../initrd.gz | |
cd .. | |
rm -r "${INITRD_DIR}" | |
} | |
local_bootloader() { | |
read -a cmdline < /proc/cmdline | |
new_cmdline=() | |
for arg in "${cmdline[@]}"; do | |
case "${arg}" in | |
root=*) | |
new_cmdline+=("${arg}") | |
;; | |
esac | |
done | |
new_cmdline+=("$@") | |
mkdir grub | |
cat <<EOF > grub/grub.cfg | |
linux /boot/vmlinuz ${new_cmdline[@]} | |
initrd /boot/initrd.gz | |
boot | |
EOF | |
} | |
image_bootloader() { | |
truncate -s100m image | |
mkfs.ext4 image | |
mkdir rootfs | |
loopdev="$(losetup --show -f image)" | |
uuid="$(blkid -s UUID -o value "${loopdev}")" | |
mount "${loopdev}" rootfs | |
mkdir rootfs/boot | |
cp vmlinuz initrd.gz rootfs/boot | |
grub-install --boot-directory rootfs/boot --force "${loopdev}" | |
cat <<EOF > rootfs/boot/grub/grub.cfg | |
linux /boot/vmlinuz root=UUID=$uuid $@ | |
initrd /boot/initrd.gz | |
boot | |
EOF | |
umount rootfs | |
rm -r rootfs | |
losetup -d "${loopdev}" | |
} | |
while ! DEBIAN_FRONTEND=noninteractive apt install -y debootstrap liblz4-tool curl cpio grub-pc; do | |
apt update | |
# don't loop multiple times | |
[ -z "${i:-}" ] && i=1 | |
done | |
rm -rf build | |
mkdir build | |
cd build | |
base | |
installer | |
local_bootloader "$@" | |
image_bootloader "$@" | |
lz4 image |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment