From 0d47ce6cf00a3da5af85422286fd44afe33840e4 Mon Sep 17 00:00:00 2001 From: Jakob Naucke Date: Tue, 19 Aug 2025 12:41:19 +0200 Subject: [PATCH 1/3] Macroize k8s operations Signed-off-by: Jakob Naucke --- operator/src/trustee.rs | 87 ++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 54 deletions(-) diff --git a/operator/src/trustee.rs b/operator/src/trustee.rs index 6037b518..bd372109 100644 --- a/operator/src/trustee.rs +++ b/operator/src/trustee.rs @@ -15,6 +15,18 @@ use crate::reference_values::ReferenceValue; const HTTPS_KEY: &str = "kbs-https-key"; const HTTPS_CERT: &str = "kbs-https-certificate"; +macro_rules! info_if_exists { + ($result:ident, $resource_type:literal, $resource_name:expr) => { + match $result { + Ok(_) => info!("Create {} {}", $resource_type, $resource_name), + Err(Error::Api(ae)) if ae.code == 409 => { + info!("{} {} already exists", $resource_type, $resource_name) + } + Err(e) => return Err(e.into()), + } + }; +} + pub async fn generate_kbs_auth_public_key( client: Client, namespace: &str, @@ -47,11 +59,8 @@ pub async fn generate_kbs_auth_public_key( }; let secrets: Api = Api::namespaced(client, namespace); - match secrets.create(&PostParams::default(), &secret).await { - Ok(s) => info!("Create secret {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => info!("Secret {} already exists", secret_name), - Err(e) => return Err(e.into()), - } + let create = secrets.create(&PostParams::default(), &secret).await; + info_if_exists!(create, "Secret", secret_name); Ok(()) } @@ -73,11 +82,8 @@ pub async fn generate_kbs_https_certificate(client: Client, namespace: &str) -> data: Some(map), ..Default::default() }; - match secrets.create(&PostParams::default(), &secret).await { - Ok(s) => info!("Create secret {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => info!("Secret {name} already exists"), - Err(e) => return Err(e.into()), - } + let create = secrets.create(&PostParams::default(), &secret).await; + info_if_exists!(create, "Secret", name); } Ok(()) @@ -110,16 +116,10 @@ pub async fn generate_kbs_configurations( ..Default::default() }; - match config_maps + let create = config_maps .create(&PostParams::default(), &config_map) - .await - { - Ok(s) => info!("Created ConfigMap {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => { - info!("ConfigMap {} already exists", configmap) - } - Err(e) => return Err(e.into()), - } + .await; + info_if_exists!(create, "ConfigMap", configmap); } Ok(()) @@ -170,14 +170,10 @@ pub async fn generate_reference_values( }; let config_maps: Api = Api::namespaced(client, namespace); - match config_maps + let create = config_maps .create(&PostParams::default(), &config_map) - .await - { - Ok(s) => info!("Created ConfigMap {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => info!("ConfigMap {} already exists", name), - Err(e) => return Err(e.into()), - } + .await; + info_if_exists!(create, "ConfigMap", name); Ok(()) } @@ -209,11 +205,8 @@ pub async fn generate_secret( }; let secrets: Api = Api::namespaced(client.clone(), namespace); - match secrets.create(&PostParams::default(), &secret).await { - Ok(s) => info!("Created Secret {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => info!("Secret {id} already exists"), - Err(e) => return Err(e.into()), - } + let create = secrets.create(&PostParams::default(), &secret).await; + info_if_exists!(create, "Secret", id); let kbs_configs: Api = Api::namespaced(client, namespace); @@ -273,14 +266,10 @@ pub async fn generate_resource_policy( }; let config_maps: Api = Api::namespaced(client, namespace); - match config_maps + let create = config_maps .create(&PostParams::default(), &config_map) - .await - { - Ok(s) => info!("Created ConfigMap {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => info!("ConfigMap {} already exists", name), - Err(e) => return Err(e.into()), - } + .await; + info_if_exists!(create, "ConfigMap", name); Ok(()) } @@ -305,14 +294,10 @@ pub async fn generate_attestation_policy( }; let config_maps: Api = Api::namespaced(client, namespace); - match config_maps + let create = config_maps .create(&PostParams::default(), &config_map) - .await - { - Ok(s) => info!("Created ConfigMap {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => info!("ConfigMap {} already exists", name), - Err(e) => return Err(e.into()), - } + .await; + info_if_exists!(create, "ConfigMap", name); Ok(()) } @@ -368,16 +353,10 @@ pub async fn generate_kbs( }; let kbs_configs: Api = Api::namespaced(client, namespace); - match kbs_configs + let create = kbs_configs .create(&PostParams::default(), &kbs_config) - .await - { - Ok(s) => info!("Created KbsConfig {:?}", s.metadata.name), - Err(Error::Api(ae)) if ae.code == 409 => { - info!("KbsConfig {} already exists", trustee.kbs_config_name) - } - Err(e) => return Err(e.into()), - } + .await; + info_if_exists!(create, "KbsConfig", trustee.kbs_config_name); Ok(()) } From 5a2802624e5a4af3cc8191765312d8a640b349cc Mon Sep 17 00:00:00 2001 From: Jakob Naucke Date: Tue, 19 Aug 2025 15:12:34 +0200 Subject: [PATCH 2/3] nit: Run cargo clippy Signed-off-by: Jakob Naucke --- operator/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/operator/src/main.rs b/operator/src/main.rs index 65edd75a..43026278 100644 --- a/operator/src/main.rs +++ b/operator/src/main.rs @@ -27,7 +27,7 @@ struct ContextData { async fn list_confidential_clusters(client: Client) -> anyhow::Result { let namespace = client.default_namespace(); - info!("Listing ConfidentialClusters in namespace '{}'", namespace); + info!("Listing ConfidentialClusters in namespace '{namespace}'"); let api: Api = Api::namespaced(client.clone(), namespace); let lp = ListParams::default(); let list = api.list(&lp).await?; @@ -39,7 +39,7 @@ async fn list_confidential_clusters(client: Client) -> anyhow::Result"), ); - return Ok(item.clone()); + Ok(item.clone()) } _ => bail!("too many confidential cluster resources defined in the namespace"), } @@ -172,8 +172,8 @@ async fn main() -> Result<()> { .run::<_, ContextData>(reconcile, error_policy, context) .for_each(|res| async move { match res { - Ok(o) => info!("reconciled {:?}", o), - Err(e) => info!("reconcile failed: {:?}", e), + Ok(o) => info!("reconciled {o:?}"), + Err(e) => info!("reconcile failed: {e:?}"), } }) .await; From a034168360be912febb4a2f8da8e86c576d799f8 Mon Sep 17 00:00:00 2001 From: Jakob Naucke Date: Tue, 19 Aug 2025 15:36:03 +0200 Subject: [PATCH 3/3] Add reference-values-in.json file with dummy values that throw errors when not replaced with hex strings Signed-off-by: Jakob Naucke --- .gitignore | 1 - README.md | 2 ++ operator/src/reference-values-in.json | 5 +++++ operator/src/tpm.rego | 6 +++--- operator/src/trustee.rs | 25 ++++++++++++++++--------- 5 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 operator/src/reference-values-in.json diff --git a/.gitignore b/.gitignore index 8666cda1..8ca923ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .kubeconfig /target /manifests -/operator/src/reference-values-in.json diff --git a/README.md b/README.md index 28cf03cc..f963c20b 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ i.e. } ``` +> Hint: You can stop tracking changes to this file with `git update-index --skip-worktree operator/src/reference-values-in.json`. + Create the cluster, install [trustee operator](https://github.com/confidential-containers/trustee-operator) and deploy the operator. diff --git a/operator/src/reference-values-in.json b/operator/src/reference-values-in.json new file mode 100644 index 00000000..895dd16f --- /dev/null +++ b/operator/src/reference-values-in.json @@ -0,0 +1,5 @@ +{ + "pcr4": "fill in your expected PCR value here", + "pcr7": "fill in your expected PCR value here", + "pcr14": "fill in your expected PCR value here" +} diff --git a/operator/src/tpm.rego b/operator/src/tpm.rego index 371f95a1..93f9528f 100644 --- a/operator/src/tpm.rego +++ b/operator/src/tpm.rego @@ -10,9 +10,9 @@ hardware := 2 if { } tpm_pcrs_valid if { - input.tpm.pcrs[4] in data.reference.tpm_pcr4 - input.tpm.pcrs[7] in data.reference.tpm_pcr7 - input.tpm.pcrs[14] in data.reference.tpm_pcr14 + lower(input.tpm.pcrs[4]) in data.reference.tpm_pcr4 + lower(input.tpm.pcrs[7]) in data.reference.tpm_pcr7 + lower(input.tpm.pcrs[14]) in data.reference.tpm_pcr14 } executables := 3 if tpm_pcrs_valid diff --git a/operator/src/trustee.rs b/operator/src/trustee.rs index bd372109..ec258131 100644 --- a/operator/src/trustee.rs +++ b/operator/src/trustee.rs @@ -141,14 +141,21 @@ pub async fn generate_reference_values( ); let reference_values = reference_values_in .iter() - .map(|(name, value)| match value { - serde_json::Value::String(_) => Ok(ReferenceValue { - version: "0.1.0".to_string(), - name: format!("tpm_{name}"), - expiration: chrono::DateTime::::MAX_UTC, - value: serde_json::Value::Array(vec![value.clone()]), - }), - _ => Err(anyhow!("Reference values had unexpected data type")), + .map(|(name, value)| { + if let serde_json::Value::String(hex) = value + && hex + .chars() + .all(|c| (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) + { + Ok(ReferenceValue { + version: "0.1.0".to_string(), + name: format!("tpm_{name}"), + expiration: chrono::DateTime::::MAX_UTC, + value: serde_json::Value::Array(vec![value.clone()]), + }) + } else { + Err(anyhow!("Reference value '{value}' had unexpected shape")) + } }) .collect::, _>>()?; let reference_values_json = serde_json::to_string(&reference_values)?; @@ -217,7 +224,7 @@ pub async fn generate_secret( .kbs_secret_resources; if existing_secrets.iter().any(|s| s == id) { info!("Secret with ID {id} already present"); - return Ok(()) + return Ok(()); } let path = jsonptr::PointerBuf::parse("/spec/kbsSecretResources")?;