Skip to content
Merged
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
117 changes: 72 additions & 45 deletions src/cmd-osbuild
Original file line number Diff line number Diff line change
Expand Up @@ -77,51 +77,73 @@ json.dump(j, sys.stdout, indent=4)
# For qemu-secex we need to do a few extra things like spin up a
# VM to run genprotimg and save off the pubkey for Ignition.
postprocess_qemu_secex() {
if [ ! -f "${genprotimgvm}" ]; then
fatal "No genprotimgvm provided at ${genprotimgvm}"
fi

# Basic qemu args:
qemu_args=(); blk_size="512"
[[ $platform == metal4k ]] && blk_size="4096"
qemu_args+=("-drive" "if=none,id=target,format=qcow2,file=${imgpath},cache=unsafe" \
"-device" "virtio-blk,serial=target,drive=target,physical_block_size=${blk_size},logical_block_size=${blk_size}")

# SecureVM (holding Universal Key for all IBM Z Mainframes) requires scripts to execute genprotimg
se_script_dir="/usr/lib/coreos-assembler/secex-genprotimgvm-scripts"
genprotimg_img="${PWD}/secex-genprotimg.img"
genprotimg_dir=$(mktemp -p "${tmp_builddir}" -d)
cp "${se_script_dir}/genprotimg-script.sh" "${se_script_dir}/post-script.sh" "${genprotimg_dir}"
# Extra kargs with dm-verity hashes
secex_kargs="ignition.firstboot"
secex_kargs+=" rootfs.roothash=$(<"${outdir}/${platform}/rootfs_hash")"
secex_kargs+=" bootfs.roothash=$(<"${outdir}/${platform}/bootfs_hash")"
echo "${secex_kargs}" > "${genprotimg_dir}/parmfile"
virt-make-fs --format=raw --type=ext4 "${genprotimg_dir}" "${genprotimg_img}"
rm -rf "${genprotimg_dir}"
qemu_args+=("-drive" "if=none,id=genprotimg,format=raw,file=${genprotimg_img}" \
"-device" "virtio-blk,serial=genprotimg,drive=genprotimg")

# GPG keys used for protecting Ignition config
tmp_gpg_home=$(mktemp -p "${tmp_builddir}" -d)
ignition_pubkey=$(mktemp -p "${tmp_builddir}")
ignition_prikey=$(mktemp -p "${tmp_builddir}")
gpg --homedir "${tmp_gpg_home}" --batch --passphrase '' --yes --quick-gen-key "Secure Execution (secex) ${build}" rsa4096 encr none
gpg --homedir "${tmp_gpg_home}" --armor --export secex > "${ignition_pubkey}"
gpg --homedir "${tmp_gpg_home}" --armor --export-secret-key secex > "${ignition_prikey}"
exec 9<"${ignition_prikey}"
rm -rf "${tmp_gpg_home}" "${ignition_prikey}"
qemu_args+=("-add-fd" "fd=9,set=3" "-drive" "if=none,id=gpgkey,format=raw,file=/dev/fdset/3,readonly=on" \
"-device" "virtio-blk,serial=gpgkey,drive=gpgkey")

/usr/lib/coreos-assembler/secex-genprotimgvm-scripts/runvm.sh \
--genprotimgvm "${genprotimgvm}" -- "${qemu_args[@]}"
rm -f "${genprotimg_img}"
exec 9>&-

# Now store the generated ${ignition_pubkey} in the builddir and meta.json
gpg_key_filename="${name}-${build}-ignition-secex-key.gpg.pub"
postprocess_artifact "ignition-gpg-key" "${ignition_pubkey}" "${gpg_key_filename}" 'True'
if [ ! -f "${genprotimgvm}" ]; then
echo "No genprotimgvm provided"
genprotimgvm="${workdir}/tmp/fake-secure-vm.qcow2"
if [ -f "${genprotimgvm}" ]; then
echo "Found locally generated ${genprotimgvm}, skipping generation"
else
if [ ! -f "${hostkey}" ]; then
fatal "No hostkey and no genprotimgvm provided"
fi
echo "Injecting user-provided hostkey into config"
ignition_cfg=$(mktemp -p "${tmp_builddir}")
butane_cfg=$(mktemp -p "${tmp_builddir}")
hostkey_name=$(basename "${hostkey}")
hostkey_path=$(dirname "${hostkey}")
cp /usr/lib/coreos-assembler/secex-genprotimgvm-scripts/genprotimg.bu "${butane_cfg}"
sed -i 's/HOSTKEY-FILE/'"${hostkey_name}"'/g' "${butane_cfg}"
butane -p -d "${hostkey_path}" "${butane_cfg}" -o "${ignition_cfg}"

cp "/srv/builds/latest/${basearch}/${name}-${build}-qemu.${basearch}.${suffix}" "${genprotimgvm}"
chmod +w "${genprotimgvm}"
genvm_args=("-drive" "if=none,id=hda,format=qcow2,file=${genprotimgvm},auto-read-only=off,cache=unsafe" \
"-device" "virtio-blk,drive=hda,bootindex=1")
kola qemuexec -i "${ignition_cfg}" -- "${genvm_args[@]}"
fi
fi

# Basic qemu args:
qemu_args=(); blk_size="512"
[[ $platform == metal4k ]] && blk_size="4096"
qemu_args+=("-drive" "if=none,id=target,format=qcow2,file=${imgpath},cache=unsafe" \
"-device" "virtio-blk,serial=target,drive=target,physical_block_size=${blk_size},logical_block_size=${blk_size}")

# SecureVM (holding Universal Key for all IBM Z Mainframes) requires scripts to execute genprotimg
se_script_dir="/usr/lib/coreos-assembler/secex-genprotimgvm-scripts"
genprotimg_img="${PWD}/secex-genprotimg.img"
genprotimg_dir=$(mktemp -p "${tmp_builddir}" -d)
cp "${se_script_dir}/genprotimg-script.sh" "${se_script_dir}/post-script.sh" "${genprotimg_dir}"
# Extra kargs with dm-verity hashes
secex_kargs="ignition.firstboot"
secex_kargs+=" rootfs.roothash=$(<"${outdir}/${platform}/rootfs_hash")"
secex_kargs+=" bootfs.roothash=$(<"${outdir}/${platform}/bootfs_hash")"
echo "${secex_kargs}" > "${genprotimg_dir}/parmfile"
virt-make-fs --format=raw --type=ext4 "${genprotimg_dir}" "${genprotimg_img}"
rm -rf "${genprotimg_dir}"
qemu_args+=("-drive" "if=none,id=genprotimg,format=raw,file=${genprotimg_img}" \
"-device" "virtio-blk,serial=genprotimg,drive=genprotimg")

# GPG keys used for protecting Ignition config
tmp_gpg_home=$(mktemp -p "${tmp_builddir}" -d)
ignition_pubkey=$(mktemp -p "${tmp_builddir}")
ignition_prikey=$(mktemp -p "${tmp_builddir}")
gpg --homedir "${tmp_gpg_home}" --batch --passphrase '' --yes --quick-gen-key "Secure Execution (secex) ${build}" rsa4096 encr none
gpg --homedir "${tmp_gpg_home}" --armor --export secex > "${ignition_pubkey}"
gpg --homedir "${tmp_gpg_home}" --armor --export-secret-key secex > "${ignition_prikey}"
exec 9<"${ignition_prikey}"
rm -rf "${tmp_gpg_home}" "${ignition_prikey}"
qemu_args+=("-add-fd" "fd=9,set=3" "-drive" "if=none,id=gpgkey,format=raw,file=/dev/fdset/3,readonly=on" \
"-device" "virtio-blk,serial=gpgkey,drive=gpgkey")

/usr/lib/coreos-assembler/secex-genprotimgvm-scripts/runvm.sh \
--genprotimgvm "${genprotimgvm}" -- "${qemu_args[@]}"
rm -f "${genprotimg_img}"
exec 9>&-

# Now store the generated ${ignition_pubkey} in the builddir and meta.json
gpg_key_filename="${name}-${build}-ignition-secex-key.gpg.pub"
postprocess_artifact "ignition-gpg-key" "${ignition_pubkey}" "${gpg_key_filename}" 'True'
}

# Here we generate the input JSON we pass to runvm_osbuild for all of our image builds
Expand Down Expand Up @@ -207,6 +229,7 @@ EOF
main() {
# Set Some Defaults
genprotimgvm=/data.secex/genprotimgvm.qcow2
hostkey=/srv/secex-hostkey
build=
force=

Expand Down Expand Up @@ -244,6 +267,10 @@ main() {
genprotimgvm="$2"
shift
;;
--hostkey)
hostkey="$2"
shift
;;
--platforms)
shift # The arg is next in position args
# Split the comma separated string of platforms into an array
Expand Down
62 changes: 43 additions & 19 deletions src/secex-genprotimgvm-scripts/genprotimg.bu
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ version: 1.5.0
passwd:
users:
- name: core
ssh_authorized_keys_local:
- id_rsa.pub
groups:
- wheel
storage:
Expand All @@ -15,14 +13,14 @@ storage:
- path: /etc/se-hostkeys/ibm-z-hostkey-1
overwrite: true
contents:
local: secex-hostkey
- path: /etc/do_genprotimg
local: HOSTKEY-FILE
- path: /usr/local/bin/do_genprotimg
overwrite: true
mode: 0755
contents:
inline: |
#!/bin/bash
set -euo pipefail
set -xeuo pipefail
trap "rm -f /var/genprotimg/signal.file" EXIT
bash /var/build/genprotimg-script.sh &
while [ ! -e "/var/genprotimg/signal.file" ]; do
Expand All @@ -31,6 +29,34 @@ storage:
genprotimg -V --no-verify -i /var/genprotimg/vmlinuz -r /var/genprotimg/initrd.img -p /var/genprotimg/parmfile -k /etc/se-hostkeys/ibm-z-hostkey-1 -o /var/genprotimg/se.img
rm -f /var/genprotimg/signal.file
bash /var/build/post-script.sh
- path: /etc/systemd/system-generators/coreos-genprotimg-generator
overwrite: true
mode: 0755
contents:
inline: |
#!/bin/bash
export PATH="/usr/bin:/usr/sbin:${PATH}"
set -euo pipefail
. /usr/lib/coreos/generator-lib.sh
if [ ! -z $(karg ignition.firstboot) ]; then
exit 0
fi
mkdir -p "${UNIT_DIR}/default.target.wants"

cat > "${UNIT_DIR}"/var-build.mount << 'EOF'
# generated by coreos-genprotimg-generator
# Mounts partition with parmfile, pre- and post- scripts used by genprotimg.service
[Unit]
Description=Genprotimg partition mount
Requires=dev-disk-by\x2did-virtio\x2dgenprotimg.device
After=dev-disk-by\x2did-virtio\x2dgenprotimg.device
[Mount]
What=/dev/disk/by-id/virtio-genprotimg
Where=/var/build
Type=ext4
Options=rw,noatime
EOF
ln -sf "../var-build.mount" "${UNIT_DIR}/default.target.wants/"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional/wondering:

I'm guessing it wouldn't work to put this unit also in the systemd section of the butane along with genprotimg.service, but with both of them enabled false and then here we just

Suggested change
ln -sf "../var-build.mount" "${UNIT_DIR}/default.target.wants/"
ln -sf "../var-build.mount" "${UNIT_DIR}/default.target.wants/"
ln -sf "../genprotimg.service "${UNIT_DIR}/default.target.wants/"

and thats pretty much all the generator does.

systemd:
units:
- name: [email protected]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to delete this if you want.. in my earlier code review comment I was just saying that if we do delete it lets put it in a separate commit with a reason even if that reason is "make it more like the ubuntu VM that is used to generate secex artifacts".

Expand All @@ -48,28 +74,26 @@ systemd:
enabled: true
contents: |
[Unit]
Description=GenProtImg
Description=Creates sdboot image on 'se' labeled partition of qemu-secex qcow2 image
ConditionKernelCommandLine=!ignition.firstboot
After=var-build.mount
[Service]
Type=oneshot
StandardOutput=journal+console
ExecStart=/etc/do_genprotimg
ExecStopPost=/sbin/halt
ExecStart=/usr/local/bin/do_genprotimg
ExecStartPost=/usr/bin/systemctl --no-block poweroff
[Install]
WantedBy=default.target
- name: var-build.mount
- name: autohalt.service
enabled: true
contents: |
[Unit]
Description=Mounts genprotimg build partition
ConditionKernelCommandLine=!ignition.firstboot
Requires=dev-disk-by\x2did-virtio\x2dgenprotimg.device
After=dev-disk-by\x2did-virtio\x2dgenprotimg.device
[Mount]
What=/dev/disk/by-id/virtio-genprotimg
Where=/var/build
Type=ext4
Options=rw,noatime
Description=Halts system on firstboot
ConditionKernelCommandLine=ignition.firstboot
After=multi-user.target
[Service]
Type=oneshot
ExecStartPre=/bin/echo "Shutting down"
ExecStart=/usr/bin/systemctl --no-block poweroff
[Install]
WantedBy=default.target
WantedBy=multi-user.target
Loading