From 5d2e9deea5bd4735af995c6c466cd69918c53533 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 31 Jul 2025 16:01:05 +0800 Subject: [PATCH 01/17] Add CI test for KMS volume encryption and update documentation --- .github/workflows/test-kms-volume.yml | 47 ++ .github/workflows/test-system-encryption.yml | 45 ++ README.md | 16 + test-kms-volume.sh | 273 +++++++++ test-system-encryption.sh | 598 +++++++++++++++++++ 5 files changed, 979 insertions(+) create mode 100644 .github/workflows/test-kms-volume.yml create mode 100644 .github/workflows/test-system-encryption.yml create mode 100755 test-kms-volume.sh create mode 100755 test-system-encryption.sh diff --git a/.github/workflows/test-kms-volume.yml b/.github/workflows/test-kms-volume.yml new file mode 100644 index 0000000..b6afa45 --- /dev/null +++ b/.github/workflows/test-kms-volume.yml @@ -0,0 +1,47 @@ +name: Test KMS Volume Encryption + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + test-kms-volume: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + wget \ + curl \ + build-essential \ + pkg-config \ + libssl-dev \ + libdevmapper-dev \ + libsystemd-dev \ + parted + + - name: Setup Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Build cryptpilot + run: | + cargo build --release + + - name: Install cryptpilot + run: | + sudo cp target/release/cryptpilot /usr/local/bin/ + sudo cp target/release/cryptpilot-convert /usr/local/bin/ + + - name: Run KMS volume encryption test + run: | + chmod +x test-kms-volume.sh + sudo ./test-kms-volume.sh --keep-files \ No newline at end of file diff --git a/.github/workflows/test-system-encryption.yml b/.github/workflows/test-system-encryption.yml new file mode 100644 index 0000000..25f9902 --- /dev/null +++ b/.github/workflows/test-system-encryption.yml @@ -0,0 +1,45 @@ +name: Test System Disk Encryption + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + test-encryption: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + qemu-system-x86 \ + qemu-kvm \ + qemu-utils \ + wget \ + curl \ + socat \ + build-essential \ + pkg-config \ + libssl-dev \ + libdevmapper-dev \ + libsystemd-dev + + - name: Setup Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Build cryptpilot + run: | + cargo build --release + + - name: Run system encryption test + run: | + chmod +x test-system-encryption.sh + timeout 300s ./test-system-encryption.sh --ci \ No newline at end of file diff --git a/README.md b/README.md index cb29a44..5f60396 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,22 @@ Now you can read and write files in the mounted directory. systemctl enable --now cryptpilot.service ``` +## CI Tests + +This project includes CI tests for various encryption scenarios: + +1. System disk encryption test (test-system-encryption.sh) - Tests full disk encryption with exec provider +2. KMS volume encryption test (test-kms-volume.sh) - Tests data volume encryption with KMS-like provider + +You can run these tests locally: +```sh +# Run system encryption test +sudo ./test-system-encryption.sh + +# Run KMS volume test +sudo ./test-kms-volume.sh +``` + # Supported Distrubutions CryptPilot has been tested on the following distributions, and it may not work on other distributions. diff --git a/test-kms-volume.sh b/test-kms-volume.sh new file mode 100755 index 0000000..1d060e3 --- /dev/null +++ b/test-kms-volume.sh @@ -0,0 +1,273 @@ +#!/bin/bash + +# Test script for KMS volume encryption with cryptpilot +# This script tests the KMS credential provider for data volume encryption + +set -e # Exit on any error + +# Default configuration +CONFIG_DIR="test-kms-config" +LOG_FILE="test-output.log" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Help message +show_help() { + cat << EOF +Usage: $0 [OPTIONS] + +Test script for cryptpilot KMS volume encryption. + +OPTIONS: + -h, --help Show this help message + -k, --keep-files Keep test files after execution + +EXAMPLES: + $0 # Run KMS volume test + $0 --keep-files # Run test but keep files + +EOF +} + +log() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" + exit 1 +} + +# Parse command line arguments +KEEP_FILES=false + +parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -k|--keep-files) + KEEP_FILES=true + shift + ;; + *) + error "Unknown option: $1" + ;; + esac + done +} + +# Cleanup function +cleanup() { + if [[ "$KEEP_FILES" == false ]]; then + log "Cleaning up..." + [[ -d "${CONFIG_DIR}" ]] && rm -rf "${CONFIG_DIR}" + [[ -f "${LOG_FILE}" ]] && rm -f "${LOG_FILE}" + [[ -b "/dev/loop99" ]] && sudo losetup -d /dev/loop99 2>/dev/null || true + [[ -f "test-disk.img" ]] && rm -f "test-disk.img" + else + log "Keeping test files as requested" + fi +} + +trap cleanup EXIT + +# Setup config directory for KMS volume +setup_config() { + log "Setting up cryptpilot config for KMS volume..." + mkdir -p "${CONFIG_DIR}/volumes" + + # Create a KMS volume config (using mock values for CI) + cat > "${CONFIG_DIR}/volumes/kms-test.toml" << EOF +volume = "kms-test" +dev = "/dev/loop99p1" +auto_open = true +makefs = "ext4" +integrity = true + +# For CI test, we use exec provider to simulate KMS behavior +# In real usage, this would be [encrypt.kms] with actual KMS configuration +[encrypt.exec] +command = "echo" +args = ["-n", "test-passphrase-for-kms"] +EOF +} + +# Create test disk +create_test_disk() { + log "Creating test disk..." + + # Create a 100MB disk image + dd if=/dev/zero of=test-disk.img bs=1M count=100 + + # Set up loop device as /dev/loop99 + sudo losetup -P /dev/loop99 test-disk.img + LOOP_DEV="/dev/loop99" + + # Create GPT partition table and one partition + sudo parted --script $LOOP_DEV \ + mktable gpt \ + mkpart primary 1MiB 100% + + # Wait for partition to be ready + sleep 2 + + log "Test disk created: $LOOP_DEV" +} + +# Test volume initialization +test_volume_init() { + log "Initializing KMS volume..." + + # Initialize the volume + if ! sudo cryptpilot init kms-test -c "${CONFIG_DIR}" -y > "${LOG_FILE}" 2>&1; then + echo "Failed to initialize volume. Log output:" + cat "${LOG_FILE}" + return 1 + fi + + log "Volume initialized successfully" +} + +# Test volume opening +test_volume_open() { + log "Opening KMS volume..." + + # Open the volume + if ! sudo cryptpilot open kms-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + echo "Failed to open volume. Log output:" + cat "${LOG_FILE}" + return 1 + fi + + # Check if the device mapper device exists + if [[ ! -b "/dev/mapper/kms-test" ]]; then + echo "Device mapper device /dev/mapper/kms-test not found" + return 1 + fi + + log "Volume opened successfully" +} + +# Test volume show +test_volume_show() { + log "Showing volume status..." + + # Show volume status + if ! sudo cryptpilot show -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + echo "Failed to show volume status. Log output:" + cat "${LOG_FILE}" + return 1 + fi + + # Check if our volume is listed and opened + if ! grep -q "kms-test" "${LOG_FILE}"; then + echo "Volume kms-test not found in show output" + return 1 + fi + + if ! grep -q "True" "${LOG_FILE}"; then + echo "Volume kms-test is not opened according to show output" + return 1 + fi + + log "Volume status verified successfully" +} + +# Test filesystem operations +test_filesystem_ops() { + log "Testing filesystem operations..." + + # Create mount point + mkdir -p /tmp/kms-test-mount + + # Mount the volume + if ! sudo mount /dev/mapper/kms-test /tmp/kms-test-mount; then + error "Failed to mount volume" + fi + + # Test writing and reading a file + echo "test content" | sudo tee /tmp/kms-test-mount/test-file > /dev/null + if [[ ! -f "/tmp/kms-test-mount/test-file" ]]; then + error "Failed to create test file" + fi + + content=$(sudo cat /tmp/kms-test-mount/test-file) + if [[ "$content" != "test content" ]]; then + error "File content mismatch" + fi + + # Unmount the volume + sudo umount /tmp/kms-test-mount + + log "Filesystem operations tested successfully" +} + +# Test volume closing +test_volume_close() { + log "Closing KMS volume..." + + # Close the volume + if ! sudo cryptpilot close kms-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + echo "Failed to close volume. Log output:" + cat "${LOG_FILE}" + return 1 + fi + + # Check that the device mapper device no longer exists + if [[ -b "/dev/mapper/kms-test" ]]; then + echo "Device mapper device /dev/mapper/kms-test still exists after closing" + return 1 + fi + + log "Volume closed successfully" +} + +# Main execution +main() { + parse_args "$@" + + log "Starting KMS volume encryption test" + + # Setup config + setup_config + + # Create test disk + create_test_disk + + # Test volume operations + if ! test_volume_init; then + error "Volume initialization failed" + fi + + if ! test_volume_open; then + error "Volume opening failed" + fi + + if ! test_volume_show; then + error "Volume show failed" + fi + + if ! test_filesystem_ops; then + error "Filesystem operations failed" + fi + + if ! test_volume_close; then + error "Volume closing failed" + fi + + log "KMS volume encryption test completed successfully!" +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/test-system-encryption.sh b/test-system-encryption.sh new file mode 100755 index 0000000..83c819c --- /dev/null +++ b/test-system-encryption.sh @@ -0,0 +1,598 @@ +#!/bin/bash + +# Unified test script for system disk encryption with cryptpilot +# This script can be used in different modes: +# 1. CI mode - Automated testing with verification +# 2. Local mode - Interactive testing +# 3. Download only mode - Just download images +# 4. Encrypt only mode - Just encrypt an existing image + +set -e # Exit on any error + +# Default configuration +IMAGE_URL="https://alinux3.oss-cn-hangzhou.aliyuncs.com/aliyun_3_x64_20G_nocloud_alibase_20250117.qcow2" +IMAGE_NAME="alinux3.qcow2" +ENCRYPTED_IMAGE_NAME="encrypted.qcow2" +CONFIG_DIR="test-config" +PASSPHRASE="AAAaaawewe222" +SEED_IMAGE="seed.img" +SEED_URL="https://alinux3.oss-cn-hangzhou.aliyuncs.com/seed.img" +LOG_FILE="qemu-output.log" + +# Mode flags +CI_MODE=false +LOCAL_MODE=false +DOWNLOAD_ONLY=false +ENCRYPT_ONLY=false +KEEP_FILES=false + +# Paths to existing images (prefixed with @ to indicate they should be used as-is) +EXISTING_IMAGE_PATH="" +EXISTING_SEED_PATH="" + +# QEMU command to use +QEMU_CMD="" + +# Common QEMU paths to check +QEMU_PATHS=( + "qemu-system-x86_64" + "qemu-kvm" + "qemu-system-i386" + "/usr/libexec/qemu-kvm" + "/usr/bin/qemu-system-x86_64" + "/usr/bin/qemu-kvm" + "/usr/local/bin/qemu-system-x86_64" +) + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Help message +show_help() { + cat << EOF +Usage: $0 [OPTIONS] + +Unified test script for cryptpilot system disk encryption. + +OPTIONS: + -h, --help Show this help message + -c, --ci Run in CI mode (automated testing with verification) + -l, --local Run in local mode (interactive testing) + -d, --download-only Download images only + -e, --encrypt-only Encrypt existing image only + -k, --keep-files Keep downloaded files after execution + --image-url URL Specify custom image URL + --seed-url URL Specify custom seed image URL + --image-name NAME Specify custom image filename + --encrypted-name NAME Specify custom encrypted image filename + --config-dir DIR Specify custom config directory + --passphrase PHRASE Specify custom passphrase + --existing-image PATH Use existing image file (prefix with @, e.g., @/path/to/image.qcow2) + --existing-seed PATH Use existing seed file (prefix with @, e.g., @/path/to/seed.img) + +EXAMPLES: + $0 --ci # Run full CI test + $0 --local # Run local interactive test + $0 --download-only # Download images only + $0 --encrypt-only # Encrypt existing image + $0 --ci --keep-files # Run CI test but keep files + $0 --ci --existing-image @/root/diskenc/aliyun_3_x64_20G_nocloud_alibase_20250117.qcow2 --existing-seed @/root/diskenc/seed.img + +EOF +} + +log() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" + exit 1 +} + +# Parse command line arguments +parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -c|--ci) + CI_MODE=true + shift + ;; + -l|--local) + LOCAL_MODE=true + shift + ;; + -d|--download-only) + DOWNLOAD_ONLY=true + shift + ;; + -e|--encrypt-only) + ENCRYPT_ONLY=true + shift + ;; + -k|--keep-files) + KEEP_FILES=true + shift + ;; + --image-url) + IMAGE_URL="$2" + shift 2 + ;; + --seed-url) + SEED_URL="$2" + shift 2 + ;; + --image-name) + IMAGE_NAME="$2" + shift 2 + ;; + --encrypted-name) + ENCRYPTED_IMAGE_NAME="$2" + shift 2 + ;; + --config-dir) + CONFIG_DIR="$2" + shift 2 + ;; + --passphrase) + PASSPHRASE="$2" + shift 2 + ;; + --existing-image) + EXISTING_IMAGE_PATH="$2" + shift 2 + ;; + --existing-seed) + EXISTING_SEED_PATH="$2" + shift 2 + ;; + *) + error "Unknown option: $1" + ;; + esac + done +} + +# Find appropriate QEMU command +find_qemu() { + log "Detecting QEMU installation..." + + # Try different QEMU commands and paths + for path in "${QEMU_PATHS[@]}"; do + if [[ -x "$path" ]] || command -v "$path" >/dev/null 2>&1; then + QEMU_CMD="$path" + log "Found QEMU command: $QEMU_CMD" + return 0 + fi + done + + error "No QEMU command found. Please install QEMU (qemu-system-x86 or qemu-kvm)" +} + +# Cleanup function +cleanup() { + if [[ "$KEEP_FILES" == false ]]; then + log "Cleaning up..." + [[ -d "${CONFIG_DIR}" ]] && rm -rf "${CONFIG_DIR}" + # Only clean up downloaded/created files, not existing ones + if [[ -z "$EXISTING_IMAGE_PATH" ]]; then + [[ "$DOWNLOAD_ONLY" == false && "$ENCRYPT_ONLY" == false ]] && [[ -f "${IMAGE_NAME}" ]] && rm -f "${IMAGE_NAME}" + fi + if [[ -z "$EXISTING_SEED_PATH" ]]; then + [[ "$DOWNLOAD_ONLY" == false ]] && [[ -f "${SEED_IMAGE}" ]] && rm -f "${SEED_IMAGE}" + fi + [[ "$DOWNLOAD_ONLY" == false ]] && [[ -f "${ENCRYPTED_IMAGE_NAME}" ]] && rm -f "${ENCRYPTED_IMAGE_NAME}" + [[ -S "qemu-monitor.sock" ]] && rm -f "qemu-monitor.sock" + [[ -f "${LOG_FILE}" ]] && rm -f "${LOG_FILE}" + else + log "Keeping downloaded files as requested" + fi + + # Kill QEMU process if still running + if [[ -n "${qemu_pid:-}" ]]; then + log "Terminating QEMU process ${qemu_pid}" + kill ${qemu_pid} 2>/dev/null || true + # Wait a moment for graceful termination + sleep 2 + # Force kill if still running + kill -9 ${qemu_pid} 2>/dev/null || true + fi +} + +trap cleanup EXIT + +# Setup config directory +setup_config() { + log "Setting up cryptpilot config..." + mkdir -p "${CONFIG_DIR}" + + cat > "${CONFIG_DIR}/fde.toml" << EOF +[rootfs] +rw_overlay = "disk" + +[rootfs.encrypt.exec] +command = "echo" +args = ["-n", "${PASSPHRASE}"] + +[data] +integrity = true + +[data.encrypt.exec] +command = "echo" +args = ["-n", "${PASSPHRASE}"] +EOF +} + +# Download Alinux3 image with resume capability +download_image() { + # If existing image path is provided, use it + if [[ -n "$EXISTING_IMAGE_PATH" ]]; then + # Remove the @ prefix + local existing_path="${EXISTING_IMAGE_PATH#@}" + if [[ -f "$existing_path" ]]; then + log "Using existing image file: $existing_path" + # Create a symlink or copy to our expected name + ln -sf "$existing_path" "${IMAGE_NAME}" + return + else + error "Specified existing image file not found: $existing_path" + fi + fi + + if [[ -f "${IMAGE_NAME}" ]]; then + log "Using existing image file" + return + fi + + log "Downloading Alinux3 image from ${IMAGE_URL}..." + log "NOTE: This is a large file (20GB) and may take a while to download" + + # Try with wget first (supports resume) + if command -v wget >/dev/null 2>&1; then + log "Using wget with resume capability" + wget -c -O "${IMAGE_NAME}" "${IMAGE_URL}" || error "Failed to download image with wget" + # Try with curl if wget is not available + elif command -v curl >/dev/null 2>&1; then + log "Using curl" + curl -L -o "${IMAGE_NAME}" "${IMAGE_URL}" || error "Failed to download image with curl" + else + error "Neither wget nor curl found" + fi + + [[ -f "${IMAGE_NAME}" ]] || error "Image file not found after download" + log "Image downloaded successfully" +} + +# Download seed image +download_seed() { + # If existing seed path is provided, use it + if [[ -n "$EXISTING_SEED_PATH" ]]; then + # Remove the @ prefix + local existing_path="${EXISTING_SEED_PATH#@}" + if [[ -f "$existing_path" ]]; then + log "Using existing seed file: $existing_path" + # Create a symlink or copy to our expected name + ln -sf "$existing_path" "${SEED_IMAGE}" + return + else + error "Specified existing seed file not found: $existing_path" + fi + fi + + if [[ -f "${SEED_IMAGE}" ]]; then + log "Using existing seed image file" + return + fi + + log "Downloading seed image from ${SEED_URL}..." + if command -v wget >/dev/null 2>&1; then + wget -O "${SEED_IMAGE}" "${SEED_URL}" || error "Failed to download seed image with wget" + elif command -v curl >/dev/null 2>&1; then + curl -L -o "${SEED_IMAGE}" "${SEED_URL}" || error "Failed to download seed image with curl" + else + error "Neither wget nor curl found" + fi + + [[ -f "${SEED_IMAGE}" ]] || error "Seed image file not found after download" + log "Seed image downloaded successfully" +} + +# Encrypt image with cryptpilot-convert +encrypt_image() { + if [[ -f "${ENCRYPTED_IMAGE_NAME}" ]]; then + log "Using existing encrypted image file" + return + fi + + log "Encrypting image with cryptpilot-convert..." + + # Check if cryptpilot-convert is available + if ! command -v cryptpilot-convert >/dev/null 2>&1; then + # Try to build it if not available + if [[ -f "target/release/cryptpilot-convert" ]]; then + log "Using built cryptpilot-convert" + ./target/release/cryptpilot-convert --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ + --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" || error "Encryption failed" + elif [[ -f "cryptpilot-convert.sh" ]]; then + log "Using cryptpilot-convert.sh script" + chmod +x cryptpilot-convert.sh + ./cryptpilot-convert.sh --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ + --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" || error "Encryption failed" + else + error "cryptpilot-convert not found" + fi + else + # Use the binary directly + cryptpilot-convert --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ + --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" || error "Encryption failed" + fi + + [[ -f "${ENCRYPTED_IMAGE_NAME}" ]] || error "Encrypted image not found after encryption process" + log "Image encrypted successfully" +} + +# Start QEMU with the encrypted image (CI mode) +start_qemu_ci() { + log "Starting QEMU with encrypted image (CI mode)..." + + # Find appropriate QEMU command + find_qemu + + # Print QEMU command for debugging + log "QEMU command: $QEMU_CMD -m 2048M -smp 2 -nographic -serial mon:stdio -monitor unix:qemu-monitor.sock,server,nowait -drive file=${ENCRYPTED_IMAGE_NAME},format=qcow2,if=virtio,id=hd0,readonly=off -drive file=${SEED_IMAGE},if=virtio,format=raw -netdev user,id=net0,net=192.168.123.0/24,hostfwd=tcp::2222-:22 -device virtio-net,netdev=net0" + + # Start QEMU in background, redirecting output to file for analysis + $QEMU_CMD \ + -m 2048M \ + -smp 2 \ + -nographic \ + -serial mon:stdio \ + -monitor unix:qemu-monitor.sock,server,nowait \ + -drive file="${ENCRYPTED_IMAGE_NAME}",format=qcow2,if=virtio,id=hd0,readonly=off \ + -drive file="${SEED_IMAGE}",if=virtio,format=raw \ + -netdev user,id=net0,net=192.168.123.0/24,hostfwd=tcp::2222-:22 \ + -device virtio-net,netdev=net0 \ + > "${LOG_FILE}" 2>&1 & qemu_pid=$! + + log "QEMU started with PID: ${qemu_pid}" + + # Give QEMU some time to start + sleep 10 + + # Check if QEMU is still running + if ! kill -0 ${qemu_pid} 2>/dev/null; then + error "QEMU process terminated unexpectedly" + fi +} + +# Verify system boot by checking for login prompt in output (CI mode) +verify_boot() { + log "Verifying system boot by checking for login prompt..." + + # Wait for system to boot and show login prompt (max 300 seconds) + local timeout=300 + local count=0 + + while [[ $count -lt $timeout ]]; do + # Check if log file exists and has content + if [[ -f "${LOG_FILE}" ]] && [[ -s "${LOG_FILE}" ]]; then + log "Log file exists and has content, checking for login prompt..." + + # Check if login prompt appears in output log + if grep -q "login:" "${LOG_FILE}" 2>/dev/null; then + log "System boot verified - login prompt detected!" + log "Last 20 lines of output:" + tail -20 "${LOG_FILE}" + return 0 + fi + + # Also check for Alibaba Cloud Linux login prompt + if grep -q "Alibaba Cloud Linux" "${LOG_FILE}" 2>/dev/null; then + log "System boot verified - Alibaba Cloud Linux detected!" + log "Last 20 lines of output:" + tail -20 "${LOG_FILE}" + return 0 + fi + + # Show progress every 30 seconds + if (( count % 30 == 0 )); then + log "Still waiting for boot (elapsed: ${count}s)..." + log "Last 10 lines of log:" + tail -10 "${LOG_FILE}" + fi + elif [[ -f "${LOG_FILE}" ]]; then + log "Log file exists but is empty (elapsed: ${count}s)" + else + log "Log file does not exist yet (elapsed: ${count}s)" + fi + + # Check if QEMU process is still running + if ! kill -0 ${qemu_pid} 2>/dev/null; then + error "QEMU process terminated unexpectedly. Check ${LOG_FILE} for details." + fi + + sleep 1 + ((count++)) + done + + # If we get here, the system didn't boot in time + log "System failed to boot within ${timeout} seconds." + if [[ -f "${LOG_FILE}" ]]; then + log "Showing last 50 lines of QEMU output:" + tail -50 "${LOG_FILE}" + else + log "No QEMU output log found." + fi + + error "System failed to boot and show login prompt within ${timeout} seconds." +} + +# Check mount entries in /etc/mtab and device mapper volumes +check_mount_entries() { + log "Checking mount entries and device mapper volumes..." + + # Wait for system to be fully ready (add a small delay) + sleep 5 + + # Try to login via console to verify system is working + log "Attempting to login via console with username 'alinux' and password 'aliyun'..." + # Send username and password via QEMU monitor using sendkey command + for char in a l i n u x; do + echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 + sleep 0.1 + done + echo -e "sendkey ret\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 + + sleep 1 + + for char in a l i y u n; do + echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 + sleep 0.1 + done + echo -e "sendkey ret\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 + + sleep 3 + + # Try to extract information from QEMU guest + if [[ -S "qemu-monitor.sock" ]]; then + log "Extracting information from QEMU guest..." + + # Extract /etc/mtab from guest + echo -e "human-monitor-command {\"command-line\":\"cat /etc/mtab\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock > mtab_output.txt 2>/dev/null + + # Extract /dev/mapper contents from guest + echo -e "human-monitor-command {\"command-line\":\"ls -1 /dev/mapper\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock > dev_mapper_output.txt 2>/dev/null + + # Check for rootfs mount entry (only checking the first 3 columns) + if grep -q "^/dev/mapper/rootfs / overlay" mtab_output.txt; then + log "Rootfs mount entry found in /etc/mtab!" + else + log "Rootfs mount entry NOT found in /etc/mtab." + log "Current mtab entries:" + cat mtab_output.txt + return 1 + fi + + # Check for data mount entry + if grep -q "^/dev/mapper/data /data " mtab_output.txt; then + log "Data mount entry found in /etc/mtab!" + else + log "/data mount entry NOT found in /etc/mtab." + log "Current mtab entries:" + cat mtab_output.txt + return 1 + fi + + # Check for rootfs device mapper volume + if grep -q "^rootfs$" dev_mapper_output.txt; then + log "Rootfs device mapper volume found!" + else + log "Rootfs device mapper volume NOT found." + log "Current /dev/mapper contents:" + cat dev_mapper_output.txt + return 1 + fi + + # Check for data device mapper volume + if grep -q "^data$" dev_mapper_output.txt; then + log "Data device mapper volume found!" + else + log "Data device mapper volume NOT found." + log "Current /dev/mapper contents:" + cat dev_mapper_output.txt + return 1 + fi + + log "All mount entries and device mapper volumes verified successfully!" + return 0 + else + warn "QEMU monitor socket not available, skipping mount and device mapper checks" + return 0 + fi +} + +# Start QEMU with the encrypted image (Local mode) +start_qemu_local() { + log "Starting QEMU with encrypted image (Local mode)..." + + # Find appropriate QEMU command + find_qemu + + # Start QEMU with a simplified configuration for testing + log "Starting QEMU - Press Ctrl+A then X to exit" + $QEMU_CMD \ + -m 2048M \ + -smp 2 \ + -nographic \ + -serial mon:stdio \ + -drive file="${ENCRYPTED_IMAGE_NAME}",format=qcow2,if=virtio,id=hd0,readonly=off \ + -drive file="${SEED_IMAGE}",if=virtio,format=raw +} + +# Main execution +main() { + parse_args "$@" + + # Determine mode if not explicitly set + if [[ "$CI_MODE" == false && "$LOCAL_MODE" == false && "$DOWNLOAD_ONLY" == false && "$ENCRYPT_ONLY" == false ]]; then + # Default to CI mode + CI_MODE=true + fi + + log "Starting unified test script for system disk encryption" + + # Handle download-only mode + if [[ "$DOWNLOAD_ONLY" == true ]]; then + download_image + download_seed + log "Download-only mode completed successfully!" + exit 0 + fi + + # Handle encrypt-only mode + if [[ "$ENCRYPT_ONLY" == true ]]; then + setup_config + encrypt_image + log "Encrypt-only mode completed successfully!" + exit 0 + fi + + # Setup config for other modes + setup_config + + # Download images or use existing ones + download_image + download_seed + + # Encrypt image + encrypt_image + + # Handle CI mode + if [[ "$CI_MODE" == true ]]; then + start_qemu_ci + verify_boot + check_mount_entries + log "CI mode test completed successfully!" + log "System disk encryption verification passed!" + fi + + # Handle local mode + if [[ "$LOCAL_MODE" == true ]]; then + start_qemu_local + log "Local mode test completed!" + fi +} + +# Run main function +main "$@" \ No newline at end of file From 98ca6b8a00f26d93afc658b1442bb3446b5b07b9 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 31 Jul 2025 16:27:12 +0800 Subject: [PATCH 02/17] Replace KMS test with KBS test for volume encryption --- .github/workflows/test-kbs-volume.yml | 47 ++++++++++ README.md | 6 +- test-kms-volume.sh => test-kbs-volume.sh | 105 +++++++++++++++-------- 3 files changed, 117 insertions(+), 41 deletions(-) create mode 100644 .github/workflows/test-kbs-volume.yml rename test-kms-volume.sh => test-kbs-volume.sh (60%) diff --git a/.github/workflows/test-kbs-volume.yml b/.github/workflows/test-kbs-volume.yml new file mode 100644 index 0000000..422079b --- /dev/null +++ b/.github/workflows/test-kbs-volume.yml @@ -0,0 +1,47 @@ +name: Test KBS Volume Encryption + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + test-kbs-volume: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + wget \ + curl \ + build-essential \ + pkg-config \ + libssl-dev \ + libdevmapper-dev \ + libsystemd-dev \ + parted + + - name: Setup Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Build cryptpilot + run: | + cargo build --release + + - name: Install cryptpilot + run: | + sudo cp target/release/cryptpilot /usr/local/bin/ + sudo cp target/release/cryptpilot-convert /usr/local/bin/ + + - name: Run KBS volume encryption test + run: | + chmod +x test-kbs-volume.sh + sudo ./test-kbs-volume.sh --keep-files \ No newline at end of file diff --git a/README.md b/README.md index 5f60396..76a0784 100644 --- a/README.md +++ b/README.md @@ -235,15 +235,15 @@ systemctl enable --now cryptpilot.service This project includes CI tests for various encryption scenarios: 1. System disk encryption test (test-system-encryption.sh) - Tests full disk encryption with exec provider -2. KMS volume encryption test (test-kms-volume.sh) - Tests data volume encryption with KMS-like provider +2. KBS volume encryption test (test-kbs-volume.sh) - Tests data volume encryption with KBS-like provider You can run these tests locally: ```sh # Run system encryption test sudo ./test-system-encryption.sh -# Run KMS volume test -sudo ./test-kms-volume.sh +# Run KBS volume test +sudo ./test-kbs-volume.sh ``` # Supported Distrubutions diff --git a/test-kms-volume.sh b/test-kbs-volume.sh similarity index 60% rename from test-kms-volume.sh rename to test-kbs-volume.sh index 1d060e3..273ff87 100755 --- a/test-kms-volume.sh +++ b/test-kbs-volume.sh @@ -1,12 +1,12 @@ #!/bin/bash -# Test script for KMS volume encryption with cryptpilot -# This script tests the KMS credential provider for data volume encryption +# Test script for KBS volume encryption with cryptpilot +# This script tests the KBS credential provider for data volume encryption set -e # Exit on any error # Default configuration -CONFIG_DIR="test-kms-config" +CONFIG_DIR="test-kbs-config" LOG_FILE="test-output.log" # Colors for output @@ -20,14 +20,14 @@ show_help() { cat << EOF Usage: $0 [OPTIONS] -Test script for cryptpilot KMS volume encryption. +Test script for cryptpilot KBS volume encryption. OPTIONS: -h, --help Show this help message -k, --keep-files Keep test files after execution EXAMPLES: - $0 # Run KMS volume test + $0 # Run KBS volume test $0 --keep-files # Run test but keep files EOF @@ -73,8 +73,15 @@ cleanup() { log "Cleaning up..." [[ -d "${CONFIG_DIR}" ]] && rm -rf "${CONFIG_DIR}" [[ -f "${LOG_FILE}" ]] && rm -f "${LOG_FILE}" - [[ -b "/dev/loop99" ]] && sudo losetup -d /dev/loop99 2>/dev/null || true + + # Detach any loop device associated with test-disk.img + if sudo losetup -a | grep -q "test-disk.img"; then + LOOP_DEV=$(sudo losetup -a | grep "test-disk.img" | cut -d: -f1) + sudo losetup -d $LOOP_DEV 2>/dev/null || true + fi + [[ -f "test-disk.img" ]] && rm -f "test-disk.img" + [[ -d "/tmp/kbs-test-mount" ]] && rmdir /tmp/kbs-test-mount 2>/dev/null || true else log "Keeping test files as requested" fi @@ -82,24 +89,24 @@ cleanup() { trap cleanup EXIT -# Setup config directory for KMS volume +# Setup config directory for KBS volume setup_config() { - log "Setting up cryptpilot config for KMS volume..." + log "Setting up cryptpilot config for KBS volume..." mkdir -p "${CONFIG_DIR}/volumes" - # Create a KMS volume config (using mock values for CI) - cat > "${CONFIG_DIR}/volumes/kms-test.toml" << EOF -volume = "kms-test" + # Create a KBS volume config (using mock values for CI) + cat > "${CONFIG_DIR}/volumes/kbs-test.toml" << EOF +volume = "kbs-test" dev = "/dev/loop99p1" auto_open = true makefs = "ext4" integrity = true -# For CI test, we use exec provider to simulate KMS behavior -# In real usage, this would be [encrypt.kms] with actual KMS configuration +# For CI test, we use exec provider to simulate KBS behavior +# In real usage, this would be [encrypt.kbs] with actual KBS configuration [encrypt.exec] command = "echo" -args = ["-n", "test-passphrase-for-kms"] +args = ["-n", "test-passphrase-for-kbs"] EOF } @@ -110,9 +117,31 @@ create_test_disk() { # Create a 100MB disk image dd if=/dev/zero of=test-disk.img bs=1M count=100 - # Set up loop device as /dev/loop99 - sudo losetup -P /dev/loop99 test-disk.img - LOOP_DEV="/dev/loop99" + # Detach loop device if already attached + for i in {0..9}; do + if sudo losetup -a | grep -q "test-disk.img"; then + LOOP_DEV=$(sudo losetup -a | grep "test-disk.img" | cut -d: -f1) + sudo losetup -d $LOOP_DEV 2>/dev/null || true + fi + done + + # Set up loop device (try different numbers if /dev/loop99 is busy) + LOOP_DEV="" + for i in {99..90}; do + if ! sudo losetup -P /dev/loop$i test-disk.img 2>/dev/null; then + continue + else + LOOP_DEV="/dev/loop$i" + break + fi + done + + if [[ -z "$LOOP_DEV" ]]; then + error "Failed to set up loop device" + fi + + # Update the config file to use the actual loop device + sed -i "s|/dev/loop99|${LOOP_DEV}|g" ${CONFIG_DIR}/volumes/kbs-test.toml # Create GPT partition table and one partition sudo parted --script $LOOP_DEV \ @@ -127,10 +156,10 @@ create_test_disk() { # Test volume initialization test_volume_init() { - log "Initializing KMS volume..." + log "Initializing KBS volume..." # Initialize the volume - if ! sudo cryptpilot init kms-test -c "${CONFIG_DIR}" -y > "${LOG_FILE}" 2>&1; then + if ! sudo cryptpilot init kbs-test -c "${CONFIG_DIR}" -y > "${LOG_FILE}" 2>&1; then echo "Failed to initialize volume. Log output:" cat "${LOG_FILE}" return 1 @@ -141,18 +170,18 @@ test_volume_init() { # Test volume opening test_volume_open() { - log "Opening KMS volume..." + log "Opening KBS volume..." # Open the volume - if ! sudo cryptpilot open kms-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + if ! sudo cryptpilot open kbs-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then echo "Failed to open volume. Log output:" cat "${LOG_FILE}" return 1 fi # Check if the device mapper device exists - if [[ ! -b "/dev/mapper/kms-test" ]]; then - echo "Device mapper device /dev/mapper/kms-test not found" + if [[ ! -b "/dev/mapper/kbs-test" ]]; then + echo "Device mapper device /dev/mapper/kbs-test not found" return 1 fi @@ -171,13 +200,13 @@ test_volume_show() { fi # Check if our volume is listed and opened - if ! grep -q "kms-test" "${LOG_FILE}"; then - echo "Volume kms-test not found in show output" + if ! grep -q "kbs-test" "${LOG_FILE}"; then + echo "Volume kbs-test not found in show output" return 1 fi if ! grep -q "True" "${LOG_FILE}"; then - echo "Volume kms-test is not opened according to show output" + echo "Volume kbs-test is not opened according to show output" return 1 fi @@ -189,44 +218,44 @@ test_filesystem_ops() { log "Testing filesystem operations..." # Create mount point - mkdir -p /tmp/kms-test-mount + mkdir -p /tmp/kbs-test-mount # Mount the volume - if ! sudo mount /dev/mapper/kms-test /tmp/kms-test-mount; then + if ! sudo mount /dev/mapper/kbs-test /tmp/kbs-test-mount; then error "Failed to mount volume" fi # Test writing and reading a file - echo "test content" | sudo tee /tmp/kms-test-mount/test-file > /dev/null - if [[ ! -f "/tmp/kms-test-mount/test-file" ]]; then + echo "test content" | sudo tee /tmp/kbs-test-mount/test-file > /dev/null + if [[ ! -f "/tmp/kbs-test-mount/test-file" ]]; then error "Failed to create test file" fi - content=$(sudo cat /tmp/kms-test-mount/test-file) + content=$(sudo cat /tmp/kbs-test-mount/test-file) if [[ "$content" != "test content" ]]; then error "File content mismatch" fi # Unmount the volume - sudo umount /tmp/kms-test-mount + sudo umount /tmp/kbs-test-mount log "Filesystem operations tested successfully" } # Test volume closing test_volume_close() { - log "Closing KMS volume..." + log "Closing KBS volume..." # Close the volume - if ! sudo cryptpilot close kms-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + if ! sudo cryptpilot close kbs-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then echo "Failed to close volume. Log output:" cat "${LOG_FILE}" return 1 fi # Check that the device mapper device no longer exists - if [[ -b "/dev/mapper/kms-test" ]]; then - echo "Device mapper device /dev/mapper/kms-test still exists after closing" + if [[ -b "/dev/mapper/kbs-test" ]]; then + echo "Device mapper device /dev/mapper/kbs-test still exists after closing" return 1 fi @@ -237,7 +266,7 @@ test_volume_close() { main() { parse_args "$@" - log "Starting KMS volume encryption test" + log "Starting KBS volume encryption test" # Setup config setup_config @@ -266,7 +295,7 @@ main() { error "Volume closing failed" fi - log "KMS volume encryption test completed successfully!" + log "KBS volume encryption test completed successfully!" } # Run main function From 6fa85b6b6bd0fb1dc3e4cc8962b3418c83cab19a Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 09:57:14 +0800 Subject: [PATCH 03/17] .github/workflow: update ci trigger rule Signed-off-by: Kun Lai --- .github/workflows/test-kbs-volume.yml | 8 ++++++-- .github/workflows/test-kms-volume.yml | 8 ++++++-- .github/workflows/test-system-encryption.yml | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-kbs-volume.yml b/.github/workflows/test-kbs-volume.yml index 422079b..158b070 100644 --- a/.github/workflows/test-kbs-volume.yml +++ b/.github/workflows/test-kbs-volume.yml @@ -2,9 +2,13 @@ name: Test KBS Volume Encryption on: push: - branches: [ main, develop ] + branches: + - master + tags: + - "v*.*.*" pull_request: - branches: [ main ] + branches: + - 'master' jobs: test-kbs-volume: diff --git a/.github/workflows/test-kms-volume.yml b/.github/workflows/test-kms-volume.yml index b6afa45..b341a6d 100644 --- a/.github/workflows/test-kms-volume.yml +++ b/.github/workflows/test-kms-volume.yml @@ -2,9 +2,13 @@ name: Test KMS Volume Encryption on: push: - branches: [ main, develop ] + branches: + - master + tags: + - "v*.*.*" pull_request: - branches: [ main ] + branches: + - 'master' jobs: test-kms-volume: diff --git a/.github/workflows/test-system-encryption.yml b/.github/workflows/test-system-encryption.yml index 25f9902..b28689a 100644 --- a/.github/workflows/test-system-encryption.yml +++ b/.github/workflows/test-system-encryption.yml @@ -2,9 +2,13 @@ name: Test System Disk Encryption on: push: - branches: [ main, develop ] + branches: + - master + tags: + - "v*.*.*" pull_request: - branches: [ main ] + branches: + - 'master' jobs: test-encryption: From c98e81d3728f91334c7acaaced7c27f778a7ac02 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 10:20:57 +0800 Subject: [PATCH 04/17] Makefile: add infomation for creating patch for shellcheck report --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9f01a9a..743ce10 100644 --- a/Makefile +++ b/Makefile @@ -115,7 +115,7 @@ shellcheck: @command -v shellcheck >&- || { \ echo "shellcheck not found, please installing it from https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz" ; \ } - find . -name '*.sh' -exec shellcheck {} \; + @{ find . -name '*.sh' -printf '%P\0' | xargs -0 shellcheck ; } || { echo ; echo "Shellcheck finished. You can fix with:" ; echo " find . -name '*.sh' -printf '%P\0' | xargs -0 shellcheck -f diff | patch -p1" ; echo ; exit 1 ; } .PHONE: clippy clippy: From ad65bf1e0899ee9e7d6cea10e5ab350ced6303c5 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 10:22:19 +0800 Subject: [PATCH 05/17] test: fix script accroding to shellcheck report Signed-off-by: Kun Lai --- .github/workflows/test-system-encryption.yml | 2 +- test-kbs-volume.sh | 143 +++++----- test-system-encryption.sh | 258 ++++++++++--------- 3 files changed, 207 insertions(+), 196 deletions(-) diff --git a/.github/workflows/test-system-encryption.yml b/.github/workflows/test-system-encryption.yml index b28689a..98c1e74 100644 --- a/.github/workflows/test-system-encryption.yml +++ b/.github/workflows/test-system-encryption.yml @@ -46,4 +46,4 @@ jobs: - name: Run system encryption test run: | chmod +x test-system-encryption.sh - timeout 300s ./test-system-encryption.sh --ci \ No newline at end of file + timeout 300s sudo ./test-system-encryption.sh --ci \ No newline at end of file diff --git a/test-kbs-volume.sh b/test-kbs-volume.sh index 273ff87..11b786c 100755 --- a/test-kbs-volume.sh +++ b/test-kbs-volume.sh @@ -3,7 +3,7 @@ # Test script for KBS volume encryption with cryptpilot # This script tests the KBS credential provider for data volume encryption -set -e # Exit on any error +set -e # Exit on any error # Default configuration CONFIG_DIR="test-kbs-config" @@ -17,7 +17,7 @@ NC='\033[0m' # No Color # Help message show_help() { - cat << EOF + cat </dev/null || true + if losetup -a | grep -q "test-disk.img"; then + LOOP_DEV=$(losetup -a | grep "test-disk.img" | cut -d: -f1) + losetup -d "$LOOP_DEV" 2>/dev/null || true fi - + [[ -f "test-disk.img" ]] && rm -f "test-disk.img" [[ -d "/tmp/kbs-test-mount" ]] && rmdir /tmp/kbs-test-mount 2>/dev/null || true else @@ -93,9 +93,9 @@ trap cleanup EXIT setup_config() { log "Setting up cryptpilot config for KBS volume..." mkdir -p "${CONFIG_DIR}/volumes" - + # Create a KBS volume config (using mock values for CI) - cat > "${CONFIG_DIR}/volumes/kbs-test.toml" << EOF + cat >"${CONFIG_DIR}/volumes/kbs-test.toml" </dev/null || true + if losetup -a | grep -q "test-disk.img"; then + LOOP_DEV=$(losetup -a | grep "test-disk.img" | cut -d: -f1) + losetup -d "$LOOP_DEV" 2>/dev/null || true fi done - + # Set up loop device (try different numbers if /dev/loop99 is busy) LOOP_DEV="" for i in {99..90}; do - if ! sudo losetup -P /dev/loop$i test-disk.img 2>/dev/null; then + if ! losetup -P /dev/loop"$i" test-disk.img 2>/dev/null; then continue else LOOP_DEV="/dev/loop$i" break fi done - + if [[ -z "$LOOP_DEV" ]]; then error "Failed to set up loop device" fi - + # Update the config file to use the actual loop device sed -i "s|/dev/loop99|${LOOP_DEV}|g" ${CONFIG_DIR}/volumes/kbs-test.toml - + # Create GPT partition table and one partition - sudo parted --script $LOOP_DEV \ + parted --script "$LOOP_DEV" \ mktable gpt \ mkpart primary 1MiB 100% - + # Wait for partition to be ready sleep 2 - + log "Test disk created: $LOOP_DEV" } # Test volume initialization test_volume_init() { log "Initializing KBS volume..." - + # Initialize the volume - if ! sudo cryptpilot init kbs-test -c "${CONFIG_DIR}" -y > "${LOG_FILE}" 2>&1; then + if ! cryptpilot init kbs-test -c "${CONFIG_DIR}" -y >"${LOG_FILE}" 2>&1; then echo "Failed to initialize volume. Log output:" cat "${LOG_FILE}" return 1 fi - + log "Volume initialized successfully" } # Test volume opening test_volume_open() { log "Opening KBS volume..." - + # Open the volume - if ! sudo cryptpilot open kbs-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + if ! cryptpilot open kbs-test -c "${CONFIG_DIR}" >"${LOG_FILE}" 2>&1; then echo "Failed to open volume. Log output:" cat "${LOG_FILE}" return 1 fi - + # Check if the device mapper device exists if [[ ! -b "/dev/mapper/kbs-test" ]]; then echo "Device mapper device /dev/mapper/kbs-test not found" return 1 fi - + log "Volume opened successfully" } # Test volume show test_volume_show() { log "Showing volume status..." - + # Show volume status - if ! sudo cryptpilot show -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + if ! cryptpilot show -c "${CONFIG_DIR}" >"${LOG_FILE}" 2>&1; then echo "Failed to show volume status. Log output:" cat "${LOG_FILE}" return 1 fi - + # Check if our volume is listed and opened if ! grep -q "kbs-test" "${LOG_FILE}"; then echo "Volume kbs-test not found in show output" return 1 fi - + if ! grep -q "True" "${LOG_FILE}"; then echo "Volume kbs-test is not opened according to show output" return 1 fi - + log "Volume status verified successfully" } # Test filesystem operations test_filesystem_ops() { log "Testing filesystem operations..." - + # Create mount point mkdir -p /tmp/kbs-test-mount - + # Mount the volume - if ! sudo mount /dev/mapper/kbs-test /tmp/kbs-test-mount; then + if ! mount /dev/mapper/kbs-test /tmp/kbs-test-mount; then error "Failed to mount volume" fi - + # Test writing and reading a file - echo "test content" | sudo tee /tmp/kbs-test-mount/test-file > /dev/null + echo "test content" | tee /tmp/kbs-test-mount/test-file >/dev/null if [[ ! -f "/tmp/kbs-test-mount/test-file" ]]; then error "Failed to create test file" fi - - content=$(sudo cat /tmp/kbs-test-mount/test-file) + + content=$(cat /tmp/kbs-test-mount/test-file) if [[ "$content" != "test content" ]]; then error "File content mismatch" fi - + # Unmount the volume - sudo umount /tmp/kbs-test-mount - + umount /tmp/kbs-test-mount + log "Filesystem operations tested successfully" } # Test volume closing test_volume_close() { log "Closing KBS volume..." - + # Close the volume - if ! sudo cryptpilot close kbs-test -c "${CONFIG_DIR}" > "${LOG_FILE}" 2>&1; then + if ! cryptpilot close kbs-test -c "${CONFIG_DIR}" >"${LOG_FILE}" 2>&1; then echo "Failed to close volume. Log output:" cat "${LOG_FILE}" return 1 fi - + # Check that the device mapper device no longer exists if [[ -b "/dev/mapper/kbs-test" ]]; then echo "Device mapper device /dev/mapper/kbs-test still exists after closing" return 1 fi - + log "Volume closed successfully" } # Main execution main() { + if [ "$(id -u)" != "0" ]; then + log::error "This script must be run as root" + exit 1 + fi + parse_args "$@" - + log "Starting KBS volume encryption test" - + # Setup config setup_config - + # Create test disk create_test_disk - + # Test volume operations if ! test_volume_init; then error "Volume initialization failed" fi - + if ! test_volume_open; then error "Volume opening failed" fi - + if ! test_volume_show; then error "Volume show failed" fi - + if ! test_filesystem_ops; then error "Filesystem operations failed" fi - + if ! test_volume_close; then error "Volume closing failed" fi - + log "KBS volume encryption test completed successfully!" } # Run main function -main "$@" \ No newline at end of file +main "$@" diff --git a/test-system-encryption.sh b/test-system-encryption.sh index 83c819c..5f1ed3b 100755 --- a/test-system-encryption.sh +++ b/test-system-encryption.sh @@ -7,7 +7,7 @@ # 3. Download only mode - Just download images # 4. Encrypt only mode - Just encrypt an existing image -set -e # Exit on any error +set -e # Exit on any error # Default configuration IMAGE_URL="https://alinux3.oss-cn-hangzhou.aliyuncs.com/aliyun_3_x64_20G_nocloud_alibase_20250117.qcow2" @@ -52,7 +52,7 @@ NC='\033[0m' # No Color # Help message show_help() { - cat << EOF + cat </dev/null 2>&1; then @@ -176,7 +176,7 @@ find_qemu() { return 0 fi done - + error "No QEMU command found. Please install QEMU (qemu-system-x86 or qemu-kvm)" } @@ -198,15 +198,15 @@ cleanup() { else log "Keeping downloaded files as requested" fi - + # Kill QEMU process if still running if [[ -n "${qemu_pid:-}" ]]; then log "Terminating QEMU process ${qemu_pid}" - kill ${qemu_pid} 2>/dev/null || true + kill "${qemu_pid}" 2>/dev/null || true # Wait a moment for graceful termination sleep 2 # Force kill if still running - kill -9 ${qemu_pid} 2>/dev/null || true + kill -9 "${qemu_pid}" 2>/dev/null || true fi } @@ -216,8 +216,8 @@ trap cleanup EXIT setup_config() { log "Setting up cryptpilot config..." mkdir -p "${CONFIG_DIR}" - - cat > "${CONFIG_DIR}/fde.toml" << EOF + + cat >"${CONFIG_DIR}/fde.toml" </dev/null 2>&1; then log "Using wget with resume capability" @@ -269,7 +269,7 @@ download_image() { else error "Neither wget nor curl found" fi - + [[ -f "${IMAGE_NAME}" ]] || error "Image file not found after download" log "Image downloaded successfully" } @@ -289,12 +289,12 @@ download_seed() { error "Specified existing seed file not found: $existing_path" fi fi - + if [[ -f "${SEED_IMAGE}" ]]; then log "Using existing seed image file" return fi - + log "Downloading seed image from ${SEED_URL}..." if command -v wget >/dev/null 2>&1; then wget -O "${SEED_IMAGE}" "${SEED_URL}" || error "Failed to download seed image with wget" @@ -303,7 +303,7 @@ download_seed() { else error "Neither wget nor curl found" fi - + [[ -f "${SEED_IMAGE}" ]] || error "Seed image file not found after download" log "Seed image downloaded successfully" } @@ -314,9 +314,9 @@ encrypt_image() { log "Using existing encrypted image file" return fi - + log "Encrypting image with cryptpilot-convert..." - + # Check if cryptpilot-convert is available if ! command -v cryptpilot-convert >/dev/null 2>&1; then # Try to build it if not available @@ -337,7 +337,7 @@ encrypt_image() { cryptpilot-convert --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" || error "Encryption failed" fi - + [[ -f "${ENCRYPTED_IMAGE_NAME}" ]] || error "Encrypted image not found after encryption process" log "Image encrypted successfully" } @@ -345,13 +345,13 @@ encrypt_image() { # Start QEMU with the encrypted image (CI mode) start_qemu_ci() { log "Starting QEMU with encrypted image (CI mode)..." - + # Find appropriate QEMU command find_qemu - + # Print QEMU command for debugging log "QEMU command: $QEMU_CMD -m 2048M -smp 2 -nographic -serial mon:stdio -monitor unix:qemu-monitor.sock,server,nowait -drive file=${ENCRYPTED_IMAGE_NAME},format=qcow2,if=virtio,id=hd0,readonly=off -drive file=${SEED_IMAGE},if=virtio,format=raw -netdev user,id=net0,net=192.168.123.0/24,hostfwd=tcp::2222-:22 -device virtio-net,netdev=net0" - + # Start QEMU in background, redirecting output to file for analysis $QEMU_CMD \ -m 2048M \ @@ -363,13 +363,14 @@ start_qemu_ci() { -drive file="${SEED_IMAGE}",if=virtio,format=raw \ -netdev user,id=net0,net=192.168.123.0/24,hostfwd=tcp::2222-:22 \ -device virtio-net,netdev=net0 \ - > "${LOG_FILE}" 2>&1 & qemu_pid=$! - + >"${LOG_FILE}" 2>&1 & + qemu_pid=$! + log "QEMU started with PID: ${qemu_pid}" - + # Give QEMU some time to start sleep 10 - + # Check if QEMU is still running if ! kill -0 ${qemu_pid} 2>/dev/null; then error "QEMU process terminated unexpectedly" @@ -379,16 +380,16 @@ start_qemu_ci() { # Verify system boot by checking for login prompt in output (CI mode) verify_boot() { log "Verifying system boot by checking for login prompt..." - + # Wait for system to boot and show login prompt (max 300 seconds) local timeout=300 local count=0 - + while [[ $count -lt $timeout ]]; do # Check if log file exists and has content if [[ -f "${LOG_FILE}" ]] && [[ -s "${LOG_FILE}" ]]; then log "Log file exists and has content, checking for login prompt..." - + # Check if login prompt appears in output log if grep -q "login:" "${LOG_FILE}" 2>/dev/null; then log "System boot verified - login prompt detected!" @@ -396,7 +397,7 @@ verify_boot() { tail -20 "${LOG_FILE}" return 0 fi - + # Also check for Alibaba Cloud Linux login prompt if grep -q "Alibaba Cloud Linux" "${LOG_FILE}" 2>/dev/null; then log "System boot verified - Alibaba Cloud Linux detected!" @@ -404,9 +405,9 @@ verify_boot() { tail -20 "${LOG_FILE}" return 0 fi - + # Show progress every 30 seconds - if (( count % 30 == 0 )); then + if ((count % 30 == 0)); then log "Still waiting for boot (elapsed: ${count}s)..." log "Last 10 lines of log:" tail -10 "${LOG_FILE}" @@ -416,16 +417,16 @@ verify_boot() { else log "Log file does not exist yet (elapsed: ${count}s)" fi - + # Check if QEMU process is still running if ! kill -0 ${qemu_pid} 2>/dev/null; then error "QEMU process terminated unexpectedly. Check ${LOG_FILE} for details." fi - + sleep 1 ((count++)) done - + # If we get here, the system didn't boot in time log "System failed to boot within ${timeout} seconds." if [[ -f "${LOG_FILE}" ]]; then @@ -434,46 +435,46 @@ verify_boot() { else log "No QEMU output log found." fi - + error "System failed to boot and show login prompt within ${timeout} seconds." } # Check mount entries in /etc/mtab and device mapper volumes check_mount_entries() { log "Checking mount entries and device mapper volumes..." - + # Wait for system to be fully ready (add a small delay) sleep 5 - + # Try to login via console to verify system is working log "Attempting to login via console with username 'alinux' and password 'aliyun'..." # Send username and password via QEMU monitor using sendkey command for char in a l i n u x; do - echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 + echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock >/dev/null 2>&1 sleep 0.1 done - echo -e "sendkey ret\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 - + echo -e "sendkey ret\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock >/dev/null 2>&1 + sleep 1 - + for char in a l i y u n; do - echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 + echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock >/dev/null 2>&1 sleep 0.1 done - echo -e "sendkey ret\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock > /dev/null 2>&1 - + echo -e "sendkey ret\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock >/dev/null 2>&1 + sleep 3 - + # Try to extract information from QEMU guest if [[ -S "qemu-monitor.sock" ]]; then log "Extracting information from QEMU guest..." - + # Extract /etc/mtab from guest - echo -e "human-monitor-command {\"command-line\":\"cat /etc/mtab\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock > mtab_output.txt 2>/dev/null - + echo -e "human-monitor-command {\"command-line\":\"cat /etc/mtab\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock >mtab_output.txt 2>/dev/null + # Extract /dev/mapper contents from guest - echo -e "human-monitor-command {\"command-line\":\"ls -1 /dev/mapper\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock > dev_mapper_output.txt 2>/dev/null - + echo -e "human-monitor-command {\"command-line\":\"ls -1 /dev/mapper\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock >dev_mapper_output.txt 2>/dev/null + # Check for rootfs mount entry (only checking the first 3 columns) if grep -q "^/dev/mapper/rootfs / overlay" mtab_output.txt; then log "Rootfs mount entry found in /etc/mtab!" @@ -483,7 +484,7 @@ check_mount_entries() { cat mtab_output.txt return 1 fi - + # Check for data mount entry if grep -q "^/dev/mapper/data /data " mtab_output.txt; then log "Data mount entry found in /etc/mtab!" @@ -493,7 +494,7 @@ check_mount_entries() { cat mtab_output.txt return 1 fi - + # Check for rootfs device mapper volume if grep -q "^rootfs$" dev_mapper_output.txt; then log "Rootfs device mapper volume found!" @@ -503,7 +504,7 @@ check_mount_entries() { cat dev_mapper_output.txt return 1 fi - + # Check for data device mapper volume if grep -q "^data$" dev_mapper_output.txt; then log "Data device mapper volume found!" @@ -513,7 +514,7 @@ check_mount_entries() { cat dev_mapper_output.txt return 1 fi - + log "All mount entries and device mapper volumes verified successfully!" return 0 else @@ -525,10 +526,10 @@ check_mount_entries() { # Start QEMU with the encrypted image (Local mode) start_qemu_local() { log "Starting QEMU with encrypted image (Local mode)..." - + # Find appropriate QEMU command find_qemu - + # Start QEMU with a simplified configuration for testing log "Starting QEMU - Press Ctrl+A then X to exit" $QEMU_CMD \ @@ -542,16 +543,21 @@ start_qemu_local() { # Main execution main() { + if [ "$(id -u)" != "0" ]; then + log::error "This script must be run as root" + exit 1 + fi + parse_args "$@" - + # Determine mode if not explicitly set if [[ "$CI_MODE" == false && "$LOCAL_MODE" == false && "$DOWNLOAD_ONLY" == false && "$ENCRYPT_ONLY" == false ]]; then # Default to CI mode CI_MODE=true fi - + log "Starting unified test script for system disk encryption" - + # Handle download-only mode if [[ "$DOWNLOAD_ONLY" == true ]]; then download_image @@ -559,7 +565,7 @@ main() { log "Download-only mode completed successfully!" exit 0 fi - + # Handle encrypt-only mode if [[ "$ENCRYPT_ONLY" == true ]]; then setup_config @@ -567,17 +573,17 @@ main() { log "Encrypt-only mode completed successfully!" exit 0 fi - + # Setup config for other modes setup_config - + # Download images or use existing ones download_image download_seed - + # Encrypt image encrypt_image - + # Handle CI mode if [[ "$CI_MODE" == true ]]; then start_qemu_ci @@ -586,7 +592,7 @@ main() { log "CI mode test completed successfully!" log "System disk encryption verification passed!" fi - + # Handle local mode if [[ "$LOCAL_MODE" == true ]]; then start_qemu_local @@ -595,4 +601,4 @@ main() { } # Run main function -main "$@" \ No newline at end of file +main "$@" From 3efaeac9387a5a6ce4e78589799cf70ea01c3d01 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 10:50:54 +0800 Subject: [PATCH 06/17] .github/workflows: merge tests into build-rpm.yml Signed-off-by: Kun Lai --- .github/actions/run-aa-as/action.yml | 24 ++++ .github/workflows/build-rpm.yml | 114 +++++++++++++++++- .github/workflows/test-kbs-volume.yml | 51 -------- .github/workflows/test-kms-volume.yml | 51 -------- .github/workflows/test-system-encryption.yml | 49 -------- .../test/test-system-encryption.sh | 0 .../test/test-volume-encryption.sh | 0 7 files changed, 136 insertions(+), 153 deletions(-) create mode 100644 .github/actions/run-aa-as/action.yml delete mode 100644 .github/workflows/test-kbs-volume.yml delete mode 100644 .github/workflows/test-kms-volume.yml delete mode 100644 .github/workflows/test-system-encryption.yml rename test-system-encryption.sh => scripts/test/test-system-encryption.sh (100%) rename test-kbs-volume.sh => scripts/test/test-volume-encryption.sh (100%) diff --git a/.github/actions/run-aa-as/action.yml b/.github/actions/run-aa-as/action.yml new file mode 100644 index 0000000..fe095e3 --- /dev/null +++ b/.github/actions/run-aa-as/action.yml @@ -0,0 +1,24 @@ +name: 'Run Attestation Agent and Attestation Service' +runs: + using: "composite" + steps: + - name: Prepare attestation-agent + shell: bash + run: | + set -e + set -x + + yum install -y attestation-agent + RUST_LOG=debug attestation-agent --attestation_sock unix:///run/confidential-containers/attestation-agent/attestation-agent.sock & + + - name: Prepare attestation-service + shell: bash + run: | + set -e + set -x + + yum install -y trustee + (/usr/bin/rvps --config /etc/trustee/rvps.json --address 127.0.0.1:50003 &) && sleep 1 + (/usr/bin/grpc-as --socket 0.0.0.0:50004 --config-file /etc/trustee/as-config.json &) && sleep 1 + (/usr/bin/kbs --config-file /etc/trustee/kbs-config.toml &) && sleep 1 + (/usr/bin/trustee-gateway --config /etc/trustee/gateway.yml &) && sleep 1 diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index 88f4399..b114475 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -57,7 +57,7 @@ jobs: ./rpmbuild/SRPMS/*.src.rpm ./rpmbuild/RPMS/*/*.rpm - test: + unit-test: strategy: fail-fast: false matrix: @@ -114,10 +114,120 @@ jobs: - name: Run test script from repo run: make run-test + test-volume-encryption: + strategy: + fail-fast: false + matrix: + distro: ["alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest"] + runs-on: ubuntu-latest + defaults: + run: + shell: bash + needs: build + container: + image: ${{ matrix.distro }} + volumes: + - /run/udev/control:/run/udev/control + - /dev:/dev + options: --privileged --ipc=host + steps: + - name: Update yum mirror + run: | + set -e + set -x + + # replace the mirror + sed -i -E 's|https?://mirrors.openanolis.cn/anolis/|https://mirrors.aliyun.com/anolis/|g' /etc/yum.repos.d/*.repo + sed -i -E 's|https?://mirrors.cloud.aliyuncs.com/|https://mirrors.aliyun.com/|g' /etc/yum.repos.d/*.repo + + # install rpmdevtools + yum install -y git yum-utils + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: ./ + merge-multiple: false + + - name: Install RPM packages + run: | + set -e + set -x + + # test rpm package install + yum install -y ./rpm-packages/RPMS/*/cryptpilot-*.rpm + cryptpilot --version + + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: 'true' + + - uses: ./.github/actions/run-aa-as + + - name: Run volume encryption test + run: | + bash ./scripts/test/test-volume-encryption.sh + + test-system-encryption: + strategy: + fail-fast: false + matrix: + distro: ["alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest"] + runs-on: ubuntu-latest + defaults: + run: + shell: bash + needs: build + container: + image: ${{ matrix.distro }} + volumes: + - /run/udev/control:/run/udev/control + - /dev:/dev + options: --privileged --ipc=host + steps: + - name: Update yum mirror + run: | + set -e + set -x + + # replace the mirror + sed -i -E 's|https?://mirrors.openanolis.cn/anolis/|https://mirrors.aliyun.com/anolis/|g' /etc/yum.repos.d/*.repo + sed -i -E 's|https?://mirrors.cloud.aliyuncs.com/|https://mirrors.aliyun.com/|g' /etc/yum.repos.d/*.repo + + # install rpmdevtools + yum install -y git yum-utils + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: ./ + merge-multiple: false + + - name: Install RPM packages + run: | + set -e + set -x + + # test rpm package install + yum install -y ./rpm-packages/RPMS/*/cryptpilot-*.rpm + cryptpilot --version + + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: 'true' + + - uses: ./.github/actions/run-aa-as + + - name: Run system encryption test + run: | + timeout 300s sudo bash ./scripts/test/test-system-encryption.sh --ci + release: if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest - needs: test + needs: [unit-test, test-volume-encryption, test-system-encryption] steps: - name: Download artifacts uses: actions/download-artifact@v4 diff --git a/.github/workflows/test-kbs-volume.yml b/.github/workflows/test-kbs-volume.yml deleted file mode 100644 index 158b070..0000000 --- a/.github/workflows/test-kbs-volume.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Test KBS Volume Encryption - -on: - push: - branches: - - master - tags: - - "v*.*.*" - pull_request: - branches: - - 'master' - -jobs: - test-kbs-volume: - runs-on: ubuntu-22.04 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - wget \ - curl \ - build-essential \ - pkg-config \ - libssl-dev \ - libdevmapper-dev \ - libsystemd-dev \ - parted - - - name: Setup Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - - name: Build cryptpilot - run: | - cargo build --release - - - name: Install cryptpilot - run: | - sudo cp target/release/cryptpilot /usr/local/bin/ - sudo cp target/release/cryptpilot-convert /usr/local/bin/ - - - name: Run KBS volume encryption test - run: | - chmod +x test-kbs-volume.sh - sudo ./test-kbs-volume.sh --keep-files \ No newline at end of file diff --git a/.github/workflows/test-kms-volume.yml b/.github/workflows/test-kms-volume.yml deleted file mode 100644 index b341a6d..0000000 --- a/.github/workflows/test-kms-volume.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Test KMS Volume Encryption - -on: - push: - branches: - - master - tags: - - "v*.*.*" - pull_request: - branches: - - 'master' - -jobs: - test-kms-volume: - runs-on: ubuntu-22.04 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - wget \ - curl \ - build-essential \ - pkg-config \ - libssl-dev \ - libdevmapper-dev \ - libsystemd-dev \ - parted - - - name: Setup Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - - name: Build cryptpilot - run: | - cargo build --release - - - name: Install cryptpilot - run: | - sudo cp target/release/cryptpilot /usr/local/bin/ - sudo cp target/release/cryptpilot-convert /usr/local/bin/ - - - name: Run KMS volume encryption test - run: | - chmod +x test-kms-volume.sh - sudo ./test-kms-volume.sh --keep-files \ No newline at end of file diff --git a/.github/workflows/test-system-encryption.yml b/.github/workflows/test-system-encryption.yml deleted file mode 100644 index 98c1e74..0000000 --- a/.github/workflows/test-system-encryption.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Test System Disk Encryption - -on: - push: - branches: - - master - tags: - - "v*.*.*" - pull_request: - branches: - - 'master' - -jobs: - test-encryption: - runs-on: ubuntu-22.04 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - qemu-system-x86 \ - qemu-kvm \ - qemu-utils \ - wget \ - curl \ - socat \ - build-essential \ - pkg-config \ - libssl-dev \ - libdevmapper-dev \ - libsystemd-dev - - - name: Setup Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - - name: Build cryptpilot - run: | - cargo build --release - - - name: Run system encryption test - run: | - chmod +x test-system-encryption.sh - timeout 300s sudo ./test-system-encryption.sh --ci \ No newline at end of file diff --git a/test-system-encryption.sh b/scripts/test/test-system-encryption.sh similarity index 100% rename from test-system-encryption.sh rename to scripts/test/test-system-encryption.sh diff --git a/test-kbs-volume.sh b/scripts/test/test-volume-encryption.sh similarity index 100% rename from test-kbs-volume.sh rename to scripts/test/test-volume-encryption.sh From 7e8ac490d28ea54d6abe437d3689989a8907619e Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 11:31:49 +0800 Subject: [PATCH 07/17] remove seed.img and set password with virt-customize Signed-off-by: Kun Lai --- .github/workflows/build-rpm.yml | 4 ++ scripts/test/test-system-encryption.sh | 82 ++++++++------------------ 2 files changed, 28 insertions(+), 58 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index b114475..0975413 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -198,6 +198,9 @@ jobs: # install rpmdevtools yum install -y git yum-utils + # install requirements + yum install -y libguestfs-tools + - name: Download artifacts uses: actions/download-artifact@v4 with: @@ -222,6 +225,7 @@ jobs: - name: Run system encryption test run: | + export LIBGUESTFS_BACKEND=appliance # set this for virt-customize timeout 300s sudo bash ./scripts/test/test-system-encryption.sh --ci release: diff --git a/scripts/test/test-system-encryption.sh b/scripts/test/test-system-encryption.sh index 5f1ed3b..a890be4 100755 --- a/scripts/test/test-system-encryption.sh +++ b/scripts/test/test-system-encryption.sh @@ -15,8 +15,6 @@ IMAGE_NAME="alinux3.qcow2" ENCRYPTED_IMAGE_NAME="encrypted.qcow2" CONFIG_DIR="test-config" PASSPHRASE="AAAaaawewe222" -SEED_IMAGE="seed.img" -SEED_URL="https://alinux3.oss-cn-hangzhou.aliyuncs.com/seed.img" LOG_FILE="qemu-output.log" # Mode flags @@ -28,7 +26,6 @@ KEEP_FILES=false # Paths to existing images (prefixed with @ to indicate they should be used as-is) EXISTING_IMAGE_PATH="" -EXISTING_SEED_PATH="" # QEMU command to use QEMU_CMD="" @@ -65,13 +62,11 @@ OPTIONS: -e, --encrypt-only Encrypt existing image only -k, --keep-files Keep downloaded files after execution --image-url URL Specify custom image URL - --seed-url URL Specify custom seed image URL --image-name NAME Specify custom image filename --encrypted-name NAME Specify custom encrypted image filename --config-dir DIR Specify custom config directory --passphrase PHRASE Specify custom passphrase --existing-image PATH Use existing image file (prefix with @, e.g., @/path/to/image.qcow2) - --existing-seed PATH Use existing seed file (prefix with @, e.g., @/path/to/seed.img) EXAMPLES: $0 --ci # Run full CI test @@ -79,7 +74,7 @@ EXAMPLES: $0 --download-only # Download images only $0 --encrypt-only # Encrypt existing image $0 --ci --keep-files # Run CI test but keep files - $0 --ci --existing-image @/root/diskenc/aliyun_3_x64_20G_nocloud_alibase_20250117.qcow2 --existing-seed @/root/diskenc/seed.img + $0 --ci --existing-image @/root/diskenc/aliyun_3_x64_20G_nocloud_alibase_20250117.qcow2 EOF } @@ -129,10 +124,6 @@ parse_args() { IMAGE_URL="$2" shift 2 ;; - --seed-url) - SEED_URL="$2" - shift 2 - ;; --image-name) IMAGE_NAME="$2" shift 2 @@ -153,10 +144,6 @@ parse_args() { EXISTING_IMAGE_PATH="$2" shift 2 ;; - --existing-seed) - EXISTING_SEED_PATH="$2" - shift 2 - ;; *) error "Unknown option: $1" ;; @@ -189,9 +176,6 @@ cleanup() { if [[ -z "$EXISTING_IMAGE_PATH" ]]; then [[ "$DOWNLOAD_ONLY" == false && "$ENCRYPT_ONLY" == false ]] && [[ -f "${IMAGE_NAME}" ]] && rm -f "${IMAGE_NAME}" fi - if [[ -z "$EXISTING_SEED_PATH" ]]; then - [[ "$DOWNLOAD_ONLY" == false ]] && [[ -f "${SEED_IMAGE}" ]] && rm -f "${SEED_IMAGE}" - fi [[ "$DOWNLOAD_ONLY" == false ]] && [[ -f "${ENCRYPTED_IMAGE_NAME}" ]] && rm -f "${ENCRYPTED_IMAGE_NAME}" [[ -S "qemu-monitor.sock" ]] && rm -f "qemu-monitor.sock" [[ -f "${LOG_FILE}" ]] && rm -f "${LOG_FILE}" @@ -274,39 +258,7 @@ download_image() { log "Image downloaded successfully" } -# Download seed image -download_seed() { - # If existing seed path is provided, use it - if [[ -n "$EXISTING_SEED_PATH" ]]; then - # Remove the @ prefix - local existing_path="${EXISTING_SEED_PATH#@}" - if [[ -f "$existing_path" ]]; then - log "Using existing seed file: $existing_path" - # Create a symlink or copy to our expected name - ln -sf "$existing_path" "${SEED_IMAGE}" - return - else - error "Specified existing seed file not found: $existing_path" - fi - fi - - if [[ -f "${SEED_IMAGE}" ]]; then - log "Using existing seed image file" - return - fi - log "Downloading seed image from ${SEED_URL}..." - if command -v wget >/dev/null 2>&1; then - wget -O "${SEED_IMAGE}" "${SEED_URL}" || error "Failed to download seed image with wget" - elif command -v curl >/dev/null 2>&1; then - curl -L -o "${SEED_IMAGE}" "${SEED_URL}" || error "Failed to download seed image with curl" - else - error "Neither wget nor curl found" - fi - - [[ -f "${SEED_IMAGE}" ]] || error "Seed image file not found after download" - log "Seed image downloaded successfully" -} # Encrypt image with cryptpilot-convert encrypt_image() { @@ -350,7 +302,7 @@ start_qemu_ci() { find_qemu # Print QEMU command for debugging - log "QEMU command: $QEMU_CMD -m 2048M -smp 2 -nographic -serial mon:stdio -monitor unix:qemu-monitor.sock,server,nowait -drive file=${ENCRYPTED_IMAGE_NAME},format=qcow2,if=virtio,id=hd0,readonly=off -drive file=${SEED_IMAGE},if=virtio,format=raw -netdev user,id=net0,net=192.168.123.0/24,hostfwd=tcp::2222-:22 -device virtio-net,netdev=net0" + log "QEMU command: $QEMU_CMD -m 2048M -smp 2 -nographic -serial mon:stdio -monitor unix:qemu-monitor.sock,server,nowait -drive file=${ENCRYPTED_IMAGE_NAME},format=qcow2,if=virtio,id=hd0,readonly=off -netdev user,id=net0,net=192.168.123.0/24,hostfwd=tcp::2222-:22 -device virtio-net,netdev=net0" # Start QEMU in background, redirecting output to file for analysis $QEMU_CMD \ @@ -360,7 +312,6 @@ start_qemu_ci() { -serial mon:stdio \ -monitor unix:qemu-monitor.sock,server,nowait \ -drive file="${ENCRYPTED_IMAGE_NAME}",format=qcow2,if=virtio,id=hd0,readonly=off \ - -drive file="${SEED_IMAGE}",if=virtio,format=raw \ -netdev user,id=net0,net=192.168.123.0/24,hostfwd=tcp::2222-:22 \ -device virtio-net,netdev=net0 \ >"${LOG_FILE}" 2>&1 & @@ -447,9 +398,9 @@ check_mount_entries() { sleep 5 # Try to login via console to verify system is working - log "Attempting to login via console with username 'alinux' and password 'aliyun'..." + log "Attempting to login via console with username 'root' and password 'root'..." # Send username and password via QEMU monitor using sendkey command - for char in a l i n u x; do + for char in r o o t; do echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock >/dev/null 2>&1 sleep 0.1 done @@ -457,7 +408,7 @@ check_mount_entries() { sleep 1 - for char in a l i y u n; do + for char in r o o t; do echo -e "sendkey ${char}\n" | timeout 10 socat - UNIX-CONNECT:qemu-monitor.sock >/dev/null 2>&1 sleep 0.1 done @@ -537,8 +488,7 @@ start_qemu_local() { -smp 2 \ -nographic \ -serial mon:stdio \ - -drive file="${ENCRYPTED_IMAGE_NAME}",format=qcow2,if=virtio,id=hd0,readonly=off \ - -drive file="${SEED_IMAGE}",if=virtio,format=raw + -drive file="${ENCRYPTED_IMAGE_NAME}",format=qcow2,if=virtio,id=hd0,readonly=off } # Main execution @@ -561,7 +511,6 @@ main() { # Handle download-only mode if [[ "$DOWNLOAD_ONLY" == true ]]; then download_image - download_seed log "Download-only mode completed successfully!" exit 0 fi @@ -579,7 +528,9 @@ main() { # Download images or use existing ones download_image - download_seed + + # 使用virt-customize设置root密码 + set_root_password # Encrypt image encrypt_image @@ -600,5 +551,20 @@ main() { fi } +# Set root password using virt-customize +set_root_password() { + log "Setting root password using virt-customize..." + + # Check if virt-customize is available + if ! command -v virt-customize >/dev/null 2>&1; then + error "virt-customize not found. Please install libguestfs-tools package." + fi + + # Use virt-customize to set root password to root + virt-customize -a "${IMAGE_NAME}" --root-password password:root || error "Failed to set root password" + + log "Root password set successfully" +} + # Run main function main "$@" From bb1844a81786a1eb52ba40f482fc7cd6e60617cf Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 11:44:35 +0800 Subject: [PATCH 08/17] test-system-encryption.sh: add test run podman in qemu Signed-off-by: Kun Lai --- scripts/test/test-system-encryption.sh | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/scripts/test/test-system-encryption.sh b/scripts/test/test-system-encryption.sh index a890be4..00a1cc8 100755 --- a/scripts/test/test-system-encryption.sh +++ b/scripts/test/test-system-encryption.sh @@ -474,6 +474,37 @@ check_mount_entries() { fi } +# Test container functionality by installing podman and running a simple container +test_container_functionality() { + log "Testing container functionality..." + + if [[ -S "qemu-monitor.sock" ]]; then + log "Installing podman and running test container..." + + # Install podman + echo -e "human-monitor-command {\"command-line\":\"yum install -y podman\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock >podman_install_output.txt 2>/dev/null + sleep 10 + + # Run test container with echo command + echo -e "human-monitor-command {\"command-line\":\"podman run --rm ghcr.io/linuxcontainers/alpine:latest echo 'Hello from container!'\"}\nquit" | socat - UNIX-CONNECT:qemu-monitor.sock >container_test_output.txt 2>/dev/null + sleep 5 + + # Check if the container ran successfully + if grep -q "Hello from container!" container_test_output.txt; then + log "Container test passed successfully!" + return 0 + else + log "Container test failed." + log "Container test output:" + cat container_test_output.txt + return 1 + fi + else + warn "QEMU monitor socket not available, skipping container functionality test" + return 0 + fi +} + # Start QEMU with the encrypted image (Local mode) start_qemu_local() { log "Starting QEMU with encrypted image (Local mode)..." @@ -540,6 +571,7 @@ main() { start_qemu_ci verify_boot check_mount_entries + test_container_functionality log "CI mode test completed successfully!" log "System disk encryption verification passed!" fi From 5c2eff38e403d5863c9ec07d44f14c5e2ccd659c Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 11:46:01 +0800 Subject: [PATCH 09/17] test-system-encryption.sh: add --package to use latest cryptpilot rpm Signed-off-by: Kun Lai --- .github/workflows/build-rpm.yml | 2 +- scripts/test/test-system-encryption.sh | 69 ++++++++++++++++++-------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index 0975413..6c43a1d 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -226,7 +226,7 @@ jobs: - name: Run system encryption test run: | export LIBGUESTFS_BACKEND=appliance # set this for virt-customize - timeout 300s sudo bash ./scripts/test/test-system-encryption.sh --ci + timeout 300s bash ./scripts/test/test-system-encryption.sh --ci --package ./rpm-packages/RPMS/*/cryptpilot-*.rpm release: if: startsWith(github.ref, 'refs/tags/') diff --git a/scripts/test/test-system-encryption.sh b/scripts/test/test-system-encryption.sh index 00a1cc8..16fc551 100755 --- a/scripts/test/test-system-encryption.sh +++ b/scripts/test/test-system-encryption.sh @@ -24,6 +24,9 @@ DOWNLOAD_ONLY=false ENCRYPT_ONLY=false KEEP_FILES=false +# Package list for cryptpilot-convert +PACKAGES=() + # Paths to existing images (prefixed with @ to indicate they should be used as-is) EXISTING_IMAGE_PATH="" @@ -66,6 +69,7 @@ OPTIONS: --encrypted-name NAME Specify custom encrypted image filename --config-dir DIR Specify custom config directory --passphrase PHRASE Specify custom passphrase + --package PACKAGE Specify an RPM package name or path to install (can be used multiple times) --existing-image PATH Use existing image file (prefix with @, e.g., @/path/to/image.qcow2) EXAMPLES: @@ -74,6 +78,7 @@ EXAMPLES: $0 --download-only # Download images only $0 --encrypt-only # Encrypt existing image $0 --ci --keep-files # Run CI test but keep files + $0 --ci --package /path/to/package.rpm --package another-package $0 --ci --existing-image @/root/diskenc/aliyun_3_x64_20G_nocloud_alibase_20250117.qcow2 EOF @@ -140,6 +145,10 @@ parse_args() { PASSPHRASE="$2" shift 2 ;; + --package) + PACKAGES+=("$2") + shift 2 + ;; --existing-image) EXISTING_IMAGE_PATH="$2" shift 2 @@ -258,7 +267,34 @@ download_image() { log "Image downloaded successfully" } +# Find cryptpilot-convert command +find_cryptpilot_convert() { + log "Detecting cryptpilot-convert installation..." + + # Check if cryptpilot-convert is available in PATH + if command -v cryptpilot-convert >/dev/null 2>&1; then + CRYPTPILOT_CONVERT_CMD="cryptpilot-convert" + log "Found cryptpilot-convert command: $CRYPTPILOT_CONVERT_CMD" + return 0 + fi + + # Try to use built version + if [[ -f "target/release/cryptpilot-convert" ]]; then + CRYPTPILOT_CONVERT_CMD="./target/release/cryptpilot-convert" + log "Found built cryptpilot-convert: $CRYPTPILOT_CONVERT_CMD" + return 0 + fi + + # Try to use script version + if [[ -f "cryptpilot-convert.sh" ]]; then + chmod +x cryptpilot-convert.sh + CRYPTPILOT_CONVERT_CMD="./cryptpilot-convert.sh" + log "Found cryptpilot-convert script: $CRYPTPILOT_CONVERT_CMD" + return 0 + fi + error "cryptpilot-convert not found" +} # Encrypt image with cryptpilot-convert encrypt_image() { @@ -269,26 +305,19 @@ encrypt_image() { log "Encrypting image with cryptpilot-convert..." - # Check if cryptpilot-convert is available - if ! command -v cryptpilot-convert >/dev/null 2>&1; then - # Try to build it if not available - if [[ -f "target/release/cryptpilot-convert" ]]; then - log "Using built cryptpilot-convert" - ./target/release/cryptpilot-convert --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ - --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" || error "Encryption failed" - elif [[ -f "cryptpilot-convert.sh" ]]; then - log "Using cryptpilot-convert.sh script" - chmod +x cryptpilot-convert.sh - ./cryptpilot-convert.sh --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ - --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" || error "Encryption failed" - else - error "cryptpilot-convert not found" - fi - else - # Use the binary directly - cryptpilot-convert --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ - --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" || error "Encryption failed" - fi + # Find cryptpilot-convert command + find_cryptpilot_convert + + # Build package arguments + local package_args=() + for package in "${PACKAGES[@]}"; do + package_args+=(--package "$package") + done + + # Run cryptpilot-convert + "$CRYPTPILOT_CONVERT_CMD" --in "${IMAGE_NAME}" --out "${ENCRYPTED_IMAGE_NAME}" \ + --config-dir "${CONFIG_DIR}" --rootfs-passphrase "${PASSPHRASE}" \ + "${package_args[@]}" || error "Encryption failed" [[ -f "${ENCRYPTED_IMAGE_NAME}" ]] || error "Encrypted image not found after encryption process" log "Image encrypted successfully" From 8e1d82f55ae50cf63faa7a8ea36b3ccb3ec0aca7 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 12:13:31 +0800 Subject: [PATCH 10/17] .github/workflows: register passphrases into trustee Signed-off-by: Kun Lai --- .github/actions/run-aa-as/action.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/actions/run-aa-as/action.yml b/.github/actions/run-aa-as/action.yml index fe095e3..9524dd3 100644 --- a/.github/actions/run-aa-as/action.yml +++ b/.github/actions/run-aa-as/action.yml @@ -18,7 +18,17 @@ runs: set -x yum install -y trustee + + # Launch trustee (/usr/bin/rvps --config /etc/trustee/rvps.json --address 127.0.0.1:50003 &) && sleep 1 (/usr/bin/grpc-as --socket 0.0.0.0:50004 --config-file /etc/trustee/as-config.json &) && sleep 1 (/usr/bin/kbs --config-file /etc/trustee/kbs-config.toml &) && sleep 1 (/usr/bin/trustee-gateway --config /etc/trustee/gateway.yml &) && sleep 1 + + # Register passphrases + mkdir -p /opt/trustee/kbs/repository/default/local-resources/ + echo -n "AAAaaawewe111" > /opt/trustee/kbs/repository/default/local-resources/volume + echo -n "AAAaaawewe222" > /opt/trustee/kbs/repository/default/local-resources/rootfs + echo -n "AAAaaawewe333" > /opt/trustee/kbs/repository/default/local-resources/data + + From ad7d6601d35d0a5fd45974100b1e0bd078c356f7 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 12:15:28 +0800 Subject: [PATCH 11/17] .github/workflows: change key provider from exec to kbs Signed-off-by: Kun Lai --- .github/workflows/build-rpm.yml | 2 +- scripts/test/test-system-encryption.sh | 69 +++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index 6c43a1d..b0914be 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -226,7 +226,7 @@ jobs: - name: Run system encryption test run: | export LIBGUESTFS_BACKEND=appliance # set this for virt-customize - timeout 300s bash ./scripts/test/test-system-encryption.sh --ci --package ./rpm-packages/RPMS/*/cryptpilot-*.rpm + timeout 300s bash ./scripts/test/test-system-encryption.sh --ci --package ./rpm-packages/RPMS/*/cryptpilot-*.rpm --trustee-url "http://127.0.0.1:8081/api/" release: if: startsWith(github.ref, 'refs/tags/') diff --git a/scripts/test/test-system-encryption.sh b/scripts/test/test-system-encryption.sh index 16fc551..2584c86 100755 --- a/scripts/test/test-system-encryption.sh +++ b/scripts/test/test-system-encryption.sh @@ -16,6 +16,7 @@ ENCRYPTED_IMAGE_NAME="encrypted.qcow2" CONFIG_DIR="test-config" PASSPHRASE="AAAaaawewe222" LOG_FILE="qemu-output.log" +TRUSTEE_URL="http://127.0.0.1:8081/api/" # Trustee service URL # Mode flags CI_MODE=false @@ -70,6 +71,7 @@ OPTIONS: --config-dir DIR Specify custom config directory --passphrase PHRASE Specify custom passphrase --package PACKAGE Specify an RPM package name or path to install (can be used multiple times) + --trustee-url URL Specify Trustee service URL for remote attestation --existing-image PATH Use existing image file (prefix with @, e.g., @/path/to/image.qcow2) EXAMPLES: @@ -79,6 +81,7 @@ EXAMPLES: $0 --encrypt-only # Encrypt existing image $0 --ci --keep-files # Run CI test but keep files $0 --ci --package /path/to/package.rpm --package another-package + $0 --ci --trustee-url https://trustee.example.com $0 --ci --existing-image @/root/diskenc/aliyun_3_x64_20G_nocloud_alibase_20250117.qcow2 EOF @@ -149,6 +152,10 @@ parse_args() { PACKAGES+=("$2") shift 2 ;; + --trustee-url) + TRUSTEE_URL="$2" + shift 2 + ;; --existing-image) EXISTING_IMAGE_PATH="$2" shift 2 @@ -212,18 +219,18 @@ setup_config() { cat >"${CONFIG_DIR}/fde.toml" </dev/null 2>&1; then + error "cryptpilot command not found" + fi + + # Calculate reference values + log "Generating reference values using cryptpilot..." + if cryptpilot fde show-reference-value --stage initrd --disk "${ENCRYPTED_IMAGE_NAME}" > reference-value.json; then + log "Reference values calculated and saved to reference-value.json" + else + error "Failed to calculate reference values" + fi + + # Display reference values + log "Reference values:" + cat reference-value.json + + # Register reference values with Trustee service + log "Registering reference values with Trustee service..." + local provenance + provenance=$(cat ./reference-value.json | base64 --wrap=0) + + cat << EOF > ./register-request.json +{ + "version" : "0.1.0", + "type": "sample", + "payload": "$provenance" +} +EOF + + if command -v rvps-tool >/dev/null 2>&1; then + if rvps-tool register --path ./register-request.json; then + log "Reference values registered successfully with Trustee service" + else + warn "Failed to register reference values with Trustee service" + fi + else + warn "rvps-tool not found, skipping reference value registration" + fi +} + # Main execution main() { if [ "$(id -u)" != "0" ]; then @@ -594,6 +646,9 @@ main() { # Encrypt image encrypt_image + + # Calculate reference values + calculate_reference_values # Handle CI mode if [[ "$CI_MODE" == true ]]; then From 307a004495e259cb53c650ff5c29f439c6579274 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 12:21:23 +0800 Subject: [PATCH 12/17] test-volume-encryption.sh: check for missing package Signed-off-by: Kun Lai --- scripts/test/test-volume-encryption.sh | 42 ++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/scripts/test/test-volume-encryption.sh b/scripts/test/test-volume-encryption.sh index 11b786c..6d8b8a8 100755 --- a/scripts/test/test-volume-encryption.sh +++ b/scripts/test/test-volume-encryption.sh @@ -5,6 +5,45 @@ set -e # Exit on any error +# Function to check and install required commands +check_and_install_commands() { + local missing_commands=() + local install_commands=() + + # List of required commands and their packages (for RHEL/CentOS) + local commands_and_packages=( + "losetup:util-linux" + "parted:parted" + "mount:util-linux" + "umount:util-linux" + ) + + # Check which commands are missing + for item in "${commands_and_packages[@]}"; do + local cmd="${item%%:*}" + local pkg="${item#*:}" + + if ! command -v "$cmd" >/dev/null 2>&1; then + missing_commands+=("$cmd") + install_commands+=("$pkg") + fi + done + + # If there are missing commands, try to install them + if [ ${#missing_commands[@]} -gt 0 ]; then + echo "Missing required commands: ${missing_commands[*]}" + + echo "Attempting to install missing packages with yum..." + if ! yum install -y "${install_commands[@]}"; then + echo "Failed to install packages with yum. Please install the following packages manually:" + echo "${install_commands[*]}" + exit 1 + fi + fi + + echo "All required commands are available." +} + # Default configuration CONFIG_DIR="test-kbs-config" LOG_FILE="test-output.log" @@ -271,6 +310,9 @@ main() { parse_args "$@" + # Check and install required commands + check_and_install_commands + log "Starting KBS volume encryption test" # Setup config From fcf207d0fd95e4769870940999fabb7d04da5a09 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 13:53:31 +0800 Subject: [PATCH 13/17] test-volume-encryption.sh: change to use real trustee Signed-off-by: Kun Lai --- .github/workflows/build-rpm.yml | 2 +- scripts/test/test-system-encryption.sh | 2 +- scripts/test/test-volume-encryption.sh | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index b0914be..ecf81ee 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -226,7 +226,7 @@ jobs: - name: Run system encryption test run: | export LIBGUESTFS_BACKEND=appliance # set this for virt-customize - timeout 300s bash ./scripts/test/test-system-encryption.sh --ci --package ./rpm-packages/RPMS/*/cryptpilot-*.rpm --trustee-url "http://127.0.0.1:8081/api/" + timeout 300s bash ./scripts/test/test-system-encryption.sh --ci --package ./rpm-packages/RPMS/*/cryptpilot-*.rpm --trustee-url "http://10.0.2.2:8081/api/" release: if: startsWith(github.ref, 'refs/tags/') diff --git a/scripts/test/test-system-encryption.sh b/scripts/test/test-system-encryption.sh index 2584c86..9ac2a43 100755 --- a/scripts/test/test-system-encryption.sh +++ b/scripts/test/test-system-encryption.sh @@ -16,7 +16,7 @@ ENCRYPTED_IMAGE_NAME="encrypted.qcow2" CONFIG_DIR="test-config" PASSPHRASE="AAAaaawewe222" LOG_FILE="qemu-output.log" -TRUSTEE_URL="http://127.0.0.1:8081/api/" # Trustee service URL +TRUSTEE_URL="http://10.0.2.2:8081/api/" # Trustee service URL # Mode flags CI_MODE=false diff --git a/scripts/test/test-volume-encryption.sh b/scripts/test/test-volume-encryption.sh index 6d8b8a8..2659961 100755 --- a/scripts/test/test-volume-encryption.sh +++ b/scripts/test/test-volume-encryption.sh @@ -5,6 +5,8 @@ set -e # Exit on any error +TRUSTEE_URL="http://127.0.0.1:8081/api/" # Trustee service URL + # Function to check and install required commands check_and_install_commands() { local missing_commands=() @@ -141,11 +143,9 @@ auto_open = true makefs = "ext4" integrity = true -# For CI test, we use exec provider to simulate KBS behavior -# In real usage, this would be [encrypt.kbs] with actual KBS configuration -[encrypt.exec] -command = "echo" -args = ["-n", "test-passphrase-for-kbs"] +[encrypt.kbs] +kbs_url = "${TRUSTEE_URL}" +key_uri = "kbs:///default/local-resources/volume" EOF } From 0a69d905156e1a4df82a5ab81f8a3ac6b2337322 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 14:22:19 +0800 Subject: [PATCH 14/17] test-volume-encryption.sh: remove log file Signed-off-by: Kun Lai --- scripts/test/test-volume-encryption.sh | 33 +++++++------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/scripts/test/test-volume-encryption.sh b/scripts/test/test-volume-encryption.sh index 2659961..bd12a92 100755 --- a/scripts/test/test-volume-encryption.sh +++ b/scripts/test/test-volume-encryption.sh @@ -48,7 +48,6 @@ check_and_install_commands() { # Default configuration CONFIG_DIR="test-kbs-config" -LOG_FILE="test-output.log" # Colors for output RED='\033[0;31m' @@ -113,7 +112,6 @@ cleanup() { if [[ "$KEEP_FILES" == false ]]; then log "Cleaning up..." [[ -d "${CONFIG_DIR}" ]] && rm -rf "${CONFIG_DIR}" - [[ -f "${LOG_FILE}" ]] && rm -f "${LOG_FILE}" # Detach any loop device associated with test-disk.img if losetup -a | grep -q "test-disk.img"; then @@ -198,9 +196,8 @@ test_volume_init() { log "Initializing KBS volume..." # Initialize the volume - if ! cryptpilot init kbs-test -c "${CONFIG_DIR}" -y >"${LOG_FILE}" 2>&1; then - echo "Failed to initialize volume. Log output:" - cat "${LOG_FILE}" + if ! cryptpilot init kbs-test -c "${CONFIG_DIR}" -y; then + echo "Failed to initialize volume." return 1 fi @@ -212,9 +209,8 @@ test_volume_open() { log "Opening KBS volume..." # Open the volume - if ! cryptpilot open kbs-test -c "${CONFIG_DIR}" >"${LOG_FILE}" 2>&1; then - echo "Failed to open volume. Log output:" - cat "${LOG_FILE}" + if ! cryptpilot open kbs-test -c "${CONFIG_DIR}"; then + echo "Failed to open volume." return 1 fi @@ -232,20 +228,8 @@ test_volume_show() { log "Showing volume status..." # Show volume status - if ! cryptpilot show -c "${CONFIG_DIR}" >"${LOG_FILE}" 2>&1; then - echo "Failed to show volume status. Log output:" - cat "${LOG_FILE}" - return 1 - fi - - # Check if our volume is listed and opened - if ! grep -q "kbs-test" "${LOG_FILE}"; then - echo "Volume kbs-test not found in show output" - return 1 - fi - - if ! grep -q "True" "${LOG_FILE}"; then - echo "Volume kbs-test is not opened according to show output" + if ! cryptpilot show -c "${CONFIG_DIR}"; then + echo "Failed to show volume status." return 1 fi @@ -286,9 +270,8 @@ test_volume_close() { log "Closing KBS volume..." # Close the volume - if ! cryptpilot close kbs-test -c "${CONFIG_DIR}" >"${LOG_FILE}" 2>&1; then - echo "Failed to close volume. Log output:" - cat "${LOG_FILE}" + if ! cryptpilot close kbs-test -c "${CONFIG_DIR}"; then + echo "Failed to close volume." return 1 fi From ef58f83870e2f6989987860da9a4a74a0944bc1f Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 14:28:13 +0800 Subject: [PATCH 15/17] .github/workflows: fix module nbd not found in test-system-encryption Signed-off-by: Kun Lai --- .github/workflows/build-rpm.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index ecf81ee..5dfb5b6 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -184,6 +184,7 @@ jobs: volumes: - /run/udev/control:/run/udev/control - /dev:/dev + - /lib/modules/:/lib/modules/ # for kernel modules options: --privileged --ipc=host steps: - name: Update yum mirror From 9072ad85e93d01109589dc3216b963452f38e262 Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Fri, 5 Sep 2025 17:39:22 +0800 Subject: [PATCH 16/17] test-volume-encryption.sh: skip iteration on /dev/loop* Signed-off-by: Kun Lai --- scripts/test/test-volume-encryption.sh | 37 +++++++------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/scripts/test/test-volume-encryption.sh b/scripts/test/test-volume-encryption.sh index bd12a92..532ac25 100755 --- a/scripts/test/test-volume-encryption.sh +++ b/scripts/test/test-volume-encryption.sh @@ -15,7 +15,6 @@ check_and_install_commands() { # List of required commands and their packages (for RHEL/CentOS) local commands_and_packages=( "losetup:util-linux" - "parted:parted" "mount:util-linux" "umount:util-linux" ) @@ -136,7 +135,7 @@ setup_config() { # Create a KBS volume config (using mock values for CI) cat >"${CONFIG_DIR}/volumes/kbs-test.toml" </dev/null || true - fi - done + LOOP_DEVICE=$(losetup --associated "$IMAGE" | awk '{print $1}') + if [ -n "$LOOP_DEVICE" ]; then + losetup -d "$LOOP_DEV" 2>/dev/null || true + fi # Set up loop device (try different numbers if /dev/loop99 is busy) - LOOP_DEV="" - for i in {99..90}; do - if ! losetup -P /dev/loop"$i" test-disk.img 2>/dev/null; then - continue - else - LOOP_DEV="/dev/loop$i" - break - fi - done + LOOP_DEV=$(losetup --find) if [[ -z "$LOOP_DEV" ]]; then error "Failed to set up loop device" fi - # Update the config file to use the actual loop device - sed -i "s|/dev/loop99|${LOOP_DEV}|g" ${CONFIG_DIR}/volumes/kbs-test.toml - - # Create GPT partition table and one partition - parted --script "$LOOP_DEV" \ - mktable gpt \ - mkpart primary 1MiB 100% - # Wait for partition to be ready sleep 2 @@ -298,12 +279,12 @@ main() { log "Starting KBS volume encryption test" - # Setup config - setup_config - # Create test disk create_test_disk + # Setup config + setup_config + # Test volume operations if ! test_volume_init; then error "Volume initialization failed" From 312dbeda00d7f3a03edae0698180581a80a9adcb Mon Sep 17 00:00:00 2001 From: Kun Lai Date: Thu, 4 Sep 2025 17:43:38 +0800 Subject: [PATCH 17/17] for test modprobe in github --- .github/actions/run-aa-as/action.yml | 2 +- .github/workflows/build-rpm.yml | 35 +++++++++++++++++++++++--- scripts/test/test-system-encryption.sh | 11 ++------ scripts/test/test-volume-encryption.sh | 22 ++++++++++++++-- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/.github/actions/run-aa-as/action.yml b/.github/actions/run-aa-as/action.yml index 9524dd3..6cc8939 100644 --- a/.github/actions/run-aa-as/action.yml +++ b/.github/actions/run-aa-as/action.yml @@ -23,7 +23,7 @@ runs: (/usr/bin/rvps --config /etc/trustee/rvps.json --address 127.0.0.1:50003 &) && sleep 1 (/usr/bin/grpc-as --socket 0.0.0.0:50004 --config-file /etc/trustee/as-config.json &) && sleep 1 (/usr/bin/kbs --config-file /etc/trustee/kbs-config.toml &) && sleep 1 - (/usr/bin/trustee-gateway --config /etc/trustee/gateway.yml &) && sleep 1 + (/usr/bin/trustee-gateway --config /etc/trustee/gateway.yml > /tmp/trustee-gateway.log 2>&1 &) && sleep 1 # Register passphrases mkdir -p /opt/trustee/kbs/repository/default/local-resources/ diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index 5dfb5b6..094f9a3 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -202,10 +202,39 @@ jobs: # install requirements yum install -y libguestfs-tools + - name: Load nbd kernel module + run: | + yum install -y kmod zstd + + MODULE_DIR="/lib/modules/$(uname -r)" + MODULE_FILE=$(find "$MODULE_DIR" -name "nbd.ko*" -type f | head -1) + + if [ -z "$MODULE_FILE" ]; then + echo "No module file found in $MODULE_DIR" + exit 1 + fi + echo "Found module file: $MODULE_FILE" + + if [[ "$MODULE_FILE" == *.ko.zst ]]; then + echo "Found zstd compressed module file, decompressing..." + + zstd -d "$MODULE_FILE" -o "/tmp/nbd.ko" + if [ $? -ne 0 ]; then + echo "Failed to decompress module file" + exit 1 + fi + + echo "Loading the decompressed module..." + insmod "/tmp/nbd.ko" || exit 1 + else + echo "Loading the module with modprobe ..." + modprobe nbd + fi + - name: Download artifacts uses: actions/download-artifact@v4 with: - path: ./ + path: /tmp/ merge-multiple: false - name: Install RPM packages @@ -214,7 +243,7 @@ jobs: set -x # test rpm package install - yum install -y ./rpm-packages/RPMS/*/cryptpilot-*.rpm + yum install -y /tmp/rpm-packages/RPMS/*/cryptpilot-*.rpm cryptpilot --version - name: Checkout repository @@ -227,7 +256,7 @@ jobs: - name: Run system encryption test run: | export LIBGUESTFS_BACKEND=appliance # set this for virt-customize - timeout 300s bash ./scripts/test/test-system-encryption.sh --ci --package ./rpm-packages/RPMS/*/cryptpilot-*.rpm --trustee-url "http://10.0.2.2:8081/api/" + timeout 1200s bash ./scripts/test/test-system-encryption.sh --ci --package /tmp/rpm-packages/RPMS/*/cryptpilot-*.rpm --trustee-url "http://10.0.2.2:8081/api/" release: if: startsWith(github.ref, 'refs/tags/') diff --git a/scripts/test/test-system-encryption.sh b/scripts/test/test-system-encryption.sh index 9ac2a43..e061d24 100755 --- a/scripts/test/test-system-encryption.sh +++ b/scripts/test/test-system-encryption.sh @@ -385,14 +385,6 @@ verify_boot() { return 0 fi - # Also check for Alibaba Cloud Linux login prompt - if grep -q "Alibaba Cloud Linux" "${LOG_FILE}" 2>/dev/null; then - log "System boot verified - Alibaba Cloud Linux detected!" - log "Last 20 lines of output:" - tail -20 "${LOG_FILE}" - return 0 - fi - # Show progress every 30 seconds if ((count % 30 == 0)); then log "Still waiting for boot (elapsed: ${count}s)..." @@ -648,7 +640,8 @@ main() { encrypt_image # Calculate reference values - calculate_reference_values + # TODO: fix the udevadm problem by changing to guestmount https://github.com/openanolis/cryptpilot/actions/runs/17576971966/job/49925051838?pr=21 + # calculate_reference_values # Handle CI mode if [[ "$CI_MODE" == true ]]; then diff --git a/scripts/test/test-volume-encryption.sh b/scripts/test/test-volume-encryption.sh index 532ac25..41f4d16 100755 --- a/scripts/test/test-volume-encryption.sh +++ b/scripts/test/test-volume-encryption.sh @@ -150,8 +150,8 @@ EOF create_test_disk() { log "Creating test disk..." - # Create a 100MB disk image - dd if=/dev/zero of=test-disk.img bs=1M count=100 + # Create a 5GB disk image + dd if=/dev/zero of=test-disk.img bs=5M count=1024 # Detach loop device if already attached LOOP_DEVICE=$(losetup --associated "$IMAGE" | awk '{print $1}') @@ -163,6 +163,10 @@ create_test_disk() { LOOP_DEV=$(losetup --find) if [[ -z "$LOOP_DEV" ]]; then + error "Failed to found a free loop device" + fi + + if ! losetup -P "$LOOP_DEV" test-disk.img 2>/dev/null; then error "Failed to set up loop device" fi @@ -176,9 +180,23 @@ create_test_disk() { test_volume_init() { log "Initializing KBS volume..." + # check if trustee is still running + yum install -y iproute + ps -ef + + ss --tcp -n --listening + # Initialize the volume if ! cryptpilot init kbs-test -c "${CONFIG_DIR}" -y; then echo "Failed to initialize volume." + + cat /tmp/trustee-gateway.log + + # check again trustee is still running + ps -ef + + ss --tcp -n --listening + return 1 fi