You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2026/01/20 07:26:07 UTC
(camel-k) 05/05: fix(jvm): simplify CA certificate add process by removing per-cert PasswordPath and cleanup tests
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 c2ef248b370aabf7801366ab67a5806adb758a00
Author: Pranjul Kalsi <pr...@gmail.com>
AuthorDate: Sun Jan 18 11:35:28 2026 +0530
fix(jvm): simplify CA certificate add process by removing per-cert PasswordPath and cleanup tests
---
docs/modules/ROOT/partials/apis/camel-k-crds.adoc | 16 +-
docs/modules/traits/pages/jvm.adoc | 63 +++-
e2e/common/traits/jvm_test.go | 33 +-
helm/camel-k/crds/camel-k-crds.yaml | 104 ++++---
pkg/apis/camel/v1/trait/jvm.go | 6 +-
.../camel.apache.org_integrationplatforms.yaml | 26 +-
.../camel.apache.org_integrationprofiles.yaml | 26 +-
.../crd/bases/camel.apache.org_integrations.yaml | 26 +-
.../config/crd/bases/camel.apache.org_pipes.yaml | 26 +-
pkg/trait/init_containers.go | 25 +-
pkg/trait/init_containers_test.go | 44 +--
pkg/trait/jvm.go | 15 +-
pkg/trait/jvm_cacert.go | 45 +--
pkg/trait/jvm_test.go | 335 +++++++++++++++++++--
14 files changed, 571 insertions(+), 219 deletions(-)
diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index f34bf5175..b14d94b53 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -6666,7 +6666,7 @@ The list of manifest platforms to use to build a container image (default `linux
* <<#_camel_apache_org_v1_trait_JVMTrait, JVMTrait>>
-CACertConfig associates a CA certificate with its password file.
+CACertConfig specifies a CA certificate to import into the truststore.
[cols="2,2a",options="header"]
|===
@@ -6680,13 +6680,6 @@ string
Path to the PEM-encoded CA certificate file to import.
-|`passwordPath` +
-string
-|
-
-
-Path to a file containing the password for importing this certificate.
-
|===
@@ -7912,6 +7905,13 @@ A list of CA certificates to import into the truststore. Certificates must be mo
Optional base truststore to use as the starting point for adding certificates.
+|`truststorePasswordPath` +
+string
+|
+
+
+Path to a file containing the password for the generated truststore. Required when using ca-certificates without base-truststore.
+
|`caCertMountPath` +
string
|
diff --git a/docs/modules/traits/pages/jvm.adoc b/docs/modules/traits/pages/jvm.adoc
index 34f128d9f..f60e1d654 100755
--- a/docs/modules/traits/pages/jvm.adoc
+++ b/docs/modules/traits/pages/jvm.adoc
@@ -71,6 +71,10 @@ Deprecated: no longer in use.
| github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait.BaseTruststore
| Optional base truststore to use as the starting point for adding certificates.
+| jvm.truststore-password-path
+| string
+| Path to a file containing the password for the generated truststore. Required when using ca-certificates without base-truststore.
+
| jvm.ca-cert-mount-path
| string
| The path where the generated truststore will be mounted (default `/etc/camel/conf.d/_truststore`).
@@ -118,7 +122,9 @@ $ kamel run --resource configmap:my-dep -t jvm.classpath=/etc/camel/resources/my
== Trusting Custom CA Certificates
-When connecting to services that use TLS with certificates signed by a private CA (e.g., internal Elasticsearch, Kafka, or databases), you can use the `ca-cert` option to add the CA certificate to the JVM's truststore.
+When connecting to services that use TLS with certificates signed by a private CA (e.g., internal Elasticsearch, Kafka, or databases), you can use the `ca-certificates` option to add CA certificates to the JVM's truststore.
+
+=== Single Certificate
First, create Kubernetes Secrets containing the CA certificate and truststore password:
@@ -135,25 +141,66 @@ Then mount the secrets using the mount trait and reference the file paths:
$ kamel run MyRoute.java \
-t mount.configs=secret:my-private-ca \
-t mount.configs=secret:my-truststore-pwd \
- -t jvm.ca-cert=/etc/camel/conf.d/_secrets/my-private-ca/ca.crt \
- -t jvm.ca-cert-password=/etc/camel/conf.d/_secrets/my-truststore-pwd/password
+ -t jvm.ca-certificates[0].cert-path=/etc/camel/conf.d/_secrets/my-private-ca/ca.crt \
+ -t jvm.truststore-password-path=/etc/camel/conf.d/_secrets/my-truststore-pwd/password
----
-If your secret uses a different key name for the certificate:
+=== Multiple Certificates
+
+You can add multiple CA certificates to the truststore:
+
+[source,console]
+----
+$ kamel run MyRoute.java \
+ -t mount.configs=secret:ca1 \
+ -t mount.configs=secret:ca2 \
+ -t mount.configs=secret:truststore-pwd \
+ -t jvm.ca-certificates[0].cert-path=/etc/camel/conf.d/_secrets/ca1/ca.crt \
+ -t jvm.ca-certificates[1].cert-path=/etc/camel/conf.d/_secrets/ca2/ca.crt \
+ -t jvm.truststore-password-path=/etc/camel/conf.d/_secrets/truststore-pwd/password
+----
+
+=== Using a Base Truststore (Preserving JDK Public CAs)
+
+To preserve the JDK's default public CA certificates while adding your custom certificates, use the `base-truststore` option:
[source,console]
----
$ kamel run MyRoute.java \
-t mount.configs=secret:my-private-ca \
- -t mount.configs=secret:my-truststore-pwd \
- -t jvm.ca-cert=/etc/camel/conf.d/_secrets/my-private-ca/custom-ca.pem \
- -t jvm.ca-cert-password=/etc/camel/conf.d/_secrets/my-truststore-pwd/password
+ -t mount.configs=secret:cacerts-pwd \
+ -t jvm.base-truststore.truststore-path=/opt/java/openjdk/lib/security/cacerts \
+ -t jvm.base-truststore.password-path=/etc/camel/conf.d/_secrets/cacerts-pwd/password \
+ -t jvm.ca-certificates[0].cert-path=/etc/camel/conf.d/_secrets/my-private-ca/ca.crt
----
+NOTE: When using `base-truststore`, you can optionally provide `truststore-password-path` to set a different password for the output truststore. If not provided, the base truststore password is used.
+
+=== Truststore Password Resolution
+
+The truststore password is determined using this priority:
+
+1. `truststore-password-path` (if explicitly provided)
+2. `base-truststore.password-path` (if base-truststore is configured)
+3. Validation error (password is required when using `ca-certificates`)
+
This will automatically:
1. Mount the secrets to the integration container (via mount trait)
2. Generate a JVM truststore using an init container
3. Configure the JVM to use the generated truststore via `-Djavax.net.ssl.trustStore`
-NOTE: The `ca-cert-password` option is **required** when using `ca-cert`. Both values must be file paths to the mounted secrets.
+=== Deprecated Syntax (Backward Compatible)
+
+The legacy `ca-cert` and `ca-cert-password` options are still supported but deprecated:
+
+[source,console]
+----
+$ kamel run MyRoute.java \
+ -t mount.configs=secret:my-private-ca \
+ -t mount.configs=secret:my-truststore-pwd \
+ -t jvm.ca-cert=/etc/camel/conf.d/_secrets/my-private-ca/ca.crt \
+ -t jvm.ca-cert-password=/etc/camel/conf.d/_secrets/my-truststore-pwd/password
+----
+
+NOTE: We recommend migrating to the new `ca-certificates` syntax for better multi-certificate support and explicit truststore password configuration.
diff --git a/e2e/common/traits/jvm_test.go b/e2e/common/traits/jvm_test.go
index e4557b739..7da1acf28 100644
--- a/e2e/common/traits/jvm_test.go
+++ b/e2e/common/traits/jvm_test.go
@@ -92,36 +92,38 @@ func TestJVMTrait(t *testing.T) {
})
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
+ // Test the new ca-certificates field with multiple certificates
cert1Pem, err := generateSelfSignedCert()
require.NoError(t, err)
cert2Pem, err := generateSelfSignedCert()
require.NoError(t, err)
- // Create secrets with both cert and password together
+ // Create secrets with certificates
caCert1Data := make(map[string]string)
caCert1Data["ca.crt"] = string(cert1Pem)
- caCert1Data["password"] = "test-password-1"
err = CreatePlainTextSecret(t, ctx, ns, "test-ca-cert-1", caCert1Data)
require.NoError(t, err)
caCert2Data := make(map[string]string)
caCert2Data["ca.crt"] = string(cert2Pem)
- caCert2Data["password"] = "test-password-2"
err = CreatePlainTextSecret(t, ctx, ns, "test-ca-cert-2", caCert2Data)
require.NoError(t, err)
+ truststorePassData := make(map[string]string)
+ truststorePassData["password"] = "truststore-password"
+ err = CreatePlainTextSecret(t, ctx, ns, "truststore-pass-multi", truststorePassData)
+ require.NoError(t, err)
+
name := RandomizedSuffixName("multicacert")
g.Expect(KamelRun(t, ctx, ns,
"./files/Java.java",
"--name", name,
"-t", "mount.configs=secret:test-ca-cert-1",
"-t", "mount.configs=secret:test-ca-cert-2",
- // Using new ca-certificates field: each certificate with its own password path
+ "-t", "mount.configs=secret:truststore-pass-multi",
"-t", "jvm.ca-certificates[0].cert-path=/etc/camel/conf.d/_secrets/test-ca-cert-1/ca.crt",
- "-t", "jvm.ca-certificates[0].password-path=/etc/camel/conf.d/_secrets/test-ca-cert-1/password",
"-t", "jvm.ca-certificates[1].cert-path=/etc/camel/conf.d/_secrets/test-ca-cert-2/ca.crt",
- "-t", "jvm.ca-certificates[1].password-path=/etc/camel/conf.d/_secrets/test-ca-cert-2/password",
+ "-t", "jvm.truststore-password-path=/etc/camel/conf.d/_secrets/truststore-pass-multi/password",
).Execute()).To(Succeed())
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong*2).Should(Equal(corev1.PodRunning))
@@ -141,10 +143,9 @@ func TestJVMTrait(t *testing.T) {
certPem, err := generateSelfSignedCert()
require.NoError(t, err)
- // Create secret with cert and password
+ // Create secret with certificate
caCertData := make(map[string]string)
caCertData["ca.crt"] = string(certPem)
- caCertData["password"] = "test-password-456"
err = CreatePlainTextSecret(t, ctx, ns, "test-ca-sys", caCertData)
require.NoError(t, err)
@@ -160,11 +161,9 @@ func TestJVMTrait(t *testing.T) {
"--name", name,
"-t", "mount.configs=secret:test-ca-sys",
"-t", "mount.configs=secret:base-ts-password",
- // Using new base-truststore field with JDK cacerts as base
"-t", "jvm.base-truststore.truststore-path=/opt/java/openjdk/lib/security/cacerts",
"-t", "jvm.base-truststore.password-path=/etc/camel/conf.d/_secrets/base-ts-password/password",
"-t", "jvm.ca-certificates[0].cert-path=/etc/camel/conf.d/_secrets/test-ca-sys/ca.crt",
- "-t", "jvm.ca-certificates[0].password-path=/etc/camel/conf.d/_secrets/test-ca-sys/password",
).Execute()).To(Succeed())
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning))
@@ -184,21 +183,25 @@ func TestJVMTrait(t *testing.T) {
certPem, err := generateSelfSignedCert()
require.NoError(t, err)
- // Create secret with both cert and password
+ // Create secret with certificate
caCertData := make(map[string]string)
caCertData["ca.crt"] = string(certPem)
- caCertData["password"] = "changeit"
err = CreatePlainTextSecret(t, ctx, ns, "test-ca-single", caCertData)
require.NoError(t, err)
+ truststorePassData := make(map[string]string)
+ truststorePassData["password"] = "truststore-password"
+ err = CreatePlainTextSecret(t, ctx, ns, "truststore-pass-single", truststorePassData)
+ require.NoError(t, err)
+
name := RandomizedSuffixName("singlecert")
g.Expect(KamelRun(t, ctx, ns,
"./files/Java.java",
"--name", name,
"-t", "mount.configs=secret:test-ca-single",
- // Using new ca-certificates field with explicit password
+ "-t", "mount.configs=secret:truststore-pass-single",
"-t", "jvm.ca-certificates[0].cert-path=/etc/camel/conf.d/_secrets/test-ca-single/ca.crt",
- "-t", "jvm.ca-certificates[0].password-path=/etc/camel/conf.d/_secrets/test-ca-single/password",
+ "-t", "jvm.truststore-password-path=/etc/camel/conf.d/_secrets/truststore-pass-single/password",
).Execute()).To(Succeed())
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning))
diff --git a/helm/camel-k/crds/camel-k-crds.yaml b/helm/camel-k/crds/camel-k-crds.yaml
index bb582cbac..9cbf81416 100644
--- a/helm/camel-k/crds/camel-k-crds.yaml
+++ b/helm/camel-k/crds/camel-k-crds.yaml
@@ -4803,17 +4803,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -4858,6 +4854,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -7311,17 +7312,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -7366,6 +7363,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -9719,17 +9721,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -9774,6 +9772,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -12104,17 +12107,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -12159,6 +12158,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -21347,17 +21351,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -21402,6 +21402,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -23688,17 +23693,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -23743,6 +23744,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -34296,17 +34302,13 @@ spec:
the truststore. Certificates must be mounted via the
mount trait.
items:
- description: CACertConfig associates a CA certificate
- with its password file.
+ description: CACertConfig specifies a CA certificate
+ to import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -34351,6 +34353,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for
+ the generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -36567,17 +36574,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -36622,6 +36625,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
diff --git a/pkg/apis/camel/v1/trait/jvm.go b/pkg/apis/camel/v1/trait/jvm.go
index 7c5d904c9..6adaa572d 100644
--- a/pkg/apis/camel/v1/trait/jvm.go
+++ b/pkg/apis/camel/v1/trait/jvm.go
@@ -17,12 +17,10 @@ limitations under the License.
package trait
-// CACertConfig associates a CA certificate with its password file.
+// CACertConfig specifies a CA certificate to import into the truststore.
type CACertConfig struct {
// Path to the PEM-encoded CA certificate file to import.
CertPath string `json:"certPath,omitempty" property:"cert-path"`
- // Path to a file containing the password for importing this certificate.
- PasswordPath string `json:"passwordPath,omitempty" property:"password-path"`
}
// BaseTruststore represents an existing truststore to use as the base for adding certificates.
@@ -65,6 +63,8 @@ type JVMTrait struct {
CACertificates []CACertConfig `json:"caCertificates,omitempty" property:"ca-certificates"`
// Optional base truststore to use as the starting point for adding certificates.
BaseTruststore *BaseTruststore `json:"baseTruststore,omitempty" property:"base-truststore"`
+ // Path to a file containing the password for the generated truststore. Required when using ca-certificates without base-truststore.
+ TruststorePasswordPath string `json:"truststorePasswordPath,omitempty" property:"truststore-password-path"`
// The path where the generated truststore will be mounted (default `/etc/camel/conf.d/_truststore`).
CACertMountPath string `json:"caCertMountPath,omitempty" property:"ca-cert-mount-path"`
// Deprecated: Use CACertificates instead. Path to a PEM-encoded CA certificate file.
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
index 3bd65993a..0f73c3592 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
@@ -1529,17 +1529,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -1584,6 +1580,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -4037,17 +4038,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -4092,6 +4089,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
index 4cc3ea37f..471165280 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
@@ -1395,17 +1395,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -1450,6 +1446,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -3780,17 +3781,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -3835,6 +3832,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
index e9d7b0178..c89bf48de 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
@@ -8233,17 +8233,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -8288,6 +8284,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -10574,17 +10575,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -10629,6 +10626,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
index a183f0500..f6c7187eb 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
@@ -8290,17 +8290,13 @@ spec:
the truststore. Certificates must be mounted via the
mount trait.
items:
- description: CACertConfig associates a CA certificate
- with its password file.
+ description: CACertConfig specifies a CA certificate
+ to import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -8345,6 +8341,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for
+ the generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
@@ -10561,17 +10562,13 @@ spec:
description: A list of CA certificates to import into the
truststore. Certificates must be mounted via the mount trait.
items:
- description: CACertConfig associates a CA certificate with
- its password file.
+ description: CACertConfig specifies a CA certificate to
+ import into the truststore.
properties:
certPath:
description: Path to the PEM-encoded CA certificate
file to import.
type: string
- passwordPath:
- description: Path to a file containing the password
- for importing this certificate.
- type: string
type: object
type: array
classpath:
@@ -10616,6 +10613,11 @@ spec:
Deprecated: no longer in use.
type: boolean
+ truststorePasswordPath:
+ description: Path to a file containing the password for the
+ generated truststore. Required when using ca-certificates
+ without base-truststore.
+ type: string
type: object
kamelets:
description: The configuration of Kamelets trait
diff --git a/pkg/trait/init_containers.go b/pkg/trait/init_containers.go
index a1e7074ba..57330f111 100644
--- a/pkg/trait/init_containers.go
+++ b/pkg/trait/init_containers.go
@@ -91,33 +91,38 @@ func (t *initContainersTrait) Configure(e *Environment) (bool, *TraitCondition,
}
t.tasks = append(t.tasks, agentDownloadTask)
}
- // Set the CA cert truststore init container if configured
if ok && jvm.hasCACerts() {
+ if err := jvm.validateCACertConfig(); err != nil {
+ return false, nil, err
+ }
+
var allCommands []string
+ importPassPath := jvm.getTruststorePasswordPath()
- 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)
- } else {
- certEntries := jvm.getAllCACertEntries()
- if len(certEntries) > 0 {
- truststorePassPath = certEntries[0].PasswordPath
- }
+ importPassPath = baseTruststore.PasswordPath
}
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,
+ i, importPassPath, jvm.getTrustStorePath(), entry.CertPath,
)
allCommands = append(allCommands, cmd)
}
+ if jvm.hasBaseTruststore() && jvm.TruststorePasswordPath != "" {
+ storepasswdCmd := fmt.Sprintf(
+ "keytool -storepasswd -keystore %s -storepass:file %s -new \"$(cat %s)\"",
+ jvm.getTrustStorePath(), jvm.getBaseTruststore().PasswordPath, jvm.TruststorePasswordPath,
+ )
+ allCommands = append(allCommands, storepasswdCmd)
+ }
+
fullCommand := strings.Join(allCommands, " && ")
- // Wrap in bash shell when there are multiple commands or shell features are used
if len(allCommands) > 1 || jvm.hasBaseTruststore() {
fullCommand = fmt.Sprintf("/bin/bash -c \"%s\"", fullCommand)
}
diff --git a/pkg/trait/init_containers_test.go b/pkg/trait/init_containers_test.go
index e2fa15b90..eb7b4d540 100644
--- a/pkg/trait/init_containers_test.go
+++ b/pkg/trait/init_containers_test.go
@@ -395,11 +395,9 @@ func TestApplyInitContainerWithCACert(t *testing.T) {
Traits: v1.Traits{
JVM: &trait.JVMTrait{
CACertificates: []trait.CACertConfig{
- {
- CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/truststore-pass/password",
- },
+ {CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt"},
},
+ TruststorePasswordPath: "/etc/camel/conf.d/_secrets/truststore-pass/password",
},
},
},
@@ -468,19 +466,11 @@ func TestApplyInitContainerWithMultipleCACerts(t *testing.T) {
Traits: v1.Traits{
JVM: &trait.JVMTrait{
CACertificates: []trait.CACertConfig{
- {
- CertPath: "/etc/camel/conf.d/_secrets/ca1/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/pass1/password",
- },
- {
- CertPath: "/etc/camel/conf.d/_secrets/ca2/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/pass2/password",
- },
- {
- CertPath: "/etc/camel/conf.d/_secrets/ca3/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/pass3/password",
- },
+ {CertPath: "/etc/camel/conf.d/_secrets/ca1/ca.crt"},
+ {CertPath: "/etc/camel/conf.d/_secrets/ca2/ca.crt"},
+ {CertPath: "/etc/camel/conf.d/_secrets/ca3/ca.crt"},
},
+ TruststorePasswordPath: "/etc/camel/conf.d/_secrets/truststore/password",
},
},
},
@@ -527,11 +517,8 @@ func TestApplyInitContainerWithMultipleCACerts(t *testing.T) {
assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/ca3/ca.crt")
assert.Contains(t, commandStr, "&&")
- firstPasswordCount := strings.Count(commandStr, "/etc/camel/conf.d/_secrets/pass1/password")
- assert.Equal(t, 3, firstPasswordCount, "All 3 keytool commands should use the first certificate's password")
-
- assert.NotContains(t, commandStr, "storepass:file /etc/camel/conf.d/_secrets/pass2/password")
- assert.NotContains(t, commandStr, "storepass:file /etc/camel/conf.d/_secrets/pass3/password")
+ truststorePasswordCount := strings.Count(commandStr, "/etc/camel/conf.d/_secrets/truststore/password")
+ assert.Equal(t, 3, truststorePasswordCount, "All 3 keytool commands should use the truststore password")
}
func TestApplyInitContainerWithCACertsBackwardCompatibility(t *testing.T) {
@@ -564,13 +551,11 @@ func TestApplyInitContainerWithCACertsBackwardCompatibility(t *testing.T) {
Traits: v1.Traits{
JVM: &trait.JVMTrait{
CACertificates: []trait.CACertConfig{
- {
- CertPath: "/etc/camel/conf.d/_secrets/ca1/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/pass1/password",
- },
+ {CertPath: "/etc/camel/conf.d/_secrets/ca1/ca.crt"},
},
- CACert: "/etc/camel/conf.d/_secrets/ca2/ca.crt",
- CACertPassword: "/etc/camel/conf.d/_secrets/pass2/password",
+ TruststorePasswordPath: "/etc/camel/conf.d/_secrets/truststore/password",
+ CACert: "/etc/camel/conf.d/_secrets/ca2/ca.crt",
+ CACertPassword: "/etc/camel/conf.d/_secrets/pass2/password",
},
},
},
@@ -639,10 +624,7 @@ func TestApplyInitContainerWithBaseTruststore(t *testing.T) {
Traits: v1.Traits{
JVM: &trait.JVMTrait{
CACertificates: []trait.CACertConfig{
- {
- CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/truststore-pass/password",
- },
+ {CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt"},
},
BaseTruststore: &trait.BaseTruststore{
TruststorePath: "/opt/java/openjdk/lib/security/cacerts",
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index fcfd29bda..3c2729e8a 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -398,18 +398,9 @@ func (t *jvmTrait) configureCaCert() []string {
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
+ truststorePassPath := t.getTruststorePasswordPath()
+ if truststorePassPath == "" {
+ return nil
}
return []string{
diff --git a/pkg/trait/jvm_cacert.go b/pkg/trait/jvm_cacert.go
index 1c5112653..2b71c7cce 100644
--- a/pkg/trait/jvm_cacert.go
+++ b/pkg/trait/jvm_cacert.go
@@ -30,10 +30,8 @@ const (
trustStoreName = "truststore.jks"
)
-// CACertEntry represents a resolved CA certificate configuration.
type CACertEntry struct {
- CertPath string
- PasswordPath string
+ CertPath string
}
// hasCACerts returns true if any CA certificates are configured.
@@ -59,21 +57,32 @@ func (t *jvmTrait) hasBaseTruststore() bool {
return t.BaseTruststore != nil && t.BaseTruststore.TruststorePath != "" && t.BaseTruststore.PasswordPath != ""
}
+func (t *jvmTrait) getTruststorePasswordPath() string {
+ if t.TruststorePasswordPath != "" {
+ return t.TruststorePasswordPath
+ }
+ if t.hasBaseTruststore() {
+ return t.BaseTruststore.PasswordPath
+ }
+ //nolint:staticcheck
+ if t.CACert != "" && t.CACertPassword != "" {
+ return t.CACertPassword
+ }
+
+ return ""
+}
+
// getBaseTruststore returns the base truststore configuration if set.
func (t *jvmTrait) getBaseTruststore() *traitv1.BaseTruststore {
return t.BaseTruststore
}
-// getAllCACertEntries returns all configured CA certificate entries.
func (t *jvmTrait) getAllCACertEntries() []CACertEntry {
var entries []CACertEntry
for _, cert := range t.CACertificates {
- if cert.CertPath != "" && cert.PasswordPath != "" {
- entries = append(entries, CACertEntry{
- CertPath: cert.CertPath,
- PasswordPath: cert.PasswordPath,
- })
+ if cert.CertPath != "" {
+ entries = append(entries, CACertEntry{CertPath: cert.CertPath})
}
}
@@ -89,23 +98,18 @@ func (t *jvmTrait) getAllCACertEntries() []CACertEntry {
}
}
if !found {
- entries = append(entries, CACertEntry{
- //nolint:staticcheck
- CertPath: t.CACert,
- //nolint:staticcheck
- PasswordPath: t.CACertPassword,
- })
+ //nolint:staticcheck
+ entries = append(entries, CACertEntry{CertPath: t.CACert})
}
}
return entries
}
-// 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]: both cert-path and password-path are required", i)
+ if cert.CertPath == "" {
+ return fmt.Errorf("CACertificates[%d]: cert-path is required", i)
}
}
@@ -122,5 +126,10 @@ func (t *jvmTrait) validateCACertConfig() error {
}
}
+ // For new CACertificates field, require explicit truststore password or base truststore
+ if len(t.CACertificates) > 0 && t.TruststorePasswordPath == "" && !t.hasBaseTruststore() {
+ return errors.New("truststore-password-path is required when using ca-certificates without base-truststore")
+ }
+
return nil
}
diff --git a/pkg/trait/jvm_test.go b/pkg/trait/jvm_test.go
index 37ae9633e..7d5e654c2 100644
--- a/pkg/trait/jvm_test.go
+++ b/pkg/trait/jvm_test.go
@@ -723,11 +723,9 @@ func TestApplyJvmTraitAgentFail(t *testing.T) {
func TestApplyJvmTraitWithCACert(t *testing.T) {
trait, environment := createNominalJvmTest(v1.IntegrationKitTypePlatform)
trait.CACertificates = []traitv1.CACertConfig{
- {
- CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/truststore-pass/password",
- },
+ {CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt"},
}
+ trait.TruststorePasswordPath = "/etc/camel/conf.d/_secrets/truststore-pass/password"
d := appsv1.Deployment{
Spec: appsv1.DeploymentSpec{
@@ -759,11 +757,9 @@ func TestApplyJvmTraitWithCACert(t *testing.T) {
func TestApplyJvmTraitWithCustomCACertMountPath(t *testing.T) {
trait, environment := createNominalJvmTest(v1.IntegrationKitTypePlatform)
trait.CACertificates = []traitv1.CACertConfig{
- {
- CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt",
- PasswordPath: "/etc/camel/conf.d/_secrets/truststore-pass/password",
- },
+ {CertPath: "/etc/camel/conf.d/_secrets/my-ca/ca.crt"},
}
+ trait.TruststorePasswordPath = "/etc/camel/conf.d/_secrets/truststore-pass/password"
trait.CACertMountPath = "/custom/truststore/path"
d := appsv1.Deployment{
@@ -797,17 +793,15 @@ func TestGetAllCACertEntries(t *testing.T) {
trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
trait.CACertificates = []traitv1.CACertConfig{
- {CertPath: "/path/to/ca1.crt", PasswordPath: "/path/to/pass1"},
- {CertPath: "/path/to/ca2.crt", PasswordPath: "/path/to/pass2"},
+ {CertPath: "/path/to/ca1.crt"},
+ {CertPath: "/path/to/ca2.crt"},
}
trait.CACert = ""
trait.CACertPassword = ""
entries := trait.getAllCACertEntries()
assert.Len(t, entries, 2)
assert.Equal(t, "/path/to/ca1.crt", entries[0].CertPath)
- assert.Equal(t, "/path/to/pass1", entries[0].PasswordPath)
assert.Equal(t, "/path/to/ca2.crt", entries[1].CertPath)
- assert.Equal(t, "/path/to/pass2", entries[1].PasswordPath)
trait.CACertificates = nil
trait.CACert = "/path/to/legacy.crt"
@@ -815,10 +809,9 @@ func TestGetAllCACertEntries(t *testing.T) {
entries = trait.getAllCACertEntries()
assert.Len(t, entries, 1)
assert.Equal(t, "/path/to/legacy.crt", entries[0].CertPath)
- assert.Equal(t, "/path/to/legacy-pass", entries[0].PasswordPath)
trait.CACertificates = []traitv1.CACertConfig{
- {CertPath: "/path/to/ca1.crt", PasswordPath: "/path/to/pass1"},
+ {CertPath: "/path/to/ca1.crt"},
}
trait.CACert = "/path/to/ca2.crt"
trait.CACertPassword = "/path/to/pass2"
@@ -840,7 +833,7 @@ func TestHasCACerts(t *testing.T) {
assert.False(t, trait.hasCACerts())
trait.CACertificates = []traitv1.CACertConfig{
- {CertPath: "/path/to/ca1.crt", PasswordPath: "/path/to/pass1"},
+ {CertPath: "/path/to/ca1.crt"},
}
trait.CACert = ""
assert.True(t, trait.hasCACerts())
@@ -850,7 +843,7 @@ func TestHasCACerts(t *testing.T) {
assert.True(t, trait.hasCACerts())
trait.CACertificates = []traitv1.CACertConfig{
- {CertPath: "/path/to/ca1.crt", PasswordPath: "/path/to/pass1"},
+ {CertPath: "/path/to/ca1.crt"},
}
trait.CACert = "/path/to/ca2.crt"
assert.True(t, trait.hasCACerts())
@@ -882,6 +875,61 @@ func TestHasBaseTruststore(t *testing.T) {
assert.True(t, trait.hasBaseTruststore())
}
+func TestGetTruststorePasswordPath(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = ""
+ trait.CACertPassword = ""
+ assert.Equal(t, "", trait.getTruststorePasswordPath())
+
+ trait.TruststorePasswordPath = "/path/to/user-provided-pass"
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ PasswordPath: "/path/to/base-pass",
+ }
+ trait.CACert = "/path/to/legacy.crt"
+ trait.CACertPassword = "/path/to/legacy-pass"
+ assert.Equal(t, "/path/to/user-provided-pass", trait.getTruststorePasswordPath())
+
+ trait.TruststorePasswordPath = "/path/to/user-provided-pass"
+ trait.BaseTruststore = nil
+ trait.CACert = "/path/to/legacy.crt"
+ trait.CACertPassword = "/path/to/legacy-pass"
+ assert.Equal(t, "/path/to/user-provided-pass", trait.getTruststorePasswordPath())
+
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = "/path/to/legacy.crt"
+ trait.CACertPassword = "/path/to/legacy-pass"
+ assert.Equal(t, "/path/to/legacy-pass", trait.getTruststorePasswordPath())
+
+ trait.TruststorePasswordPath = "/path/to/user-provided-pass"
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ }
+ trait.CACert = ""
+ trait.CACertPassword = ""
+ assert.Equal(t, "/path/to/user-provided-pass", trait.getTruststorePasswordPath())
+
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ }
+ trait.CACert = "/path/to/legacy.crt"
+ trait.CACertPassword = "/path/to/legacy-pass"
+ assert.Equal(t, "/path/to/legacy-pass", trait.getTruststorePasswordPath())
+
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ }
+ trait.CACert = ""
+ trait.CACertPassword = ""
+ assert.Equal(t, "", trait.getTruststorePasswordPath())
+}
+
func TestValidateCACertConfig(t *testing.T) {
trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
@@ -889,21 +937,54 @@ func TestValidateCACertConfig(t *testing.T) {
trait.CACert = ""
trait.CACertPassword = ""
trait.BaseTruststore = nil
+ trait.TruststorePasswordPath = ""
+ assert.NoError(t, trait.validateCACertConfig())
+
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/ca.crt"},
+ }
+ trait.TruststorePasswordPath = "/path/to/truststore-pass"
+ assert.NoError(t, trait.validateCACertConfig())
+
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/ca.crt"},
+ }
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ assert.Error(t, trait.validateCACertConfig())
+ assert.Contains(t, trait.validateCACertConfig().Error(), "truststore-password-path is required")
+
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/ca.crt"},
+ }
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ PasswordPath: "/path/to/base-pass",
+ }
assert.NoError(t, trait.validateCACertConfig())
trait.CACertificates = []traitv1.CACertConfig{
- {CertPath: "/path/to/ca.crt", PasswordPath: "/path/to/pass"},
+ {CertPath: "/path/to/ca.crt"},
}
+ trait.TruststorePasswordPath = "/path/to/truststore-pass"
+ trait.BaseTruststore = nil
assert.NoError(t, trait.validateCACertConfig())
trait.CACertificates = []traitv1.CACertConfig{
- {CertPath: "/path/to/ca.crt", PasswordPath: ""},
+ {CertPath: "/path/to/ca.crt"},
}
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = "/path/to/legacy.crt"
+ trait.CACertPassword = "/path/to/legacy-pass"
assert.Error(t, trait.validateCACertConfig())
+ assert.Contains(t, trait.validateCACertConfig().Error(), "truststore-password-path is required")
trait.CACertificates = nil
trait.CACert = "/path/to/ca.crt"
trait.CACertPassword = ""
+ trait.TruststorePasswordPath = ""
assert.Error(t, trait.validateCACertConfig())
trait.CACert = "/path/to/ca.crt"
@@ -923,3 +1004,221 @@ func TestValidateCACertConfig(t *testing.T) {
}
assert.NoError(t, trait.validateCACertConfig())
}
+
+func TestAllCACertScenarios(t *testing.T) {
+ t.Run("Scenario1_NothingConfigured", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = nil
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.False(t, trait.hasCACerts())
+ assert.Equal(t, "", trait.getTruststorePasswordPath())
+ })
+
+ t.Run("Scenario2_CACertificatesNoPassword", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/cert"},
+ }
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ assert.Equal(t, "", trait.getTruststorePasswordPath())
+ err := trait.validateCACertConfig()
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "truststore-password-path is required")
+ })
+
+ t.Run("Scenario3_CACertificatesWithTruststorePassword", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/cert"},
+ }
+ trait.TruststorePasswordPath = "/path/to/ts-pass"
+ trait.BaseTruststore = nil
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ assert.Equal(t, "/path/to/ts-pass", trait.getTruststorePasswordPath())
+ assert.NoError(t, trait.validateCACertConfig())
+ })
+
+ t.Run("Scenario4_CACertificatesWithBaseTruststore", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/cert"},
+ }
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ PasswordPath: "/path/to/base-pass",
+ }
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ assert.True(t, trait.hasBaseTruststore())
+ assert.Equal(t, "/path/to/base-pass", trait.getTruststorePasswordPath())
+ assert.NoError(t, trait.validateCACertConfig())
+ })
+
+ t.Run("Scenario5_AllPasswordSourcesTruststorePasswordWins", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/cert"},
+ }
+ trait.TruststorePasswordPath = "/path/to/ts-pass"
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ PasswordPath: "/path/to/base-pass",
+ }
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ assert.True(t, trait.hasBaseTruststore())
+ assert.Equal(t, "/path/to/ts-pass", trait.getTruststorePasswordPath())
+ assert.NoError(t, trait.validateCACertConfig())
+ })
+
+ t.Run("Scenario6_CACertificatesWithLegacyNoExplicitPassword", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/cert"},
+ }
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = "/path/to/legacy-cert"
+ trait.CACertPassword = "/path/to/legacy-pass"
+
+ assert.True(t, trait.hasCACerts())
+ assert.Equal(t, "/path/to/legacy-pass", trait.getTruststorePasswordPath())
+ err := trait.validateCACertConfig()
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "truststore-password-path is required")
+ })
+
+ t.Run("Scenario7_LegacyOnly", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = nil
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = "/path/to/legacy-cert"
+ trait.CACertPassword = "/path/to/legacy-pass"
+
+ assert.True(t, trait.hasCACerts())
+ assert.Equal(t, "/path/to/legacy-pass", trait.getTruststorePasswordPath())
+ assert.NoError(t, trait.validateCACertConfig())
+ })
+
+ t.Run("Scenario8_LegacyWithoutPassword", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = nil
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = "/path/to/legacy-cert"
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ assert.Equal(t, "", trait.getTruststorePasswordPath())
+ err := trait.validateCACertConfig()
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "ca-cert-password is required")
+ })
+
+ t.Run("Scenario9_BaseTruststoreOnlyNoCerts", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = nil
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ PasswordPath: "/path/to/base-pass",
+ }
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.False(t, trait.hasCACerts())
+ assert.True(t, trait.hasBaseTruststore())
+ assert.Equal(t, "/path/to/base-pass", trait.getTruststorePasswordPath())
+ assert.NoError(t, trait.validateCACertConfig())
+ })
+
+ t.Run("Scenario10_IncompleteBaseTruststoreWithTsPassword", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/cert"},
+ }
+ trait.TruststorePasswordPath = "/path/to/ts-pass"
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ PasswordPath: "",
+ }
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ assert.False(t, trait.hasBaseTruststore())
+ assert.Equal(t, "/path/to/ts-pass", trait.getTruststorePasswordPath())
+
+ err := trait.validateCACertConfig()
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "base-truststore: both truststore-path and password-path are required")
+ })
+
+ t.Run("Scenario11_IncompleteBaseTruststoreNoTsPassword", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: "/path/to/cert"},
+ }
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = &traitv1.BaseTruststore{
+ TruststorePath: "/path/to/cacerts",
+ PasswordPath: "",
+ }
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ assert.False(t, trait.hasBaseTruststore())
+ assert.Equal(t, "", trait.getTruststorePasswordPath())
+ err := trait.validateCACertConfig()
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "base-truststore: both truststore-path and password-path are required")
+ })
+
+ t.Run("Scenario12_EmptyCACertificatesArray", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{}
+ trait.TruststorePasswordPath = ""
+ trait.BaseTruststore = nil
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.False(t, trait.hasCACerts())
+ assert.Equal(t, "", trait.getTruststorePasswordPath())
+ assert.NoError(t, trait.validateCACertConfig())
+ })
+
+ t.Run("Scenario13_CACertificatesEntryMissingCertPath", func(t *testing.T) {
+ trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform)
+ trait.CACertificates = []traitv1.CACertConfig{
+ {CertPath: ""},
+ }
+ trait.TruststorePasswordPath = "/path/to/ts-pass"
+ trait.BaseTruststore = nil
+ trait.CACert = ""
+ trait.CACertPassword = ""
+
+ assert.True(t, trait.hasCACerts())
+ err := trait.validateCACertConfig()
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "cert-path is required")
+ })
+}