From a22dce016e589552c5dbfca116fdefeebaa31737 Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 21 Apr 2026 16:43:39 +0200 Subject: [PATCH 1/4] feat: Add domain components to the subject DN if enabled --- .../src/backend/auto_tls/mod.rs | 21 +++++++++++++++++++ rust/operator-binary/src/backend/mod.rs | 17 +++++++++++++++ rust/operator-binary/src/backend/pod_info.rs | 6 ++++++ 3 files changed, 44 insertions(+) diff --git a/rust/operator-binary/src/backend/auto_tls/mod.rs b/rust/operator-binary/src/backend/auto_tls/mod.rs index dfa9d424..27acb336 100644 --- a/rust/operator-binary/src/backend/auto_tls/mod.rs +++ b/rust/operator-binary/src/backend/auto_tls/mod.rs @@ -355,6 +355,21 @@ impl SecretBackend for TlsGenerate { } } + let domain_components = if selector.autotls_cert_domain_components_in_subject_dn { + [ + Some(pod_info.pod_name.as_str()), + pod_info.service_name.as_deref(), + Some(&pod_info.namespace), + Some("svc"), + ] + .into_iter() + .flatten() + .chain(pod_info.kubernetes_cluster_domain.split('.')) + .collect() + } else { + vec![] + }; + let pod_cert = X509Builder::new() .and_then(|mut x509| { let subject_name = X509NameBuilder::new() @@ -363,6 +378,12 @@ impl SecretBackend for TlsGenerate { Nid::COMMONNAME, "generated certificate for pod", )?; + for domain_component in domain_components { + name.append_entry_by_nid( + Nid::DOMAINCOMPONENT, + domain_component, + )?; + } Ok(name) })? .build(); diff --git a/rust/operator-binary/src/backend/mod.rs b/rust/operator-binary/src/backend/mod.rs index 8d57c774..218512f7 100644 --- a/rust/operator-binary/src/backend/mod.rs +++ b/rust/operator-binary/src/backend/mod.rs @@ -129,6 +129,13 @@ pub struct SecretVolumeSelector { )] pub autotls_cert_jitter_factor: f64, + #[serde( + rename = "secrets.stackable.tech/backend.autotls.cert.domain-components-in-subject-dn", + deserialize_with = "SecretVolumeSelector::deserialize_str_as_bool", + default + )] + pub autotls_cert_domain_components_in_subject_dn: bool, + /// The TLS cert lifetime (when using the [`cert_manager`] backend). /// /// The format is documented in . @@ -301,6 +308,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/backend/pod_info.rs b/rust/operator-binary/src/backend/pod_info.rs index d4236ff5..2c1e44d2 100644 --- a/rust/operator-binary/src/backend/pod_info.rs +++ b/rust/operator-binary/src/backend/pod_info.rs @@ -104,7 +104,9 @@ pub enum FromPodError { #[derive(Debug)] pub struct PodInfo { pub pod_ips: Vec, + pub pod_name: String, pub service_name: Option, + pub namespace: String, pub node_name: String, pub node_ips: Vec, pub listener_addresses: Option, @@ -119,6 +121,8 @@ impl PodInfo { scopes: &[SecretScope], ) -> Result { use from_pod_error::*; + let pod_name = pod.metadata.name.clone().context(NoPodNameSnafu)?; + let namespace = pod.metadata.namespace.clone().context(NoNamespaceSnafu)?; let node_name = pod .spec .as_ref() @@ -150,7 +154,9 @@ impl PodInfo { .context(from_pod_error::IllegalAddressSnafu { address: ip }) }) .collect::>()?, + pod_name, service_name: pod.spec.as_ref().and_then(|spec| spec.subdomain.clone()), + namespace, node_name, node_ips: node .status From 9b5e31ca4ce8844c4aa70d3762734f5f4e14e8ff Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Mon, 18 May 2026 12:51:28 +0200 Subject: [PATCH 2/4] test(tls): Add a test case for a subject DN with domain components --- tests/templates/kuttl/tls/10_consumer.yaml.j2 | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/templates/kuttl/tls/10_consumer.yaml.j2 b/tests/templates/kuttl/tls/10_consumer.yaml.j2 index 8a8f4b32..544d2d0b 100644 --- a/tests/templates/kuttl/tls/10_consumer.yaml.j2 +++ b/tests/templates/kuttl/tls/10_consumer.yaml.j2 @@ -22,7 +22,7 @@ spec: CERT_NAME=tls.crt CA_NAME=ca.crt {% endif %} - - | + set -euo pipefail ls -la /stackable/tls-3d ls -la /stackable/tls-42h @@ -67,11 +67,18 @@ spec: assert_trusted_roots_contain "cert 4b" assert_trusted_roots_contain "cert 5" assert_trusted_roots_contain "cert 6" + + echo Test subject DN with domain components + + openssl x509 -in /stackable/tls-domain-components/tls.crt -subject -noout | \ + grep "subject=CN=generated certificate for pod, DC=tls-consumer-.*, DC=$NAMESPACE, DC=svc, DC=.*" volumeMounts: - mountPath: /stackable/tls-3d name: tls-3d - mountPath: /stackable/tls-42h name: tls-42h + - mountPath: /stackable/tls-domain-components + name: tls-domain-components volumes: - name: tls-3d ephemeral: @@ -111,6 +118,21 @@ spec: resources: requests: storage: "1" + - name: tls-domain-components + ephemeral: + volumeClaimTemplate: + metadata: + annotations: + secrets.stackable.tech/class: tls-$NAMESPACE + secrets.stackable.tech/scope: pod + secrets.stackable.tech/backend.autotls.cert.domain-components-in-subject-dn: "true" + spec: + storageClassName: secrets.stackable.tech + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "1" securityContext: runAsUser: 1000 runAsGroup: 1000 From ba7c1a9cabd6b2088caaf6ce1c716d288fa7d5fc Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 19 May 2026 16:20:52 +0200 Subject: [PATCH 3/4] chore: Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf2c12eb..75de0fad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,15 @@ All notable changes to this project will be documented in this file. - Support configuring the name of the key in the ConfigMap/Secret, in which the PEM encoded CA certificate of the Truststore should be placed. This is e.g. needed to be able to use the generated Secret within an OpenShift Ingress ([#679]). +- Support adding domain components to the subject DN of TLS certificates with the volume annotaton + `secrets.stackable.tech/backend.autotls.cert.domain-components-in-subject-dn` ([#708]). ### Changed - Document Helm deployed RBAC permissions and remove unnecessary permissions ([#693]). [#693]: https://github.com/stackabletech/secret-operator/pull/693 +[#708]: https://github.com/stackabletech/secret-operator/pull/708 ## [26.3.0] - 2026-03-16 From 7d945c1885609e3467c24fef05bb13757cbb3703 Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Tue, 19 May 2026 16:25:50 +0200 Subject: [PATCH 4/4] chore: Fix typo in the changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e6e067e..db09adc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - Support configuring the name of the key in the ConfigMap/Secret, in which the PEM encoded CA certificate of the Truststore should be placed. This is e.g. needed to be able to use the generated Secret within an OpenShift Ingress ([#679]). -- Support adding domain components to the subject DN of TLS certificates with the volume annotaton +- Support adding domain components to the subject DN of TLS certificates with the volume annotation `secrets.stackable.tech/backend.autotls.cert.domain-components-in-subject-dn` ([#708]). ### Changed