From 9e20782f97eb80544c599a164dfa0528c215b441 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Mon, 29 Sep 2025 16:43:39 +0200 Subject: [PATCH 01/14] Only run unit tests Only run the unit tests since the integration tests require a cluster to be created and configured. Signed-off-by: Alice Frosi --- .github/workflows/rust.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c2b22769..65161a0c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -46,7 +46,7 @@ jobs: - name: "cargo build" run: cargo build --all-targets - name: "cargo test" - run: cargo test --all-targets + run: cargo test --bins tests-release-stable: name: "Tests (release), stable toolchain" runs-on: "ubuntu-24.04" @@ -68,9 +68,9 @@ jobs: - name: "Build CRDs" run: make crds-rs - name: "cargo build (release)" - run: cargo build --all-targets --release + run: cargo build --lib --release - name: "cargo test (release)" - run: cargo test --all-targets --release + run: cargo test --bins --release tests-release-msrv: name: "Tests (release), minimum supported toolchain" runs-on: "ubuntu-24.04" @@ -98,9 +98,9 @@ jobs: - name: "Build CRDs" run: make crds-rs - name: "cargo build (release)" - run: cargo build --all-targets --release + run: cargo build --lib --release - name: "cargo test (release)" - run: cargo test --all-targets --release + run: cargo test --bins --release tests-other-channels: name: "Tests, unstable toolchain" runs-on: "ubuntu-24.04" @@ -126,6 +126,6 @@ jobs: - name: "Build CRDs" run: make crds-rs - name: "cargo build" - run: cargo build --all-targets + run: cargo build --lib - name: "cargo test" - run: cargo test --all-targets + run: cargo test --bins From 763c55732fb146cbc49dec8ab7e45eeb66cfc4bc Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Thu, 2 Oct 2025 13:57:25 +0200 Subject: [PATCH 02/14] Fix script create-cluster-kind Set timeout for the kind cluster and avoid the replace flag for docker Signed-off-by: Alice Frosi --- scripts/create-cluster-kind.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/create-cluster-kind.sh b/scripts/create-cluster-kind.sh index 860e2c75..1c0bd9f3 100755 --- a/scripts/create-cluster-kind.sh +++ b/scripts/create-cluster-kind.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # SPDX-FileCopyrightText: Alice Frosi # SPDX-FileCopyrightText: Jakob Naucke @@ -10,13 +10,17 @@ set -o errexit source scripts/common.sh if [ "$(kind get clusters 2>/dev/null)" != "kind" ]; then - kind create cluster --config kind/config.yaml + kind create cluster --config kind/config.yaml --wait 5m fi reg_name='kind-registry' reg_port='5000' +args="" +if [ "$RUNTIME" == podman ]; then + args=$args" --replace" +fi if [ "$($RUNTIME inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then - $RUNTIME run --replace --network kind \ + $RUNTIME run $args --network kind \ -d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \ registry:2 fi From 783fc5e92d997377a1e331ee60a508280cfa109d Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Wed, 8 Oct 2025 14:54:13 +0200 Subject: [PATCH 03/14] Skip PCR 7 KubeVirt is using centos stream 9 secure boot variables and our library compute the ones from fedora. This will be fixed in a follow-up PR. Signed-off-by: Alice Frosi --- operator/src/tpm.rego | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator/src/tpm.rego b/operator/src/tpm.rego index 93f9528f..eecc33b1 100644 --- a/operator/src/tpm.rego +++ b/operator/src/tpm.rego @@ -11,7 +11,7 @@ hardware := 2 if { tpm_pcrs_valid if { lower(input.tpm.pcrs[4]) in data.reference.tpm_pcr4 - lower(input.tpm.pcrs[7]) in data.reference.tpm_pcr7 +## lower(input.tpm.pcrs[7]) in data.reference.tpm_pcr7 lower(input.tpm.pcrs[14]) in data.reference.tpm_pcr14 } From fa8ac702de80b7d4d8bb4397008f79fe13e3785e Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Thu, 2 Oct 2025 17:37:29 +0200 Subject: [PATCH 04/14] Exclude tests/README.md from the license checks Signed-off-by: Alice Frosi --- REUSE.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/REUSE.toml b/REUSE.toml index 3fb43d60..f604dd19 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -10,7 +10,8 @@ path = [ "operator/src/resource.rego", "operator/src/tpm.rego", "docs/pics/*", - "docs/design/*" + "docs/design/*", + "tests/README.md" ] SPDX-FileCopyrightText = [ "Alice Frosi ", From c481ed565839971d74e0bcd473d7588d62c34510 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Mon, 6 Oct 2025 12:38:25 +0200 Subject: [PATCH 05/14] Set verbose output for the cluster creation Setting -x for the cluster creation for better debuggability on the ci. Signed-off-by: Alice Frosi --- scripts/create-cluster-kind.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create-cluster-kind.sh b/scripts/create-cluster-kind.sh index 1c0bd9f3..4be61861 100755 --- a/scripts/create-cluster-kind.sh +++ b/scripts/create-cluster-kind.sh @@ -5,7 +5,7 @@ # # SPDX-License-Identifier: CC0-1.0 -set -o errexit +set -xo errexit source scripts/common.sh From b60ba6fd7bdeace42a07a8374cad7c2d8a95a07a Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Mon, 6 Oct 2025 09:22:01 +0200 Subject: [PATCH 06/14] Replace source command Source isn't recognized as command by the github actions. Signed-off-by: Alice Frosi --- scripts/clean-cluster-kind.sh | 2 +- scripts/create-cluster-kind.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/clean-cluster-kind.sh b/scripts/clean-cluster-kind.sh index 8b20927b..5e23c0c4 100755 --- a/scripts/clean-cluster-kind.sh +++ b/scripts/clean-cluster-kind.sh @@ -7,7 +7,7 @@ set -x -source scripts/common.sh +. scripts/common.sh for image in "$@"; do if ${RUNTIME} exec -ti kind-control-plane crictl inspecti ${image} &> /dev/null ; then diff --git a/scripts/create-cluster-kind.sh b/scripts/create-cluster-kind.sh index 4be61861..ba19ce28 100755 --- a/scripts/create-cluster-kind.sh +++ b/scripts/create-cluster-kind.sh @@ -7,7 +7,7 @@ set -xo errexit -source scripts/common.sh +. scripts/common.sh if [ "$(kind get clusters 2>/dev/null)" != "kind" ]; then kind create cluster --config kind/config.yaml --wait 5m From 3ee9890362f37fad950ebf3c28f0e2036837dec0 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 4 Nov 2025 16:07:26 +0100 Subject: [PATCH 07/14] Install KubeVirt KubeVirt doesn't properly work with the default CNI plugin of kind. Therefore, it requires calico as CNI. Signed-off-by: Alice Frosi --- REUSE.toml | 4 +- examples/vm-coreos-ign.yaml | 86 ++++++++++++++++++++++++++++++++++ kind/config.yaml | 2 + scripts/create-cluster-kind.sh | 2 + scripts/install-kubevirt.sh | 14 ++++++ 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 examples/vm-coreos-ign.yaml create mode 100755 scripts/install-kubevirt.sh diff --git a/REUSE.toml b/REUSE.toml index f604dd19..7e63e292 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -11,7 +11,9 @@ path = [ "operator/src/tpm.rego", "docs/pics/*", "docs/design/*", - "tests/README.md" + "tests/README.md", + "examples/vm-coreos-ign.yaml", + "scripts/install-kubevirt.sh" ] SPDX-FileCopyrightText = [ "Alice Frosi ", diff --git a/examples/vm-coreos-ign.yaml b/examples/vm-coreos-ign.yaml new file mode 100644 index 00000000..acf30321 --- /dev/null +++ b/examples/vm-coreos-ign.yaml @@ -0,0 +1,86 @@ +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + name: coreos-trustee +spec: + runStrategy: Always + template: + metadata: + annotations: + kubevirt.io/ignitiondata: | + { + "ignition": { + "config": { + "merge": [ + { + "source": "http://register-server.confidential-clusters.svc.cluster.local:8000/ignition-clevis-pin-trustee" + } + ] + }, + "version": "3.5.0" + }, + "passwd": { + "users": [ + { + "name": "core", + "sshAuthorizedKeys": [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCWvljBdqqjHvIOIKftFbDTJ4DvWa8cbnZlK9HHrn7lhXwvmCY0FkvL9dtD0azgJkwYRMGyOAqDMTk6S1oV04ZjAlbQgmtoldiAtkIJez6uZV3AdBzm0UnOD8O0sIhtRHfCAGxiAcT5oANfCD+YpJ7c4LPAetX/OaU40cLSVU1dA6YNAB5hZoqJ5h54W6gf6NEK5zkHclDsSO9oeyxkeirNAeL83GdLmX76PAAtQkr4H5K6S9ZnGd5at7HxRdZ5KuGElmwYwMxsWBOxZFl8glQ4UgAIX7TWopUYxZNNmYtTl1GwPJA+UyYfu60ryX6YOic3H/s9GUADqq/7ahKvnWa6iRa0+xkdy+GrrJMQOmBoCHzUGECDeu+N1JEcuHGnMy+bDSsGG6mz5dQT+VqdVcqosnGesobeuGOswAA2yW9rc/I4s7i9zGRzOD5u+xE/topYstqXZ3PYUgjzTi1V3pTwgBf5SSJYaxIap1s7nupZ86CjU3hvCdjcEQ69b3zYmKSjsGJ6+deL+C17CYYBqqUllYce2a/LoAwB4d1wGQ8vu8gwhyaI+tg2z0PZDGae21rF2ahYueOOd8W4nuqPuxtOUE80g3S3iYGKkctLNM/iWB/HFRyykg/Go/vllL1tapqfW2d5YGihXMO/iy4vtXaxA8pGKcnrcX8dvb8ufQt59w== core" + ] + } + ] + }, + "storage": { + "files": [ + { + "path": "/etc/profile.d/systemd-pager.sh", + "contents": { + "compression": "", + "source": "data:,%23%20Tell%20systemd%20to%20not%20use%20a%20pager%20when%20printing%20information%0Aexport%20SYSTEMD_PAGER%3Dcat%0A" + }, + "mode": 420 + } + ] + }, + "systemd": { + "units": [ + { + "enabled": false, + "name": "zincati.service" + }, + { + "dropins": [ + { + "contents": "[Service]\n# Override Execstart in main unit\nExecStart=\n# Add new Execstart with `-` prefix to ignore failure`\nExecStart=-/usr/sbin/agetty --autologin core --noclear %I $TERM\n", + "name": "autologin-core.conf" + } + ], + "name": "serial-getty@ttyS0.service" + } + ] + } + } + spec: + domain: + features: + smm: + enabled: true + firmware: + bootloader: + efi: + persistent: true + devices: + tpm: + persistent: true + disks: + - name: containerdisk + disk: + bus: virtio + rng: {} + resources: + requests: + memory: 4096M + volumes: + - name: containerdisk + containerDisk: + image: "localhost:5000/fedora-coreos:clevis-pin" + imagePullPolicy: Always diff --git a/kind/config.yaml b/kind/config.yaml index 772df21f..d14cf0c7 100644 --- a/kind/config.yaml +++ b/kind/config.yaml @@ -18,3 +18,5 @@ nodes: hostPort: 8000 featureGates: "ImageVolume": true +networking: + disableDefaultCNI: true diff --git a/scripts/create-cluster-kind.sh b/scripts/create-cluster-kind.sh index ba19ce28..7ba7bdfd 100755 --- a/scripts/create-cluster-kind.sh +++ b/scripts/create-cluster-kind.sh @@ -48,3 +48,5 @@ data: host: "localhost:${reg_port}" help: "https://kind.sigs.k8s.io/docs/user/local-registry/" EOF + +kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/calico.yaml diff --git a/scripts/install-kubevirt.sh b/scripts/install-kubevirt.sh new file mode 100755 index 00000000..99dad3f5 --- /dev/null +++ b/scripts/install-kubevirt.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +. scripts/common.sh + +# Fix kvm permission on kind +$RUNTIME exec -ti kind-control-plane chmod 666 /dev/kvm +export VERSION=$(curl -s https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt) +kubectl create -f "https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml" +kubectl create -f "https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml" + +kubectl patch kubevirt kubevirt -n kubevirt --type='merge' -p \ +'{"spec":{"configuration":{"developerConfiguration":{"featureGates":["ExperimentalIgnitionSupport"]}}}}' + +kubectl wait --for=jsonpath='{.status.phase}'=Deployed kubevirt/kubevirt -n kubevirt --timeout=10m From 86f0e52fc8239ebf2c11ffff50a345cc3a90fc5c Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Wed, 8 Oct 2025 08:59:00 +0200 Subject: [PATCH 08/14] Fix job name It possible that the job name has a '-' has 63 character and the name is invalid. Signed-off-by: Alice Frosi --- operator/src/reference_values.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/operator/src/reference_values.rs b/operator/src/reference_values.rs index a49d1042..09cd6e13 100644 --- a/operator/src/reference_values.rs +++ b/operator/src/reference_values.rs @@ -183,16 +183,21 @@ pub async fn launch_rv_job_controller(ctx: RvContextData) { ); } -async fn compute_fresh_pcrs(ctx: RvContextData, boot_image: &str) -> anyhow::Result<()> { - // Name job by sanitized image name, plus a hash to disambiguate - // tags that differed only beyond the truncation limit +// Name job by sanitized image name, plus a hash to disambiguate +// tags that differed only beyond the truncation limit +fn get_job_name(boot_image: &str) -> Result { let rfc1035_boot_image = boot_image.replace(['.', ':', '/', '@', '_'], "-"); let boot_image_hash = hash(MessageDigest::sha1(), boot_image.as_bytes())?; let mut boot_image_hash_str = hex::encode(boot_image_hash); boot_image_hash_str.truncate(10); - let mut job_name = format!("{PCR_COMMAND_NAME}-{boot_image_hash_str}-{rfc1035_boot_image}"); - job_name.truncate(63); + let job_name = format!("{PCR_COMMAND_NAME}-{boot_image_hash_str}-{rfc1035_boot_image}"); + let trimmed: String = job_name.chars().take(63).collect(); + let trimmed = trimmed.trim_end_matches('-').to_string(); + Ok(trimmed) +} +async fn compute_fresh_pcrs(ctx: RvContextData, boot_image: &str) -> anyhow::Result<()> { + let job_name = get_job_name(boot_image)?; let pod_spec = build_compute_pcrs_pod_spec(boot_image, &ctx.pcrs_compute_image); let job = Job { metadata: ObjectMeta { From ef495088cb2e1a82498930bf117340388d5dae35 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Wed, 8 Oct 2025 12:24:26 +0200 Subject: [PATCH 09/14] Add rules for installing kubevirt and the cluster cleanup Signed-off-by: Alice Frosi --- Makefile | 9 +++++++++ examples/vm-coreos-ign.yaml | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3852d692..18c20e3f 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,12 @@ manifests: cocl-gen cluster-up: scripts/create-cluster-kind.sh +cluster-cleanup: + $(KUBECTL) delete -f manifests/confidential_cluster_cr.yaml + $(KUBECTL) delete -f manifests/confidential_cluster_crd.yaml + $(KUBECTL) delete -f manifests/operator.yaml + + cluster-down: scripts/delete-cluster-kind.sh @@ -100,6 +106,9 @@ endif $(KUBECTL) apply -f kind/register-forward.yaml $(KUBECTL) apply -f kind/kbs-forward.yaml +install-kubevirt: + scripts/install-kubevirt.sh + clean: cargo clean rm -rf bin manifests $(CRD_YAML_PATH) $(CRD_RS_PATH) diff --git a/examples/vm-coreos-ign.yaml b/examples/vm-coreos-ign.yaml index acf30321..01a1645c 100644 --- a/examples/vm-coreos-ign.yaml +++ b/examples/vm-coreos-ign.yaml @@ -82,5 +82,5 @@ spec: volumes: - name: containerdisk containerDisk: - image: "localhost:5000/fedora-coreos:clevis-pin" + image: "quay.io/confidential-clusters/fedora-coreos-kubevirt:latest" imagePullPolicy: Always From 6156194f7dc6a097305b1e97bf905e5ba999c291 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 4 Nov 2025 15:15:05 +0100 Subject: [PATCH 10/14] Add integration test framework and confidential cluster tests Introduction of a new test framework for integration testing: - Create test_utils crate in workspace root with: - TestContext for test lifecycle management - Automatic namespace creation/cleanup - Operator deployment and manifest generation - Helper macros (test_info!, named_test!, setup!) - Polling utility for async resource waiting - Add confidential_cluster integration test that validates: - ConfidentialCluster CR creation and reconciliation - Image PCRs computation and ConfigMap updates - Resource cleanup on CR deletion. Signed-off-by: Alice Frosi --- Cargo.lock | 806 +++++++++++++++++++--------------- Cargo.toml | 4 +- test_utils/Cargo.toml | 22 + test_utils/src/lib.rs | 560 +++++++++++++++++++++++ test_utils/src/timer.rs | 66 +++ tests/Cargo.toml | 15 +- tests/README.md | 21 + tests/confidential_cluster.rs | 146 ++++++ 8 files changed, 1288 insertions(+), 352 deletions(-) create mode 100644 test_utils/Cargo.toml create mode 100644 test_utils/src/lib.rs create mode 100644 test_utils/src/timer.rs create mode 100644 tests/README.md create mode 100644 tests/confidential_cluster.rs diff --git a/Cargo.lock b/Cargo.lock index 691ab804..916ae4fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -71,9 +71,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -86,22 +86,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -154,9 +154,15 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.5.0" @@ -185,7 +191,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -202,15 +208,15 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.104", + "syn 2.0.110", "thiserror 1.0.69", ] [[package]] name = "backon" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302eaff5357a264a2c42f127ecb8bac761cf99749fc3dc95677e2743991f99e7" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ "fastrand", "gloo-timers", @@ -219,9 +225,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -229,7 +235,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -267,9 +273,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -300,18 +306,19 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.30" +version = "1.2.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" dependencies = [ + "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" @@ -324,7 +331,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -358,14 +365,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "clevis-pin-trustee-lib" @@ -387,11 +394,36 @@ dependencies = [ "serde_json", ] +[[package]] +name = "cocl-operator-test-utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "cocl-operator-lib", + "compute-pcrs-lib", + "env_logger", + "k8s-openapi", + "kube", + "log", + "serde_json", + "serde_yaml", + "tokio", + "uuid", +] + [[package]] name = "cocl-operator-tests" version = "0.1.0" dependencies = [ + "anyhow", + "cocl-operator-lib", + "cocl-operator-test-utils", + "compute-pcrs-lib", + "k8s-openapi", + "kube", "regex", + "serde_json", + "tokio", ] [[package]] @@ -442,9 +474,9 @@ dependencies = [ [[package]] name = "const_format" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ "const_format_proc_macros", ] @@ -536,7 +568,7 @@ checksum = "5d914fcc6452d133236ee067a9538be25ba6a644a450e1a6c617da84bf029854" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -570,7 +602,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -584,7 +616,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -595,7 +627,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -606,7 +638,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -617,9 +649,9 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", ] @@ -642,7 +674,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -652,7 +684,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -672,7 +704,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -694,14 +726,14 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "educe" @@ -712,7 +744,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -732,29 +764,29 @@ dependencies = [ [[package]] name = "enum-ordinalize" -version = "4.3.0" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" dependencies = [ "enum-ordinalize-derive", ] [[package]] name = "enum-ordinalize-derive" -version = "4.3.1" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "env_filter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ "log", "regex", @@ -781,19 +813,19 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -816,11 +848,17 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -855,9 +893,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -906,7 +944,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -941,9 +979,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -957,19 +995,19 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", ] [[package]] @@ -981,14 +1019,14 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "git-version" @@ -1007,7 +1045,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -1040,7 +1078,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.10.0", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -1055,15 +1093,21 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hdrhistogram" version = "7.5.4" @@ -1254,18 +1298,20 @@ dependencies = [ [[package]] name = "hyper" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "http 1.3.1", "http-body 1.0.1", "httparse", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -1278,7 +1324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527d4d619ca2c2aafa31ec139a3d1d60bf557bf7578a1f20f743637eccd9ca19" dependencies = [ "http 1.3.1", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "linked_hash_set", "once_cell", @@ -1310,7 +1356,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "pin-project-lite", "tokio", @@ -1325,7 +1371,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "native-tls", "tokio", @@ -1335,9 +1381,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ "base64 0.22.1", "bytes", @@ -1346,12 +1392,12 @@ dependencies = [ "futures-util", "http 1.3.1", "http-body 1.0.1", - "hyper 1.6.0", + "hyper 1.7.0", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -1359,9 +1405,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1383,9 +1429,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1396,9 +1442,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1409,11 +1455,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1424,42 +1469,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1521,12 +1562,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.0", ] [[package]] @@ -1537,9 +1578,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" dependencies = [ "memchr", "serde", @@ -1547,13 +1588,13 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1564,9 +1605,9 @@ checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -1594,33 +1635,33 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -1717,7 +1758,7 @@ dependencies = [ "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-openssl", "hyper-timeout", "hyper-util", @@ -1768,7 +1809,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -1783,7 +1824,7 @@ dependencies = [ "backon", "educe", "futures", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "hostname", "json-patch", "k8s-openapi", @@ -1806,9 +1847,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "lief" @@ -1816,7 +1857,7 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18773f648622afc222330700726227739936a1fa0040b91f007c80605525c4ff" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "cxx", "lief-ffi", "num-bigint", @@ -1852,9 +1893,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212" +checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82" dependencies = [ "cc", ] @@ -1867,32 +1908,31 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linked_hash_set" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae85b5be22d9843c80e5fc80e9b64c8a3b1f98f867c709956eca3efff4e92e2" +checksum = "984fb35d06508d1e69fc91050cceba9c0b748f983e6739fa2c7a9237154c52c8" dependencies = [ "linked-hash-map", ] [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] @@ -1904,9 +1944,9 @@ checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "miette" @@ -1937,7 +1977,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -1963,17 +2003,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -2044,7 +2085,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2067,9 +2108,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -2090,7 +2131,7 @@ dependencies = [ "oci-spec", "olpc-cjson", "regex", - "reqwest 0.12.23", + "reqwest 0.12.24", "serde", "serde_json", "sha2", @@ -2136,9 +2177,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl" @@ -2146,7 +2187,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "cfg-if", "foreign-types", "libc", @@ -2163,7 +2204,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2236,9 +2277,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2246,49 +2287,48 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror 2.0.17", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -2296,22 +2336,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "pest_meta" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ "pest", "sha2", @@ -2334,7 +2374,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2372,9 +2412,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -2437,23 +2477,23 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -2496,31 +2536,31 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.15" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", ] [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2548,9 +2588,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "register-server" @@ -2615,9 +2655,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "base64 0.22.1", "bytes", @@ -2626,7 +2666,7 @@ dependencies = [ "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-tls", "hyper-util", "js-sys", @@ -2668,21 +2708,21 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2708,9 +2748,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ "zeroize", ] @@ -2727,9 +2767,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -2739,18 +2779,18 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "schemars" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" dependencies = [ "dyn-clone", "ref-cast", @@ -2761,14 +2801,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80" +checksum = "301858a4023d78debd2353c7426dc486001bddc91ae31a76fb1f55132f7e2633" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2808,7 +2848,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "core-foundation", "core-foundation-sys", "libc", @@ -2817,9 +2857,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -2868,7 +2908,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2879,16 +2919,17 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "serde_ignored" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b516445dac1e3535b6d658a7b528d771153dfb272ed4180ca4617a20550365ff" +checksum = "115dffd5f3853e06e746965a20dcbae6ee747ae30b543d91b0e089668bb07798" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -2922,7 +2963,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.10.0", + "indexmap 2.12.0", "itoa", "ryu", "serde", @@ -2959,18 +3000,24 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "slab" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -2996,12 +3043,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3012,9 +3059,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" @@ -3037,7 +3084,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3087,9 +3134,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", @@ -3119,7 +3166,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3145,15 +3192,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.21.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3203,7 +3250,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3214,14 +3261,14 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "time" -version = "0.3.41" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "num-conv", @@ -3232,15 +3279,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -3272,9 +3319,9 @@ dependencies = [ "mio", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.0", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -3285,7 +3332,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3322,9 +3369,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -3343,7 +3390,7 @@ dependencies = [ "futures-core", "futures-util", "hdrhistogram", - "indexmap 2.10.0", + "indexmap 2.12.0", "pin-project-lite", "slab", "sync_wrapper 1.0.2", @@ -3361,7 +3408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ "base64 0.22.1", - "bitflags 2.9.1", + "bitflags 2.10.0", "bytes", "futures-util", "http 1.3.1", @@ -3407,7 +3454,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3446,9 +3493,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" @@ -3464,9 +3511,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-linebreak" @@ -3476,9 +3523,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] @@ -3509,13 +3556,14 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3542,8 +3590,9 @@ version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", + "serde", "wasm-bindgen", ] @@ -3604,45 +3653,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -3653,9 +3689,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3663,22 +3699,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.104", - "wasm-bindgen-backend", + "syn 2.0.110", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -3698,9 +3734,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -3736,37 +3772,37 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.1.3", + "windows-link 0.2.1", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3777,26 +3813,26 @@ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.1", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.1", ] [[package]] @@ -3828,11 +3864,20 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.61.1" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -3859,13 +3904,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3878,6 +3940,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3890,6 +3958,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3902,12 +3976,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3920,6 +4006,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3932,6 +4024,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3944,6 +4042,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3956,6 +4060,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winreg" version = "0.50.0" @@ -3967,27 +4077,23 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3995,34 +4101,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -4042,21 +4148,21 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -4065,9 +4171,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -4076,13 +4182,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3aef1959..127592b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ # SPDX-License-Identifier: CC0-1.0 [workspace] -members = ["compute-pcrs", "lib", "operator", "register-server", "tests"] +members = ["compute-pcrs", "lib", "operator", "register-server", "test_utils", "tests"] resolver = "3" [workspace.package] @@ -23,4 +23,6 @@ kube = { version = "2.0.1", default-features = false, features = ["derive", "run log = "0.4.28" serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.141" +serde_yaml = "0.9" tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread"] } +uuid = { version = "1.0", features = ["v4", "serde"] } diff --git a/test_utils/Cargo.toml b/test_utils/Cargo.toml new file mode 100644 index 00000000..7cf416db --- /dev/null +++ b/test_utils/Cargo.toml @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: Alice Frosi +# +# SPDX-License-Identifier: CC0-1.0 + +[package] +name = "cocl-operator-test-utils" +version = "0.1.0" +edition.workspace = true +rust-version.workspace = true + +[dependencies] +anyhow.workspace = true +cocl-operator-lib = { path = "../lib" } +compute-pcrs-lib.workspace = true +env_logger.workspace = true +k8s-openapi.workspace = true +kube = { workspace = true } +log.workspace = true +serde_json.workspace = true +serde_yaml.workspace = true +tokio = { workspace = true, features = ["process"] } +uuid.workspace = true diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs new file mode 100644 index 00000000..f9f7f8be --- /dev/null +++ b/test_utils/src/lib.rs @@ -0,0 +1,560 @@ +// SPDX-FileCopyrightText: Alice Frosi +// +// SPDX-License-Identifier: MIT + +use k8s_openapi::api::apps::v1::Deployment; +use k8s_openapi::api::core::v1::{ConfigMap, Namespace}; +use kube::api::DeleteParams; +use kube::{Api, Client}; +use std::collections::BTreeMap; +use std::path::Path; +use std::sync::Once; +use std::time::Duration; +use tokio::process::Command; + +pub mod timer; +pub use timer::Poller; + +use compute_pcrs_lib::Pcr; + +pub fn compare_pcrs(actual: &[Pcr], expected: &[Pcr]) -> bool { + if actual.len() != expected.len() { + return false; + } + + for (a, e) in actual.iter().zip(expected.iter()) { + if a.id != e.id || a.value != e.value { + return false; + } + } + + true +} + +#[macro_export] +macro_rules! test_info { + ($test_name:expr, $($arg:tt)*) => {{ + const GREEN: &str = "\x1b[32m"; + const RESET: &str = "\x1b[0m"; + println!("{}INFO{}: {}: {}", GREEN, RESET, $test_name, format!($($arg)*)); + }} +} + +static INIT: Once = Once::new(); + +pub struct TestContext { + client: Client, + test_namespace: String, + manifests_dir: String, + test_name: String, +} + +impl TestContext { + pub async fn new(test_name: &str) -> anyhow::Result { + INIT.call_once(|| { + let _ = env_logger::builder().is_test(true).try_init(); + }); + + let client = setup_test_client().await?; + let namespace = test_namespace_name(); + + let ctx = Self { + client, + test_namespace: namespace, + manifests_dir: String::new(), + test_name: test_name.to_string(), + }; + + let manifests_dir = ctx.create_temp_manifests_dir()?; + let mut ctx = ctx; + ctx.manifests_dir = manifests_dir; + + ctx.create_namespace().await?; + ctx.apply_operator_manifests().await?; + + test_info!( + &ctx.test_name, + "Execute test in the namespace {}", + ctx.test_namespace + ); + + Ok(ctx) + } + + pub fn client(&self) -> &Client { + &self.client + } + + pub fn namespace(&self) -> &str { + &self.test_namespace + } + + pub async fn cleanup(&self) -> anyhow::Result<()> { + self.cleanup_namespace().await?; + self.cleanup_manifests_dir()?; + Ok(()) + } + + async fn create_namespace(&self) -> anyhow::Result<()> { + test_info!( + &self.test_name, + "Creating test namespace: {}", + self.test_namespace + ); + let namespace_api: Api = Api::all(self.client.clone()); + let namespace = Namespace { + metadata: k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta { + name: Some(self.test_namespace.clone()), + labels: Some(BTreeMap::from([("test".to_string(), "true".to_string())])), + ..Default::default() + }, + ..Default::default() + }; + + namespace_api + .create(&Default::default(), &namespace) + .await?; + Ok(()) + } + + async fn cleanup_namespace(&self) -> anyhow::Result<()> { + let namespace_api: Api = Api::all(self.client.clone()); + let dp = DeleteParams::default(); + + match namespace_api.get(&self.test_namespace).await { + Ok(_) => { + namespace_api.delete(&self.test_namespace, &dp).await?; + test_info!(&self.test_name, "Deleted namespace {}", self.test_namespace); + } + Err(kube::Error::Api(ae)) if ae.code == 404 => { + test_info!(&self.test_name, "Namespace already deleted"); + } + Err(e) => return Err(e.into()), + } + Ok(()) + } + + fn create_temp_manifests_dir(&self) -> anyhow::Result { + let temp_dir = std::env::temp_dir(); + let manifests_dir = temp_dir.join(format!("manifests-{}", uuid::Uuid::new_v4())); + std::fs::create_dir_all(&manifests_dir)?; + let dir_str = manifests_dir + .to_str() + .ok_or_else(|| anyhow::anyhow!("Invalid temp directory path"))? + .to_string(); + test_info!( + &self.test_name, + "Created temp manifests directory: {}", + dir_str + ); + Ok(dir_str) + } + + fn cleanup_manifests_dir(&self) -> anyhow::Result<()> { + if Path::new(&self.manifests_dir).exists() { + std::fs::remove_dir_all(&self.manifests_dir)?; + test_info!( + &self.test_name, + "Removed manifests directory: {}", + self.manifests_dir + ); + } + Ok(()) + } + + async fn wait_for_deployment_ready( + &self, + deployments_api: &Api, + deployment_name: &str, + timeout_secs: u64, + ) -> anyhow::Result<()> { + test_info!( + &self.test_name, + "Waiting for deployment {} to be ready", + deployment_name + ); + let poller = Poller::new() + .with_timeout(Duration::from_secs(timeout_secs)) + .with_interval(Duration::from_secs(5)) + .with_error_message(format!( + "{deployment_name} deployment does not have 1 available replica after {timeout_secs} seconds" + )); + + let test_name_owned = self.test_name.clone(); + poller + .poll_async(move || { + let api = deployments_api.clone(); + let name = deployment_name.to_string(); + let tn = test_name_owned.clone(); + async move { + let deployment = api.get(&name).await?; + + if let Some(status) = &deployment.status { + if let Some(available_replicas) = status.available_replicas { + if available_replicas == 1 { + test_info!(&tn, "{} deployment has 1 available replica", name); + return Ok(()); + } + } + } + + Err(anyhow::anyhow!( + "{name} deployment does not have 1 available replica yet" + )) + } + }) + .await + } + + async fn apply_operator_manifests(&self) -> anyhow::Result<()> { + test_info!( + &self.test_name, + "Generating manifests in {}", + self.manifests_dir + ); + + let workspace_root = std::env::current_dir()?.join(".."); + let controller_gen_path = workspace_root.join("bin/controller-gen-v0.19.0"); + + test_info!( + &self.test_name, + "Generating CRDs and RBAC with controller-gen at: {}", + controller_gen_path.display() + ); + + let crd_temp_dir = Path::new(&self.manifests_dir).join("crd"); + let rbac_temp_dir = Path::new(&self.manifests_dir).join("rbac"); + std::fs::create_dir_all(&crd_temp_dir)?; + std::fs::create_dir_all(&rbac_temp_dir)?; + + let crd_temp_dir_str = crd_temp_dir + .to_str() + .ok_or_else(|| anyhow::anyhow!("Invalid CRD temp directory path"))?; + let rbac_temp_dir_str = rbac_temp_dir + .to_str() + .ok_or_else(|| anyhow::anyhow!("Invalid RBAC temp directory path"))?; + + let crd_gen_output = Command::new(&controller_gen_path) + .args([ + "rbac:roleName=cocl-operator-role", + "crd", + "webhook", + "paths=./...", + &format!("output:crd:artifacts:config={crd_temp_dir_str}"), + &format!("output:rbac:artifacts:config={rbac_temp_dir_str}"), + ]) + .current_dir(&workspace_root) + .output() + .await?; + + if !crd_gen_output.status.success() { + let stderr = String::from_utf8_lossy(&crd_gen_output.stderr); + return Err(anyhow::anyhow!( + "Failed to generate CRDs and RBAC: {stderr}" + )); + } + + test_info!(&self.test_name, "CRDs and RBAC generated successfully"); + + let cocl_gen_path = workspace_root.join("cocl-gen"); + if !cocl_gen_path.exists() { + return Err(anyhow::anyhow!( + "cocl-gen not found at {}. Run 'make cocl-gen' first.", + cocl_gen_path.display() + )); + } + + let manifest_gen_output = Command::new(&cocl_gen_path) + .args([ + "-namespace", + &self.test_namespace, + "-output-dir", + &self.manifests_dir, + "-image", + "localhost:5000/confidential-clusters/cocl-operator:latest", + "-pcrs-compute-image", + "localhost:5000/confidential-clusters/compute-pcrs:latest", + "-trustee-image", + "quay.io/confidential-clusters/key-broker-service:tpm-verifier-built-in-as-20250711", + "-register-server-image", + "localhost:5000/confidential-clusters/registration-server:latest" + ]) + .output() + .await?; + + if !manifest_gen_output.status.success() { + let stderr = String::from_utf8_lossy(&manifest_gen_output.stderr); + return Err(anyhow::anyhow!("Failed to generate manifests: {stderr}")); + } + + test_info!(&self.test_name, "Manifests generated successfully"); + + let crd_check_output = Command::new("kubectl") + .args([ + "get", + "crd", + "confidentialclusters.confidential-clusters.io", + ]) + .output() + .await?; + + if crd_check_output.status.success() { + test_info!( + &self.test_name, + "ConfidentialCluster CRD already exists, skipping CRD creation" + ); + } else { + test_info!(&self.test_name, "Applying CRDs"); + let crd_apply_output = Command::new("kubectl") + .args(["apply", "-f", crd_temp_dir_str]) + .output() + .await?; + + if !crd_apply_output.status.success() { + let stderr = String::from_utf8_lossy(&crd_apply_output.stderr); + return Err(anyhow::anyhow!("Failed to apply CRDs: {stderr}")); + } + } + + test_info!(&self.test_name, "Preparing RBAC manifests"); + + let sa_src = workspace_root.join("config/rbac/service_account.yaml"); + let sa_content = std::fs::read_to_string(&sa_src)?.replace( + "namespace: system", + &format!("namespace: {}", self.test_namespace), + ); + let sa_dst = rbac_temp_dir.join("service_account.yaml"); + std::fs::write(&sa_dst, sa_content)?; + + let role_path = rbac_temp_dir.join("role.yaml"); + let role_content = std::fs::read_to_string(&role_path)?.replace( + "name: cocl-operator-role", + &format!("name: {}-cocl-operator-role", self.test_namespace), + ); + std::fs::write(&role_path, role_content)?; + + let rb_src = workspace_root.join("config/rbac/role_binding.yaml"); + let rb_content = std::fs::read_to_string(&rb_src)? + .replace( + "name: manager-rolebinding", + &format!("name: {}-manager-rolebinding", self.test_namespace), + ) + .replace( + "name: cocl-operator-role", + &format!("name: {}-cocl-operator-role", self.test_namespace), + ) + .replace( + "namespace: system", + &format!("namespace: {}", self.test_namespace), + ); + let rb_dst = rbac_temp_dir.join("role_binding.yaml"); + std::fs::write(&rb_dst, rb_content)?; + + let le_role_src = workspace_root.join("config/rbac/leader_election_role.yaml"); + let le_role_content = std::fs::read_to_string(&le_role_src)?.replace( + "namespace: system", + &format!("namespace: {}", self.test_namespace), + ); + let le_role_dst = rbac_temp_dir.join("leader_election_role.yaml"); + std::fs::write(&le_role_dst, le_role_content)?; + + let le_rb_src = workspace_root.join("config/rbac/leader_election_role_binding.yaml"); + let le_rb_content = std::fs::read_to_string(&le_rb_src)?.replace( + "namespace: system", + &format!("namespace: {}", self.test_namespace), + ); + let le_rb_dst = rbac_temp_dir.join("leader_election_role_binding.yaml"); + std::fs::write(&le_rb_dst, le_rb_content)?; + + test_info!(&self.test_name, "Preparing RBAC kustomization"); + let kustomization_content = format!( + r#"# SPDX-FileCopyrightText: Generated for testing +# SPDX-License-Identifier: CC0-1.0 + +namespace: {} + +resources: + - service_account.yaml + - role.yaml + - role_binding.yaml + - leader_election_role.yaml + - leader_election_role_binding.yaml +"#, + self.test_namespace + ); + + let temp_kustomization_path = rbac_temp_dir.join("kustomization.yaml"); + std::fs::write(&temp_kustomization_path, kustomization_content)?; + + test_info!(&self.test_name, "Applying RBAC"); + let rbac_apply_output = Command::new("kubectl") + .args(["apply", "-k", rbac_temp_dir_str]) + .output() + .await?; + + if !rbac_apply_output.status.success() { + let stderr = String::from_utf8_lossy(&rbac_apply_output.stderr); + return Err(anyhow::anyhow!("Failed to apply RBAC: {stderr}")); + } + + test_info!(&self.test_name, "Applying operator manifest"); + let manifests_path = Path::new(&self.manifests_dir); + let operator_manifest_path = manifests_path.join("operator.yaml"); + let operator_manifest_str = operator_manifest_path + .to_str() + .ok_or_else(|| anyhow::anyhow!("Invalid operator manifest path"))?; + + let operator_output = Command::new("kubectl") + .args(["apply", "-f", operator_manifest_str]) + .output() + .await?; + + if !operator_output.status.success() { + let stderr = String::from_utf8_lossy(&operator_output.stderr); + return Err(anyhow::anyhow!("Failed to apply operator.yaml: {stderr}")); + } + + test_info!( + &self.test_name, + "Updating CR manifest with publicTrusteeAddr" + ); + let trustee_addr = format!("kbs-service.{}.svc.cluster.local:8080", self.test_namespace); + let cr_manifest_path = manifests_path.join("confidential_cluster_cr.yaml"); + + let cr_content = std::fs::read_to_string(&cr_manifest_path)?; + let mut cr_value: serde_yaml::Value = serde_yaml::from_str(&cr_content)?; + + if let Some(spec) = cr_value.get_mut("spec") { + if let Some(spec_map) = spec.as_mapping_mut() { + spec_map.insert( + serde_yaml::Value::String("publicTrusteeAddr".to_string()), + serde_yaml::Value::String(trustee_addr.clone()), + ); + } + } + + let updated_content = serde_yaml::to_string(&cr_value)?; + std::fs::write(&cr_manifest_path, updated_content)?; + + test_info!( + &self.test_name, + "Updated CR manifest with publicTrusteeAddr: {}", + trustee_addr + ); + + test_info!(&self.test_name, "Applying CR manifest"); + let cr_manifest_str = cr_manifest_path + .to_str() + .ok_or_else(|| anyhow::anyhow!("Invalid CR manifest path"))?; + let cr_output = Command::new("kubectl") + .args(["apply", "-f", cr_manifest_str]) + .output() + .await?; + + if !cr_output.status.success() { + let stderr = String::from_utf8_lossy(&cr_output.stderr); + return Err(anyhow::anyhow!( + "Failed to apply confidential_cluster_cr.yaml: {stderr}" + )); + } + + let deployments_api: Api = + Api::namespaced(self.client.clone(), &self.test_namespace); + + self.wait_for_deployment_ready(&deployments_api, "cocl-operator", 120) + .await?; + self.wait_for_deployment_ready(&deployments_api, "register-server", 300) + .await?; + self.wait_for_deployment_ready(&deployments_api, "trustee-deployment", 180) + .await?; + + test_info!( + &self.test_name, + "Waiting for image-pcrs ConfigMap to be created" + ); + let configmap_api: Api = + Api::namespaced(self.client.clone(), &self.test_namespace); + + let poller = Poller::new() + .with_timeout(Duration::from_secs(60)) + .with_interval(Duration::from_secs(5)) + .with_error_message(format!( + "image-pcrs ConfigMap in the namespace {} not found", + self.test_namespace + )); + + let test_name_owned = self.test_name.clone(); + poller + .poll_async(move || { + let api = configmap_api.clone(); + let tn = test_name_owned.clone(); + async move { + let result = api.get("image-pcrs").await; + if result.is_ok() { + test_info!(&tn, "image-pcrs ConfigMap created"); + } + result + } + }) + .await?; + + Ok(()) + } +} + +#[macro_export] +macro_rules! named_test { + (async fn $name:ident() -> anyhow::Result<()> { $($body:tt)* }) => { + #[tokio::test] + async fn $name() -> anyhow::Result<()> { + const TEST_NAME: &str = stringify!($name); + $($body)* + } + }; +} + +#[macro_export] +macro_rules! setup { + () => {{ $crate::TestContext::new(TEST_NAME) }}; +} + +async fn setup_test_client() -> anyhow::Result { + let client = Client::try_default().await?; + Ok(client) +} + +fn test_namespace_name() -> String { + format!("test-{}", &uuid::Uuid::new_v4().to_string()[..8]) +} + +pub async fn wait_for_resource_deleted( + api: &Api, + resource_name: &str, + timeout_secs: u64, + interval_secs: u64, +) -> anyhow::Result<()> +where + K: kube::Resource + Clone + std::fmt::Debug, + K: k8s_openapi::serde::de::DeserializeOwned, +{ + let poller = Poller::new() + .with_timeout(Duration::from_secs(timeout_secs)) + .with_interval(Duration::from_secs(interval_secs)) + .with_error_message(format!("waiting for {resource_name} to be deleted")); + + poller + .poll_async(|| { + let api = api.clone(); + let name = resource_name.to_string(); + async move { + match api.get(&name).await { + Ok(_) => Err("{name} still exists, retrying..."), + Err(kube::Error::Api(ae)) if ae.code == 404 => Ok(()), + Err(e) => { + panic!("Unexpected error while fetching {name}: {e:?}"); + } + } + } + }) + .await +} diff --git a/test_utils/src/timer.rs b/test_utils/src/timer.rs new file mode 100644 index 00000000..a1f70ec5 --- /dev/null +++ b/test_utils/src/timer.rs @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: Alice Frosi +// +// SPDX-License-Identifier: MIT + +use std::time::Duration; + +pub struct Poller { + timeout: Duration, + interval: Duration, + error_message: Option, +} + +impl Default for Poller { + fn default() -> Self { + Self::new() + } +} + +impl Poller { + pub fn new() -> Self { + Self { + timeout: Duration::from_secs(30), + interval: Duration::from_secs(5), + error_message: None, + } + } + + pub fn with_timeout(mut self, timeout: Duration) -> Self { + self.timeout = timeout; + self + } + + pub fn with_interval(mut self, interval: Duration) -> Self { + self.interval = interval; + self + } + + pub fn with_error_message>(mut self, message: S) -> Self { + self.error_message = Some(message.into()); + self + } + + pub async fn poll_async(&self, mut check_fn: F) -> anyhow::Result + where + F: FnMut() -> Fut, + Fut: std::future::Future>, + E: std::fmt::Debug, + { + let start_time = std::time::Instant::now(); + + loop { + match check_fn().await { + Ok(result) => return Ok(result), + Err(_) => { + if start_time.elapsed() >= self.timeout { + let error_msg = self.error_message.as_ref().cloned().unwrap_or_else(|| { + format!("Polling timed out after {:?}", self.timeout) + }); + return Err(anyhow::anyhow!(error_msg)); + } + tokio::time::sleep(self.interval).await; + } + } + } + } +} diff --git a/tests/Cargo.toml b/tests/Cargo.toml index a678fc0d..bbba182f 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -1,4 +1,5 @@ # SPDX-FileCopyrightText: Jakob Naucke +# SPDX-FileCopyrightText: Alice Frosi # # SPDX-License-Identifier: CC0-1.0 @@ -9,7 +10,19 @@ edition.workspace = true rust-version.workspace = true [dependencies] -regex = "1.12.2" +anyhow.workspace = true +cocl-operator-lib = { path = "../lib" } +cocl-operator-test-utils = { path = "../test_utils" } +compute-pcrs-lib.workspace = true +k8s-openapi.workspace = true +kube = { workspace = true } +regex = "1" +serde_json.workspace = true +tokio = { workspace = true } + +[[test]] +name = "confidential_cluster" +path = "confidential_cluster.rs" [[test]] name = "equal_conditions" diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..07865c5b --- /dev/null +++ b/tests/README.md @@ -0,0 +1,21 @@ +# Integration tests + +The integration tests evaluate if the operator is functioning correctly. Each integration tests is deployed in a new +namespace in a way to guarantee the isolation of a test from the other, and to be able to run them in parallel. +The operator is installed in each namespace before running the actual tests with the `setup` function. +Upon a successful test, the namespace is cleaned up, otherwise it is kept for inspecting the state. + +## Setup the integration tests locally +Run the tests locally with kind: +``` +export RUNTIME=docker +make cluster-up +export REGISTRY=localhost:5000/confidential-clusters +make push +make integration-tests +``` + +Each test can also be run independently using cargo test. Example: +```bash +$ cargo test test_confidential_cluster_uninstall -- --no-capture +``` diff --git a/tests/confidential_cluster.rs b/tests/confidential_cluster.rs new file mode 100644 index 00000000..34dadb1a --- /dev/null +++ b/tests/confidential_cluster.rs @@ -0,0 +1,146 @@ +// SPDX-FileCopyrightText: Alice Frosi +// +// SPDX-License-Identifier: MIT + +use cocl_operator_lib::ConfidentialCluster; +use cocl_operator_lib::reference_values::ImagePcrs; +use cocl_operator_test_utils::*; +use compute_pcrs_lib::{Part, Pcr}; +use k8s_openapi::api::apps::v1::Deployment; +use k8s_openapi::api::core::v1::ConfigMap; +use kube::{Api, api::DeleteParams}; +use std::time::Duration; + +named_test!( + async fn test_confidential_cluster_uninstall() -> anyhow::Result<()> { + let test_ctx = setup!().await?; + let client = test_ctx.client(); + let namespace = test_ctx.namespace(); + let name = "confidential-cluster"; + + let configmap_api: Api = Api::namespaced(client.clone(), namespace); + + // Delete the cocl cr + let api: Api = Api::namespaced(client.clone(), namespace); + let dp = DeleteParams::default(); + api.delete(name, &dp).await?; + + // Wait until it disappears + wait_for_resource_deleted(&api, name, 120, 5).await?; + + let deployments_api: Api = Api::namespaced(client.clone(), namespace); + wait_for_resource_deleted(&deployments_api, "trustee-deployment", 120, 1).await?; + wait_for_resource_deleted(&deployments_api, "register-server", 120, 1).await?; + wait_for_resource_deleted(&configmap_api, "image-pcrs", 120, 1).await?; + + test_ctx.cleanup().await?; + + Ok(()) + } +); + +named_test! { +async fn test_image_pcrs_configmap_updates() -> anyhow::Result<()> { + let test_ctx = setup!().await?; + let client = test_ctx.client(); + let namespace = test_ctx.namespace(); + + let configmap_api: Api = Api::namespaced(client.clone(), namespace); + + let poller = Poller::new() + .with_timeout(Duration::from_secs(180)) + .with_interval(Duration::from_secs(5)) + .with_error_message("image-pcrs ConfigMap not populated with data".to_string()); + + poller + .poll_async(|| { + let api = configmap_api.clone(); + async move { + let cm = api.get("image-pcrs").await?; + + if let Some(data) = &cm.data { + if let Some(image_pcrs_json) = data.get("image-pcrs.json") { + if !image_pcrs_json.is_empty() { + return Ok(()); + } + } + } + + Err(anyhow::anyhow!("image-pcrs ConfigMap not yet populated with image-pcrs.json data")) + } + }) + .await?; + + let image_pcrs_cm = configmap_api.get("image-pcrs").await?; + assert_eq!(image_pcrs_cm.metadata.name.as_deref(), Some("image-pcrs")); + + let data = image_pcrs_cm.data.as_ref() + .expect("image-pcrs ConfigMap should have data field"); + + assert!(!data.is_empty(), "image-pcrs ConfigMap should have data"); + + let image_pcrs_json = data.get("image-pcrs.json") + .expect("image-pcrs ConfigMap should have image-pcrs.json key"); + + assert!(!image_pcrs_json.is_empty(), "image-pcrs.json should not be empty"); + + // Parse the image-pcrs.json using the ImagePcrs structure + let image_pcrs: ImagePcrs = serde_json::from_str(image_pcrs_json) + .expect("image-pcrs.json should be valid ImagePcrs JSON"); + + assert!(!image_pcrs.0.is_empty(), "image-pcrs.json should contain at least one image entry"); + + let expected_pcrs = vec![ + Pcr { + id: 4, + value: "551bbd142a716c67cd78336593c2eb3b547b575e810ced4501d761082b5cd4a8".to_string(), + parts: vec![ + Part { name: "EV_EFI_ACTION".to_string(), hash: "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba".to_string() }, + Part { name: "EV_SEPARATOR".to_string(), hash: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119".to_string() }, + Part { name: "EV_EFI_BOOT_SERVICES_APPLICATION".to_string(), hash: "94896c17d49fc8c8df0cc2836611586edab1615ce7cb58cf13fc5798de56b367".to_string() }, + Part { name: "EV_EFI_BOOT_SERVICES_APPLICATION".to_string(), hash: "bc6844fc7b59b4f0c7da70a307fc578465411d7a2c34b0f4dc2cc154c873b644".to_string() }, + Part { name: "EV_EFI_BOOT_SERVICES_APPLICATION".to_string(), hash: "2b1dc59bc61dbbc3db11a6f3b0708c948efd46cceb7f6c8ea2024b8d1b8c829a".to_string() }, + ], + }, + Pcr { + id: 7, + value: "b3a56a06c03a65277d0a787fcabc1e293eaa5d6dd79398f2dda741f7b874c65d".to_string(), + parts: vec![ + Part { name: "EV_EFI_VARIABLE_DRIVER_CONFIG".to_string(), hash: "ccfc4bb32888a345bc8aeadaba552b627d99348c767681ab3141f5b01e40a40e".to_string() }, + Part { name: "EV_EFI_VARIABLE_DRIVER_CONFIG".to_string(), hash: "adb6fc232943e39c374bf4782b6c697f43c39fca1f4b51dfceda21164e19a893".to_string() }, + Part { name: "EV_EFI_VARIABLE_DRIVER_CONFIG".to_string(), hash: "b5432fe20c624811cb0296391bfdf948ebd02f0705ab8229bea09774023f0ebf".to_string() }, + Part { name: "EV_EFI_VARIABLE_DRIVER_CONFIG".to_string(), hash: "4313e43de720194a0eabf4d6415d42b5a03a34fdc47bb1fc924cc4e665e6893d".to_string() }, + Part { name: "EV_EFI_VARIABLE_DRIVER_CONFIG".to_string(), hash: "001004ba58a184f09be6c1f4ec75a246cc2eefa9637b48ee428b6aa9bce48c55".to_string() }, + Part { name: "EV_SEPARATOR".to_string(), hash: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119".to_string() }, + Part { name: "EV_EFI_VARIABLE_AUTHORITY".to_string(), hash: "4d4a8e2c74133bbdc01a16eaf2dbb5d575afeb36f5d8dfcf609ae043909e2ee9".to_string() }, + Part { name: "EV_EFI_VARIABLE_AUTHORITY".to_string(), hash: "e8e9578f5951ef16b1c1aa18ef02944b8375ec45ed4b5d8cdb30428db4a31016".to_string() }, + Part { name: "EV_EFI_VARIABLE_AUTHORITY".to_string(), hash: "ad5901fd581e6640c742c488083b9ac2c48255bd28a16c106c6f9df52702ee3f".to_string() }, + ], + }, + Pcr { + id: 14, + value: "17cdefd9548f4383b67a37a901673bf3c8ded6f619d36c8007562de1d93c81cc".to_string(), + parts: vec![ + Part { name: "EV_IPL".to_string(), hash: "e8e48e3ad10bc243341b4663c0057aef0ec7894ccc9ecb0598f0830fa57f7220".to_string() }, + Part { name: "EV_IPL".to_string(), hash: "8d8a3aae50d5d25838c95c034aadce7b548c9a952eb7925e366eda537c59c3b0".to_string() }, + Part { name: "EV_IPL".to_string(), hash: "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a".to_string() }, + ], + }, + ]; + + let mut found_expected_pcrs = false; + for (_image_ref, image_data) in image_pcrs.0.iter() { + if compare_pcrs(&image_data.pcrs, &expected_pcrs) { + found_expected_pcrs = true; + break; + } + } + + assert!(found_expected_pcrs, + "At least one image should have the expected PCR values"); + + test_ctx.cleanup().await?; + + Ok(()) +} +} From 976ac6a4186127ac6a07b1b56f6c8fca74452437 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 4 Nov 2025 15:15:48 +0100 Subject: [PATCH 11/14] Testing attestation with KubeVirt VM Add support for KubeVirt-based integration testing: - Add virtualization feature flag to test_utils and tests crates - Create test_utils/src/virt.rs with KubeVirt helper functions: - SSH key generation and injection into ssh-agent - Ignition config generation - KubeVirt VM creation and lifecycle management - SSH command execution via virtctl - Encrypted root device verification - Add attestation integration test that validates: - if a VM attests and boots successfully - if the attestation can be run in parallel by starting 2 VMs - if the attestation properly works for subsequent boots by rebooting the VM multiple times Tests can run with: cargo test --features virtualization Signed-off-by: Alice Frosi --- Cargo.lock | 364 ++++++++++++++++++++++++++++++++++++ test_utils/Cargo.toml | 7 + test_utils/src/lib.rs | 20 ++ test_utils/src/virt.rs | 410 +++++++++++++++++++++++++++++++++++++++++ tests/Cargo.toml | 7 + tests/README.md | 6 + tests/attestation.rs | 245 ++++++++++++++++++++++++ 7 files changed, 1059 insertions(+) create mode 100644 test_utils/src/virt.rs create mode 100644 tests/attestation.rs diff --git a/Cargo.lock b/Cargo.lock index 916ae4fc..1568982d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -247,6 +247,12 @@ dependencies = [ "backtrace", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.13.1" @@ -265,6 +271,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + [[package]] name = "bitflags" version = "1.3.2" @@ -334,6 +346,16 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.5.51" @@ -402,13 +424,17 @@ dependencies = [ "cocl-operator-lib", "compute-pcrs-lib", "env_logger", + "ignition-config", "k8s-openapi", "kube", "log", + "rand_core", "serde_json", "serde_yaml", + "ssh-key", "tokio", "uuid", + "which", ] [[package]] @@ -472,6 +498,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const_format" version = "0.2.35" @@ -532,6 +564,18 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -647,6 +691,16 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "deranged" version = "0.5.5" @@ -714,6 +768,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -735,6 +790,20 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "educe" version = "0.6.0" @@ -753,6 +822,25 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.35" @@ -792,6 +880,12 @@ dependencies = [ "regex", ] +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "env_logger" version = "0.11.8" @@ -848,6 +942,16 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "find-msvc-tools" version = "0.1.4" @@ -985,6 +1089,7 @@ checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1066,6 +1171,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "h2" version = "0.3.27" @@ -1570,6 +1686,15 @@ dependencies = [ "hashbrown 0.16.0", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -1844,6 +1969,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libc" @@ -1851,6 +1979,12 @@ version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "lief" version = "0.17.1" @@ -2071,6 +2205,22 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c79c15c05d4bf82b6f5ef163104cc81a760d8e874d38ac50ab67c8877b647b" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2097,6 +2247,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2104,6 +2265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2269,6 +2431,44 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "rand_core", + "sha2", +] + [[package]] name = "parking" version = "2.2.1" @@ -2308,6 +2508,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2389,6 +2598,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -2434,6 +2664,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2692,6 +2931,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.14" @@ -2706,6 +2955,27 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "sha2", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -2833,6 +3103,20 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secrecy" version = "0.10.3" @@ -3007,6 +3291,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -3057,6 +3351,58 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "cipher", + "ssh-encoding", +] + +[[package]] +name = "ssh-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +dependencies = [ + "base64ct", + "pem-rfc7468", + "sha2", +] + +[[package]] +name = "ssh-key" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3" +dependencies = [ + "num-bigint-dig", + "p256", + "p384", + "p521", + "rand_core", + "rsa", + "sec1", + "sha2", + "signature", + "ssh-cipher", + "ssh-encoding", + "subtle", + "zeroize", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -3748,6 +4094,18 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "which" +version = "7.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +dependencies = [ + "either", + "env_home", + "rustix", + "winsafe", +] + [[package]] name = "winapi" version = "0.3.9" @@ -4076,6 +4434,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "wit-bindgen" version = "0.46.0" diff --git a/test_utils/Cargo.toml b/test_utils/Cargo.toml index 7cf416db..de194e21 100644 --- a/test_utils/Cargo.toml +++ b/test_utils/Cargo.toml @@ -8,15 +8,22 @@ version = "0.1.0" edition.workspace = true rust-version.workspace = true +[features] +virtualization = [] + [dependencies] anyhow.workspace = true cocl-operator-lib = { path = "../lib" } compute-pcrs-lib.workspace = true env_logger.workspace = true +ignition-config = "0.5.0" k8s-openapi.workspace = true kube = { workspace = true } log.workspace = true +rand_core = "0.6" serde_json.workspace = true serde_yaml.workspace = true +ssh-key = { version = "0.6", features = ["rsa", "std"] } tokio = { workspace = true, features = ["process"] } uuid.workspace = true +which = "7.0" diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index f9f7f8be..2031ea78 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs @@ -15,6 +15,9 @@ use tokio::process::Command; pub mod timer; pub use timer::Poller; +#[cfg(feature = "virtualization")] +pub mod virt; + use compute_pcrs_lib::Pcr; pub fn compare_pcrs(actual: &[Pcr], expected: &[Pcr]) -> bool { @@ -89,6 +92,10 @@ impl TestContext { &self.test_namespace } + pub fn info(&self, message: impl std::fmt::Display) { + test_info!(&self.test_name, "{}", message); + } + pub async fn cleanup(&self) -> anyhow::Result<()> { self.cleanup_namespace().await?; self.cleanup_manifests_dir()?; @@ -513,6 +520,19 @@ macro_rules! named_test { }; } +// virt_test labels the tests that require virtualization +#[macro_export] +macro_rules! virt_test { + (async fn $name:ident() -> anyhow::Result<()> { $($body:tt)* }) => { + #[cfg(feature = "virtualization")] + #[tokio::test] + async fn $name() -> anyhow::Result<()> { + const TEST_NAME: &str = stringify!($name); + $($body)* + } + }; +} + #[macro_export] macro_rules! setup { () => {{ $crate::TestContext::new(TEST_NAME) }}; diff --git a/test_utils/src/virt.rs b/test_utils/src/virt.rs new file mode 100644 index 00000000..819a81ff --- /dev/null +++ b/test_utils/src/virt.rs @@ -0,0 +1,410 @@ +// SPDX-FileCopyrightText: Alice Frosi +// +// SPDX-License-Identifier: MIT + +use ignition_config::v3_5::{ + Config, Dropin, File, Ignition, IgnitionConfig, Passwd, Resource, Storage, Systemd, Unit, User, +}; +use kube::Client; +use std::path::Path; +use std::time::Duration; +use tokio::process::Command; + +use super::Poller; + +pub fn generate_ssh_key_pair() -> anyhow::Result<(String, String, std::path::PathBuf)> { + use rand_core::OsRng; + use ssh_key::{Algorithm, LineEnding, PrivateKey}; + use std::fs; + use std::os::unix::fs::PermissionsExt; + use std::process::Command as StdCommand; + + let private_key = PrivateKey::random(&mut OsRng, Algorithm::Rsa { hash: None })?; + let private_key_str = private_key.to_openssh(LineEnding::LF)?.to_string(); + let public_key = private_key.public_key(); + let public_key_str = public_key.to_openssh()?; + + // Save private key to a temporary file + let temp_dir = std::env::temp_dir(); + let key_path = temp_dir.join(format!("ssh_key_{}", uuid::Uuid::new_v4())); + fs::write(&key_path, &private_key_str)?; + + // Set proper permissions (0600) for SSH key + let mut perms = fs::metadata(&key_path)?.permissions(); + perms.set_mode(0o600); + fs::set_permissions(&key_path, perms)?; + + // Add key to ssh-agent using synchronous command + let ssh_add_output = StdCommand::new("ssh-add") + .arg(key_path.to_str().unwrap()) + .output()?; + + if !ssh_add_output.status.success() { + let stderr = String::from_utf8_lossy(&ssh_add_output.stderr); + // Clean up the key file if ssh-add fails + let _ = fs::remove_file(&key_path); + return Err(anyhow::anyhow!( + "Failed to add SSH key to agent: {}", + stderr + )); + } + + Ok((private_key_str, public_key_str, key_path)) +} + +pub fn generate_ignition_config( + ssh_public_key: &str, + register_server_url: &str, +) -> serde_json::Value { + // Create the ignition configuration + let ignition = Ignition { + version: "3.5.0".to_string(), + config: Some(IgnitionConfig { + merge: Some(vec![Resource { + source: Some(register_server_url.to_string()), + compression: None, + http_headers: None, + verification: None, + }]), + replace: None, + }), + proxy: None, + security: None, + timeouts: None, + }; + + let mut user = User::new("core".to_string()); + user.ssh_authorized_keys = Some(vec![ssh_public_key.to_string()]); + let config = Config { + ignition, + kernel_arguments: None, + passwd: Some(Passwd { + users: Some(vec![user]), + groups: None, + }), + storage: Some(Storage { + directories: None, + disks: None, + files: Some(vec![File { + path: "/etc/profile.d/systemd-pager.sh".to_string(), + contents: Some(Resource { + source: Some("data:,%23%20Tell%20systemd%20to%20not%20use%20a%20pager%20when%20printing%20information%0Aexport%20SYSTEMD_PAGER%3Dcat%0A".to_string()), + compression: Some(String::new()), + http_headers: None, + verification: None, + }), + mode: Some(420), + append: None, + group: None, + overwrite: None, + user: None, + }]), + filesystems: None, + links: None, + luks: None, + raid: None, + }), + systemd: Some(Systemd { + units: Some(vec![ + Unit { + name: "zincati.service".to_string(), + enabled: Some(false), + contents: None, + dropins: None, + mask: None, + }, + Unit { + name: "serial-getty@ttyS0.service".to_string(), + enabled: None, + contents: None, + mask: None, + dropins: Some(vec![Dropin { + name: "autologin-core.conf".to_string(), + contents: Some("[Service]\n# Override Execstart in main unit\nExecStart=\n# Add new Execstart with `-` prefix to ignore failure`\nExecStart=-/usr/sbin/agetty --autologin core --noclear %I $TERM\n".to_string()), + }]), + }, + ]), + }), + }; + + serde_json::to_value(&config).expect("Failed to serialize ignition config") +} + +/// Create a KubeVirt VirtualMachine with the specified configuration +/// TODO create rust a create for KubeVirt virtual machines +pub async fn create_kubevirt_vm( + client: &Client, + namespace: &str, + vm_name: &str, + ssh_public_key: &str, + register_server_url: &str, + image: &str, +) -> anyhow::Result<()> { + use kube::Api; + use kube::api::PostParams; + use kube::core::DynamicObject; + use kube::discovery; + + let ignition_config = generate_ignition_config(ssh_public_key, register_server_url); + let ignition_json = serde_json::to_string(&ignition_config)?; + + let vm_spec = serde_json::json!({ + "apiVersion": "kubevirt.io/v1", + "kind": "VirtualMachine", + "metadata": { + "name": vm_name, + "namespace": namespace + }, + "spec": { + "runStrategy": "Always", + "template": { + "metadata": { + "annotations": { + "kubevirt.io/ignitiondata": ignition_json + } + }, + "spec": { + "domain": { + "features": { + "smm": { + "enabled": true + } + }, + "firmware": { + "bootloader": { + "efi": { + "persistent": true + } + } + }, + "devices": { + "tpm": { + "persistent": true + }, + "disks": [ + { + "name": "containerdisk", + "disk": { + "bus": "virtio" + } + } + ], + "rng": {} + }, + "resources": { + "requests": { + "memory": "4096M" + } + } + }, + "volumes": [ + { + "name": "containerdisk", + "containerDisk": { + "image": image, + "imagePullPolicy": "Always" + } + } + ] + } + } + } + }); + + let discovery = discovery::Discovery::new(client.clone()).run().await?; + + let apigroup = discovery + .groups() + .find(|g| g.name() == "kubevirt.io") + .ok_or_else(|| anyhow::anyhow!("kubevirt.io API group not found"))?; + + let (ar, _caps) = apigroup + .recommended_kind("VirtualMachine") + .ok_or_else(|| anyhow::anyhow!("VirtualMachine kind not found"))?; + + let api: Api = Api::namespaced_with(client.clone(), namespace, &ar); + let vm_object: DynamicObject = serde_json::from_value(vm_spec)?; + + api.create(&PostParams::default(), &vm_object).await?; + + Ok(()) +} + +/// Wait for a KubeVirt VirtualMachine to reach Running phase +pub async fn wait_for_vm_running( + client: &Client, + namespace: &str, + vm_name: &str, + timeout_secs: u64, +) -> anyhow::Result<()> { + use kube::api::Api; + use kube::core::DynamicObject; + use kube::discovery; + + // Discover the VirtualMachine API + let discovery = discovery::Discovery::new(client.clone()).run().await?; + + let apigroup = discovery + .groups() + .find(|g| g.name() == "kubevirt.io") + .ok_or_else(|| anyhow::anyhow!("kubevirt.io API group not found"))?; + + let (ar, _caps) = apigroup + .recommended_kind("VirtualMachine") + .ok_or_else(|| anyhow::anyhow!("VirtualMachine kind not found"))?; + + let api: Api = Api::namespaced_with(client.clone(), namespace, &ar); + + let poller = Poller::new() + .with_timeout(Duration::from_secs(timeout_secs)) + .with_interval(Duration::from_secs(5)) + .with_error_message(format!( + "VirtualMachine {} did not reach Running phase after {} seconds", + vm_name, timeout_secs + )); + + poller + .poll_async(|| { + let api = api.clone(); + let name = vm_name.to_string(); + async move { + let vm = api.get(&name).await?; + + // Check VM status phase + if let Some(status) = vm.data.get("status") { + if let Some(phase) = status.get("printableStatus") { + if let Some(phase_str) = phase.as_str() { + if phase_str == "Running" { + return Ok(()); + } + } + } + } + + Err(anyhow::anyhow!( + "VirtualMachine {} is not in Running phase yet", + name + )) + } + }) + .await +} + +pub async fn virtctl_ssh_exec( + namespace: &str, + vm_name: &str, + key_path: &Path, + command: &str, +) -> anyhow::Result { + if which::which("virtctl").is_err() { + return Err(anyhow::anyhow!( + "virtctl command not found. Please install virtctl first." + )); + } + + let _vm_target = format!("core@vmi/{}/{}", vm_name, namespace); + let full_cmd = format!( + "virtctl ssh -i {} core@vmi/{}/{} -t '-o IdentitiesOnly=yes' -t '-o StrictHostKeyChecking=no' --known-hosts /dev/null -c '{}'", + key_path.display(), + vm_name, + namespace, + command + ); + + let output = Command::new("sh").arg("-c").arg(full_cmd).output().await?; + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(anyhow::anyhow!("virtctl ssh command failed: {}", stderr)); + } + + Ok(String::from_utf8_lossy(&output.stdout).to_string()) +} + +pub async fn wait_for_vm_ssh_ready( + namespace: &str, + vm_name: &str, + key_path: &Path, + timeout_secs: u64, +) -> anyhow::Result<()> { + let poller = Poller::new() + .with_timeout(Duration::from_secs(timeout_secs)) + .with_interval(Duration::from_secs(10)) + .with_error_message(format!( + "SSH access to VM {}/{} did not become available after {} seconds", + namespace, vm_name, timeout_secs + )); + + poller + .poll_async(|| { + let ns = namespace.to_string(); + let vm = vm_name.to_string(); + let key = key_path.to_path_buf(); + async move { + // Try a simple command to check if SSH is ready + match virtctl_ssh_exec(&ns, &vm, &key, "echo ready").await { + Ok(_) => Ok(()), + Err(e) => Err(anyhow::anyhow!("SSH not ready yet: {}", e)), + } + } + }) + .await +} + +pub async fn verify_encrypted_root( + namespace: &str, + vm_name: &str, + key_path: &Path, +) -> anyhow::Result { + let output = virtctl_ssh_exec(namespace, vm_name, key_path, "lsblk -o NAME,TYPE -J").await?; + + // Parse JSON output + let lsblk_output: serde_json::Value = serde_json::from_str(&output)?; + + // Look for a device with name "root" and type "crypt" + if let Some(blockdevices) = lsblk_output.get("blockdevices") { + if let Some(devices) = blockdevices.as_array() { + for device in devices { + // Check the device itself + if is_root_crypt_device(device) { + return Ok(true); + } + + // Check children devices recursively + if let Some(children) = device.get("children") { + if let Some(children_arr) = children.as_array() { + for child in children_arr { + if is_root_crypt_device(child) { + return Ok(true); + } + // Check nested children + if let Some(nested_children) = child.get("children") { + if let Some(nested_arr) = nested_children.as_array() { + for nested in nested_arr { + if is_root_crypt_device(nested) { + return Ok(true); + } + } + } + } + } + } + } + } + } + } + + Ok(false) +} + +fn is_root_crypt_device(device: &serde_json::Value) -> bool { + let name = device.get("name").and_then(|n| n.as_str()); + let dev_type = device.get("type").and_then(|t| t.as_str()); + + if let (Some(n), Some(t)) = (name, dev_type) { + if n == "root" && t == "crypt" { + return true; + } + } + + false +} diff --git a/tests/Cargo.toml b/tests/Cargo.toml index bbba182f..2f79fd31 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -9,6 +9,9 @@ version = "0.1.0" edition.workspace = true rust-version.workspace = true +[features] +virtualization = [] + [dependencies] anyhow.workspace = true cocl-operator-lib = { path = "../lib" } @@ -24,6 +27,10 @@ tokio = { workspace = true } name = "confidential_cluster" path = "confidential_cluster.rs" +[[test]] +name = "attestation" +path = "attestation.rs" + [[test]] name = "equal_conditions" path = "equal_conditions.rs" diff --git a/tests/README.md b/tests/README.md index 07865c5b..65a8beec 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,12 +6,18 @@ The operator is installed in each namespace before running the actual tests with Upon a successful test, the namespace is cleaned up, otherwise it is kept for inspecting the state. ## Setup the integration tests locally +The tests use [`virtctl`](https://kubevirt.io/user-guide/user_workloads/virtctl_client_tool/) in order to interact with +VM, like getting the serial console and verifying that the guest has correctly booted by ssh-ing into it. + +N.B KubeVirt requires the cluster to be run as a privileged container on the host in order to handle the devices. Therefore, for now, we have moved to Docker with kind in order to generate the cluster. In the future, we might be able to move to rootful podman. + Run the tests locally with kind: ``` export RUNTIME=docker make cluster-up export REGISTRY=localhost:5000/confidential-clusters make push +make install-kubevirt make integration-tests ``` diff --git a/tests/attestation.rs b/tests/attestation.rs new file mode 100644 index 00000000..69266ce8 --- /dev/null +++ b/tests/attestation.rs @@ -0,0 +1,245 @@ +// SPDX-FileCopyrightText: Alice Frosi +// +// SPDX-License-Identifier: MIT + +use cocl_operator_test_utils::*; + +#[cfg(feature = "virtualization")] +use cocl_operator_test_utils::virt; + +virt_test! { +async fn test_attestation() -> anyhow::Result<()> { + let test_ctx = setup!().await?; + let client = test_ctx.client(); + let namespace = test_ctx.namespace(); + + let (_private_key, public_key, key_path) = virt::generate_ssh_key_pair()?; + test_ctx.info(format!("Generated SSH key pair and added to ssh-agent: {:?}", key_path)); + + let vm_name = "test-coreos-vm"; + let register_server_url = format!( + "http://register-server.{}.svc.cluster.local:8000/ignition-clevis-pin-trustee", + namespace + ); + let image = "quay.io/confidential-clusters/fedora-coreos-kubevirt:latest"; + + test_ctx.info(format!("Creating VM: {}", vm_name)); + virt::create_kubevirt_vm( + client, + namespace, + vm_name, + &public_key, + ®ister_server_url, + image, + ) + .await?; + + test_ctx.info(format!("Waiting for VM {} to reach Running state", vm_name)); + virt::wait_for_vm_running(client, namespace, vm_name, 180).await?; + test_ctx.info(format!("VM {} is Running", vm_name)); + + test_ctx.info(format!("Waiting for SSH access to VM {}", vm_name)); + virt::wait_for_vm_ssh_ready(namespace, vm_name, &key_path, 300).await?; + test_ctx.info("SSH access is ready"); + + test_ctx.info("Verifying encrypted root device"); + let has_encrypted_root = virt::verify_encrypted_root(namespace, vm_name, &key_path).await?; + + let _ = std::fs::remove_file(&key_path); + + assert!( + has_encrypted_root, + "VM should have an encrypted root device (attestation failed)" + ); + test_ctx.info("Attestation successful: encrypted root device verified"); + + test_ctx.cleanup().await?; + + Ok(()) +} +} + +virt_test! { +async fn test_parallel_vm_attestation() -> anyhow::Result<()> { + let test_ctx = setup!().await?; + let client = test_ctx.client(); + let namespace = test_ctx.namespace(); + + test_ctx.info("Testing parallel VM attestation - launching 2 VMs simultaneously"); + + // Generate SSH keys for both VMs + let (_private_key1, public_key1, key_path1) = virt::generate_ssh_key_pair()?; + let (_private_key2, public_key2, key_path2) = virt::generate_ssh_key_pair()?; + test_ctx.info("Generated SSH key pairs for both VMs"); + + let register_server_url = format!( + "http://register-server.{}.svc.cluster.local:8000/ignition-clevis-pin-trustee", + namespace + ); + let image = "quay.io/confidential-clusters/fedora-coreos-kubevirt:latest"; + + // Launch both VMs in parallel + let vm1_name = "test-coreos-vm1"; + let vm2_name = "test-coreos-vm2"; + + test_ctx.info("Creating VM1 and VM2 in parallel"); + let (vm1_result, vm2_result) = tokio::join!( + virt::create_kubevirt_vm( + client, + namespace, + vm1_name, + &public_key1, + ®ister_server_url, + image, + ), + virt::create_kubevirt_vm( + client, + namespace, + vm2_name, + &public_key2, + ®ister_server_url, + image, + ) + ); + + vm1_result?; + vm2_result?; + test_ctx.info("Both VMs created successfully"); + + // Wait for both VMs to reach Running state in parallel + test_ctx.info("Waiting for both VMs to reach Running state"); + let (vm1_running, vm2_running) = tokio::join!( + virt::wait_for_vm_running(client, namespace, vm1_name, 300), + virt::wait_for_vm_running(client, namespace, vm2_name, 300) + ); + + vm1_running?; + vm2_running?; + test_ctx.info("Both VMs are Running"); + + // Wait for SSH access on both VMs in parallel + test_ctx.info("Waiting for SSH access on both VMs"); + let (ssh1_ready, ssh2_ready) = tokio::join!( + virt::wait_for_vm_ssh_ready(namespace, vm1_name, &key_path1, 300), + virt::wait_for_vm_ssh_ready(namespace, vm2_name, &key_path2, 300) + ); + + ssh1_ready?; + ssh2_ready?; + test_ctx.info("SSH access ready on both VMs"); + + // Verify attestation on both VMs in parallel + test_ctx.info("Verifying encrypted root on both VMs"); + let (vm1_encrypted, vm2_encrypted) = tokio::join!( + virt::verify_encrypted_root(namespace, vm1_name, &key_path1), + virt::verify_encrypted_root(namespace, vm2_name, &key_path2) + ); + + let vm1_has_encrypted_root = vm1_encrypted?; + let vm2_has_encrypted_root = vm2_encrypted?; + + // Clean up SSH keys + let _ = std::fs::remove_file(&key_path1); + let _ = std::fs::remove_file(&key_path2); + + assert!( + vm1_has_encrypted_root, + "VM1 should have an encrypted root device (attestation failed)" + ); + assert!( + vm2_has_encrypted_root, + "VM2 should have an encrypted root device (attestation failed)" + ); + + test_ctx.info("Both VMs successfully attested with encrypted root devices"); + + test_ctx.cleanup().await?; + + Ok(()) +} +} + +virt_test! { +async fn test_vm_reboot_attestation() -> anyhow::Result<()> { + let test_ctx = setup!().await?; + let client = test_ctx.client(); + let namespace = test_ctx.namespace(); + + test_ctx.info("Testing VM reboot - VM should successfully boot after multiple reboots"); + + let (_private_key, public_key, key_path) = virt::generate_ssh_key_pair()?; + test_ctx.info(format!("Generated SSH key pair: {:?}", key_path)); + + let vm_name = "test-coreos-reboot"; + let register_server_url = format!( + "http://register-server.{}.svc.cluster.local:8000/ignition-clevis-pin-trustee", + namespace + ); + let image = "quay.io/confidential-clusters/fedora-coreos-kubevirt:latest"; + + test_ctx.info(format!("Creating VM: {}", vm_name)); + virt::create_kubevirt_vm( + client, + namespace, + vm_name, + &public_key, + ®ister_server_url, + image, + ) + .await?; + + test_ctx.info("Waiting for VM to reach Running state"); + virt::wait_for_vm_running(client, namespace, vm_name, 300).await?; + + test_ctx.info("Waiting for SSH access"); + virt::wait_for_vm_ssh_ready(namespace, vm_name, &key_path, 300).await?; + + test_ctx.info("Verifying initial encrypted root device"); + let has_encrypted_root = virt::verify_encrypted_root(namespace, vm_name, &key_path).await?; + assert!( + has_encrypted_root, + "VM should have encrypted root device on initial boot" + ); + test_ctx.info("Initial boot: attestation successful"); + + // Perform multiple reboots + let num_reboots = 3; + for i in 1..=num_reboots { + test_ctx.info(format!("Performing reboot {} of {}", i, num_reboots)); + + // Reboot the VM via SSH + let _reboot_result = virt::virtctl_ssh_exec( + namespace, + vm_name, + &key_path, + "sudo systemctl reboot" + ).await; + + tokio::time::sleep(std::time::Duration::from_secs(10)).await; + + test_ctx.info(format!("Waiting for SSH access after reboot {}", i)); + virt::wait_for_vm_ssh_ready(namespace, vm_name, &key_path, 300).await?; + + // Verify encrypted root is still present after reboot + test_ctx.info(format!("Verifying encrypted root after reboot {}", i)); + let has_encrypted_root = virt::verify_encrypted_root(namespace, vm_name, &key_path).await?; + assert!( + has_encrypted_root, + "VM should have encrypted root device after reboot {}", i + ); + test_ctx.info(format!("Reboot {}: attestation successful", i)); + } + + // Clean up SSH key + let _ = std::fs::remove_file(&key_path); + + test_ctx.info(format!( + "VM successfully rebooted {} times with encrypted root device maintained", + num_reboots + )); + + test_ctx.cleanup().await?; + + Ok(()) +} +} From 0b934d39858abc27b2ca6cdc2dc200a1ce65f6b6 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 14 Oct 2025 10:38:08 +0200 Subject: [PATCH 12/14] Add make rule for running the integration tests Signed-off-by: Alice Frosi --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 18c20e3f..5533744d 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,10 @@ test: test-release: cargo test --workspace --all-targets --release +integration-tests: + RUST_LOG=info cargo test --test confidential_cluster --test attestation --features virtualization -- \ + --no-capture --test-threads=3 + $(LOCALBIN): mkdir -p $(LOCALBIN) From 667bd68a5375a8b54d4959939e127abc4fe6198e Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Wed, 12 Nov 2025 14:26:01 +0100 Subject: [PATCH 13/14] Fix kind cluster waiting Without the installation of the standard CNI, the waiting for the cluster to be ready times out. This is probably a bug in kind, then let's create the cluster and wait for the API server to be running. Signed-off-by: Alice Frosi --- scripts/create-cluster-kind.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/create-cluster-kind.sh b/scripts/create-cluster-kind.sh index 7ba7bdfd..c863c0b7 100755 --- a/scripts/create-cluster-kind.sh +++ b/scripts/create-cluster-kind.sh @@ -10,7 +10,8 @@ set -xo errexit . scripts/common.sh if [ "$(kind get clusters 2>/dev/null)" != "kind" ]; then - kind create cluster --config kind/config.yaml --wait 5m + kind create cluster --config kind/config.yaml + kubectl wait --for=condition=Ready pod -l component=kube-apiserver -n kube-system fi reg_name='kind-registry' From a4c708af02fd1a4f24088c3877e7dd1c23b402be Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Wed, 12 Nov 2025 16:21:18 +0100 Subject: [PATCH 14/14] Run the integration tests serially We still need to investigate how to correctly parellelize the tests, for now to get the first tests integrated we decide to run them serially. Signed-off-by: Alice Frosi --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5533744d..67b97d58 100644 --- a/Makefile +++ b/Makefile @@ -137,7 +137,7 @@ test-release: integration-tests: RUST_LOG=info cargo test --test confidential_cluster --test attestation --features virtualization -- \ - --no-capture --test-threads=3 + --no-capture --test-threads=1 $(LOCALBIN): mkdir -p $(LOCALBIN)