#!/usr/bin/env bash # Helper script for running commands to generate Secure Boot files. set -euo pipefail usage() { cat >&2 <&2 exit 2 fi } parse_args() { while [ ${#} -gt 0 ] ; do case "${1}" in --help ) usage; exit 0 ;; --sdk-image ) shift; SDK_IMAGE="${1}" ;; --output-dir ) shift; OUTPUT_DIR="${1}" ;; *) ;; esac shift done # Required arguments required_arg "--output-dir" "${OUTPUT_DIR:-}" } parse_args "${@}" # Create the output directory with the current user, rather than letting Docker # create it as a root-owned directory. mkdir -p "${OUTPUT_DIR}" # To avoid needing separate scripts to parse args and launch the SDK container, # the logic to generate the profile is found below the separator. Copy that to # a temporary file so it can be executed using the desired method. PRELUDE_END=$(awk '/=\^\.\.\^=/ { print NR+1; exit 0; }' "${0}") SBKEYS_SCRIPT="$(mktemp)" cleanup() { rm -f "${SBKEYS_SCRIPT}" } trap 'cleanup' EXIT tail -n +"${PRELUDE_END}" "${0}" >"${SBKEYS_SCRIPT}" chmod +x "${SBKEYS_SCRIPT}" if [ -n "${SDK_IMAGE:-}" ] ; then docker run -a stdin -a stdout -a stderr --rm \ --user "$(id -u):$(id -g)" \ --security-opt label:disable \ -v "${OUTPUT_DIR}":"${OUTPUT_DIR}" \ -v "${SBKEYS_SCRIPT}":"${SBKEYS_SCRIPT}" \ -e OUTPUT_DIR="${OUTPUT_DIR}" \ "${SDK_IMAGE}" bash "${SBKEYS_SCRIPT}" else export OUTPUT_DIR bash "${SBKEYS_SCRIPT}" fi exit # =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= set -euo pipefail WORKDIR="$(mktemp -d)" cd "${WORKDIR}" cleanup() { rm -rf "${WORKDIR}" } trap 'cleanup' EXIT genca() { local ca cn ca="${1:?}" cn="${2:?}" openssl req -newkey rsa:2048 \ -batch -noenc -new -x509 -sha256 -days 3650 \ -subj "/CN=${cn}/" \ -keyout "${ca}.key" -out "${ca}.crt" } genkey() { local ca key cn ca="${1:?}" key="${2:?}" cn="${3:?}" openssl genrsa -verbose \ -out "${key}.key" 2048 openssl req -new \ -key "${key}.key" \ -subj "/CN=${cn}/" \ -out "${key}.csr" openssl req \ -in "${key}.csr" \ -CA "${ca}.crt" -CAkey "${ca}.key" \ -config /dev/null \ -days 3650 -x509 -sha256 -copy_extensions none \ -addext "basicConstraints=CA:FALSE" \ -addext "extendedKeyUsage=codeSigning,1.3.6.1.4.1.311.10.3.6" \ -out "${key}.crt" } # Generate local EFI CAs and signing keys. genca PK "Bottlerocket Secure Boot Platform CA" genca KEK "Bottlerocket Secure Boot Key Exchange CA" genca db "Bottlerocket Secure Boot Database CA" genca vendor "Bottlerocket Secure Boot Vendor CA" genkey db shim-sign "Bottlerocket Shim Signing Key" genkey vendor code-sign "Bottlerocket Code Signing Key" # Generate GPG key for signing grub.cfg. export GNUPGHOME="${WORKDIR}" gpg --gen-key --batch < config-sign.key # Generate EFI vars for use with EC2 or others. GUID="$(uuidgen --random)" virt-fw-vars \ --set-pk "${GUID}" PK.crt \ --add-kek "${GUID}" KEK.crt \ --add-db "${GUID}" db.crt \ --secure-boot \ --output-json "efi-vars.json" virt-fw-vars \ --set-json "efi-vars.json" \ --output-aws "efi-vars.aws" # Copy all expected files out. cp -t "${OUTPUT_DIR}" \ PK.{key,crt} \ KEK.{key,crt} \ db.{key,crt} \ vendor.{key,crt} \ shim-sign.{key,crt} \ code-sign.{key,crt} \ config-sign.key \ efi-vars.{aws,json}