From 346f5283ab881dcc9900b395b8039985ed39a67f Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 24 Sep 2025 15:26:51 +0200 Subject: [PATCH 1/3] fix: Prevent missing certificates --- CHANGELOG.md | 8 +++++++ rust/operator-binary/src/controller.rs | 3 +++ .../src/security/authentication.rs | 23 ++++++++++--------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6298809e..8d300280 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ All notable changes to this project will be documented in this file. - Helm: Allow Pod `priorityClassName` to be configured ([#840]). +### Fixed + +- Previously we had a bug that could lead to missing certificates ([#XXX]). + + This could be the case when you specified multiple CAs in your SecretClass. + We now correctly handle multiple certificates in this cases. + See [this GitHub issue](https://github.com/stackabletech/issues/issues/764) for details + [#840]: https://github.com/stackabletech/nifi-operator/pull/840 ## [25.7.0] - 2025-07-23 diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 9440566a..02e0d292 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -951,6 +951,9 @@ async fn build_node_rolegroup_statefulset( )); } + // Note(sbernauer): In https://github.com/stackabletech/issues/issues/764 we migrated all usages + // of keytool to our own cert-utils tool. As it uses the same code as secret-operator, it also + // uses RC2. Thus, the keytool usage here LGTM (no alias trickery) and has my nod of approval. prepare_args.extend(vec![ // The source directory is a secret-op mount and we do not want to write / add anything in there // Therefore we import all the contents to a truststore in "writeable" empty dirs. diff --git a/rust/operator-binary/src/security/authentication.rs b/rust/operator-binary/src/security/authentication.rs index 4f6633c0..e1aaa294 100644 --- a/rust/operator-binary/src/security/authentication.rs +++ b/rust/operator-binary/src/security/authentication.rs @@ -136,22 +136,14 @@ impl NifiAuthenticationConfig { } Self::Ldap { provider } => { if let Some(ca_path) = provider.tls.tls_ca_cert_mount_path() { - commands.extend(vec![ - "echo Adding LDAP tls cert to global truststore".to_string(), - format!("keytool -importcert -file {ca_path} -keystore {STACKABLE_SERVER_TLS_DIR}/truststore.p12 -storetype pkcs12 -noprompt -alias ldap_ca_cert -storepass {STACKABLE_TLS_STORE_PASSWORD}"), - ]); + commands.push(add_cert_to_truststore(&ca_path, STACKABLE_SERVER_TLS_DIR)); } } Self::Oidc { provider, .. } => { let (_, admin_password_file) = self.get_user_and_password_file_paths(); - commands.extend(vec![ - format!("export STACKABLE_ADMIN_PASSWORD=\"$(cat {admin_password_file} | java -jar /bin/stackable-bcrypt.jar)\""), - ]); + commands.push(format!("export STACKABLE_ADMIN_PASSWORD=\"$(cat {admin_password_file} | java -jar /bin/stackable-bcrypt.jar)\"")); if let Some(ca_path) = provider.tls.tls_ca_cert_mount_path() { - commands.extend(vec![ - "echo Adding OIDC tls cert to global truststore".to_string(), - format!("keytool -importcert -file {ca_path} -keystore {STACKABLE_SERVER_TLS_DIR}/truststore.p12 -storetype pkcs12 -noprompt -alias oidc_ca_cert -storepass {STACKABLE_TLS_STORE_PASSWORD}"), - ]); + commands.push(add_cert_to_truststore(&ca_path, STACKABLE_SERVER_TLS_DIR)); } } } @@ -259,6 +251,15 @@ impl NifiAuthenticationConfig { } } +/// Adds a PEM file to configured PKCS12 truststore (using the [`STACKABLE_TLS_STORE_PASSWORD`] +/// password) +fn add_cert_to_truststore(cert_file: &str, destination_directory: &str) -> String { + let truststore = format!("{destination_directory}/truststore.p12"); + format!( + "cert-tools generate-pkcs12-truststore --pkcs12 {truststore}:{STACKABLE_TLS_STORE_PASSWORD} --pem {cert_file} --out {truststore} --out-password {STACKABLE_TLS_STORE_PASSWORD}" + ) +} + fn get_ldap_login_identity_provider( ldap: &ldap::v1alpha1::AuthenticationProvider, ) -> Result { From 5948704482fd0f5eea00f9cc22e36beef58f03e4 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 24 Sep 2025 15:29:00 +0200 Subject: [PATCH 2/3] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d300280..e334130e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,13 +10,14 @@ All notable changes to this project will be documented in this file. ### Fixed -- Previously we had a bug that could lead to missing certificates ([#XXX]). +- Previously we had a bug that could lead to missing certificates ([#844]). This could be the case when you specified multiple CAs in your SecretClass. We now correctly handle multiple certificates in this cases. See [this GitHub issue](https://github.com/stackabletech/issues/issues/764) for details [#840]: https://github.com/stackabletech/nifi-operator/pull/840 +[#844]: https://github.com/stackabletech/nifi-operator/pull/844 ## [25.7.0] - 2025-07-23 From 8c33023c3f16627fe819202fe8c87709ea734288 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Thu, 25 Sep 2025 06:31:57 +0200 Subject: [PATCH 3/3] chore: Increase test timeouts --- tests/templates/kuttl/external-access/30-assert.yaml | 4 ++-- tests/templates/kuttl/ldap/03-assert.yaml | 2 +- tests/templates/kuttl/smoke_v1/50-assert.yaml | 2 +- tests/templates/kuttl/smoke_v2/50-assert.yaml | 2 +- tests/templates/kuttl/upgrade/03-assert.yaml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/templates/kuttl/external-access/30-assert.yaml b/tests/templates/kuttl/external-access/30-assert.yaml index c8122146..819b2d59 100644 --- a/tests/templates/kuttl/external-access/30-assert.yaml +++ b/tests/templates/kuttl/external-access/30-assert.yaml @@ -3,9 +3,9 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert metadata: name: install-nifi -timeout: 300 +timeout: 1200 commands: - - script: kubectl -n $NAMESPACE wait --for=condition=available=true nificlusters.nifi.stackable.tech/test-nifi --timeout 301s + - script: kubectl -n $NAMESPACE wait --for=condition=available=true nificlusters.nifi.stackable.tech/test-nifi --timeout 1201s --- apiVersion: apps/v1 kind: StatefulSet diff --git a/tests/templates/kuttl/ldap/03-assert.yaml b/tests/templates/kuttl/ldap/03-assert.yaml index d511ff46..f56ce239 100644 --- a/tests/templates/kuttl/ldap/03-assert.yaml +++ b/tests/templates/kuttl/ldap/03-assert.yaml @@ -1,7 +1,7 @@ --- apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 300 +timeout: 1200 --- apiVersion: apps/v1 kind: StatefulSet diff --git a/tests/templates/kuttl/smoke_v1/50-assert.yaml b/tests/templates/kuttl/smoke_v1/50-assert.yaml index d511ff46..f56ce239 100644 --- a/tests/templates/kuttl/smoke_v1/50-assert.yaml +++ b/tests/templates/kuttl/smoke_v1/50-assert.yaml @@ -1,7 +1,7 @@ --- apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 300 +timeout: 1200 --- apiVersion: apps/v1 kind: StatefulSet diff --git a/tests/templates/kuttl/smoke_v2/50-assert.yaml b/tests/templates/kuttl/smoke_v2/50-assert.yaml index d511ff46..f56ce239 100644 --- a/tests/templates/kuttl/smoke_v2/50-assert.yaml +++ b/tests/templates/kuttl/smoke_v2/50-assert.yaml @@ -1,7 +1,7 @@ --- apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 300 +timeout: 1200 --- apiVersion: apps/v1 kind: StatefulSet diff --git a/tests/templates/kuttl/upgrade/03-assert.yaml b/tests/templates/kuttl/upgrade/03-assert.yaml index d511ff46..f56ce239 100644 --- a/tests/templates/kuttl/upgrade/03-assert.yaml +++ b/tests/templates/kuttl/upgrade/03-assert.yaml @@ -1,7 +1,7 @@ --- apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 300 +timeout: 1200 --- apiVersion: apps/v1 kind: StatefulSet