kvm-test: add --secure-boot option
Adds an option to configure the VM to load SecureBoot enabled firmware. SecureBoot is a feature of UEFI, which means --boot (for legacy BIOS boot) is incompatible with this flag. Providing both will result in an error. This will be useful for testing MOK enrollment behavior, as on reboot you can confirm if you are presented with mokmanager or regular first boot.
This commit is contained in:
parent
283cae41eb
commit
11027c55d6
|
@ -17,6 +17,7 @@ import dataclasses
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import shlex
|
import shlex
|
||||||
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
@ -99,6 +100,11 @@ class Context:
|
||||||
self.iso = f'/tmp/kvm-test/{self.release}-test.iso'
|
self.iso = f'/tmp/kvm-test/{self.release}-test.iso'
|
||||||
self.hostname = f'{self.release}-test'
|
self.hostname = f'{self.release}-test'
|
||||||
self.target = f'/tmp/kvm-test/{self.hostname}.img'
|
self.target = f'/tmp/kvm-test/{self.hostname}.img'
|
||||||
|
parent = pathlib.Path(self.target).parent
|
||||||
|
self.ovmf = {
|
||||||
|
'CODE': parent / f'{self.hostname}_OVMF_CODE_4M_ms.fd',
|
||||||
|
'VARS': parent / f'{self.hostname}_OVMF_VARS_4M_ms.fd'
|
||||||
|
}
|
||||||
self.password = salted_crypt('ubuntu')
|
self.password = salted_crypt('ubuntu')
|
||||||
self.cloudconfig = f'''\
|
self.cloudconfig = f'''\
|
||||||
#cloud-config
|
#cloud-config
|
||||||
|
@ -168,8 +174,13 @@ parser.add_argument('--basesnap', default=None, action='store',
|
||||||
help='use slimy-update-snap on this snap')
|
help='use slimy-update-snap on this snap')
|
||||||
parser.add_argument('--snap', default=None, action='store',
|
parser.add_argument('--snap', default=None, action='store',
|
||||||
help='inject this snap into the ISO')
|
help='inject this snap into the ISO')
|
||||||
parser.add_argument('-B', '--bios', action='store_true', default=False,
|
# Boot Options
|
||||||
|
boot_group = parser.add_mutually_exclusive_group()
|
||||||
|
boot_group.add_argument('-B', '--bios', action='store_true', default=False,
|
||||||
help='boot in BIOS mode (default mode is UEFI)')
|
help='boot in BIOS mode (default mode is UEFI)')
|
||||||
|
boot_group.add_argument('--secure-boot', action='store_true', default=False,
|
||||||
|
help='Use SecureBoot', dest="secureboot")
|
||||||
|
|
||||||
parser.add_argument('-c', '--channel', action='store',
|
parser.add_argument('-c', '--channel', action='store',
|
||||||
help='build iso with snap from channel')
|
help='build iso with snap from channel')
|
||||||
parser.add_argument('-d', '--disksize', help='size of disk to create')
|
parser.add_argument('-d', '--disksize', help='size of disk to create')
|
||||||
|
@ -473,11 +484,19 @@ def tpm(emulator: Optional[TPMEmulator]) -> List[str]:
|
||||||
|
|
||||||
|
|
||||||
def bios(ctx):
|
def bios(ctx):
|
||||||
ret = []
|
|
||||||
# https://help.ubuntu.com/community/UEFI
|
# https://help.ubuntu.com/community/UEFI
|
||||||
if not ctx.args.bios:
|
if ctx.args.bios:
|
||||||
ret = ['-bios', '/usr/share/qemu/OVMF.fd']
|
return []
|
||||||
return ret
|
elif ctx.args.secureboot:
|
||||||
|
# Speical setup for a secureboot virtual machine
|
||||||
|
# https://wiki.debian.org/SecureBoot/VirtualMachine
|
||||||
|
return ['-machine', 'q35,smm=on',
|
||||||
|
'-global', 'driver=cfi.pflash01,property=secure,value=on',
|
||||||
|
'-drive', f'if=pflash,format=raw,unit=0,file={ctx.ovmf["CODE"]}',
|
||||||
|
'-drive', f'if=pflash,format=raw,unit=1,file={ctx.ovmf["VARS"]}'
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
return ['-bios', '/usr/share/qemu/OVMF.fd']
|
||||||
|
|
||||||
|
|
||||||
def memory(ctx):
|
def memory(ctx):
|
||||||
|
@ -523,6 +542,14 @@ def install(ctx):
|
||||||
raise Exception('refusing to overwrite existing image, use the ' +
|
raise Exception('refusing to overwrite existing image, use the ' +
|
||||||
'-o option to allow overwriting')
|
'-o option to allow overwriting')
|
||||||
|
|
||||||
|
# Only copy the files with secureboot, always overwrite on install
|
||||||
|
if ctx.args.secureboot:
|
||||||
|
# We really don't *have* to copy the code over, but the code and vars
|
||||||
|
# are pairs and successfully reading from /usr/share/... directly
|
||||||
|
# depends on permissions
|
||||||
|
shutil.copy("/usr/share/OVMF/OVMF_CODE_4M.ms.fd", ctx.ovmf["CODE"])
|
||||||
|
shutil.copy("/usr/share/OVMF/OVMF_VARS_4M.ms.fd", ctx.ovmf["VARS"])
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory() as tempdir:
|
||||||
mntdir = f'{tempdir}/mnt'
|
mntdir = f'{tempdir}/mnt'
|
||||||
os.mkdir(mntdir)
|
os.mkdir(mntdir)
|
||||||
|
@ -618,6 +645,11 @@ def boot(ctx):
|
||||||
|
|
||||||
with kvm_prepare_common(ctx) as kvm:
|
with kvm_prepare_common(ctx) as kvm:
|
||||||
kvm.extend(drive(target))
|
kvm.extend(drive(target))
|
||||||
|
if ctx.args.secureboot:
|
||||||
|
if not ctx.ovmf["VARS"].exists():
|
||||||
|
raise Exception(f"Couldn't find firmware variables file {str(ctx.ovmf['VARS'])!r}")
|
||||||
|
if not ctx.ovmf["CODE"].exists():
|
||||||
|
raise Exception(f"Couldn't find firmware code file {str(ctx.ovmf['CODE'])!r}")
|
||||||
run(kvm)
|
run(kvm)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue