Skip to content

Commit

Permalink
Merge pull request #522 from flatcar/jepio/tpm-refactor
Browse files Browse the repository at this point in the history
qemu: extract swtpm
  • Loading branch information
jepio authored Apr 11, 2024
2 parents a262f21 + 613b6e6 commit 346be89
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 58 deletions.
1 change: 1 addition & 0 deletions cmd/kola/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ func init() {
sv(&kola.QEMUOptions.BIOSImage, "qemu-bios", "", "BIOS 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.")

// BrightBox specific options
sv(&kola.BrightboxOptions.ClientID, "brightbox-client-id", "", "Brightbox client ID")
Expand Down
58 changes: 2 additions & 56 deletions kola/tests/misc/tpm.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
package misc

import (
"fmt"
"os"
"strings"
"time"

"github.com/coreos/go-semver/semver"
"github.com/coreos/pkg/capnslog"
"github.com/flatcar/mantle/kola/cluster"
"github.com/flatcar/mantle/kola/register"
"github.com/flatcar/mantle/platform"
"github.com/flatcar/mantle/platform/conf"
"github.com/flatcar/mantle/platform/machine/qemu"
"github.com/flatcar/mantle/platform/machine/unprivqemu"
"github.com/flatcar/mantle/system/exec"
"github.com/flatcar/mantle/util"
)

const (
Expand Down Expand Up @@ -311,19 +305,14 @@ func init() {
}

func tpmTest(c cluster.TestCluster, userData *conf.UserData, mountpoint string, variant string) {
swtpm, err := startSwtpm()
if err != nil {
c.Fatalf("could not start software TPM emulation: %v", err)
}
defer swtpm.stop()

options := platform.MachineOptions{
AdditionalDisks: []platform.Disk{
{Size: "520M", DeviceOpts: []string{"serial=secondary"}},
},
SoftwareTPMSocket: swtpm.socketPath,
EnableTPM: true,
}
var m platform.Machine
var err error
switch pc := c.Cluster.(type) {
// These cases have to be separated because otherwise the golang compiler doesn't type-check
// the case bodies using the proper subtype of `pc`.
Expand Down Expand Up @@ -370,46 +359,3 @@ func tpmTest(c cluster.TestCluster, userData *conf.UserData, mountpoint string,
checkIfMountpointIsEncrypted(c, m, "/")
}
}

type softwareTPM struct {
process *exec.ExecCmd
socketPath string
dir string
}

func startSwtpm() (*softwareTPM, error) {
swtpm := &softwareTPM{}

swtpmDir, err := os.MkdirTemp("", "swtpm-")
if err != nil {
return nil, err
}
swtpm.dir = swtpmDir
swtpm.socketPath = fmt.Sprintf("%v/swtpm-sock", swtpm.dir)

swtpm.process = exec.Command("swtpm", "socket", "--tpmstate", fmt.Sprintf("dir=%v", swtpm.dir), "--ctrl", fmt.Sprintf("type=unixio,path=%v", swtpm.socketPath), "--tpm2")
out, err := swtpm.process.StdoutPipe()
if err != nil {
return nil, err
}
go util.LogFrom(capnslog.INFO, out)

if err = swtpm.process.Start(); err != nil {
return nil, err
}

plog.Debugf("swtpm PID: %v", swtpm.process.Pid())

return swtpm, nil
}

func (swtpm *softwareTPM) stop() {
if err := swtpm.process.Kill(); err != nil {
plog.Errorf("Error killing swtpm: %v", err)
}
// To be double sure that we do not delete the wrong directory, check that "tpm" occurs in the directory path we delete.
if strings.Contains(swtpm.dir, "tpm") {
plog.Debugf("Delete swtpm temporary directory %v", swtpm.dir)
os.RemoveAll(swtpm.dir)
}
}
51 changes: 51 additions & 0 deletions platform/local/tpm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package local

import (
"fmt"
"os"

"github.com/coreos/pkg/capnslog"
"github.com/flatcar/mantle/system/exec"
"github.com/flatcar/mantle/util"
)

type SoftwareTPM struct {
process *exec.ExecCmd
socketPath string
dir string
}

func NewSwtpm(dir string) (*SoftwareTPM, error) {
swtpm := &SoftwareTPM{}

os.Mkdir(dir, 0700)
swtpm.dir = dir
swtpm.socketPath = fmt.Sprintf("%v/sock", swtpm.dir)

swtpm.process = exec.Command("swtpm", "socket", "--tpmstate", fmt.Sprintf("dir=%v", swtpm.dir), "--ctrl", fmt.Sprintf("type=unixio,path=%v", swtpm.socketPath), "--tpm2")
out, err := swtpm.process.StderrPipe()
if err != nil {
return nil, err
}
go util.LogFrom(capnslog.INFO, out)

if err = swtpm.process.Start(); err != nil {
return nil, err
}

plog.Debugf("swtpm PID: %v", swtpm.process.Pid())

return swtpm, nil
}

func (swtpm *SoftwareTPM) Stop() {
if err := swtpm.process.Kill(); err != nil {
plog.Errorf("Error killing swtpm: %v", err)
}
plog.Debugf("Delete swtpm temporary directory %v", swtpm.dir)
os.RemoveAll(swtpm.dir)
}

func (swtpm *SoftwareTPM) SocketPath() string {
return swtpm.socketPath
}
20 changes: 20 additions & 0 deletions platform/machine/qemu/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ type Cluster struct {
func (qc *Cluster) NewMachine(userdata *conf.UserData) (platform.Machine, error) {
options := platform.MachineOptions{
ExtraPrimaryDiskSize: qc.flight.opts.ExtraBaseDiskSize,
// Use for 'kola spawn'; test cases should pass true through
// NewMachineWithOptions()
EnableTPM: qc.flight.opts.EnableTPM,
}
return qc.NewMachineWithOptions(userdata, options)
}
Expand Down Expand Up @@ -111,6 +114,20 @@ ExecStartPost=/usr/bin/ln -fs /run/metadata/flatcar /run/metadata/coreos
consolePath: filepath.Join(dir, "console.txt"),
}

var swtpm *local.SoftwareTPM
if options.EnableTPM {
swtpm, err = local.NewSwtpm(filepath.Join(dir, "tpm"))
if err != nil {
return nil, fmt.Errorf("starting swtpm: %v", err)
}
options.SoftwareTPMSocket = swtpm.SocketPath()
defer func() {
if swtpm != nil {
swtpm.Stop()
}
}()
}

qmCmd, extraFiles, err := platform.CreateQEMUCommand(qc.flight.opts.Board, qm.id, qc.flight.opts.BIOSImage, qm.consolePath, confPath, qc.flight.diskImagePath, conf.IsIgnition(), options)
if err != nil {
return nil, err
Expand Down Expand Up @@ -150,6 +167,9 @@ ExecStartPost=/usr/bin/ln -fs /run/metadata/flatcar /run/metadata/coreos
return nil, err
}

// from this point on Destroy() is responsible for cleaning up swtpm
qm.swtpm, swtpm = swtpm, nil

plog.Debugf("qemu PID (manual cleanup needed if --remove=false): %v", qm.qemu.Pid())

if err := platform.StartMachine(qm, qm.journal); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions platform/machine/qemu/flight.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type Options struct {

ExtraBaseDiskSize string

EnableTPM bool

*platform.Options
}

Expand Down
5 changes: 4 additions & 1 deletion platform/machine/qemu/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type machine struct {
journal *platform.Journal
consolePath string
console string
swtpm *local.SoftwareTPM
}

func (m *machine) ID() string {
Expand Down Expand Up @@ -70,7 +71,9 @@ func (m *machine) Destroy() {
if err := m.qemu.Kill(); err != nil {
plog.Errorf("Error killing instance %v: %v", m.ID(), err)
}

if m.swtpm != nil {
m.swtpm.Stop()
}
m.journal.Destroy()

if buf, err := ioutil.ReadFile(m.consolePath); err == nil {
Expand Down
3 changes: 2 additions & 1 deletion platform/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
type MachineOptions struct {
AdditionalDisks []Disk
ExtraPrimaryDiskSize string
EnableTPM bool
SoftwareTPMSocket string
}

Expand Down Expand Up @@ -348,7 +349,7 @@ func CreateQEMUCommand(board, uuid, biosImage, consolePath, confPath, diskImageP
"-device", "virtio-rng-pci,rng=rng0",
)

if options.SoftwareTPMSocket != "" {
if options.EnableTPM {
var tpm string
switch board {
case "amd64-usr":
Expand Down

0 comments on commit 346be89

Please sign in to comment.