mirror of
https://github.com/fscotto/infra.git
synced 2026-09-27 19:03:47 +00:00
* feat(aegis): add ARM image bootstrap workflow * feat(aegis): manage firewall and SSH hardening * feat(aegis): harden Fedora IoT services * chore(aegis): remove local TLS configuration * fix(aegis): restore supported Fedora IoT bootstrap
148 lines
3.3 KiB
Bash
Executable File
148 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
|
|
set -eu
|
|
|
|
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
|
|
BUTANE_IMAGE=${BUTANE_IMAGE:-quay.io/coreos/butane:release}
|
|
BUTANE_SOURCE=${BUTANE_SOURCE:-"$SCRIPT_DIR/aegis.bu"}
|
|
IGNITION_OUTPUT=${IGNITION_OUTPUT:-"$SCRIPT_DIR/config.ign"}
|
|
SSH_PUBLIC_KEY=${SSH_PUBLIC_KEY:-"$HOME/.ssh/id_ed25519.pub"}
|
|
WIFI_SECURITY=${WIFI_SECURITY:-wpa-psk}
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage:
|
|
generate-aegis-ign.sh
|
|
generate-aegis-ign.sh --write IMAGE DEVICE
|
|
|
|
Environment overrides:
|
|
BUTANE_IMAGE Butane container image (default: quay.io/coreos/butane:release)
|
|
BUTANE_SOURCE Butane source path (default: aegis.bu beside this script)
|
|
IGNITION_OUTPUT Ignition output path (default: config.ign beside this script)
|
|
SSH_PUBLIC_KEY SSH public key passed to arm-image-installer
|
|
WIFI_SSID Wi-Fi SSID; prompted if unset in --write mode
|
|
WIFI_PASS Wi-Fi password; prompted if unset in --write mode
|
|
WIFI_SECURITY Wi-Fi security type (default: wpa-psk)
|
|
USAGE
|
|
}
|
|
|
|
require_command() {
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
printf 'Error: required command not found: %s\n' "$1" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
read_required() {
|
|
prompt=$1
|
|
value=$2
|
|
|
|
if [ -z "$value" ]; then
|
|
printf '%s' "$prompt" >&2
|
|
IFS= read -r value
|
|
fi
|
|
|
|
if [ -z "$value" ]; then
|
|
printf '%s\n' 'Error: a value is required.' >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s' "$value"
|
|
}
|
|
|
|
read_secret() {
|
|
value=$1
|
|
|
|
if [ -z "$value" ]; then
|
|
printf '%s' 'Wi-Fi password: ' >&2
|
|
stty -echo
|
|
IFS= read -r value
|
|
stty echo
|
|
printf '\n' >&2
|
|
fi
|
|
|
|
if [ -z "$value" ]; then
|
|
printf '%s\n' 'Error: a value is required.' >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s' "$value"
|
|
}
|
|
|
|
write_image=false
|
|
case $# in
|
|
0)
|
|
;;
|
|
3)
|
|
if [ "$1" != '--write' ]; then
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
write_image=true
|
|
IMAGE=$2
|
|
DEVICE=$3
|
|
;;
|
|
*)
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
require_command podman
|
|
|
|
if [ ! -f "$BUTANE_SOURCE" ]; then
|
|
printf 'Error: Butane source not found: %s\n' "$BUTANE_SOURCE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
OUTPUT_DIR=$(dirname "$IGNITION_OUTPUT")
|
|
if [ ! -d "$OUTPUT_DIR" ]; then
|
|
printf 'Error: output directory not found: %s\n' "$OUTPUT_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
umask 077
|
|
TEMP_OUTPUT=$(mktemp "$OUTPUT_DIR/.config.ign.XXXXXX")
|
|
trap 'rm -f "$TEMP_OUTPUT"' EXIT HUP INT TERM
|
|
|
|
podman run --rm -i "$BUTANE_IMAGE" --strict < "$BUTANE_SOURCE" > "$TEMP_OUTPUT"
|
|
mv "$TEMP_OUTPUT" "$IGNITION_OUTPUT"
|
|
trap - EXIT HUP INT TERM
|
|
|
|
printf 'Generated Ignition config: %s\n' "$IGNITION_OUTPUT"
|
|
|
|
if [ "$write_image" = false ]; then
|
|
exit 0
|
|
fi
|
|
|
|
if [ ! -f "$IMAGE" ]; then
|
|
printf 'Error: image not found: %s\n' "$IMAGE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -b "$DEVICE" ]; then
|
|
printf 'Error: target is not a block device: %s\n' "$DEVICE" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$SSH_PUBLIC_KEY" ]; then
|
|
printf 'Error: SSH public key not found: %s\n' "$SSH_PUBLIC_KEY" >&2
|
|
exit 1
|
|
fi
|
|
|
|
require_command arm-image-installer
|
|
WIFI_SSID=$(read_required 'Wi-Fi SSID: ' "${WIFI_SSID:-}")
|
|
WIFI_PASS=$(read_secret "${WIFI_PASS:-}")
|
|
|
|
printf 'Writing %s to %s.\n' "$IMAGE" "$DEVICE" >&2
|
|
sudo arm-image-installer \
|
|
--image="$IMAGE" \
|
|
--target=rpi4 \
|
|
--media="$DEVICE" \
|
|
--ignition="$IGNITION_OUTPUT" \
|
|
--addkey="$SSH_PUBLIC_KEY" \
|
|
--resizefs \
|
|
--wifi-ssid="$WIFI_SSID" \
|
|
--wifi-pass="$WIFI_PASS" \
|
|
--wifi-security="$WIFI_SECURITY"
|