Skip to content

Commit

Permalink
add tests for libtdx_attest (#240)
Browse files Browse the repository at this point in the history
* add tests for libtdx_attest

* add test in checkbox
  • Loading branch information
hector-cao authored Oct 7, 2024
1 parent 198137e commit 7ee64c0
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 6 deletions.
12 changes: 12 additions & 0 deletions tests/checkbox/checkbox-provider-tdx/units/tests/jobs.pxu
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ command:
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
setup-env-and-run test_guest_ita.py

id: tdx-guest/td-libtdx-attest
category_id: tdx-guest
flags: simple
_summary: Test guest libtdx_attest
depends:
after:
requires:
executable.name == 'qemu-system-x86_64'
command:
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH
setup-env-and-run test_guest_tdxattest.py

id: tdx-guest/td-guest-reboot
category_id: tdx-guest
flags: simple
Expand Down
30 changes: 28 additions & 2 deletions tests/lib/Qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,21 @@ class QemuMachineType:
Qemu_Machine_Params = {
QemuEfiMachine.OVMF_Q35:['-machine', 'q35,kernel_irqchip=split'],
QemuEfiMachine.OVMF_Q35_TDX:[
'-object', 'tdx-guest,id=tdx',
'-machine', 'q35,kernel_irqchip=split,confidential-guest-support=tdx']
}
def __init__(self, machine = QemuEfiMachine.OVMF_Q35_TDX):
self.machine = machine
self.quote_sock = False
def enable_quote_socket(self):
self.quote_sock = True
def args(self):
return self.Qemu_Machine_Params[self.machine]
qemu_args = self.Qemu_Machine_Params[self.machine]
if self.machine == QemuEfiMachine.OVMF_Q35_TDX:
tdx_object = {'qom-type':'tdx-guest', 'id':'tdx'}
if self.quote_sock:
tdx_object.update({'quote-generation-socket':{'type': 'vsock', 'cid':'2','port':'4050'}})
qemu_args = ['-object', str(tdx_object)] + qemu_args
return qemu_args

class QemuBootType:
def __init__(self,
Expand Down Expand Up @@ -417,7 +425,25 @@ def rsync_file(self, fname, dest, sudo=False):
shell=True,
stdout=subprocess.DEVNULL)

def exec_command(self, cmd):
"""
Exec a command without checking the return code
Returns a triple:
- ret (return code)
- stdout
- stderr
"""
_, stdout, stderr = self.ssh_conn.exec_command(cmd)
ret_status = stdout.channel.recv_exit_status()
return ret_status, stdout, stderr

def check_exec(self, cmd, err_msg=None):
"""
Exec a command and check the return code
Returns a 2-tuple:
- stdout
- stderr
"""
_, stdout, stderr = self.ssh_conn.exec_command(cmd)
if err_msg==None:
err_msg=f'Execution of {cmd} failed'
Expand Down
7 changes: 3 additions & 4 deletions tests/tests/test_guest_ita.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,11 @@ def change_qgsd_state(state):


def run_trust_authority():
object = '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "vsock", "cid":"2","port":"4050"}}'
Qemu.QemuMachineType.Qemu_Machine_Params[Qemu.QemuEfiMachine.OVMF_Q35_TDX][1] = object

quote_str = ""
with Qemu.QemuMachine() as qm:
qm.qcmd.add_vsock(3)
machine = qm.qcmd.plugins['machine']
machine.enable_quote_socket()

qm.run()

ssh = Qemu.QemuSSH(qm)
Expand Down
123 changes: 123 additions & 0 deletions tests/tests/test_guest_tdxattest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env python3
#
# Copyright 2024 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
#

import random
import string

import Qemu

# This file contains tests for the tdxattest lib in the guest
# The tdxattest library allows application to request a quote from the
# host system
# This request can be done through 2 channels:
# - vsock : the application connects directly to the QGSD service in the host
# - configfs tsm : the application use configsf tsm to ask the guest kernel
# to contact the QGSD service for the quote generation

def test_guest_tdxattest_tsm():
"""
TDX attest library
Success when only TSM is available
vsock support is disabled by removing the configuration file and not enabling
the vsock support in QEMU command line
"""
with Qemu.QemuMachine() as qm:
machine = qm.qcmd.plugins['machine']
machine.enable_quote_socket()

qm.run()
ssh = Qemu.QemuSSH(qm)

ssh.check_exec('rm -f /etc/tdx-attest.conf')
stdout, _ = ssh.check_exec('/usr/share/doc/libtdx-attest-dev/examples/test_tdx_attest')

assert 'Successfully get the TD Quote' in stdout.read().decode()

def test_guest_tdxattest_tsm_failure():
"""
TDX attest library
Failure if we force the lib to use TSM but QEMU does not have the
quote generation socket specified.
"""
with Qemu.QemuMachine() as qm:
qm.run()
ssh = Qemu.QemuSSH(qm)

ssh.check_exec('rm -f /etc/tdx-attest.conf')

ret, stdout, stderr = ssh.exec_command('/usr/share/doc/libtdx-attest-dev/examples/test_tdx_attest')
assert (ret != 0) and ('Failed to get the quote' in stderr.read().decode())

def test_guest_tdxattest_vsock():
"""
TDX attest library
Success when only vsock is available
ConfigFs TSM is disabled
"""
with Qemu.QemuMachine() as qm:
qm.qcmd.add_vsock(10)

qm.run()
ssh = Qemu.QemuSSH(qm)

disable_tsm(ssh)

stdout, _ = ssh.check_exec('/usr/share/doc/libtdx-attest-dev/examples/test_tdx_attest')

assert 'Successfully get the TD Quote' in stdout.read().decode()

def test_guest_tdxattest_vsock_failure():
"""
TDX attest library
Failure if we force the lib to use vsock and QEMU does not have the
vsock arguments specified
"""
with Qemu.QemuMachine() as qm:
qm.run()
ssh = Qemu.QemuSSH(qm)

disable_tsm(ssh)

ret, stdout, stderr = ssh.exec_command('/usr/share/doc/libtdx-attest-dev/examples/test_tdx_attest')
assert (ret != 0) and ('Failed to get the quote' in stderr.read().decode())

def test_guest_tdxattest_failure():
"""
TDX attest library
Fail when vsock and TSM are both disabled
"""
with Qemu.QemuMachine() as qm:
qm.run()
ssh = Qemu.QemuSSH(qm)

disable_tsm(ssh)
ssh.check_exec('rm -f /etc/tdx-attest.conf')

ret, stdout, stderr = ssh.exec_command('/usr/share/doc/libtdx-attest-dev/examples/test_tdx_attest')

assert (ret != 0) and ('Failed to get the quote' in stderr.read().decode())

def disable_tsm(ssh):
"""
Disable the configfs tsm
There is no official way to disable the configfs tsm functionality
but we can simulate configfs tsm errors by bind mounting an empty folder
on top of the tsm folder.
"""
tmp_folder_name=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(4))
ssh.check_exec(f'mkdir -p /tmp/{tmp_folder_name}')
ssh.check_exec(f'mount --bind /tmp/{tmp_folder_name} /sys/kernel/config/tsm/report/')

0 comments on commit 7ee64c0

Please sign in to comment.