Support secure boot.
This commit is contained in:
parent
0225d02114
commit
46c7e8c527
5 changed files with 59 additions and 46 deletions
|
|
@ -36,11 +36,11 @@
|
||||||
# Whether to provide a software TPM (defaults to false)
|
# Whether to provide a software TPM (defaults to false)
|
||||||
# "useTpm": false
|
# "useTpm": false
|
||||||
|
|
||||||
# How to boot:
|
# How to boot (see https://github.com/mnlipp/VM-Operator/blob/main/org.jdrupes.vmoperator.runner.qemu/resources/org/jdrupes/vmoperator/runner/qemu/defaults.yaml):
|
||||||
# * bios
|
# * bios
|
||||||
# * uefi
|
# * uefi[-4m]
|
||||||
# * secure
|
# * secure[-4m]
|
||||||
# "bootMode": "uefi"
|
# "firmware": "uefi"
|
||||||
|
|
||||||
# When terminating, a graceful powerdown is attempted. If it
|
# When terminating, a graceful powerdown is attempted. If it
|
||||||
# doesn't succeed within the given timeout (seconds) SIGTERM
|
# doesn't succeed within the given timeout (seconds) SIGTERM
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,33 @@
|
||||||
# Candidate paths for code and templates for firmware rom and flash
|
# Candidate paths for code and templates for firmware rom and vars
|
||||||
"firmware":
|
"firmware":
|
||||||
"rom":
|
"bios":
|
||||||
- "/usr/share/OVMF/OVMF_CODE.fd"
|
"rom": []
|
||||||
- "/usr/share/edk2/x64/OVMF_CODE.fd"
|
"vars": []
|
||||||
"flash":
|
"uefi":
|
||||||
- "/usr/share/edk2/ovmf/OVMF_VARS.fd"
|
"rom":
|
||||||
- "/usr/share/edk2/x64/OVMF_CODE.fd"
|
- "/usr/share/edk2/ovmf/OVMF_CODE.fd"
|
||||||
|
- "/usr/share/edk2/x64/OVMF_CODE.fd"
|
||||||
|
"vars":
|
||||||
|
- "/usr/share/edk2/ovmf/OVMF_VARS.fd"
|
||||||
|
- "/usr/share/edk2/x64/OVMF_VARS.fd"
|
||||||
|
"uefi-4m":
|
||||||
|
"rom":
|
||||||
|
- "/usr/share/edk2/ovmf-4m/OVMF_CODE.fd"
|
||||||
|
- "/usr/share/edk2/x64/OVMF_CODE.4m.fd"
|
||||||
|
"vars":
|
||||||
|
- "/usr/share/edk2/ovmf-4m/OVMF_VARS.fd"
|
||||||
|
- "/usr/share/edk2/x64/OVMF_VARS.4m.fd"
|
||||||
"secure":
|
"secure":
|
||||||
"flash":
|
"rom":
|
||||||
- "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd"
|
- "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd"
|
||||||
- "/usr/share/edk2/x64/OVMF_CODE.secboot.fd"
|
- "/usr/share/edk2/x64/OVMF_CODE.secboot.fd"
|
||||||
|
"vars":
|
||||||
|
- "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd"
|
||||||
|
- "/usr/share/edk2/x64/OVMF_VARS.fd"
|
||||||
|
"secure-4m":
|
||||||
|
"rom":
|
||||||
|
- "/usr/share/edk2/ovmf-4m/OVMF_CODE.secboot.fd"
|
||||||
|
- "/usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd"
|
||||||
|
"vars":
|
||||||
|
- "/usr/share/edk2/ovmf-4m/OVMF_CODE.secboot.fd"
|
||||||
|
- "/usr/share/edk2/x64/OVMF_VARS.4m.fd"
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,6 @@ class Configuration implements Dto {
|
||||||
@SuppressWarnings("PMD.FieldNamingConventions")
|
@SuppressWarnings("PMD.FieldNamingConventions")
|
||||||
protected final Logger logger = Logger.getLogger(getClass().getName());
|
protected final Logger logger = Logger.getLogger(getClass().getName());
|
||||||
|
|
||||||
public static final Object BOOT_MODE_UEFI = "uefi";
|
|
||||||
public static final Object BOOT_MODE_SECURE = "secure";
|
|
||||||
|
|
||||||
public String dataDir;
|
public String dataDir;
|
||||||
public String runtimeDir;
|
public String runtimeDir;
|
||||||
public String template;
|
public String template;
|
||||||
|
|
@ -44,7 +41,7 @@ class Configuration implements Dto {
|
||||||
public Path swtpmSocket;
|
public Path swtpmSocket;
|
||||||
public Path monitorSocket;
|
public Path monitorSocket;
|
||||||
public Path firmwareRom;
|
public Path firmwareRom;
|
||||||
public Path firmwareFlash;
|
public Path firmwareVars;
|
||||||
@SuppressWarnings("PMD.ShortVariable")
|
@SuppressWarnings("PMD.ShortVariable")
|
||||||
public Vm vm;
|
public Vm vm;
|
||||||
|
|
||||||
|
|
@ -56,7 +53,7 @@ class Configuration implements Dto {
|
||||||
public String name;
|
public String name;
|
||||||
public String uuid;
|
public String uuid;
|
||||||
public boolean useTpm;
|
public boolean useTpm;
|
||||||
public String bootMode = "uefi";
|
public String firmware = "uefi";
|
||||||
public String maximumRam;
|
public String maximumRam;
|
||||||
public String currentRam;
|
public String currentRam;
|
||||||
public String cpuModel = "host";
|
public String cpuModel = "host";
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,6 @@ import org.apache.commons.cli.CommandLineParser;
|
||||||
import org.apache.commons.cli.DefaultParser;
|
import org.apache.commons.cli.DefaultParser;
|
||||||
import org.apache.commons.cli.Option;
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import static org.jdrupes.vmoperator.runner.qemu.Configuration.BOOT_MODE_SECURE;
|
|
||||||
import static org.jdrupes.vmoperator.runner.qemu.Configuration.BOOT_MODE_UEFI;
|
|
||||||
import org.jdrupes.vmoperator.runner.qemu.StateController.State;
|
import org.jdrupes.vmoperator.runner.qemu.StateController.State;
|
||||||
import org.jdrupes.vmoperator.util.ExtendedObjectWrapper;
|
import org.jdrupes.vmoperator.util.ExtendedObjectWrapper;
|
||||||
import org.jgrapes.core.Channel;
|
import org.jgrapes.core.Channel;
|
||||||
|
|
@ -151,7 +149,7 @@ public class Runner extends Component {
|
||||||
private static final String DEFAULT_TEMPLATE
|
private static final String DEFAULT_TEMPLATE
|
||||||
= "Standard-VM-latest.ftl.yaml";
|
= "Standard-VM-latest.ftl.yaml";
|
||||||
private static final String SAVED_TEMPLATE = "VM.ftl.yaml";
|
private static final String SAVED_TEMPLATE = "VM.ftl.yaml";
|
||||||
private static final String FW_FLASH = "fw-flash.fd";
|
private static final String FW_VARS = "fw-vars.fd";
|
||||||
|
|
||||||
private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
|
private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
|
||||||
private final JsonNode defaults;
|
private final JsonNode defaults;
|
||||||
|
|
@ -255,8 +253,9 @@ public class Runner extends Component {
|
||||||
@SuppressWarnings({ "PMD.CognitiveComplexity",
|
@SuppressWarnings({ "PMD.CognitiveComplexity",
|
||||||
"PMD.DataflowAnomalyAnalysis" })
|
"PMD.DataflowAnomalyAnalysis" })
|
||||||
private void setFirmwarePaths() throws IOException {
|
private void setFirmwarePaths() throws IOException {
|
||||||
|
JsonNode firmware = defaults.path("firmware").path(config.vm.firmware);
|
||||||
// Get file for firmware ROM
|
// Get file for firmware ROM
|
||||||
JsonNode codePaths = defaults.path("firmware").path("rom");
|
JsonNode codePaths = firmware.path("rom");
|
||||||
for (var p : codePaths) {
|
for (var p : codePaths) {
|
||||||
var path = Path.of(p.asText());
|
var path = Path.of(p.asText());
|
||||||
if (Files.exists(path)) {
|
if (Files.exists(path)) {
|
||||||
|
|
@ -264,24 +263,14 @@ public class Runner extends Component {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get file for firmware flash, if necessary
|
// Get file for firmware vars, if necessary
|
||||||
config.firmwareFlash = Path.of(config.dataDir, FW_FLASH);
|
config.firmwareVars = Path.of(config.dataDir, FW_VARS);
|
||||||
if (!Files.exists(config.firmwareFlash)) {
|
if (!Files.exists(config.firmwareVars)) {
|
||||||
JsonNode srcPaths = null;
|
for (var p : firmware.path("vars")) {
|
||||||
if (BOOT_MODE_UEFI.equals(config.vm.bootMode)) {
|
var path = Path.of(p.asText());
|
||||||
srcPaths = defaults.path("firmware").path("flash");
|
if (Files.exists(path)) {
|
||||||
} else if (BOOT_MODE_SECURE.equals(config.vm.bootMode)) {
|
Files.copy(path, config.firmwareVars);
|
||||||
srcPaths = defaults.path("firmware")
|
break;
|
||||||
.path("secure").path("flash");
|
|
||||||
}
|
|
||||||
// If UEFI boot, srcPaths != null
|
|
||||||
if (srcPaths != null) {
|
|
||||||
for (var p : srcPaths) {
|
|
||||||
var path = Path.of(p.asText());
|
|
||||||
if (Files.exists(path)) {
|
|
||||||
Files.copy(path, config.firmwareFlash);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -304,8 +293,10 @@ public class Runner extends Component {
|
||||||
// Configure data model
|
// Configure data model
|
||||||
var model = new HashMap<String, Object>();
|
var model = new HashMap<String, Object>();
|
||||||
model.put("runtimeDir", config.runtimeDir);
|
model.put("runtimeDir", config.runtimeDir);
|
||||||
model.put("firmwareRom", config.firmwareRom.toString());
|
model.put("firmwareRom", Optional.ofNullable(config.firmwareRom)
|
||||||
model.put("firmwareFlash", config.firmwareFlash.toString());
|
.map(Object::toString).orElse(null));
|
||||||
|
model.put("firmwareVars", Optional.ofNullable(config.firmwareVars)
|
||||||
|
.map(Object::toString).orElse(null));
|
||||||
model.put("vm", config.vm);
|
model.put("vm", config.vm);
|
||||||
|
|
||||||
// Combine template and data and parse result
|
// Combine template and data and parse result
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@
|
||||||
# For smm=on see https://scumjr.github.io/2016/01/04/playing-with-smm-and-qemu/.
|
# For smm=on see https://scumjr.github.io/2016/01/04/playing-with-smm-and-qemu/.
|
||||||
# Configure ROM/EEPROM for UEFI.
|
# Configure ROM/EEPROM for UEFI.
|
||||||
- [ "-machine", "pc-q35-7.0,usb=off,vmport=off,dump-guest-core=off\
|
- [ "-machine", "pc-q35-7.0,usb=off,vmport=off,dump-guest-core=off\
|
||||||
<#if vm.bootMode == "secure">,smm=on</#if>\
|
<#if vm.firmware?starts_with("secure")>,smm=on</#if>\
|
||||||
<#if vm.bootMode != "bios">,pflash0=fw-rom-device\
|
<#if firmwareRom??>,pflash0=fw-rom-device\
|
||||||
,pflash1=fw-eeprom-device</#if>,memory-backend=pc.ram,hpet=off" ]
|
,pflash1=fw-eeprom-device</#if>,memory-backend=pc.ram,hpet=off" ]
|
||||||
# * https://bugzilla.redhat.com/show_bug.cgi?id=1170533, may be unnecessary
|
# * https://bugzilla.redhat.com/show_bug.cgi?id=1170533, may be unnecessary
|
||||||
- [ "-global", "ICH9-LPC.disable_s3=1" ]
|
- [ "-global", "ICH9-LPC.disable_s3=1" ]
|
||||||
|
|
@ -54,17 +54,21 @@
|
||||||
# -global driver=cfi.pflash01,property=secure,value=on
|
# -global driver=cfi.pflash01,property=secure,value=on
|
||||||
# -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/local/qemu/master-key.aes"}'
|
# -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/local/qemu/master-key.aes"}'
|
||||||
# {{- end }}
|
# {{- end }}
|
||||||
<#if vm.bootMode != "bios">
|
<#if firmwareRom??>
|
||||||
# * Provide ROM/EEPROM devices (instead of built-in BIOS)
|
# * Provide ROM/EEPROM devices (instead of built-in BIOS)
|
||||||
- [ "-blockdev", "node-name=fw-rom-file,driver=file,cache.direct=on,\
|
- [ "-blockdev", "node-name=fw-rom-file,driver=file,cache.direct=on,\
|
||||||
filename=${ firmwareRom },auto-read-only=true,discard=unmap" ]
|
filename=${ firmwareRom },auto-read-only=true,discard=unmap" ]
|
||||||
- [ "-blockdev", "node-name=fw-rom-device,driver=raw,\
|
- [ "-blockdev", "node-name=fw-rom-device,driver=raw,\
|
||||||
read-only=true,file=fw-rom-file" ]
|
read-only=true,file=fw-rom-file" ]
|
||||||
- [ "-blockdev", "node-name=fw-eeprom-file,driver=file,cache.direct=on,\
|
- [ "-blockdev", "node-name=fw-eeprom-file,driver=file,cache.direct=on,\
|
||||||
filename=${ firmwareFlash },auto-read-only=true,discard=unmap" ]
|
filename=${ firmwareVars },auto-read-only=true,discard=unmap" ]
|
||||||
- [ "-blockdev", "node-name=fw-eeprom-device,driver=raw,\
|
- [ "-blockdev", "node-name=fw-eeprom-device,driver=raw,\
|
||||||
read-only=false,file=fw-eeprom-file" ]
|
read-only=false,file=fw-eeprom-file" ]
|
||||||
</#if>
|
</#if>
|
||||||
|
# https://wiki.debian.org/SecureBoot/VirtualMachine
|
||||||
|
<#if vm.firmware?starts_with("secure")>
|
||||||
|
- [ "-global", "driver=cfi.pflash01,property=secure,value=on" ]
|
||||||
|
</#if>
|
||||||
# * Provide RAM
|
# * Provide RAM
|
||||||
- [ "-object", "memory-backend-ram,id=pc.ram,\
|
- [ "-object", "memory-backend-ram,id=pc.ram,\
|
||||||
size=${ vm.maximumRam!"1G" }" ]
|
size=${ vm.maximumRam!"1G" }" ]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue