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

kola: Add secureboot CI test #547

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion build
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ cross_build() {
echo "Building $a/$1"
mkdir -p "bin/$a"
CGO_ENABLED=0 GOARCH=$a \
go build -mod=vendor -ldflags "${ldflags}" \
go build -mod=vendor -ldflags "${ldflags}" -gcflags="all=-N -l" \
-o "bin/$a/$1" "${REPO_PATH}/cmd/$1"
done
}
Expand Down
10 changes: 6 additions & 4 deletions cmd/kola/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var (
"rhcos": "v3",
}

kolaDefaultBIOS = map[string]string{
kolaDefaultFirmware = map[string]string{
"amd64-usr": "bios-256k.bin",
"arm64-usr": sdk.BuildRoot() + "/images/arm64-usr/latest/flatcar_production_qemu_uefi_efi_code.fd",
}
Expand Down Expand Up @@ -87,6 +87,7 @@ func init() {
sv(&kola.UpdatePayloadFile, "update-payload", "", "Path to an update payload that should be made available to tests")
bv(&kola.ForceFlatcarKey, "force-flatcar-key", false, "Use the Flatcar production key to verify update payload")
sv(&kola.Options.IgnitionVersion, "ignition-version", "", "Ignition version override: v2, v3")
bv(&kola.Options.EnableSecureboot, "enable-secureboot", false, "Instantiate a Secureboot Machine")
iv(&kola.Options.SSHRetries, "ssh-retries", kolaSSHRetries, "Number of retries with the SSH timeout when starting the machine")
dv(&kola.Options.SSHTimeout, "ssh-timeout", kolaSSHTimeout, "A timeout for a single try of establishing an SSH connection when starting the machine")

Expand Down Expand Up @@ -222,8 +223,9 @@ func init() {
// QEMU-specific options
sv(&kola.QEMUOptions.Board, "board", defaultTargetBoard, "target board")
sv(&kola.QEMUOptions.DiskImage, "qemu-image", "", "path to CoreOS disk image")
sv(&kola.QEMUOptions.BIOSImage, "qemu-bios", "", "BIOS to use for QEMU vm")
sv(&kola.QEMUOptions.Firmware, "qemu-firmware", "", "firmware image to use for QEMU vm")
sv(&kola.QEMUOptions.VNC, "qemu-vnc", "", "VNC port (0 for 5900, 1 for 5901, etc.)")
sv(&kola.QEMUOptions.OVMFVars, "qemu-ovmf-vars", "", "OVMF vars file to use for QEMU vm")
bv(&kola.QEMUOptions.UseVanillaImage, "qemu-skip-mangle", false, "don't modify CL disk image to capture console log")
sv(&kola.QEMUOptions.ExtraBaseDiskSize, "qemu-grow-base-disk-by", "", "grow base disk by the given size in bytes, following optional 1024-based suffixes are allowed: b (ignored), k, K, M, G, T")
bv(&kola.QEMUOptions.EnableTPM, "qemu-tpm", false, "enable TPM device in QEMU. Requires installing swtpm. Use only with 'kola spawn', test cases are responsible for creating a VM with TPM explicitly.")
Expand Down Expand Up @@ -303,8 +305,8 @@ func syncOptions() error {
kola.QEMUOptions.DiskImage = image
}

if kola.QEMUOptions.BIOSImage == "" {
kola.QEMUOptions.BIOSImage = kolaDefaultBIOS[kola.QEMUOptions.Board]
if kola.QEMUOptions.Firmware == "" {
kola.QEMUOptions.Firmware = kolaDefaultFirmware[kola.QEMUOptions.Board]
}
units, _ := root.PersistentFlags().GetStringSlice("debug-systemd-units")
for _, unit := range units {
Expand Down
10 changes: 7 additions & 3 deletions platform/machine/qemu/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,15 @@ ExecStartPost=/usr/bin/ln -fs /run/metadata/flatcar /run/metadata/coreos

// This uses path arguments with path values being
// relative to the folder created for this machine
biosImage, err := filepath.Abs(qc.flight.opts.BIOSImage)
firmware, err := filepath.Abs(qc.flight.opts.Firmware)
if err != nil {
return nil, fmt.Errorf("failed to canonicalize bios path: %v", err)
return nil, fmt.Errorf("failed to canonicalize firmware path: %v", err)
}
qmCmd, extraFiles, err := platform.CreateQEMUCommand(qc.flight.opts.Board, qm.id, biosImage, qm.consolePath, confPath, qc.flight.diskImagePath, conf.IsIgnition(), options)
ovmfVars, err := filepath.Abs(qc.flight.opts.OVMFVars)
if err != nil {
return nil, fmt.Errorf("failed to canonicalize ovmf vars path: %v", err)
}
qmCmd, extraFiles, err := platform.CreateQEMUCommand(qc.flight.opts.Board, qm.id, firmware, ovmfVars, qm.consolePath, confPath, qc.flight.diskImagePath, qc.flight.opts.EnableSecureboot, conf.IsIgnition(), options)
if err != nil {
return nil, err
}
Expand Down
7 changes: 5 additions & 2 deletions platform/machine/qemu/flight.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ type Options struct {
// DiskImage is the full path to the disk image to boot in QEMU.
DiskImage string

// BIOSImage is name of the BIOS file to pass to QEMU.
// Firmware is name of the Firmware file to pass to QEMU.
// It can be a plain name, or a full path.
BIOSImage string
Firmware string

// OMVF Vars file to pass to QEMU UEFI
OVMFVars string

// Don't modify CL disk images to add console logging
UseVanillaImage bool
Expand Down
10 changes: 7 additions & 3 deletions platform/machine/unprivqemu/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,15 @@ LinkLocalAddressing=no
}
// This uses path arguments with path values being
// relative to the folder created for this machine
biosImage, err := filepath.Abs(qc.flight.opts.BIOSImage)
firmware, err := filepath.Abs(qc.flight.opts.Firmware)
if err != nil {
return nil, fmt.Errorf("failed to canonicalize bios path: %v", err)
return nil, fmt.Errorf("failed to canonicalize firmware path: %v", err)
}
qmCmd, extraFiles, err := platform.CreateQEMUCommand(qc.flight.opts.Board, qm.id, biosImage, qm.consolePath, confPath, qc.flight.diskImagePath, conf.IsIgnition(), options)
ovmfVars, err := filepath.Abs(qc.flight.opts.OVMFVars)
if err != nil {
return nil, fmt.Errorf("failed to canonicalize ovmf vars path: %v", err)
}
qmCmd, extraFiles, err := platform.CreateQEMUCommand(qc.flight.opts.Board, qm.id, firmware, ovmfVars, qm.consolePath, confPath, qc.flight.diskImagePath, qc.flight.opts.EnableSecureboot, conf.IsIgnition(), options)
if err != nil {
return nil, err
}
Expand Down
3 changes: 3 additions & 0 deletions platform/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ type Options struct {
// Board is the board used by the image
Board string

// Toggle to instantiate a secureboot instance.
EnableSecureboot bool

// How many times to retry establishing an SSH connection when
// creating a journal or when doing a machine check.
SSHRetries int
Expand Down
44 changes: 40 additions & 4 deletions platform/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ package platform
import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
origExec "os/exec"
"path/filepath"
"regexp"
"runtime"
"slices"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -293,7 +295,7 @@ func mkpath(basedir string) (string, error) {
return f.Name(), nil
}

func CreateQEMUCommand(board, uuid, biosImage, consolePath, confPath, diskImagePath string, isIgnition bool, options MachineOptions) ([]string, []*os.File, error) {
func CreateQEMUCommand(board, uuid, firmware, ovmfVars, consolePath, confPath, diskImagePath string, enableSecureboot, isIgnition bool, options MachineOptions) ([]string, []*os.File, error) {
var qmCmd []string

// As we expand this list of supported native + board
Expand All @@ -307,7 +309,7 @@ func CreateQEMUCommand(board, uuid, biosImage, consolePath, confPath, diskImageP
qmBinary = "qemu-system-x86_64"
qmCmd = []string{
"qemu-system-x86_64",
"-machine", "accel=kvm",
"-machine", "q35,accel=kvm,smm=on",
"-cpu", "host",
"-m", "2512",
}
Expand Down Expand Up @@ -340,16 +342,45 @@ func CreateQEMUCommand(board, uuid, biosImage, consolePath, confPath, diskImageP
}

qmCmd = append(qmCmd,
"-bios", biosImage,
"-smp", "4",
"-uuid", uuid,
"-display", "none",
"-chardev", "file,id=log,path="+consolePath,
"-serial", "chardev:log",
"-object", "rng-random,filename=/dev/urandom,id=rng0",
"-device", "virtio-rng-pci,rng=rng0",
"-drive", fmt.Sprintf("if=pflash,unit=0,file=%v,format=raw,readonly=on", firmware),
)

if enableSecureboot == true {
// Create a copy of the OVMF Vars
ovmfVarsSrc, err := os.Open(ovmfVars)
if err != nil {
return nil, nil, err
}
defer ovmfVarsSrc.Close()

ovmfVarsCopy, err := ioutil.TempFile("/var/tmp/", "mantle-qemu")
if err != nil {
return nil, nil, err
}

if _, err := io.Copy(ovmfVarsCopy, ovmfVarsSrc); err != nil {
return nil, nil, err
}

_, err = ovmfVarsCopy.Seek(0, 0)
if err != nil {
return nil, nil, err
}

qmCmd = append(qmCmd,
"-global", "ICH9-LPC.disable_s3=1",
"-global", "driver=cfi.pflash01,property=secure,value=on",
"-drive", fmt.Sprintf("if=pflash,unit=1,file=%v,format=raw", ovmfVarsCopy.Name()),
)
}

if options.EnableTPM {
var tpm string
switch board {
Expand Down Expand Up @@ -413,6 +444,11 @@ func CreateQEMUCommand(board, uuid, biosImage, consolePath, confPath, diskImageP
fdset := 1

for _, disk := range allDisks {
bootIndexArg := ""
if slices.Contains(disk.DeviceOpts, "serial=primary-disk") {
bootIndexArg = ",bootindex=1"
}

optionsDiskFile, err := disk.setupFile()
if err != nil {
return nil, nil, err
Expand All @@ -423,7 +459,7 @@ func CreateQEMUCommand(board, uuid, biosImage, consolePath, confPath, diskImageP
id := fmt.Sprintf("d%d", fdnum)
qmCmd = append(qmCmd, "-add-fd", fmt.Sprintf("fd=%d,set=%d", fdnum, fdset),
"-drive", fmt.Sprintf("if=none,id=%s,format=qcow2,file=/dev/fdset/%d%s", id, fdset, autoReadOnly),
"-device", Virtio(board, "blk", fmt.Sprintf("drive=%s%s", id, disk.getOpts())))
"-device", Virtio(board, "blk", fmt.Sprintf("drive=%s%s%s", id, disk.getOpts(), bootIndexArg)))
fdnum += 1
fdset += 1
}
Expand Down