From 81bec4dab415b5dad98755381c1d000a8da23be9 Mon Sep 17 00:00:00 2001 From: Techassi Date: Fri, 6 Feb 2026 15:11:53 +0100 Subject: [PATCH] feat: Add annotation to provision public secret data only --- rust/operator-binary/src/backend/mod.rs | 26 ++++++++++ rust/operator-binary/src/csi_server/node.rs | 25 ++++----- rust/operator-binary/src/format/mod.rs | 19 ++++--- rust/operator-binary/src/format/well_known.rs | 52 +++++++++++-------- .../src/truststore_controller.rs | 1 + 5 files changed, 83 insertions(+), 40 deletions(-) diff --git a/rust/operator-binary/src/backend/mod.rs b/rust/operator-binary/src/backend/mod.rs index 2c346056..f4a12c2a 100644 --- a/rust/operator-binary/src/backend/mod.rs +++ b/rust/operator-binary/src/backend/mod.rs @@ -73,6 +73,7 @@ pub struct SecretVolumeSelector { /// The desired format of the mounted secrets /// /// Currently supported formats: + /// /// - `tls-pem` - A Kubernetes-style triple of PEM-encoded certificate files (`tls.crt`, `tls.key`, `ca.crt`). /// - `tls-pkcs12` - A PKCS#12 key store named `keystore.p12` and truststore named `truststore.p12`. /// - `kerberos` - A Kerberos keytab named `keytab`, along with a `krb5.conf`. @@ -138,6 +139,21 @@ pub struct SecretVolumeSelector { default )] pub cert_manager_cert_lifetime: Option, + + // TODO (@Techassi): Name to be decided. Will potentially be renamed. + /// Only provision non-sensitive secret data. + /// + /// - TLS (PEM): Only provision the `ca.crt` file + /// - TLS (PKCS#12): Only provision the `truststore.p12` file + /// - Kerberos: Only provision the `krb5.conf` file + /// + /// This defaults to `false` to be backwords compatible with behaviour before SDP 26.3.0. + #[serde( + rename = "secrets.stackable.tech/only-provision-identity", + deserialize_with = "SecretVolumeSelector::deserialize_str_as_bool", + default + )] + pub only_provision_identity: bool, } /// Configuration provided by the [`TrustStore`] selecting what trust data should be provided. @@ -270,6 +286,16 @@ impl SecretVolumeSelector { ) }) } + + fn deserialize_str_as_bool<'de, D: Deserializer<'de>>(de: D) -> Result { + let str = String::deserialize(de)?; + str.parse().map_err(|_| { + ::invalid_value( + Unexpected::Str(&str), + &"a string containing a boolean", + ) + }) + } } #[derive(Debug)] diff --git a/rust/operator-binary/src/csi_server/node.rs b/rust/operator-binary/src/csi_server/node.rs index c6c9d422..3980c98d 100644 --- a/rust/operator-binary/src/csi_server/node.rs +++ b/rust/operator-binary/src/csi_server/node.rs @@ -26,10 +26,7 @@ use crate::{ self, SecretBackendError, SecretContents, SecretVolumeSelector, pod_info::{self, PodInfo}, }, - format::{ - self, SecretFormat, - well_known::{CompatibilityOptions, NamingOptions}, - }, + format, grpc::csi::v1::{ NodeExpandVolumeRequest, NodeExpandVolumeResponse, NodeGetCapabilitiesRequest, NodeGetCapabilitiesResponse, NodeGetInfoRequest, NodeGetInfoResponse, @@ -220,10 +217,16 @@ impl SecretProvisionerNode { &self, target_path: &Path, data: SecretContents, - format: Option, - names: NamingOptions, - compat: CompatibilityOptions, + selector: SecretVolumeSelector, ) -> Result<(), PublishError> { + let SecretVolumeSelector { + only_provision_identity, + format, + compat, + names, + .. + } = selector; + let create_secret = { let mut opts = OpenOptions::new(); opts.create(true) @@ -234,9 +237,10 @@ impl SecretProvisionerNode { .mode(0o640); opts }; + for (k, v) in data .data - .into_files(format, names, compat) + .into_files(format, names, compat, only_provision_identity) .context(publish_error::FormatDataSnafu)? { // The following few lines of code do some basic checks against @@ -423,10 +427,7 @@ impl Node for SecretProvisionerNode { self.save_secret_data( &target_path, data, - // NOTE (@Techassi): At this point, we might want to pass the whole selector instead - selector.format, - selector.names, - selector.compat, + selector ) .await?; Ok(Response::new(NodePublishVolumeResponse {})) diff --git a/rust/operator-binary/src/format/mod.rs b/rust/operator-binary/src/format/mod.rs index 7a268b9c..1c192cb4 100644 --- a/rust/operator-binary/src/format/mod.rs +++ b/rust/operator-binary/src/format/mod.rs @@ -22,7 +22,7 @@ pub enum SecretData { impl SecretData { pub fn parse(self) -> Result { match self { - Self::WellKnown(x) => Ok(x), + Self::WellKnown(data) => Ok(data), Self::Unknown(files) => WellKnownSecretData::from_files(files), } } @@ -32,15 +32,20 @@ impl SecretData { format: Option, names: NamingOptions, compat: CompatibilityOptions, + only_identity: bool, ) -> Result { - if let Some(format) = format { - Ok(self.parse()?.convert_to(format, compat)?.into_files(names)) + let files = if let Some(format) = format { + self.parse()? + .convert_to(format, compat)? + .into_files(names, only_identity) } else { - Ok(match self { - SecretData::WellKnown(data) => data.into_files(names), + match self { + SecretData::WellKnown(data) => data.into_files(names, only_identity), SecretData::Unknown(files) => files, - }) - } + } + }; + + Ok(files) } } diff --git a/rust/operator-binary/src/format/well_known.rs b/rust/operator-binary/src/format/well_known.rs index ce513058..74cc8444 100644 --- a/rust/operator-binary/src/format/well_known.rs +++ b/rust/operator-binary/src/format/well_known.rs @@ -47,35 +47,45 @@ pub enum WellKnownSecretData { } impl WellKnownSecretData { - pub fn into_files(self, names: NamingOptions) -> SecretFiles { + pub fn into_files(self, names: NamingOptions, only_identity: bool) -> SecretFiles { match self { WellKnownSecretData::TlsPem(TlsPem { certificate_pem, key_pem, ca_pem, - }) => [ - Some(names.tls_pem_cert_name).zip(certificate_pem), - Some(names.tls_pem_key_name).zip(key_pem), - Some((names.tls_pem_ca_name, ca_pem)), - ] - .into_iter() - .flatten() - .collect(), + }) => { + let mut files = vec![Some((names.tls_pem_ca_name, ca_pem))]; + + if !only_identity { + files.extend([ + Some(names.tls_pem_cert_name).zip(certificate_pem), + Some(names.tls_pem_key_name).zip(key_pem), + ]); + } + + files.into_iter().flatten().collect() + } WellKnownSecretData::TlsPkcs12(TlsPkcs12 { keystore, truststore, - }) => [ - Some(names.tls_pkcs12_keystore_name).zip(keystore), - Some((names.tls_pkcs12_truststore_name, truststore)), - ] - .into_iter() - .flatten() - .collect(), - WellKnownSecretData::Kerberos(Kerberos { keytab, krb5_conf }) => [ - (FILE_KERBEROS_KEYTAB_KEYTAB.to_string(), keytab), - (FILE_KERBEROS_KEYTAB_KRB5_CONF.to_string(), krb5_conf), - ] - .into(), + }) => { + let mut files = vec![Some((names.tls_pkcs12_truststore_name, truststore))]; + + if !only_identity { + files.push(Some(names.tls_pkcs12_keystore_name).zip(keystore)); + } + + files.into_iter().flatten().collect() + } + WellKnownSecretData::Kerberos(Kerberos { keytab, krb5_conf }) => { + let mut files = vec![(FILE_KERBEROS_KEYTAB_KRB5_CONF.to_string(), krb5_conf)]; + + if !only_identity { + files.push((FILE_KERBEROS_KEYTAB_KEYTAB.to_string(), keytab)); + } + + SecretFiles::from_iter(files) + } } } diff --git a/rust/operator-binary/src/truststore_controller.rs b/rust/operator-binary/src/truststore_controller.rs index 4346646c..46c2a1c5 100644 --- a/rust/operator-binary/src/truststore_controller.rs +++ b/rust/operator-binary/src/truststore_controller.rs @@ -291,6 +291,7 @@ async fn reconcile( truststore.spec.format, NamingOptions::default(), CompatibilityOptions::default(), + false, ) .context(FormatDataSnafu { secret_class: secret_class_ref,