Skip to content
Draft
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
7 changes: 7 additions & 0 deletions modules/build/common/snpguest/mkosi.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ LATEST_TAG="${SNPGUEST_TAG:-$(curl -s https://api.github.com/repos/virtee/snpgue
# Download and install into DESTDIR with correct permissions
curl -fsSL "https://github.com/virtee/snpguest/releases/download/${LATEST_TAG}/snpguest" \
| install -D -m 0755 /dev/stdin "${DESTDIR}/usr/local/bin/snpguest"

# Record which tag was actually installed. Unless SNPGUEST_TAG is set, the
# line above resolves "latest" at build time, so two builds of identical
# source can contain different tooling with nothing to say so. sev_verify
# reads this file and reports it, making each image self-describing.
printf '%s\n' "${LATEST_TAG}" \
| install -D -m 0644 /dev/stdin "${DESTDIR}/usr/local/share/sev-certify/snpguest-tag"
25 changes: 25 additions & 0 deletions sev_verify/cert_tests/c3_0/c3_0_0_0/attestation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,31 @@ def steps() -> list[BaseStep]:
host_dest="request.bin",
timeout=120,
),
# Capture the report a second way, through the kernel's vendor-neutral
# configfs-TSM interface, which returns the raw bytes without parsing
# them. This is diagnostic rather than a check: when the snpguest steps
# above fail because the report cannot be classified, they leave no
# artifact behind, and the report is then the one thing needed to find
# out why. Typed "info" so a kernel without configfs-TSM support costs
# nothing.
Step.for_guest(
name="Capture report via configfs-TSM",
type="info",
command=(
"D=/sys/kernel/config/tsm/report/sev_verify; "
"rmdir $D 2>/dev/null; mkdir $D || exit 1; "
"head -c 64 /dev/urandom > $D/inblob && cat $D/outblob > /tmp/tsm-report.bin; "
"rc=$?; rmdir $D 2>/dev/null; exit $rc"
),
timeout=60,
),
Step.for_guest_pull(
name="Pull configfs-TSM report",
type="info",
guest_src="/tmp/tsm-report.bin",
host_dest="tsm-report.bin",
timeout=120,
),
Step.for_host(
name="Fetch certificate chain from kds",
type="setup",
Expand Down
17 changes: 13 additions & 4 deletions sev_verify/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from datetime import datetime, timezone
from pathlib import Path

from .environment import detect_environment
from .os_info import update_environment_with_guest_os
from .environment import detect_environment, find_recent_report, summarize_report
from .os_info import update_environment_with_guest_info
from .models import (
CertificationDefinition,
CertificationResult,
Expand Down Expand Up @@ -407,7 +407,7 @@ def execute_test(
sr, new_launch = run_vm_launch_step(step, profile)
launch = new_launch
if launch is not None and launch.ok and environment is not None:
update_environment_with_guest_os(environment, launch.profile)
update_environment_with_guest_info(environment, launch.profile)
elif step.kind == "vm_stop":
if launch is None:
sr = StepResult(
Expand All @@ -433,7 +433,7 @@ def execute_test(
if launch is None:
launch = profile.vm_launch()
if launch.ok and environment is not None:
update_environment_with_guest_os(environment, launch.profile)
update_environment_with_guest_info(environment, launch.profile)
if not launch.ok:
sr = StepResult(
step=step,
Expand Down Expand Up @@ -711,6 +711,7 @@ def main(argv: list[str] | None = None) -> int:
print(f"Warning: no tests match level filter(s) {levels!r} "
f"in certification {cert.version}", file=sys.stderr)
continue
run_started = time.time()
cr = execute_certification(
cert,
guest_path,
Expand All @@ -720,6 +721,14 @@ def main(argv: list[str] | None = None) -> int:
environment=environment,
)
cert_results.append(cr)

# Describe a report this run produced, if any. Done here rather than in
# a test because it is environment, not a result: which report version
# and CPUID the firmware emitted determines how every consumer parses it.
if environment is not None and not environment.get("report_summary"):
report_path = find_recent_report(args.artifacts_dir, run_started)
if report_path is not None:
environment["report_summary"] = summarize_report(report_path)
total_tests += len(cr.test_results)
total_passed += sum(1 for tr in cr.test_results if tr.result == "pass")

Expand Down
Loading