Skip to content

Instantly share code, notes, and snippets.

@hashbrowncipher
Created December 22, 2017 16:44
Show Gist options
  • Save hashbrowncipher/361f8cf8ccee6ce1fe617eb4f23089c3 to your computer and use it in GitHub Desktop.
Save hashbrowncipher/361f8cf8ccee6ce1fe617eb4f23089c3 to your computer and use it in GitHub Desktop.
builds a gof3r-based image installer
#!/bin/bash
set -x
set -o errexit
set -o nounset
set -o pipefail
readonly INITRD_DIR=initrd
base() {
debootstrap \
--include "openssh-server less vim-tiny python3-yaml" \
--variant=minbase \
xenial "${INITRD_DIR}"
cd "${INITRD_DIR}"
echo "deb http://archive.ubuntu.com/ubuntu xenial universe" >> etc/apt/sources.list
echo "deb http://archive.ubuntu.com/ubuntu xenial-security main" >> etc/apt/sources.list
head -n6 "../../${BASH_SOURCE}" > root/kernel.sh
cat >> root/kernel.sh <<EOF
cd /root
apt update
apt install liblz4-tool
apt download linux-image-4.13.0-21-generic
dpkg -x *.deb /
sed -ie 's/^root:\*:/root::/' /etc/shadow
EOF
chmod +x root/kernel.sh
chroot . /root/kernel.sh
cp boot/vmlinuz* ../vmlinuz
rm -rf -- \
boot/vmlinuz* \
etc/ssh/ssh_host_*_key* \
etc/hostname \
root/* \
var/lib/dpkg \
var/lib/apt \
var/log \
var/cache/apt \
var/lib/dpkg \
var/lib/apt/lists \
usr/share/doc \
usr/share/i18n \
usr/share/locale
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}"
tar -C usr/bin --strip-components=1 -xzvf "../${GOF3R_FILENAME}"
rm "../${GOF3R_FILENAME}"
cat > root/installer <<EOF
#!/usr/bin/python3
import http.client
import os
import subprocess
import yaml
def get_root():
with open('/proc/cmdline') as fh:
line = fh.readline.strip()
for entry in line.split(' ')
k, v = entry.split('=', 1)
if k == 'root':
return v
def fix_root(root):
if root.startswith('UUID='):
return '/dev/disk/by-uuid/' + root[5:]
return root
def get_source(user_data)
loaded = yaml.loads(user_data)
install_args = loaded['s3_installer']
bucket = install_args['bucket']
key = install_args['key']
return bucket, key
conn = http.client.HTTPSonnection("169.254.169.254")
conn.request("GET", "/latest/user-data")
resp = conn.getresponse()
assert resp.status == 200
user_data = resp.read()
bucket, key = get_source(user_data)
root = get_root()
assert root is not None
root = fix_root(root)
with open(root, 'wb') as dest:
lz4 = subprocess.Popen(['lz4', '-d'], stdout=dest, stdin=subprocess.PIPE)
gof3r = subprocess.Popen(["gof3r", "get", "-b", bucket, "-k", key], stdout=lz4.stdin)
lz4.stdin.close()
assert gof3r.wait() == 0
assert lz4.wait() == 0
os.execlp('shutdown', '-f')
EOF
chmod +x root/installer
cat >> etc/rc.local <<EOF
/root/installer > /var/log/installer.log 2>&1
EOF
cd ..
}
mkdir build
cd build
base
installer
cd "${INITRD_DIR}"
find . -print0 | cpio -o -H newc -R 0:0 --null | gzip > ../initrd.gz
cd ..
rm -r "${INITRD_DIR}"
mkdir boot
mv vmlinuz initrd.gz boot
truncate -s10g image
sgdisk -o image
sgdisk -n 1:2048:20971486 image
sgdisk -c 1:root
loopdev=$(losetup -s -f image)
$(grep "${loopdev}$" /proc/partitions | awk '{ print "mknod looped b", $1, $2 }')
mkfs.ext4 looped
mkdir rootfs
mount looped rootfs
mkdir rootfs/boot
cp vmlinuz initrd.gz rootfs/boot
losetup -d "${loopdev}"
umount rootfs
rm looped rootfs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment