summary: Run a smoke test on UC22 with encryption enabled

details: |
    This test checks basic snapd commands on UC22 with secure boot and encryption enabled

systems: [ubuntu-22.04-64, ubuntu-24.04-64]

environment:
    NESTED_EXTRA_CMDLINE/tokens: ubuntu-core.force-experimental-tokens=1
    NESTED_EXTRA_CMDLINE/files: ubuntu-core.force-experimental-tokens=0
    EXPECT_TOKENS/tokens: true
    EXPECT_TOKENS/files: false

prepare: |
    if os.query is-ubuntu-lt 24.04 && [ "${EXPECT_TOKENS}" = true ]; then
        tests.exec skip-test "Tokens require UC 24.04" && exit 0
    fi
    tests.nested build-image core
    tests.nested create-vm core

execute: |
    tests.exec is-skipped && exit 0

    echo "Wait for the system to be seeded first"
    remote.exec "sudo snap wait system seed.loaded"

    echo "Ensure 'snap install' works"
    remote.exec "sudo snap install test-snapd-sh"

    echo "Ensure 'snap list' works and test-snapd-sh snap is installed"
    remote.exec "snap list" | MATCH test-snapd-sh

    echo "Ensure 'snap find' works"
    remote.exec "snap find test-snapd-sh" | MATCH ^test-snapd-sh

    echo "Ensure 'snap info' works"
    remote.exec "snap info test-snapd-sh" | MATCH '^name:\ +test-snapd-sh'

    echo "Ensure 'snap remove' works"
    remote.exec "sudo snap remove test-snapd-sh"

    echo "Ensure 'snap list' works and test-snapd-sh snap is removed"
    remote.exec "! snap list test-snapd-sh"

    echo "Ensure 'snap recovery show-keys' works as root"
    remote.exec "sudo snap recovery --show-keys" | MATCH 'recovery:\s+[0-9]{5}-[0-9]{5}-[0-9]{5}-[0-9]{5}-[0-9]{5}-[0-9]{5}-[0-9]{5}-[0-9]{5}'
    echo "But not as user (normal file permissions prevent this)"
    if remote.exec "snap recovery --show-keys"; then
        echo "snap recovery --show-key should not work as a user"
        exit 1
    fi

    if os.query is-ubuntu-ge 24.04 && [ "${EXPECT_TOKENS}" = true ]; then
        remote.exec "sudo cryptsetup luksDump --dump-json-metadata /dev/disk/by-label/ubuntu-data-enc" >data.json
        remote.exec "sudo cryptsetup luksDump --dump-json-metadata /dev/disk/by-label/ubuntu-save-enc" >save.json
        # TODO: use gojq
        data_default_token_type="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default").type' data.json)"
        data_default_platform_name="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default").ubuntu_fde_data.platform_name' data.json)"
        data_fallback_token_type="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default-fallback").type' data.json)"
        data_fallback_platform_name="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default-fallback").ubuntu_fde_data.platform_name' data.json)"
        save_default_token_type="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default").type' save.json)"
        save_default_platform_name="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default").ubuntu_fde_data.platform_name' save.json)"
        save_fallback_token_type="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default-fallback").type' save.json)"
        save_fallback_platform_name="$(jq -r '.tokens.[]|select(.ubuntu_fde_name=="default-fallback").ubuntu_fde_data.platform_name' save.json)"

        test "${data_default_token_type}" = "ubuntu-fde"
        test "${data_fallback_token_type}" = "ubuntu-fde"
        test "${save_default_token_type}" = "ubuntu-fde"
        test "${save_fallback_token_type}" = "ubuntu-fde"

        test "${data_default_platform_name}" = "tpm2"
        test "${data_fallback_platform_name}" = "tpm2"
        test "${save_default_platform_name}" = "plainkey"
        test "${save_fallback_platform_name}" = "tpm2"

        remote.exec "! test -f /run/mnt/ubuntu-boot/device/fde/ubuntu-data.sealed-key"
        remote.exec "! test -f /run/mnt/ubuntu-seed/device/fde/ubuntu-data.recovery.sealed-key"
        remote.exec "! test -f /run/mnt/ubuntu-seed/device/fde/ubuntu-save.recovery.sealed-key"
    else
        remote.exec "test -f /run/mnt/ubuntu-boot/device/fde/ubuntu-data.sealed-key"
        remote.exec "test -f /run/mnt/ubuntu-seed/device/fde/ubuntu-data.recovery.sealed-key"
        remote.exec "test -f /run/mnt/ubuntu-seed/device/fde/ubuntu-save.recovery.sealed-key"
    fi

    if os.query is-ubuntu-ge 24.04; then
        remote.exec "udevadm info --query=name /dev/disk/snapd/disk" | MATCH "."
        remote.exec "udevadm info --query=property --property=ID_PART_ENTRY_NAME --value /dev/disk/snapd/ubuntu-seed" | MATCH "^ubuntu-seed$"
        remote.exec "udevadm info --query=property --property=ID_PART_ENTRY_NAME --value /dev/disk/snapd/ubuntu-boot" | MATCH "^ubuntu-boot$"
        remote.exec "udevadm info --query=property --property=ID_PART_ENTRY_NAME --value /dev/disk/snapd/ubuntu-data-luks" | MATCH "^ubuntu-data$"
        remote.exec "udevadm info --query=property --property=ID_PART_ENTRY_NAME --value /dev/disk/snapd/ubuntu-save-luks" | MATCH "^ubuntu-save$"
        # TODO: when udev rules are available in core-base, we should also test those
        #remote.exec "udevadm info --query=property --property=DM_NAME --value /dev/disk/snapd/ubuntu-data" | MATCH "^ubuntu-data"
        #remote.exec "udevadm info --query=property --property=DM_NAME --value /dev/disk/snapd/ubuntu-save" | MATCH "^ubuntu-save"
    fi

    remote.exec "sudo cat /var/lib/snapd/state.json" >state.json
    runrecover_handle=$(gojq -r '.data.fde."keyslot-roles"."run+recover"."tpm2-pcr-policy-revocation-counter"' <state.json)
    run_handle=$(gojq -r '.data.fde."keyslot-roles"."run"."tpm2-pcr-policy-revocation-counter"' <state.json)
    recover_handle=$(gojq -r '.data.fde."keyslot-roles".recover."tpm2-pcr-policy-revocation-counter"' <state.json)

    # Revocation counter handles are expected in a specific range
    # This range is defined in secboot/secboot.go (PCRPolicyCounterHandleRange)
    [ "${runrecover_handle}" -ge $((0x01880005)) ]
    [ "${runrecover_handle}" -le $((0x0188000f)) ]
    # All profiles should use the same handle
    [ "${runrecover_handle}" -eq "${run_handle}" ]
    [ "${runrecover_handle}" -eq "${recover_handle}" ]
