Skip to content
Open
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
33 changes: 19 additions & 14 deletions qemu/deps/sev-snp/regular_attestation_workflow.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#!/bin/bash
set -e

check_status() {
if [ $? -ne 0 ]; then
echo "Error: $1"
exit 1
fi
}

# Check for the required CPU model parameter
if [[ -z "$1" ]]; then
Expand Down Expand Up @@ -30,23 +36,22 @@ fetch_retry() {

# Verify regular attestation workflow on snp guest
snpguest report attestation-report.bin request-data.txt --random
if [[ ! -f attestation-report.bin ]]; then
echo "Error: attestation-report.bin not created."
exit 1
fi
snpguest display report attestation-report.bin

check_status "Error: Failed display attestation-report."

# Fetch cert
set +e
fetch_retry "snpguest fetch ca pem ${cpu_model} ./ -e vcek"
if [[ $? -ne 0 ]]; then
echo "ok"
exit 1
fi
fetch_retry "snpguest fetch ca -e vcek pem ./ ${cpu_model}"
check_status "Error: Failed to fetch CA certificate."

fetch_retry "snpguest fetch vcek pem ${cpu_model} ./ attestation-report.bin"
if [[ $? -ne 0 ]]; then
exit 1
fi
fetch_retry "snpguest fetch vcek -p ${cpu_model} pem ./ attestation-report.bin"
check_status "Error: Failed to fetch VCEK certificate."

# Verify certs
set -e
snpguest verify certs ./
snpguest verify attestation ./ attestation-report.bin
check_status "Error: Failed to verify certificates."
snpguest verify attestation -p ${cpu_model} ./ attestation-report.bin
check_status "Error: Failed to verify attestation."
150 changes: 150 additions & 0 deletions qemu/deps/sev-snp/snpguest_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#!/bin/bash

check_status() {
if [ $? -ne 0 ]; then
echo "Error: $1"
exit 1
fi
}

usage() {
echo "Usage: $0 [--repo <repository_url>] [--branch <branch_name> | --tag <tag_name>]"
echo " --repo : Git repository URL (default: https://github.com/virtee/snpguest.git)"
echo " --branch : Branch name to checkout (default: main)"
echo " --tag : Tag name to checkout"
echo "Note: --branch and --tag are mutually exclusive."
exit 1
}

trap 'echo "Cleaning up..."; rm -rf snpguest; exit 1' ERR

REPO_URL="https://github.com/virtee/snpguest.git"
BRANCH="main"
TAG=""
while [[ $# -gt 0 ]]; do
case "$1" in
--repo)
REPO_URL="$2"
shift 2
;;
--branch)
[ -n "$TAG" ] && { echo "Error: Cannot specify both --branch and --tag"; usage; }
BRANCH="$2"
shift 2
;;
--tag)
[ -n "$BRANCH" ] && [ "$BRANCH" != "main" ] && { echo "Error: Cannot specify both --branch and --tag"; usage; }
TAG="$2"
BRANCH=""
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1"
usage
;;
esac
done

sudo -n true 2>/dev/null || { echo "Error: sudo privileges required"; exit 1; }

echo "Validating repository: $REPO_URL..."
git ls-remote "$REPO_URL" >/dev/null 2>&1
check_status "Invalid or inaccessible repository: $REPO_URL"

if [ -n "$TAG" ]; then
echo "Validating tag: $TAG..."
git ls-remote --tags "$REPO_URL" | grep -q "refs/tags/$TAG$"
check_status "Tag '$TAG' does not exist in repository"
elif [ -n "$BRANCH" ]; then
echo "Validating branch: $BRANCH..."
git ls-remote --heads "$REPO_URL" | grep -q "refs/heads/$BRANCH$"
check_status "Branch '$BRANCH' does not exist in repository"
fi

echo "Installing build essentials..."

if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
else
echo "Cannot detect operating system."
exit 1
fi

case "$OS" in
ubuntu|debian)
sudo apt update
check_status "Failed to update package lists"
sudo apt install -y build-essential git curl
check_status "Failed to install build-essential"
;;
rhel|centos|fedora|rocky|almalinux)
sudo yum groupinstall -y "Development Tools"
check_status "Failed to install Development Tools"
sudo yum install -y curl git
check_status "Failed to install dependencies like curl/git"
;;
*)
echo "Unsupported operating system: $OS"
exit 1
;;
esac

echo "Prerequisites installed successfully."

echo "Installing Rust..."
if command -v rustc >/dev/null 2>&1; then
echo "Rust is already installed. Skipping installation."
else
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
check_status "Failed to install Rust"
fi

if [ -f "$HOME/.cargo/env" ]; then
. "$HOME/.cargo/env"
else
echo "Error: Rust environment file not found"
exit 1
fi

rustc --version
check_status "Rust installation verification failed"
echo "Rust installed successfully."

echo "Cloning snpguest repository from $REPO_URL"
if [ -d snpguest ]
then
echo "Removing previous snpguest directory"
rm -rf snpguest
fi
git clone "$REPO_URL" snpguest
check_status "Failed to clone snpguest repository"
[ -d "snpguest" ] || { echo "Error: snpguest directory not found"; exit 1; }
cd snpguest

if [ -n "$TAG" ]; then
echo "Checking out tag: $TAG..."
git checkout "tags/$TAG"
check_status "Failed to checkout tag $TAG"
elif [ -n "$BRANCH" ]; then
echo "Checking out branch: $BRANCH..."
git checkout "$BRANCH"
check_status "Failed to checkout branch $BRANCH"
fi

echo "Building snpguest..."
cargo build --release
check_status "Failed to build snpguest"

[ -w /usr/local/bin ] || { echo "Error: /usr/local/bin is not writable"; exit 1; }
cp "$PWD/target/release/snpguest" /usr/local/bin
check_status "Failed to copy snpguest to /usr/local/bin"

snpguest --version
check_status "snpguest installation verification failed"
echo "snpguest installed successfully."

exit 0
43 changes: 43 additions & 0 deletions qemu/tests/cfg/snp_attestation.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
- snp_attestation:
type = snp_basic_config
only Linux
kill_vm = yes
login_timeout = 240
start_vm = no
image_snapshot = yes
mem = 8192
smp = 8
required_qemu = [9.1.0, )
vm_secure_guest_type = snp
vm_sev_reduced_phys_bits = 1
vm_sev_cbitpos = 51
virtio_dev_disable_legacy = on
vm_mem_backend = memory-backend-memfd
bios_path = /usr/share/edk2/ovmf/OVMF.amdsev.fd
snp_module_path = "/sys/module/kvm_amd/parameters/sev_snp"
module_status = Y y 1
snp_guest_check = "journalctl|grep -i -w snp"
guest_tool_install = "dnf install -y snpguest"
snpguest_sourcebuild = 1
attestation_script = regular_attestation_workflow.sh
snpguest_install_script = snpguest_install.sh
guest_dir = /home
guest_cmd = ${guest_dir}/${attestation_script}
host_script = sev-snp/${attestation_script}
snpguest_buildcmd = "${guest_dir}/${snpguest_install_script} --repo https://github.com/virtee/snpguest.git --tag v0.9.1"
snpguest_build_location = sev-snp/${snpguest_install_script}
variants:
- policy_default:
snp_policy = 196608
vm_secure_guest_object_options = "policy=${snp_policy}"
- policy_debug:
snp_policy = 720896
vm_secure_guest_object_options = "policy=${snp_policy}"
- policy_singlesocket:
socket_count_cmd = 'lscpu |grep Socket|head -1 | cut -d ":" -f 2 | tr -d " "'
snp_policy = 1245184
vm_secure_guest_object_options = "policy=${snp_policy}"
- policy_singlesocket_debug:
socket_count_cmd = 'lscpu |grep Socket|head -1 | cut -d ":" -f 2 | tr -d " "'
snp_policy = 1769472
vm_secure_guest_object_options = "policy=${snp_policy}"
40 changes: 32 additions & 8 deletions qemu/tests/snp_basic_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,36 @@ def run(test, params, env):
if int(process.getoutput(socket_count_cmd, shell=True)) != 1:
test.cancel("Host cpu has more than 1 socket, skip the case.")

family_id = cpu.get_family()
model_id = cpu.get_model()
dict_cpu = {"251": "milan", "2517": "genoa", "2617": "turin"}
key = str(family_id) + str(model_id)
host_cpu_model = dict_cpu.get(key, "unknown")

family_id = int(cpu.get_family())
model_id = int(cpu.get_model())
dict_cpu = {
"milan": [25, 0, 15],
"genoa": [25, 16, 31],
"bergamo": [25, 160, 175],
"turin": [26, 0, 31],
}
host_cpu_model = None
for platform, values in dict_cpu.items():
if values[0] == family_id:
if model_id >= values[1] and model_id <= values[2]:
host_cpu_model = platform
if not host_cpu_model:
test.cancel("Unsupported paltform. Requires milan or above.")
test.log.info("Detected platform: %s", host_cpu_model)
vm_name = params["main_vm"]
vm = env.get_vm(vm_name)
vm.create()
vm.verify_alive()
session = vm.wait_for_login(timeout=timeout)
verify_dmesg()
# Check for /dev/sev-guest inside the guest
test.log.info("Checking for SNP attestation support in guest")
rc_code = session.cmd_status("ls /dev/sev-guest")
if rc_code:
test.cancel(
"Error: Unable to open /dev/sev-guest. Guest kernel support for "
"SNP attestation is missing."
)
vm_policy = vm.params.get_numeric("snp_policy")
guest_check_cmd = params["snp_guest_check"]
sev_guest_info = vm.monitor.query_sev()
Expand All @@ -67,14 +85,20 @@ def run(test, params, env):
host_file = os.path.join(deps_dir, host_script)
try:
vm.copy_files_to(host_file, guest_dir)
session.cmd_output(params["guest_tool_install"], timeout=240)
if params.get("snpguest_sourcebuild", "0") == "1":
snpguest_build_location = params["snpguest_build_location"]
install_snpguest = os.path.join(deps_dir, snpguest_build_location)
vm.copy_files_to(install_snpguest, guest_dir)
session.cmd_output(params["snpguest_buildcmd"], timeout=360)
else:
session.cmd_output(params["guest_tool_install"], timeout=240)
session.cmd_output("chmod 755 %s" % guest_cmd)
except Exception as e:
test.fail("Guest test preperation fail: %s" % str(e))
guest_cmd = guest_cmd + " " + host_cpu_model
s = session.cmd_status(guest_cmd, timeout=360)
if s:
test.fail("Guest script error")
test.fail("Guest script error, check the session logs for further details")
finally:
session.close()
vm.destroy()