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 diff --git a/Cargo.lock b/Cargo.lock index 691ab804..1568982d 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]] @@ -241,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" @@ -259,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" @@ -267,9 +285,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 +318,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 +343,17 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "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]] @@ -358,14 +387,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 +416,40 @@ dependencies = [ "serde_json", ] +[[package]] +name = "cocl-operator-test-utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "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]] 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]] @@ -440,11 +498,17 @@ 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.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ "const_format_proc_macros", ] @@ -500,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" @@ -536,7 +612,7 @@ checksum = "5d914fcc6452d133236ee067a9538be25ba6a644a450e1a6c617da84bf029854" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -570,7 +646,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -584,7 +660,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -595,7 +671,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -606,7 +682,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -615,11 +691,21 @@ 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.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", ] @@ -642,7 +728,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -652,7 +738,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 +758,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -682,6 +768,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -694,14 +781,28 @@ 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 = "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" @@ -712,7 +813,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -721,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" @@ -732,34 +852,40 @@ 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", ] +[[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" @@ -781,19 +907,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 +942,27 @@ 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" +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 +997,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 +1048,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -941,12 +1083,13 @@ 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", + "zeroize", ] [[package]] @@ -957,19 +1100,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 +1124,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 +1150,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -1028,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" @@ -1040,7 +1194,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.10.0", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -1055,15 +1209,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 +1414,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 +1440,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 +1472,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 +1487,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.6.0", + "hyper 1.7.0", "hyper-util", "native-tls", "tokio", @@ -1335,9 +1497,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 +1508,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 +1521,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 +1545,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 +1558,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 +1571,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 +1585,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 +1678,21 @@ 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]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", ] [[package]] @@ -1537,9 +1703,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 +1713,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 +1730,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 +1760,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 +1883,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 +1934,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -1783,7 +1949,7 @@ dependencies = [ "backon", "educe", "futures", - "hashbrown 0.15.4", + "hashbrown 0.15.5", "hostname", "json-patch", "k8s-openapi", @@ -1803,12 +1969,21 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[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 = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "lief" @@ -1816,7 +1991,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 +2027,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 +2042,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 +2078,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 +2111,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -1963,17 +2137,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]] @@ -2030,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" @@ -2044,7 +2235,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2056,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" @@ -2063,13 +2265,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[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 +2293,7 @@ dependencies = [ "oci-spec", "olpc-cjson", "regex", - "reqwest 0.12.23", + "reqwest 0.12.24", "serde", "serde_json", "sha2", @@ -2136,9 +2339,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 +2349,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 +2366,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2228,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" @@ -2236,9 +2477,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 +2487,57 @@ 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 = "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.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 +2545,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 +2583,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2349,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" @@ -2372,9 +2642,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", ] @@ -2394,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" @@ -2437,23 +2716,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 +2775,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 +2827,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 +2894,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 +2905,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", @@ -2652,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" @@ -2666,23 +2955,44 @@ 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.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 +3018,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 +3037,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 +3049,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 +3071,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]] @@ -2793,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" @@ -2808,7 +3132,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 +3141,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 +3192,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -2879,16 +3203,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 +3247,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 +3284,34 @@ 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 = "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" +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 +3337,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]] @@ -3010,11 +3351,63 @@ 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.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" @@ -3037,7 +3430,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3087,9 +3480,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 +3512,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3145,15 +3538,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 +3596,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3214,14 +3607,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 +3625,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 +3665,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 +3678,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3322,9 +3715,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 +3736,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 +3754,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 +3800,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.110", ] [[package]] @@ -3446,9 +3839,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 +3857,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 +3869,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 +3902,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 +3936,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 +3999,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 +4035,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 +4045,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 +4080,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", @@ -3712,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" @@ -3736,37 +4130,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 +4171,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 +4222,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 +4262,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 +4298,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 +4316,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 +4334,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 +4364,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 +4382,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 +4400,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 +4418,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 +4435,29 @@ dependencies = [ ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "winsafe" +version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 +4465,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 +4512,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 +4535,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 +4546,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/Makefile b/Makefile index 3852d692..67b97d58 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) @@ -126,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=1 + $(LOCALBIN): mkdir -p $(LOCALBIN) diff --git a/REUSE.toml b/REUSE.toml index 3fb43d60..7e63e292 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -10,7 +10,10 @@ path = [ "operator/src/resource.rego", "operator/src/tpm.rego", "docs/pics/*", - "docs/design/*" + "docs/design/*", + "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..01a1645c --- /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: "quay.io/confidential-clusters/fedora-coreos-kubevirt:latest" + 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/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 { 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 } 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 860e2c75..c863c0b7 100755 --- a/scripts/create-cluster-kind.sh +++ b/scripts/create-cluster-kind.sh @@ -1,22 +1,27 @@ -#!/bin/sh +#!/usr/bin/env bash # SPDX-FileCopyrightText: Alice Frosi # SPDX-FileCopyrightText: Jakob Naucke # # SPDX-License-Identifier: CC0-1.0 -set -o errexit +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 + kubectl wait --for=condition=Ready pod -l component=kube-apiserver -n kube-system 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 @@ -44,3 +49,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 diff --git a/test_utils/Cargo.toml b/test_utils/Cargo.toml new file mode 100644 index 00000000..de194e21 --- /dev/null +++ b/test_utils/Cargo.toml @@ -0,0 +1,29 @@ +# 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 + +[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 new file mode 100644 index 00000000..2031ea78 --- /dev/null +++ b/test_utils/src/lib.rs @@ -0,0 +1,580 @@ +// 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; + +#[cfg(feature = "virtualization")] +pub mod virt; + +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 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()?; + 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)* + } + }; +} + +// 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) }}; +} + +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/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 a678fc0d..2f79fd31 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 @@ -8,8 +9,27 @@ version = "0.1.0" edition.workspace = true rust-version.workspace = true +[features] +virtualization = [] + [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 = "attestation" +path = "attestation.rs" [[test]] name = "equal_conditions" diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..65a8beec --- /dev/null +++ b/tests/README.md @@ -0,0 +1,27 @@ +# 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 +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 +``` + +Each test can also be run independently using cargo test. Example: +```bash +$ cargo test test_confidential_cluster_uninstall -- --no-capture +``` 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(()) +} +} 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(()) +} +}