Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

twoliter: Embed generate-local-sbkeys script #122

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions twoliter/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn main() {
paths.copy_file("rpm2img");
paths.copy_file("rpm2kmodkit");
paths.copy_file("rpm2migrations");
paths.copy_file("generate-local-sbkeys");

// Create tarball in memory.
println!("Starting tarball creation at {:?}", SystemTime::now());
Expand Down
2 changes: 1 addition & 1 deletion twoliter/embedded/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ echo "No Secure Boot signing profile found in ${profile}." >&2
echo "Generating local keys." >&2

mkdir -p "${BUILDSYS_SBKEYS_PROFILE_DIR}"
${BUILDSYS_SBKEYS_DIR}/generate-local-sbkeys \
${TWOLITER_TOOLS_DIR}/generate-local-sbkeys \
--sdk-image "${TLPRIVATE_SDK_IMAGE}" \
--output-dir "${BUILDSYS_SBKEYS_PROFILE_DIR}"
'''
Expand Down
165 changes: 165 additions & 0 deletions twoliter/embedded/generate-local-sbkeys
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#!/usr/bin/env bash

# Helper script for running commands to generate Secure Boot files.

set -euo pipefail

usage() {
cat >&2 <<EOF
usage: ${0##*/} [--sdk-image SDK_IMAGE]
[--output-dir OUTPUT_DIR]

Generate Secure Boot related files. Local-only edition.

Options:
--sdk-image Name of the (optional) SDK image to use.
--output-dir Path where the files will be written.
--help shows this usage text
EOF
}

required_arg() {
local arg="${1:?}"
local value="${2}"
if [ -z "${value}" ]; then
echo "ERROR: ${arg} is required" >&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 <<EOF
Key-Type: RSA
Key-Length: 2048
Name-Real: Bottlerocket Config Signing Key
Expire-Date: 0
%no-protection
EOF

# Export the GPG key.
gpg --armor --export-secret-keys > 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}
6 changes: 0 additions & 6 deletions twoliter/src/cmd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,6 @@ impl BuildVariant {
// Create a sbkeys directory in the main project
debug!("sbkeys dir not found. Creating a temporary directory");
fs::create_dir_all(&sbkeys_dir)?;
sdk_container
.cp_out(
Path::new("twoliter/alpha/sbkeys/generate-local-sbkeys"),
&sbkeys_dir,
)
.await?;
};

// TODO: Remove once models is no longer conditionally compiled.
Expand Down