Merge pull request #1754 from ogayot/kvm-test-tpm
kvm-test: support emulating a TPM 2.0
This commit is contained in:
commit
03e9a401b9
|
@ -13,13 +13,15 @@ import argparse
|
||||||
import contextlib
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
import crypt
|
import crypt
|
||||||
|
import dataclasses
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
import shlex
|
import shlex
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
from typing import List, Tuple
|
from typing import List, Optional, Tuple
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,6 +194,9 @@ parser.add_argument('--force-autoinstall', default=None,
|
||||||
parser.add_argument('--force-no-autoinstall', default=None,
|
parser.add_argument('--force-no-autoinstall', default=None,
|
||||||
action='store_false', dest="autoinstall",
|
action='store_false', dest="autoinstall",
|
||||||
help='do not pass autoinstall on the kernel command line')
|
help='do not pass autoinstall on the kernel command line')
|
||||||
|
parser.add_argument('--with-tpm2', action='store_true',
|
||||||
|
help='''emulate a TPM 2.0 interface (requires swtpm
|
||||||
|
package)''')
|
||||||
|
|
||||||
|
|
||||||
cc_group = parser.add_mutually_exclusive_group()
|
cc_group = parser.add_mutually_exclusive_group()
|
||||||
|
@ -419,6 +424,22 @@ def nets(ctx) -> List[str]:
|
||||||
return nics
|
return nics
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class TPMEmulator:
|
||||||
|
socket: pathlib.Path
|
||||||
|
logfile: pathlib.Path
|
||||||
|
tpmstate: pathlib.Path
|
||||||
|
|
||||||
|
|
||||||
|
def tpm(emulator: Optional[TPMEmulator]) -> List[str]:
|
||||||
|
if emulator is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return ['-chardev', f'socket,id=chrtpm,path={emulator.socket}',
|
||||||
|
'-tpmdev', 'emulator,id=tpm0,chardev=chrtpm',
|
||||||
|
'-device', 'tpm-tis,tpmdev=tpm0']
|
||||||
|
|
||||||
|
|
||||||
def bios(ctx):
|
def bios(ctx):
|
||||||
ret = []
|
ret = []
|
||||||
# https://help.ubuntu.com/community/UEFI
|
# https://help.ubuntu.com/community/UEFI
|
||||||
|
@ -431,7 +452,9 @@ def memory(ctx):
|
||||||
return ['-m', ctx.args.memory or ctx.default_mem]
|
return ['-m', ctx.args.memory or ctx.default_mem]
|
||||||
|
|
||||||
|
|
||||||
def kvm_common(ctx):
|
@contextlib.contextmanager
|
||||||
|
def kvm_prepare_common(ctx):
|
||||||
|
'''Spawn needed background processes and return the CLI options for QEMU'''
|
||||||
ret = ['kvm', '-no-reboot']
|
ret = ['kvm', '-no-reboot']
|
||||||
ret.extend(('-vga', 'virtio'))
|
ret.extend(('-vga', 'virtio'))
|
||||||
ret.extend(memory(ctx))
|
ret.extend(memory(ctx))
|
||||||
|
@ -439,7 +462,15 @@ def kvm_common(ctx):
|
||||||
ret.extend(nets(ctx))
|
ret.extend(nets(ctx))
|
||||||
if ctx.args.sound:
|
if ctx.args.sound:
|
||||||
ret.extend(('-device', 'AC97', '-device', 'usb-ehci'))
|
ret.extend(('-device', 'AC97', '-device', 'usb-ehci'))
|
||||||
return ret
|
|
||||||
|
if ctx.args.with_tpm2:
|
||||||
|
tpm_emulator_context = tpm_emulator()
|
||||||
|
else:
|
||||||
|
tpm_emulator_context = contextlib.nullcontext()
|
||||||
|
|
||||||
|
with tpm_emulator_context as tpm_emulator_cm:
|
||||||
|
ret.extend(tpm(tpm_emulator_cm))
|
||||||
|
yield ret
|
||||||
|
|
||||||
|
|
||||||
def get_initrd(mntdir):
|
def get_initrd(mntdir):
|
||||||
|
@ -463,7 +494,7 @@ def install(ctx):
|
||||||
os.mkdir(mntdir)
|
os.mkdir(mntdir)
|
||||||
appends = []
|
appends = []
|
||||||
|
|
||||||
kvm = kvm_common(ctx)
|
with kvm_prepare_common(ctx) as kvm:
|
||||||
|
|
||||||
if ctx.args.iso:
|
if ctx.args.iso:
|
||||||
iso = ctx.args.iso
|
iso = ctx.args.iso
|
||||||
|
@ -512,12 +543,38 @@ def install(ctx):
|
||||||
run(kvm)
|
run(kvm)
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def tpm_emulator(directory=None):
|
||||||
|
if directory is None:
|
||||||
|
directory_context = tempfile.TemporaryDirectory()
|
||||||
|
else:
|
||||||
|
directory_context = contextlib.nullcontext(enter_result=directory)
|
||||||
|
|
||||||
|
with directory_context as tempdir:
|
||||||
|
socket = os.path.join(tempdir, 'swtpm-sock')
|
||||||
|
logfile = os.path.join(tempdir, 'log')
|
||||||
|
tpmstate = tempdir
|
||||||
|
|
||||||
|
ps = subprocess.Popen(['swtpm', 'socket',
|
||||||
|
'--tpmstate', f'dir={tpmstate}',
|
||||||
|
'--ctrl', f'type=unixio,path={socket}',
|
||||||
|
'--tpm2',
|
||||||
|
'--log', f'file={logfile},level=20'],
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
yield TPMEmulator(socket=pathlib.Path(socket),
|
||||||
|
logfile=pathlib.Path(logfile),
|
||||||
|
tpmstate=pathlib.Path(tpmstate))
|
||||||
|
finally:
|
||||||
|
ps.communicate()
|
||||||
|
|
||||||
|
|
||||||
def boot(ctx):
|
def boot(ctx):
|
||||||
target = ctx.target
|
target = ctx.target
|
||||||
if ctx.args.img:
|
if ctx.args.img:
|
||||||
target = ctx.args.img
|
target = ctx.args.img
|
||||||
|
|
||||||
kvm = kvm_common(ctx)
|
with kvm_prepare_common(ctx) as kvm:
|
||||||
kvm.extend(drive(target))
|
kvm.extend(drive(target))
|
||||||
run(kvm)
|
run(kvm)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue