Add support for generating PCR configuration at image build time

We need to ship some PCR measurements alongside images in order to make it
easier for admins to provide an appropriate policy. Add some tooling to
generate the appropriate hashes during build, pack those into a zip file
and upload it.
This commit is contained in:
Matthew Garrett 2016-03-29 15:34:20 -07:00
parent c75583f2b8
commit 56aa7e5a17
5 changed files with 84 additions and 2 deletions

View File

@ -285,6 +285,9 @@ finish_image() {
local install_grub=0
local disk_img="${BUILD_DIR}/${image_name}"
local pcr_policy="${image_name%.bin}_pcr_policy.zip"
local pcr_dir="${BUILD_DIR}/pcrs"
mkdir -p "${pcr_dir}"
# Copy kernel to support dm-verity boots
sudo mkdir -p "${root_fs_dir}/boot/coreos"
@ -361,6 +364,7 @@ finish_image() {
"${root_fs_dir}/boot/coreos/vmlinuz-a"
fi
${BUILD_LIBRARY_DIR}/generate_kernel_hash.sh "${root_fs_dir}/boot/coreos/vmlinuz-a" ${COREOS_VERSION} >${pcr_dir}/kernel.config
rm -rf "${BUILD_DIR}"/configroot
cleanup_mounts "${root_fs_dir}"
trap - EXIT
@ -381,5 +385,9 @@ finish_image() {
--target="${target}" --disk_image="${disk_img}" --noverity
fi
done
${BUILD_LIBRARY_DIR}/generate_grub_hashes.py ${disk_img} /usr/lib/grub/ ${pcr_dir} ${COREOS_VERSION}
fi
pushd ${BUILD_DIR}
zip -r -9 $pcr_policy pcrs
popd
}

View File

@ -91,6 +91,7 @@ create_dev_image() {
local image_contents="${image_name%.bin}_contents.txt"
local image_packages="${image_name%.bin}_packages.txt"
local image_licenses="${image_name%.bin}_licenses.txt"
local image_pcr_policy="${image_name%.bin}_pcr_policy.zip"
start_image "${image_name}" "${disk_layout}" "${root_fs_dir}" "${update_group}"
@ -125,5 +126,6 @@ EOF
upload_image -d "${BUILD_DIR}/${image_name}.bz2.DIGESTS" \
"${BUILD_DIR}/${image_contents}" \
"${BUILD_DIR}/${image_packages}" \
"${BUILD_DIR}/${image_name}"
"${BUILD_DIR}/${image_name}" \
"${BUILD_DIR}/${image_pcr_policy}"
}

View File

@ -0,0 +1,57 @@
#!/usr/bin/python
import hashlib
import json
import os
import string
import subprocess
import sys
filename = sys.argv[1]
grubdir = sys.argv[2]
outputdir = sys.argv[3]
version = sys.argv[4]
bootoffset = string.atoi(subprocess.check_output(['cgpt', 'show', '-i', '2', '-b', filename])) * 512
with open(filename, "rb") as f:
boot = f.read(440)
f.seek(bootoffset)
diskboot = f.read(512)
corelen = bytearray(diskboot)[508] | bytearray(diskboot)[509] << 8
f.seek(bootoffset+512)
core = f.read(corelen * 512)
hashes = {"4": {"binaryvalues": [{"values": [{"value": hashlib.sha1(boot).hexdigest(), "description": "CoreOS Grub boot.img %s" % version}]}]},
"8": {"binaryvalues" : [{"values": [{"value": hashlib.sha1(diskboot).hexdigest(), "description": "CoreOS Grub diskboot.img %s" % version}]}]},
"9": {"binaryvalues": [{"values": [{"value": hashlib.sha1(core).hexdigest(), "description": "CoreOS Grub core.img %s" % version}]}]}}
with open(os.path.join(outputdir, "grub_loader.config"), "w") as f:
f.write(json.dumps(hashes, sort_keys=True))
hashvalues = []
for folder, subs, files in os.walk(grubdir):
for filename in files:
if filename.endswith(".mod"):
with open(os.path.join(folder, filename), "rb") as f:
mod = f.read()
value = hashlib.sha1(mod).hexdigest()
description = "CoreOS Grub %s %s" % (filename, version)
hashvalues.append({"value": value, "description": description})
with open(os.path.join(outputdir, "grub_modules.config"), "w") as f:
f.write(json.dumps({"9": {"binaryvalues": [{"prefix": "grub_module", "values": hashvalues}]}}))
with open(os.path.join(outputdir, "kernel_cmdline.config"), "w") as f:
f.write(json.dumps({"8": {"asciivalues": [{"prefix": "grub_kernel_cmdline", "values": [{"value": "rootflags=rw mount.usrflags=ro BOOT_IMAGE=/coreos/vmlinuz-[ab] mount.usr=PARTUUID=\S{36} rootflags=rw mount.usrflags=ro consoleblank=0 root=LABEL=ROOT (console=\S+)? (coreos.autologin=\S+)? verity.usrhash=\\S{64}", "description": "CoreOS kernel command line %s" % version}]}]}}))
commands = [{"value": '\[.*\]', "description": "CoreOS Grub configuration %s" % version},
{"value": 'gptprio.next -d usr -u usr_uuid', "description": "CoreOS Grub configuration %s" % version},
{"value": 'insmod all_video', "description": "CoreOS Grub configuration %s" % version},
{"value": 'linux /coreos/vmlinuz-[ab] rootflags=rw mount.usrflags=ro consoleblank=0 root=LABEL=ROOT (console=\S+)? (coreos.autologin=\S+)?', "description": "CoreOS Grub configuration %s" % version},
{"value": 'menuentry CoreOS \S+ --id=coreos\S* {', "description": "CoreOS Grub configuration %s" % version},
{"value": 'search --no-floppy --set first_boot --disk-uuid 00000000-0000-0000-0000-000000000001', "description": "CoreOS Grub configuration %s" % version},
{"value": 'search --no-floppy --set oem --part-label OEM --hint hd0,gpt1', "description": "CoreOS Grub configuration %s" % version},
{"value": 'set .+', "description": "CoreOS Grub configuration %s" % version},
{"value": 'setparams CoreOS default', "description": "CoreOS Grub configuration %s" % version},
{"value": 'source (hd0,gpt6)/grub.cfg', "description": "CoreOS Grub configuration %s" % version}]
with open(os.path.join(outputdir, "grub_commands.config"), "w") as f:
f.write(json.dumps({"8": {"asciivalues": [{"prefix": "grub_cmd", "values": commands}]}}))

View File

@ -0,0 +1,13 @@
#!/usr/bin/python
import hashlib
import json
import os
import sys
path=sys.argv[1]
version=sys.argv[2]
with open(path, "rb") as f:
kernel = f.read()
print json.dumps({"9": {"binaryvalues": [{"prefix": "grub_linux", "values": [{"value": hashlib.sha1(kernel).hexdigest(), "description": "coreos-%s" % version}]}]}})

View File

@ -66,6 +66,7 @@ create_prod_image() {
local image_contents="${image_name%.bin}_contents.txt"
local image_packages="${image_name%.bin}_packages.txt"
local image_licenses="${image_name%.bin}_licenses.txt"
local image_pcr_policy="${image_name%.bin}_pcr_policy.zip"
start_image "${image_name}" "${disk_layout}" "${root_fs_dir}" "${update_group}"
@ -111,5 +112,6 @@ EOF
upload_image -d "${BUILD_DIR}/${image_name}.bz2.DIGESTS" \
"${BUILD_DIR}/${image_contents}" \
"${BUILD_DIR}/${image_packages}" \
"${BUILD_DIR}/${image_name}"
"${BUILD_DIR}/${image_name}" \
"${BUILD_DIR}/${image_pcr_policy}"
}