From e275b4fb96b8f439942e913ac178836afb509bd3 Mon Sep 17 00:00:00 2001 From: Lucas Fontes Date: Mon, 15 Jul 2024 16:35:01 -0300 Subject: [PATCH] Using upstream structs Signed-off-by: Lucas Fontes --- .../src/v1alpha1/wasmcloud_host_config.rs | 29 +---- src/controller.rs | 120 +++++++++++++----- src/lib.rs | 3 + 3 files changed, 94 insertions(+), 58 deletions(-) diff --git a/crates/types/src/v1alpha1/wasmcloud_host_config.rs b/crates/types/src/v1alpha1/wasmcloud_host_config.rs index ad16c28..e23493f 100644 --- a/crates/types/src/v1alpha1/wasmcloud_host_config.rs +++ b/crates/types/src/v1alpha1/wasmcloud_host_config.rs @@ -1,4 +1,4 @@ -use k8s_openapi::api::core::v1::{PodSpec, ResourceRequirements}; +use k8s_openapi::api::core::v1::{PodSpec, ResourceRequirements, Volume}; use kube::CustomResource; use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema}; use serde::{Deserialize, Serialize}; @@ -189,34 +189,9 @@ fn default_nats_leafnode_port() -> u16 { 7422 } -#[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] -pub struct ConfigMapSource { - /// Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - pub name: String, - - /// Specify whether the ConfigMap must be defined - pub optional: Option, -} - -#[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] -pub struct SecretSource { - /// Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - pub name: String, - - /// Specify whether the ConfigMap must be defined - pub optional: Option, -} - -#[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct CertificateSource { - pub config_map_ref: Option, - pub secret_ref: Option, -} - #[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)] pub struct WasmCloudHostCertificates { - pub authorities: Option>, + pub authorities: Option>, } #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] diff --git a/src/controller.rs b/src/controller.rs index b9828cb..4739152 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -418,50 +418,86 @@ async fn pod_template(config: &WasmCloudHostConfig, ctx: Arc) -> Result .clone() .and_then(|certificates| certificates.authorities) { - for (i, authority) in authorities.iter().enumerate() { - // configmaps - if let Some(configmap) = &authority.config_map_ref { - let volume_name = format!("cert-authority-{i}"); - let volume_path = format!("/wasmcloud/certificates/authorities/{volume_name}"); - match discover_configmap_certificates( + for authority in authorities.iter() { + let authority_name = authority.name.clone(); + let volume_name = format!("ca-{authority_name}"); + let volume_path = format!("/wasmcloud/certificates/{volume_name}"); + let mut items: Vec = vec![]; + + // secrets + if let Some(secret_ref) = &authority.secret { + let secret_name = match &secret_ref.secret_name { + Some(s) => s, + None => { + return Err(Error::CertificateError(format!( + "Missing secret name for authority '{authority_name}'" + ))) + } + }; + + items = discover_secret_certificates( config.namespace().unwrap_or_default().as_str(), - configmap.name.as_str(), + secret_name.as_str(), &ctx, ) - .await - { - Ok(items) => { - for item in items { - wasmcloud_args.push("--tls-ca-path".to_string()); - wasmcloud_args.push(format!("{volume_path}/{item}")); - } - } - Err(e) => { - if let Some(is_optional) = &configmap.optional { - if !is_optional { - return Err(e); - } - } else { - continue; - } - } - }; + .await?; + + if items.is_empty() { + continue; + } + volumes.push(Volume { name: volume_name.clone(), - config_map: Some(ConfigMapVolumeSource { - name: Some(configmap.name.clone()), + secret: Some(SecretVolumeSource { + secret_name: Some(secret_name.to_string()), ..Default::default() }), ..Default::default() }); + } + + // configmaps + if let Some(configmap_ref) = &authority.config_map { + let configmap_name = match &configmap_ref.name { + Some(s) => s, + None => { + return Err(Error::CertificateError(format!( + "Missing configmap name for authority '{authority_name}'" + ))) + } + }; + items = discover_configmap_certificates( + config.namespace().unwrap_or_default().as_str(), + configmap_name.as_str(), + &ctx, + ) + .await?; - wasm_volume_mounts.push(VolumeMount { + if items.is_empty() { + continue; + } + + volumes.push(Volume { name: volume_name.clone(), - read_only: Some(true), - mount_path: volume_path, + config_map: Some(ConfigMapVolumeSource { + name: Some(configmap_name.to_string()), + ..Default::default() + }), ..Default::default() }); } + + wasm_volume_mounts.push(VolumeMount { + name: volume_name.clone(), + read_only: Some(true), + mount_path: volume_path.clone(), + ..Default::default() + }); + + for item in items { + wasmcloud_args.push("--tls-ca-path".to_string()); + wasmcloud_args.push(format!("{volume_path}/{item}")); + } } } @@ -559,7 +595,29 @@ async fn discover_configmap_certificates( ctx: &Context, ) -> Result> { let kube_client = ctx.client.clone(); - let api = Api::::namespaced(kube_client, &namespace); + let api = Api::::namespaced(kube_client, namespace); + let mut certs = Vec::new(); + + let raw_config_map = api.get(name).await?; + + if let Some(raw_data) = raw_config_map.data { + for (key, _) in raw_data { + if key.ends_with(".crt") { + certs.push(key) + } + } + } + + Ok(certs) +} + +async fn discover_secret_certificates( + namespace: &str, + name: &str, + ctx: &Context, +) -> Result> { + let kube_client = ctx.client.clone(); + let api = Api::::namespaced(kube_client, namespace); let mut certs = Vec::new(); let raw_config_map = api.get(name).await?; diff --git a/src/lib.rs b/src/lib.rs index e9b67a3..efc18b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,9 @@ pub enum Error { #[error("Error retrieving secrets: {0}")] SecretError(String), + #[error("Certificate error: {0}")] + CertificateError(String), + #[error("Error rendering template: {0}")] RenderError(#[from] RenderError), }