This is an automated email from the ASF dual-hosted git repository. pcongiusti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit df0d06dd46cbf3e6e9a78e830208eb1ea7455d7c Author: Pranjul Kalsi <[email protected]> AuthorDate: Fri Jan 16 14:41:38 2026 +0530 fix: simplify CA certificate handling and preserve base truststore password --- e2e/common/traits/jvm_test.go | 38 -------------------------------------- pkg/trait/init_containers.go | 22 +++++++--------------- pkg/trait/init_containers_test.go | 4 ++-- pkg/trait/jvm.go | 19 +++++++++++++------ pkg/trait/jvm_cacert.go | 16 ++++++---------- 5 files changed, 28 insertions(+), 71 deletions(-) diff --git a/e2e/common/traits/jvm_test.go b/e2e/common/traits/jvm_test.go index 189c5b7cf..e4557b739 100644 --- a/e2e/common/traits/jvm_test.go +++ b/e2e/common/traits/jvm_test.go @@ -91,44 +91,6 @@ func TestJVMTrait(t *testing.T) { g.Eventually(IntegrationLogs(t, ctx, ns, name), TestTimeoutShort).Should(ContainSubstring("Hello World!")) }) - t.Run("JVM trait CA cert (deprecated fields)", func(t *testing.T) { - certPem, err := generateSelfSignedCert() - require.NoError(t, err) - - caCertData := make(map[string]string) - caCertData["ca.crt"] = string(certPem) - - err = CreatePlainTextSecret(t, ctx, ns, "test-ca-cert", caCertData) - require.NoError(t, err) - - passwordData := make(map[string]string) - passwordData["password"] = "test-password-123" - err = CreatePlainTextSecret(t, ctx, ns, "test-ca-password", passwordData) - require.NoError(t, err) - - name := RandomizedSuffixName("cacert") - g.Expect(KamelRun(t, ctx, ns, - "./files/Java.java", - "--name", name, - "-t", "mount.configs=secret:test-ca-cert", - "-t", "mount.configs=secret:test-ca-password", - // Using deprecated fields for backward compatibility test - "-t", "jvm.ca-cert=/etc/camel/conf.d/_secrets/test-ca-cert/ca.crt", - "-t", "jvm.ca-cert-password=/etc/camel/conf.d/_secrets/test-ca-password/password", - ).Execute()).To(Succeed()) - - g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning)) - g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue)) - - pod := IntegrationPod(t, ctx, ns, name)() - g.Expect(pod).NotTo(BeNil()) - initContainerNames := make([]string, 0) - for _, c := range pod.Spec.InitContainers { - initContainerNames = append(initContainerNames, c.Name) - } - g.Expect(initContainerNames).To(ContainElement("generate-truststore")) - }) - t.Run("JVM trait multiple CA certs", func(t *testing.T) { // Test the new ca-certificates field with multiple certificates, each with its own password cert1Pem, err := generateSelfSignedCert() diff --git a/pkg/trait/init_containers.go b/pkg/trait/init_containers.go index 1183e3ac2..a1e7074ba 100644 --- a/pkg/trait/init_containers.go +++ b/pkg/trait/init_containers.go @@ -95,28 +95,20 @@ func (t *initContainersTrait) Configure(e *Environment) (bool, *TraitCondition, if ok && jvm.hasCACerts() { var allCommands []string + var truststorePassPath string if jvm.hasBaseTruststore() { baseTruststore := jvm.getBaseTruststore() + truststorePassPath = baseTruststore.PasswordPath copyCmd := fmt.Sprintf("cp %s %s", baseTruststore.TruststorePath, jvm.getTrustStorePath()) allCommands = append(allCommands, copyCmd) - - entries := jvm.getAllCACertEntries() - if len(entries) > 0 { - changePassCmd := fmt.Sprintf( - "keytool -storepasswd -keystore %s -storepass:file %s -new $(cat %s)", - jvm.getTrustStorePath(), baseTruststore.PasswordPath, entries[0].PasswordPath, - ) - allCommands = append(allCommands, changePassCmd) + } else { + certEntries := jvm.getAllCACertEntries() + if len(certEntries) > 0 { + truststorePassPath = certEntries[0].PasswordPath } } - certEntries := jvm.getAllCACertEntries() - // Use the first certificate's password for all imports since they share the same truststore - truststorePassPath := "" - if len(certEntries) > 0 { - truststorePassPath = certEntries[0].PasswordPath - } - for i, entry := range certEntries { + for i, entry := range jvm.getAllCACertEntries() { cmd := fmt.Sprintf( "keytool -importcert -noprompt -alias custom-ca-%d -storepass:file %s -keystore %s -file %s", i, truststorePassPath, jvm.getTrustStorePath(), entry.CertPath, diff --git a/pkg/trait/init_containers_test.go b/pkg/trait/init_containers_test.go index ff2bcdfc0..e2fa15b90 100644 --- a/pkg/trait/init_containers_test.go +++ b/pkg/trait/init_containers_test.go @@ -686,9 +686,9 @@ func TestApplyInitContainerWithBaseTruststore(t *testing.T) { assert.Contains(t, commandStr, "/bin/bash") assert.Contains(t, commandStr, "cp /opt/java/openjdk/lib/security/cacerts") - assert.Contains(t, commandStr, "keytool -storepasswd") - assert.Contains(t, commandStr, "-storepass:file /etc/camel/conf.d/_secrets/base-truststore-pass/password") + assert.NotContains(t, commandStr, "keytool -storepasswd") assert.Contains(t, commandStr, "keytool -importcert") + assert.Contains(t, commandStr, "-storepass:file /etc/camel/conf.d/_secrets/base-truststore-pass/password") assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/my-ca/ca.crt") assert.Contains(t, commandStr, "&&") } diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go index 22120eb65..fcfd29bda 100644 --- a/pkg/trait/jvm.go +++ b/pkg/trait/jvm.go @@ -398,15 +398,22 @@ func (t *jvmTrait) configureCaCert() []string { return nil } - // Get the password path from the first certificate entry - // All certificates use the same truststore, so we use the first entry's password - entries := t.getAllCACertEntries() - if len(entries) == 0 { - return nil + // Determine which password to use for the truststore: + // If base truststore exists, use its password (we keep the original truststore password) + // Otherwise, use the first certificate's password + var truststorePassPath string + if t.hasBaseTruststore() { + truststorePassPath = t.getBaseTruststore().PasswordPath + } else { + entries := t.getAllCACertEntries() + if len(entries) == 0 { + return nil + } + truststorePassPath = entries[0].PasswordPath } return []string{ "-Djavax.net.ssl.trustStore=" + t.getTrustStorePath(), - fmt.Sprintf("-Djavax.net.ssl.trustStorePassword=$(cat %s)", entries[0].PasswordPath), + fmt.Sprintf("-Djavax.net.ssl.trustStorePassword=$(cat %s)", truststorePassPath), } } diff --git a/pkg/trait/jvm_cacert.go b/pkg/trait/jvm_cacert.go index 54ddc9216..1c5112653 100644 --- a/pkg/trait/jvm_cacert.go +++ b/pkg/trait/jvm_cacert.go @@ -104,11 +104,8 @@ func (t *jvmTrait) getAllCACertEntries() []CACertEntry { // validateCACertConfig validates the CA certificate configuration. func (t *jvmTrait) validateCACertConfig() error { for i, cert := range t.CACertificates { - if cert.CertPath != "" && cert.PasswordPath == "" { - return fmt.Errorf("CACertificates[%d]: password path is required when certificate path is specified", i) - } - if cert.CertPath == "" && cert.PasswordPath != "" { - return fmt.Errorf("CACertificates[%d]: certificate path is required when password path is specified", i) + if cert.CertPath == "" || cert.PasswordPath == "" { + return fmt.Errorf("CACertificates[%d]: both cert-path and password-path are required", i) } } @@ -118,11 +115,10 @@ func (t *jvmTrait) validateCACertConfig() error { } if t.BaseTruststore != nil { - if t.BaseTruststore.TruststorePath != "" && t.BaseTruststore.PasswordPath == "" { - return errors.New("base-truststore password path is required when truststore path is specified") - } - if t.BaseTruststore.TruststorePath == "" && t.BaseTruststore.PasswordPath != "" { - return errors.New("base-truststore truststore path is required when password path is specified") + hasTruststorePath := t.BaseTruststore.TruststorePath != "" + hasPasswordPath := t.BaseTruststore.PasswordPath != "" + if hasTruststorePath != hasPasswordPath { + return errors.New("base-truststore: both truststore-path and password-path are required") } }
