From 0498881a7cb68f83c5e59ebd1c6ae810b36672c8 Mon Sep 17 00:00:00 2001 From: Yair Podemsky Date: Thu, 29 Jan 2026 15:30:11 +0200 Subject: [PATCH 1/2] Update Container images to fedora 43 Updating all Fedroa container images to version 43. Also updating rust version to 1.88 Signed-off-by: Yair Podemsky --- .github/workflows/lint.yml | 2 +- Cargo.toml | 2 +- Containerfile | 4 ++-- attestation-key-register/Containerfile | 4 ++-- compute-pcrs/Containerfile | 4 ++-- register-server/Containerfile | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50261314..cfc8b744 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,7 +22,7 @@ concurrency: env: CARGO_TERM_COLOR: always # Pinned toolchain for linting - ACTIONS_LINTS_TOOLCHAIN: 1.85.0 + ACTIONS_LINTS_TOOLCHAIN: 1.88.0 jobs: linting: diff --git a/Cargo.toml b/Cargo.toml index 87d9752a..8823fb0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ resolver = "3" [workspace.package] edition = "2024" -rust-version = "1.85" +rust-version = "1.88" [workspace.dependencies] anyhow = "1.0.100" diff --git a/Containerfile b/Containerfile index a2d168bd..2aa7d88d 100644 --- a/Containerfile +++ b/Containerfile @@ -5,7 +5,7 @@ ARG build_type # Dependency build stage -FROM ghcr.io/trusted-execution-clusters/buildroot AS builder +FROM ghcr.io/trusted-execution-clusters/buildroot:fedora AS builder ARG build_type WORKDIR /build @@ -31,6 +31,6 @@ COPY operator/src operator/src RUN cargo build -p operator $(if [ "$build_type" = release ]; then echo --release; fi) # Distribution stage -FROM quay.io/fedora/fedora:42 +FROM quay.io/fedora/fedora:43 ARG build_type COPY --from=builder "/build/target/$build_type/operator" /usr/bin diff --git a/attestation-key-register/Containerfile b/attestation-key-register/Containerfile index a287db7a..de0677a3 100644 --- a/attestation-key-register/Containerfile +++ b/attestation-key-register/Containerfile @@ -3,7 +3,7 @@ # SPDX-License-Identifier: CC0-1.0 ARG build_type -FROM ghcr.io/trusted-execution-clusters/buildroot AS builder +FROM ghcr.io/trusted-execution-clusters/buildroot:fedora AS builder ARG build_type WORKDIR /build @@ -26,7 +26,7 @@ RUN sed -i 's/members =.*/members = ["lib", "attestation-key-register"]/' Cargo. COPY attestation-key-register/src attestation-key-register/src RUN cargo build -p attestation-key-register $(if [ "$build_type" = release ]; then echo --release; fi) -FROM quay.io/fedora/fedora:42 +FROM quay.io/fedora/fedora:43 ARG build_type COPY --from=builder "/build/target/$build_type/attestation-key-register" /usr/bin EXPOSE 8001 diff --git a/compute-pcrs/Containerfile b/compute-pcrs/Containerfile index d1aa1e0e..6286a0b4 100644 --- a/compute-pcrs/Containerfile +++ b/compute-pcrs/Containerfile @@ -4,7 +4,7 @@ # SPDX-License-Identifier: CC0-1.0 ARG build_type -FROM ghcr.io/trusted-execution-clusters/buildroot AS builder +FROM ghcr.io/trusted-execution-clusters/buildroot:fedora AS builder ARG build_type WORKDIR /build @@ -28,7 +28,7 @@ RUN sed -i 's/members =.*/members = ["compute-pcrs", "lib"]/' Cargo.toml && \ COPY compute-pcrs/src compute-pcrs/src RUN cargo build -p compute-pcrs $(if [ "$build_type" = release ]; then echo --release; fi) -FROM quay.io/fedora/fedora:42 +FROM quay.io/fedora/fedora:43 ARG build_type COPY --from=builder "/build/target/$build_type/compute-pcrs" /usr/bin COPY --from=builder /build/reference-values /reference-values diff --git a/register-server/Containerfile b/register-server/Containerfile index 975a202f..7124a1cf 100644 --- a/register-server/Containerfile +++ b/register-server/Containerfile @@ -3,7 +3,7 @@ # SPDX-License-Identifier: CC0-1.0 ARG build_type -FROM ghcr.io/trusted-execution-clusters/buildroot AS builder +FROM ghcr.io/trusted-execution-clusters/buildroot:fedora AS builder ARG build_type WORKDIR /build @@ -27,7 +27,7 @@ RUN sed -i 's/members =.*/members = ["lib", "register-server"]/' Cargo.toml && \ COPY register-server/src register-server/src RUN cargo build -p register-server $(if [ "$build_type" = release ]; then echo --release; fi) -FROM quay.io/fedora/fedora:42 +FROM quay.io/fedora/fedora:43 ARG build_type COPY --from=builder "/build/target/$build_type/register-server" /usr/bin EXPOSE 3030 From 5687211eda1e8472cffb0201e799e514e06bf98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Tue, 23 Dec 2025 08:33:31 +0100 Subject: [PATCH 2/2] rust: Update minimum toolchain to 1.88 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minimum rust version was set to 1.85. Fedora is way above that threshold at the moment. Future EL releases will be above that as well. While on it, fix some of the linter errors that arise from the minimum version update. Co-authored-by: Yair Podemsky Signed-off-by: BeƱat Gartzia Arruabarrena --- attestation-key-register/src/main.rs | 15 ++++----- operator/src/attestation_key_register.rs | 29 +++++++---------- operator/src/reference_values.rs | 14 ++++---- operator/src/trustee.rs | 2 +- test_utils/src/lib.rs | 41 ++++++++++++------------ test_utils/src/virt/mod.rs | 3 +- tests/attestation.rs | 21 ++++++------ tests/trusted_execution_cluster.rs | 25 +++++++-------- 8 files changed, 70 insertions(+), 80 deletions(-) diff --git a/attestation-key-register/src/main.rs b/attestation-key-register/src/main.rs index fdf6202d..01ea1fbf 100644 --- a/attestation-key-register/src/main.rs +++ b/attestation-key-register/src/main.rs @@ -42,7 +42,7 @@ async fn handle_registration( client: Client, addr: Option, ) -> Result { - info!("Received registration request: {:?}", registration); + info!("Received registration request: {registration:?}"); let api: Api = Api::default_namespaced(client); @@ -52,8 +52,7 @@ async fn handle_registration( if key.spec.public_key == registration.public_key { let existing_name = key.metadata.name.unwrap_or_default(); error!( - "Duplicate public key detected: already exists in AttestationKey '{}'", - existing_name + "Duplicate public key detected: already exists in AttestationKey '{existing_name}'" ); return Ok(reply::with_status( reply::json(&serde_json::json!({ @@ -66,11 +65,11 @@ async fn handle_registration( } } Err(e) => { - error!("Failed to list AttestationKeys: {}", e); + error!("Failed to list AttestationKeys: {e}"); return Ok(reply::with_status( reply::json(&serde_json::json!({ "status": "error", - "message": format!("Failed to check for existing keys: {}", e), + "message": format!("Failed to check for existing keys: {e}"), })), StatusCode::INTERNAL_SERVER_ERROR, )); @@ -108,11 +107,11 @@ async fn handle_registration( )) } Err(e) => { - error!("Failed to create AttestationKey: {}", e); + error!("Failed to create AttestationKey: {e}"); Ok(reply::with_status( reply::json(&serde_json::json!({ "status": "error", - "message": format!("Failed to create AttestationKey: {}", e), + "message": format!("Failed to create AttestationKey: {e}"), })), StatusCode::INTERNAL_SERVER_ERROR, )) @@ -147,7 +146,7 @@ async fn main() -> anyhow::Result<()> { .and_then(handle_registration); let addr = SocketAddr::from(([0, 0, 0, 0], args.port)); - info!("Listening on {}", addr); + info!("Listening on {addr}"); warp::serve(register).run(addr).await; diff --git a/operator/src/attestation_key_register.rs b/operator/src/attestation_key_register.rs index 7a326537..8a6069ae 100644 --- a/operator/src/attestation_key_register.rs +++ b/operator/src/attestation_key_register.rs @@ -133,13 +133,13 @@ async fn ak_reconcile( client: Arc, ) -> Result { let ak_name = ak.metadata.name.clone().unwrap_or_default(); - info!("Attestation Key reconciliation for: {}", ak_name); + info!("Attestation Key reconciliation for: {ak_name}"); let client = Arc::unwrap_or_clone(client); let machines: Api = Api::default_namespaced(client.clone()); let lp = ListParams::default(); let machine_list: ObjectList = machines.list(&lp).await.map_err(|e| { - eprintln!("Error fetching machine list: {}", e); + eprintln!("Error fetching machine list: {e}"); ControllerError::Anyhow(e.into()) })?; for machine in &machine_list.items { @@ -180,15 +180,15 @@ async fn machine_reconcile( let aks: Api = Api::default_namespaced(client.clone()); let lp = ListParams::default(); let ak_list: ObjectList = aks.list(&lp).await.map_err(|e| { - eprintln!("Error fetching attestation key list: {}", e); + eprintln!("Error fetching attestation key list: {e}"); ControllerError::Anyhow(e.into()) })?; for ak in ak_list.items { - if let Some(ak_address) = &ak.spec.address { - if *ak_address == machine_address { - approve_ak(&ak, &machine, client.clone()).await?; - return Ok(Action::await_change()); - } + if let Some(ak_address) = &ak.spec.address + && *ak_address == machine_address + { + approve_ak(&ak, &machine, client.clone()).await?; + return Ok(Action::await_change()); } } Ok(Action::await_change()) @@ -313,10 +313,7 @@ async fn secret_reconcile( return Ok(Action::await_change()); } - info!( - "Secret reconciliation for AttestationKey secret: {}", - secret_name - ); + info!("Secret reconciliation for AttestationKey secret: {secret_name}"); let secrets: Api = Api::default_namespaced(Arc::unwrap_or_clone(client.clone())); finalizer(&secrets, ATTESTATION_KEY_SECRET_FINALIZER, secret, |ev| async move { @@ -328,15 +325,14 @@ async fn secret_reconcile( .await .map(|_| Action::await_change()) .map_err(|e| { - eprintln!("Error updating attestation key volumes on secret apply: {}", e); + eprintln!("Error updating attestation key volumes on secret apply: {e}"); finalizer::Error::::ApplyFailed(e.into()) }) } Event::Cleanup(secret) => { let secret_name = secret.metadata.name.clone().unwrap_or_default(); info!( - "AttestationKey secret {} is being deleted, updating trustee deployment volumes", - secret_name + "AttestationKey secret {secret_name} is being deleted, updating trustee deployment volumes" ); let client = Arc::unwrap_or_clone(client); // Update trustee deployment - secrets with deletion_timestamp will be filtered out @@ -345,8 +341,7 @@ async fn secret_reconcile( .map(|_| Action::await_change()) .map_err(|e| { eprintln!( - "Error updating attestation key volumes during secret deletion: {}", - e + "Error updating attestation key volumes during secret deletion: {e}" ); finalizer::Error::::CleanupFailed(e.into()) }) diff --git a/operator/src/reference_values.rs b/operator/src/reference_values.rs index 29bd6485..671d5351 100644 --- a/operator/src/reference_values.rs +++ b/operator/src/reference_values.rs @@ -297,13 +297,13 @@ pub async fn handle_new_image( let config_maps: Api = Api::default_namespaced(ctx.client.clone()); let mut image_pcrs_map = config_maps.get(PCR_CONFIG_MAP).await?; let mut image_pcrs = get_image_pcrs(image_pcrs_map.clone())?; - if let Some(pcr) = image_pcrs.0.get(resource_name) { - if pcr.reference == boot_image { - info!("Image {boot_image} was to be allowed, but already was allowed"); - return trustee::update_reference_values(ctx) - .await - .map(|_| COMMITTED_REASON); - } + if let Some(pcr) = image_pcrs.0.get(resource_name) + && pcr.reference == boot_image + { + info!("Image {boot_image} was to be allowed, but already was allowed"); + return trustee::update_reference_values(ctx) + .await + .map(|_| COMMITTED_REASON); } let image_ref: oci_client::Reference = boot_image.parse()?; if image_ref.digest().is_none() { diff --git a/operator/src/trustee.rs b/operator/src/trustee.rs index abdb9dbf..38947b4c 100644 --- a/operator/src/trustee.rs +++ b/operator/src/trustee.rs @@ -256,7 +256,7 @@ pub async fn update_attestation_keys(client: Client) -> Result<()> { name: secret_name.to_string(), items: Some(vec![KeyToPath { key: "public_key".to_string(), - path: format!("{}.pub", secret_name), + path: format!("{secret_name}.pub"), ..Default::default() }]), ..Default::default() diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index 08e47cce..8ba3d43c 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs @@ -370,13 +370,12 @@ impl TestContext { 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(()); - } - } + if let Some(status) = &deployment.status + && let Some(available_replicas) = status.available_replicas + && available_replicas == 1 + { + test_info!(&tn, "{} deployment has 1 available replica", name); + return Ok(()); } Err(anyhow!( @@ -485,14 +484,14 @@ impl TestContext { let ns = self.test_namespace.clone(); 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: {}", ns)); + .replace("namespace: system", &format!("namespace: {ns}")); 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: trusted-cluster-operator-role", - &format!("name: {}-trusted-cluster-operator-role", ns), + &format!("name: {ns}-trusted-cluster-operator-role"), ); std::fs::write(&role_path, role_content)?; @@ -500,21 +499,21 @@ impl TestContext { let rb = "name: manager-rolebinding"; let role = "name: trusted-cluster-operator-role"; let rb_content = std::fs::read_to_string(&rb_src)? - .replace(rb, &format!("name: {}-manager-rolebinding", ns)) - .replace(role, &format!("name: {}-trusted-cluster-operator-role", ns)) - .replace("namespace: system", &format!("namespace: {}", ns)); + .replace(rb, &format!("name: {ns}-manager-rolebinding")) + .replace(role, &format!("name: {ns}-trusted-cluster-operator-role")) + .replace("namespace: system", &format!("namespace: {ns}")); 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: {}", ns)); + .replace("namespace: system", &format!("namespace: {ns}")); 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: {}", ns)); + .replace("namespace: system", &format!("namespace: {ns}")); let le_rb_dst = rbac_temp_dir.join("leader_election_role_binding.yaml"); std::fs::write(&le_rb_dst, le_rb_content)?; @@ -570,13 +569,13 @@ impl TestContext { 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()), - ); - } + if let Some(spec) = cr_value.get_mut("spec") + && 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)?; diff --git a/test_utils/src/virt/mod.rs b/test_utils/src/virt/mod.rs index 65e4f767..d3e109c0 100644 --- a/test_utils/src/virt/mod.rs +++ b/test_utils/src/virt/mod.rs @@ -242,8 +242,7 @@ pub trait VmBackend: Send + Sync { .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", - avail_prefix, timeout_secs + "SSH access to VM did not become {avail_prefix}available after {timeout_secs} seconds" )); let check_fn = || { diff --git a/tests/attestation.rs b/tests/attestation.rs index a682f4f0..608f61a5 100644 --- a/tests/attestation.rs +++ b/tests/attestation.rs @@ -38,16 +38,17 @@ impl SingleAttestationContext { async fn new(vm_name: &str, test_ctx: &TestContext) -> Result { let client = test_ctx.client(); let namespace = test_ctx.namespace(); + let backend = virt::create_backend(client.clone(), namespace, vm_name)?; - test_ctx.info(format!("Creating VM: {}", vm_name)); + test_ctx.info(format!("Creating VM: {vm_name}")); backend.create_vm().await?; - test_ctx.info(format!("Waiting for VM {} to reach Running state", vm_name)); + test_ctx.info(format!("Waiting for VM {vm_name} to reach Running state")); backend.wait_for_running(600).await?; - test_ctx.info(format!("VM {} is Running", vm_name)); + test_ctx.info(format!("VM {vm_name} is Running")); - test_ctx.info(format!("Waiting for SSH access to VM {}", vm_name)); + test_ctx.info(format!("Waiting for SSH access to VM {vm_name}")); backend.wait_for_vm_ssh_ready(600).await?; test_ctx.info("SSH access is ready"); @@ -162,29 +163,29 @@ async fn test_vm_reboot_attestation() -> anyhow::Result<()> { // Perform multiple reboots let num_reboots = 3; for i in 1..=num_reboots { - test_ctx.info(format!("Performing reboot {} of {}", i, num_reboots)); + test_ctx.info(format!("Performing reboot {i} of {num_reboots}")); // Reboot the VM via SSH let _reboot_result = att_ctx.backend.ssh_exec("sudo systemctl reboot").await; - test_ctx.info(format!("Waiting for lack of SSH access after reboot {}", i)); + test_ctx.info(format!("Waiting for lack of SSH access after reboot {i}")); att_ctx.backend.wait_for_vm_ssh_unavail(30).await?; - test_ctx.info(format!("Waiting for SSH access after reboot {}", i)); + test_ctx.info(format!("Waiting for SSH access after reboot {i}")); att_ctx.backend.wait_for_vm_ssh_ready(300).await?; // Verify encrypted root is still present after reboot - test_ctx.info(format!("Verifying encrypted root after reboot {}", i)); + test_ctx.info(format!("Verifying encrypted root after reboot {i}")); let has_encrypted_root = att_ctx.verify_encrypted_root().await?; assert!( has_encrypted_root, "VM should have encrypted root device after reboot {i}" ); - test_ctx.info(format!("Reboot {}: attestation successful", i)); + test_ctx.info(format!("Reboot {i}: attestation successful")); } test_ctx.info(format!( - "VM successfully rebooted {num_reboots} times with encrypted root device maintained", + "VM successfully rebooted {num_reboots} times with encrypted root device maintained" )); att_ctx.cleanup().await?; test_ctx.cleanup().await?; diff --git a/tests/trusted_execution_cluster.rs b/tests/trusted_execution_cluster.rs index 6a60cd49..abd0fc9c 100644 --- a/tests/trusted_execution_cluster.rs +++ b/tests/trusted_execution_cluster.rs @@ -60,14 +60,12 @@ async fn test_image_pcrs_configmap_updates() -> anyhow::Result<()> { 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 let Ok(image_pcrs) = serde_json::from_str::(image_pcrs_json) { - if !image_pcrs.0.is_empty() { - return Ok(()); - } - } - } + if let Some(data) = &cm.data + && let Some(image_pcrs_json) = data.get("image-pcrs.json") + && let Ok(image_pcrs) = serde_json::from_str::(image_pcrs_json) + && !image_pcrs.0.is_empty() + { + return Ok(()); } Err(anyhow::anyhow!("image-pcrs ConfigMap not yet populated with image-pcrs.json data")) @@ -167,12 +165,11 @@ async fn test_image_disallow() -> anyhow::Result<()> { let api = configmap_api.clone(); async move { let cm = api.get("trustee-data").await?; - if let Some(data) = &cm.data { - if let Some(reference_values_json) = data.get("reference-values.json") { - if !reference_values_json.contains(EXPECTED_PCR4) { - return Ok(()); - } - } + if let Some(data) = &cm.data + && let Some(reference_values_json) = data.get("reference-values.json") + && !reference_values_json.contains(EXPECTED_PCR4) + { + return Ok(()); } Err(anyhow::anyhow!("Reference value not yet removed")) }