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 0d3db56b5c2ec6bd785dd212a84cd5c143dbcfdc Author: Pranjul Kalsi <[email protected]> AuthorDate: Tue Jan 13 15:47:42 2026 +0530 feat(jvm): Add multi-certificate and system truststore support for CA certs --- docs/modules/ROOT/partials/apis/camel-k-crds.adoc | 23 +- docs/modules/traits/pages/jvm.adoc | 17 +- e2e/common/traits/jvm_test.go | 115 +++++++++- helm/camel-k/crds/camel-k-crds.yaml | 168 +++++++++++---- pkg/apis/camel/v1/trait/jvm.go | 13 +- pkg/apis/camel/v1/trait/zz_generated.deepcopy.go | 10 + .../camel.apache.org_integrationplatforms.yaml | 42 +++- .../camel.apache.org_integrationprofiles.yaml | 42 +++- .../crd/bases/camel.apache.org_integrations.yaml | 42 +++- .../config/crd/bases/camel.apache.org_pipes.yaml | 42 +++- pkg/trait/init_containers.go | 48 ++++- pkg/trait/init_containers_test.go | 234 +++++++++++++++++++++ pkg/trait/jvm_cacert.go | 67 ++++-- pkg/trait/jvm_test.go | 107 ++++++++-- pkg/trait/mount.go | 2 +- 15 files changed, 833 insertions(+), 139 deletions(-) diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc index 5d2e88a33..d1effbd3a 100644 --- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc +++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc @@ -7836,13 +7836,20 @@ The Jar dependency which will run the application. Leave it empty for managed In A list of JVM agents to download and execute with format `<agent-name>;<agent-url>[;<jvm-agent-options>]`. +|`caCerts` + +[]string +| + + +A list of paths to PEM-encoded CA certificates to import into the truststore. +Certificates must be mounted via the mount trait. + |`caCert` + string | -Path to a PEM-encoded CA certificate file. -Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" +Path to a PEM-encoded CA certificate file. Use CACerts for multiple certificates. |`caCertMountPath` + string @@ -7857,8 +7864,16 @@ string | -Required when caCert is set. Path to a file containing the truststore password. -Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" +Path to a custom truststore password file. +Default: uses "changeit" if not specified. + +|`caCertUseSystemTruststore` + +bool +| + + +If true, the JDK's default cacerts is copied as the base truststore. +Default: false (empty truststore). |=== diff --git a/docs/modules/traits/pages/jvm.adoc b/docs/modules/traits/pages/jvm.adoc index c3300594f..39a7f7641 100755 --- a/docs/modules/traits/pages/jvm.adoc +++ b/docs/modules/traits/pages/jvm.adoc @@ -63,10 +63,14 @@ Deprecated: no longer in use. | []string | A list of JVM agents to download and execute with format `<agent-name>;<agent-url>[;<jvm-agent-options>]`. +| jvm.ca-certs +| []string +| A list of paths to PEM-encoded CA certificates to import into the truststore. +Certificates must be mounted via the mount trait. + | jvm.ca-cert | string -| Path to a PEM-encoded CA certificate file. -Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" +| Path to a PEM-encoded CA certificate file. Use CACerts for multiple certificates. | jvm.ca-cert-mount-path | string @@ -75,8 +79,13 @@ Default: "/etc/camel/conf.d/_truststore" | jvm.ca-cert-password | string -| Required when caCert is set. Path to a file containing the truststore password. -Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" +| Path to a custom truststore password file. +Default: uses "changeit" if not specified. + +| jvm.ca-cert-use-system-truststore +| bool +| If true, the JDK's default cacerts is copied as the base truststore. +Default: false (empty truststore). |=== diff --git a/e2e/common/traits/jvm_test.go b/e2e/common/traits/jvm_test.go index 6e143b98b..f2a8fc5ea 100644 --- a/e2e/common/traits/jvm_test.go +++ b/e2e/common/traits/jvm_test.go @@ -120,7 +120,120 @@ func TestJVMTrait(t *testing.T) { 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)) - // Verify init container was added + 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) { + // Generate two valid self-signed certificates + cert1Pem, err := generateSelfSignedCert() + require.NoError(t, err) + cert2Pem, err := generateSelfSignedCert() + require.NoError(t, err) + + caCert1Data := make(map[string]string) + caCert1Data["ca.crt"] = string(cert1Pem) + err = CreatePlainTextSecret(t, ctx, ns, "test-ca-cert-1", caCert1Data) + require.NoError(t, err) + + caCert2Data := make(map[string]string) + caCert2Data["ca.crt"] = string(cert2Pem) + err = CreatePlainTextSecret(t, ctx, ns, "test-ca-cert-2", caCert2Data) + require.NoError(t, err) + + passwordData := make(map[string]string) + passwordData["password"] = "test-password-123" + err = CreatePlainTextSecret(t, ctx, ns, "test-multi-ca-password", passwordData) + 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", + "-t", "mount.configs=secret:test-multi-ca-password", + "-t", "jvm.ca-certs=/etc/camel/conf.d/_secrets/test-ca-cert-1/ca.crt", + "-t", "jvm.ca-certs=/etc/camel/conf.d/_secrets/test-ca-cert-2/ca.crt", + "-t", "jvm.ca-cert-password=/etc/camel/conf.d/_secrets/test-multi-ca-password/password", + ).Execute()).To(Succeed()) + + g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong*2).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 CA cert with system truststore", func(t *testing.T) { + // Generate a valid self-signed certificate + certPem, err := generateSelfSignedCert() + require.NoError(t, err) + + caCertData := make(map[string]string) + caCertData["ca.crt"] = string(certPem) + err = CreatePlainTextSecret(t, ctx, ns, "test-ca-sys", caCertData) + require.NoError(t, err) + + passwordData := make(map[string]string) + passwordData["password"] = "test-password-456" + err = CreatePlainTextSecret(t, ctx, ns, "test-ca-sys-password", passwordData) + require.NoError(t, err) + + name := RandomizedSuffixName("syscacert") + g.Expect(KamelRun(t, ctx, ns, + "./files/Java.java", + "--name", name, + "-t", "mount.configs=secret:test-ca-sys", + "-t", "mount.configs=secret:test-ca-sys-password", + "-t", "jvm.ca-certs=/etc/camel/conf.d/_secrets/test-ca-sys/ca.crt", + "-t", "jvm.ca-cert-password=/etc/camel/conf.d/_secrets/test-ca-sys-password/password", + "-t", "jvm.ca-cert-use-system-truststore=true", + ).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 CA cert with default password", 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-default-pass", caCertData) + require.NoError(t, err) + + // Note: No password secret is provided, will use default "changeit" + name := RandomizedSuffixName("defaultpass") + g.Expect(KamelRun(t, ctx, ns, + "./files/Java.java", + "--name", name, + "-t", "mount.configs=secret:test-ca-default-pass", + "-t", "jvm.ca-certs=/etc/camel/conf.d/_secrets/test-ca-default-pass/ca.crt", + ).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) diff --git a/helm/camel-k/crds/camel-k-crds.yaml b/helm/camel-k/crds/camel-k-crds.yaml index 301bbb9c0..1bdcfb2ab 100644 --- a/helm/camel-k/crds/camel-k-crds.yaml +++ b/helm/camel-k/crds/camel-k-crds.yaml @@ -4776,9 +4776,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -4787,9 +4786,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -7258,9 +7269,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -7269,9 +7279,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -9640,9 +9662,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -9651,9 +9672,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -11999,9 +12032,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -12010,9 +12042,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -21216,9 +21260,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -21227,9 +21270,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -23531,9 +23586,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -23542,9 +23596,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -34112,9 +34178,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. + Use CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -34123,9 +34188,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -36357,9 +36434,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -36368,9 +36444,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) diff --git a/pkg/apis/camel/v1/trait/jvm.go b/pkg/apis/camel/v1/trait/jvm.go index 6ce82cab6..232205e1d 100644 --- a/pkg/apis/camel/v1/trait/jvm.go +++ b/pkg/apis/camel/v1/trait/jvm.go @@ -45,13 +45,18 @@ type JVMTrait struct { Jar string `json:"jar,omitempty" property:"jar"` // A list of JVM agents to download and execute with format `<agent-name>;<agent-url>[;<jvm-agent-options>]`. Agents []string `json:"agents,omitempty" property:"agents"` - // Path to a PEM-encoded CA certificate file. - // Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + // A list of paths to PEM-encoded CA certificates to import into the truststore. + // Certificates must be mounted via the mount trait. + CACerts []string `json:"caCerts,omitempty" property:"ca-certs"` + // Path to a PEM-encoded CA certificate file. Use CACerts for multiple certificates. CACert string `json:"caCert,omitempty" property:"ca-cert"` // 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"` - // Required when caCert is set. Path to a file containing the truststore password. - // Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + // Path to a custom truststore password file. + // Default: uses "changeit" if not specified. CACertPassword string `json:"caCertPassword,omitempty" property:"ca-cert-password"` + // If true, the JDK's default cacerts is copied as the base truststore. + // Default: false (empty truststore). + CACertUseSystemTruststore *bool `json:"caCertUseSystemTruststore,omitempty" property:"ca-cert-use-system-truststore"` } diff --git a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go index 24cd6c132..ed7752e52 100644 --- a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go @@ -581,6 +581,16 @@ func (in *JVMTrait) DeepCopyInto(out *JVMTrait) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.CACerts != nil { + in, out := &in.CACerts, &out.CACerts + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.CACertUseSystemTruststore != nil { + in, out := &in.CACertUseSystemTruststore, &out.CACertUseSystemTruststore + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JVMTrait. 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 79c2711be..3308ff925 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml @@ -1502,9 +1502,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -1513,9 +1512,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -3984,9 +3995,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -3995,9 +4005,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) 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 a41a34546..1db55503a 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml @@ -1368,9 +1368,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -1379,9 +1378,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -3727,9 +3738,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -3738,9 +3748,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) 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 bb1aebbb0..4adf8f7fe 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml @@ -8206,9 +8206,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -8217,9 +8216,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -10521,9 +10532,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -10532,9 +10542,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) 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 b2325b12c..c325d43c1 100644 --- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml +++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml @@ -8262,9 +8262,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. + Use CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -8273,9 +8272,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) @@ -10507,9 +10518,8 @@ spec: type: string type: array caCert: - description: |- - Path to a PEM-encoded CA certificate file. - Example: "/etc/camel/conf.d/_secrets/my-ca/ca.crt" + description: Path to a PEM-encoded CA certificate file. Use + CACerts for multiple certificates. type: string caCertMountPath: description: |- @@ -10518,9 +10528,21 @@ spec: type: string caCertPassword: description: |- - Required when caCert is set. Path to a file containing the truststore password. - Example: "/etc/camel/conf.d/_secrets/truststore-pass/password" + Path to a custom truststore password file. + Default: uses "changeit" if not specified. type: string + caCertUseSystemTruststore: + description: |- + If true, the JDK's default cacerts is copied as the base truststore. + Default: false (empty truststore). + type: boolean + caCerts: + description: |- + A list of paths to PEM-encoded CA certificates to import into the truststore. + Certificates must be mounted via the mount trait. + items: + type: string + type: array classpath: description: Additional JVM classpath (use `Linux` classpath separator) diff --git a/pkg/trait/init_containers.go b/pkg/trait/init_containers.go index 574a1da18..1654b9afe 100644 --- a/pkg/trait/init_containers.go +++ b/pkg/trait/init_containers.go @@ -92,19 +92,49 @@ 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.hasCACert() { - if err := jvm.validateCACertConfig(); err != nil { - return false, nil, err + if ok && jvm.hasCACerts() { + var allCommands []string + effectivePassword := jvm.getEffectiveTruststorePassword() + + if jvm.useSystemTruststore() { + copyCmd := fmt.Sprintf("cp %s %s", jdkCacertsPath, jvm.getTrustStorePath()) + allCommands = append(allCommands, copyCmd) + + if jvm.hasCustomPassword() { + changePassCmd := fmt.Sprintf( + "keytool -storepasswd -keystore %s -storepass %s -new %s", + jvm.getTrustStorePath(), jdkCacertsDefaultPassword, effectivePassword, + ) + allCommands = append(allCommands, changePassCmd) + } + } + + certPaths := jvm.getAllCACertPaths() + for i, certPath := range certPaths { + var cmd string + if jvm.hasCustomPassword() { + cmd = fmt.Sprintf( + "keytool -importcert -noprompt -alias custom-ca-%d -storepass:file %s -keystore %s -file %s", + i, jvm.getCACertPasswordPath(), jvm.getTrustStorePath(), certPath, + ) + } else { + cmd = fmt.Sprintf( + "keytool -importcert -noprompt -alias custom-ca-%d -storepass %s -keystore %s -file %s", + i, jdkCacertsDefaultPassword, jvm.getTrustStorePath(), certPath, + ) + } + allCommands = append(allCommands, cmd) + } + + fullCommand := strings.Join(allCommands, " && ") + // Wrap in bash shell when there are multiple commands or shell features are used + if len(allCommands) > 1 || jvm.useSystemTruststore() { + fullCommand = fmt.Sprintf("/bin/bash -c \"%s\"", fullCommand) } - // keytool reads password from file using -storepass:file - keytoolCmd := fmt.Sprintf( - "keytool -importcert -noprompt -alias custom-ca -storepass:file %s -keystore %s -file %s", - jvm.getCACertPasswordPath(), jvm.getTrustStorePath(), jvm.getCACertPath(), - ) caCertTask := containerTask{ name: "generate-truststore", image: defaults.BaseImage(), - command: keytoolCmd, + command: fullCommand, } t.tasks = append(t.tasks, caCertTask) } diff --git a/pkg/trait/init_containers_test.go b/pkg/trait/init_containers_test.go index afad65841..9fef79054 100644 --- a/pkg/trait/init_containers_test.go +++ b/pkg/trait/init_containers_test.go @@ -18,6 +18,7 @@ limitations under the License. package trait import ( + "strings" "testing" v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1" @@ -432,3 +433,236 @@ func TestApplyInitContainerWithCACert(t *testing.T) { assert.Contains(t, initContainer.Command[0], "keytool") } + +func TestApplyInitContainerWithMultipleCACerts(t *testing.T) { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-it", + Labels: map[string]string{ + v1.IntegrationLabel: "my-it", + }, + }, + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{}, + }, + }, + } + catalog, _ := camel.DefaultCatalog() + traitCatalog := NewCatalog(nil) + fakeClient, _ := internal.NewFakeClient(deployment) + environment := Environment{ + Client: fakeClient, + CamelCatalog: catalog, + Catalog: traitCatalog, + Resources: kubernetes.NewCollection(), + Integration: &v1.Integration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-it", + }, + Spec: v1.IntegrationSpec{ + Traits: v1.Traits{ + JVM: &trait.JVMTrait{ + CACerts: []string{ + "/etc/camel/conf.d/_secrets/ca1/ca.crt", + "/etc/camel/conf.d/_secrets/ca2/ca.crt", + "/etc/camel/conf.d/_secrets/ca3/ca.crt", + }, + CACertPassword: "/etc/camel/conf.d/_secrets/truststore-pass/password", + }, + }, + }, + Status: v1.IntegrationStatus{ + Phase: v1.IntegrationPhaseRunning, + }, + }, + Platform: &v1.IntegrationPlatform{ + Spec: v1.IntegrationPlatformSpec{ + Cluster: v1.IntegrationPlatformClusterOpenShift, + Build: v1.IntegrationPlatformBuildSpec{ + PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyJib, + Registry: v1.RegistrySpec{Address: "registry"}, + RuntimeVersion: catalog.Runtime.Version, + }, + }, + Status: v1.IntegrationPlatformStatus{ + Phase: v1.IntegrationPlatformPhaseReady, + }, + }, + } + environment.Resources.Add(deployment) + environment.Platform.ResyncStatusFullConfig() + _, _, err := traitCatalog.apply(&environment) + + require.NoError(t, err) + + deploy := environment.Resources.GetDeploymentForIntegration(environment.Integration) + require.NotNil(t, deploy) + + require.Len(t, deploy.Spec.Template.Spec.InitContainers, 1) + initContainer := deploy.Spec.Template.Spec.InitContainers[0] + assert.Equal(t, "generate-truststore", initContainer.Name) + assert.Equal(t, defaults.BaseImage(), initContainer.Image) + + commandStr := strings.Join(initContainer.Command, " ") + assert.Contains(t, commandStr, "/bin/bash") + assert.Contains(t, commandStr, "keytool") + assert.Contains(t, commandStr, "custom-ca-0") + assert.Contains(t, commandStr, "custom-ca-1") + assert.Contains(t, commandStr, "custom-ca-2") + assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/ca1/ca.crt") + assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/ca2/ca.crt") + assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/ca3/ca.crt") + assert.Contains(t, commandStr, "&&") +} + +func TestApplyInitContainerWithCACertsBackwardCompatibility(t *testing.T) { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-it", + Labels: map[string]string{ + v1.IntegrationLabel: "my-it", + }, + }, + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{}, + }, + }, + } + catalog, _ := camel.DefaultCatalog() + traitCatalog := NewCatalog(nil) + fakeClient, _ := internal.NewFakeClient(deployment) + environment := Environment{ + Client: fakeClient, + CamelCatalog: catalog, + Catalog: traitCatalog, + Resources: kubernetes.NewCollection(), + Integration: &v1.Integration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-it", + }, + Spec: v1.IntegrationSpec{ + Traits: v1.Traits{ + JVM: &trait.JVMTrait{ + CACerts: []string{ + "/etc/camel/conf.d/_secrets/ca1/ca.crt", + }, + CACert: "/etc/camel/conf.d/_secrets/ca2/ca.crt", + CACertPassword: "/etc/camel/conf.d/_secrets/truststore-pass/password", + }, + }, + }, + Status: v1.IntegrationStatus{ + Phase: v1.IntegrationPhaseRunning, + }, + }, + Platform: &v1.IntegrationPlatform{ + Spec: v1.IntegrationPlatformSpec{ + Cluster: v1.IntegrationPlatformClusterOpenShift, + Build: v1.IntegrationPlatformBuildSpec{ + PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyJib, + Registry: v1.RegistrySpec{Address: "registry"}, + RuntimeVersion: catalog.Runtime.Version, + }, + }, + Status: v1.IntegrationPlatformStatus{ + Phase: v1.IntegrationPlatformPhaseReady, + }, + }, + } + environment.Resources.Add(deployment) + environment.Platform.ResyncStatusFullConfig() + _, _, err := traitCatalog.apply(&environment) + + require.NoError(t, err) + + deploy := environment.Resources.GetDeploymentForIntegration(environment.Integration) + require.NotNil(t, deploy) + + require.Len(t, deploy.Spec.Template.Spec.InitContainers, 1) + initContainer := deploy.Spec.Template.Spec.InitContainers[0] + + commandStr := strings.Join(initContainer.Command, " ") + assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/ca1/ca.crt") + assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/ca2/ca.crt") +} + +func TestApplyInitContainerWithSystemTruststore(t *testing.T) { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-it", + Labels: map[string]string{ + v1.IntegrationLabel: "my-it", + }, + }, + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{}, + }, + }, + } + catalog, _ := camel.DefaultCatalog() + traitCatalog := NewCatalog(nil) + fakeClient, _ := internal.NewFakeClient(deployment) + environment := Environment{ + Client: fakeClient, + CamelCatalog: catalog, + Catalog: traitCatalog, + Resources: kubernetes.NewCollection(), + Integration: &v1.Integration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-it", + }, + Spec: v1.IntegrationSpec{ + Traits: v1.Traits{ + JVM: &trait.JVMTrait{ + CACerts: []string{ + "/etc/camel/conf.d/_secrets/my-ca/ca.crt", + }, + CACertPassword: "/etc/camel/conf.d/_secrets/truststore-pass/password", + CACertUseSystemTruststore: ptr.To(true), + }, + }, + }, + Status: v1.IntegrationStatus{ + Phase: v1.IntegrationPhaseRunning, + }, + }, + Platform: &v1.IntegrationPlatform{ + Spec: v1.IntegrationPlatformSpec{ + Cluster: v1.IntegrationPlatformClusterOpenShift, + Build: v1.IntegrationPlatformBuildSpec{ + PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyJib, + Registry: v1.RegistrySpec{Address: "registry"}, + RuntimeVersion: catalog.Runtime.Version, + }, + }, + Status: v1.IntegrationPlatformStatus{ + Phase: v1.IntegrationPlatformPhaseReady, + }, + }, + } + environment.Resources.Add(deployment) + environment.Platform.ResyncStatusFullConfig() + _, _, err := traitCatalog.apply(&environment) + + require.NoError(t, err) + + deploy := environment.Resources.GetDeploymentForIntegration(environment.Integration) + require.NotNil(t, deploy) + + require.Len(t, deploy.Spec.Template.Spec.InitContainers, 1) + initContainer := deploy.Spec.Template.Spec.InitContainers[0] + assert.Equal(t, "generate-truststore", initContainer.Name) + + commandStr := strings.Join(initContainer.Command, " ") + assert.Contains(t, commandStr, "/bin/bash") + + assert.Contains(t, commandStr, "cp $JAVA_HOME/lib/security/cacerts") + assert.Contains(t, commandStr, "keytool -storepasswd") + assert.Contains(t, commandStr, "-storepass changeit") + assert.Contains(t, commandStr, "keytool -importcert") + assert.Contains(t, commandStr, "/etc/camel/conf.d/_secrets/my-ca/ca.crt") + assert.Contains(t, commandStr, "&&") +} diff --git a/pkg/trait/jvm_cacert.go b/pkg/trait/jvm_cacert.go index 7d11f678e..87ecd4cdd 100644 --- a/pkg/trait/jvm_cacert.go +++ b/pkg/trait/jvm_cacert.go @@ -17,17 +17,22 @@ limitations under the License. package trait -import "errors" +import ( + "k8s.io/utils/ptr" +) const ( - defaultCACertMountPath = "/etc/camel/conf.d/_truststore" - caCertVolumeName = "jvm-truststore" - trustStoreName = "truststore.jks" - truststorePasswordEnvVar = "TRUSTSTORE_PASSWORD" + defaultCACertMountPath = "/etc/camel/conf.d/_truststore" + caCertVolumeName = "jvm-truststore" + trustStoreName = "truststore.jks" + truststorePasswordEnvVar = "TRUSTSTORE_PASSWORD" + jdkCacertsPath = "$JAVA_HOME/lib/security/cacerts" + jdkCacertsDefaultPassword = "changeit" ) -func (t *jvmTrait) hasCACert() bool { - return t.CACert != "" +// hasCACerts returns true if any CA certificates are configured (either via CACerts array or CACert). +func (t *jvmTrait) hasCACerts() bool { + return len(t.CACerts) > 0 || t.CACert != "" } func (t *jvmTrait) getCACertMountPath() string { @@ -42,24 +47,50 @@ func (t *jvmTrait) getTrustStorePath() string { return t.getCACertMountPath() + "/" + trustStoreName } -// validateCACertConfig validates that the required file paths are provided. -func (t *jvmTrait) validateCACertConfig() error { - if t.CACert == "" { - return nil - } - if t.CACertPassword == "" { - return errors.New("ca-cert-password is required when ca-cert is set") +// hasCustomPassword returns true if a custom password file path is provided. +func (t *jvmTrait) hasCustomPassword() bool { + return t.CACertPassword != "" +} + +// getEffectiveTruststorePassword returns the password for the truststore. +func (t *jvmTrait) getEffectiveTruststorePassword() string { + if t.hasCustomPassword() { + return "$(cat " + t.CACertPassword + ")" } - return nil + return jdkCacertsDefaultPassword } -// getCACertPath returns the user-provided CA certificate file path. -func (t *jvmTrait) getCACertPath() string { - return t.CACert +// getAllCACertPaths returns all configured CA certificate paths. +// It merges the CACert (if set) with the CACerts array. +func (t *jvmTrait) getAllCACertPaths() []string { + var paths []string + + paths = append(paths, t.CACerts...) + + if t.CACert != "" { + found := false + for _, p := range paths { + if p == t.CACert { + found = true + + break + } + } + if !found { + paths = append(paths, t.CACert) + } + } + + return paths } // getCACertPasswordPath returns the user-provided password file path. func (t *jvmTrait) getCACertPasswordPath() string { return t.CACertPassword } + +// useSystemTruststore returns true if JDK's default cacerts should be used as base. +func (t *jvmTrait) useSystemTruststore() bool { + return ptr.Deref(t.CACertUseSystemTruststore, false) +} diff --git a/pkg/trait/jvm_test.go b/pkg/trait/jvm_test.go index 7402d748a..f0290a530 100644 --- a/pkg/trait/jvm_test.go +++ b/pkg/trait/jvm_test.go @@ -752,24 +752,6 @@ func TestApplyJvmTraitWithCACert(t *testing.T) { assert.Contains(t, d.Spec.Template.Spec.Containers[0].Args, "-Djavax.net.ssl.trustStorePassword=$(TRUSTSTORE_PASSWORD)") } -func TestValidateCACertConfig(t *testing.T) { - trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform) - - trait.CACert = "" - err := trait.validateCACertConfig() - require.NoError(t, err) - - trait.CACert = "/etc/camel/conf.d/_secrets/my-ca/ca.crt" - trait.CACertPassword = "" - err = trait.validateCACertConfig() - require.Error(t, err) - assert.Contains(t, err.Error(), "ca-cert-password is required") - - trait.CACertPassword = "/etc/camel/conf.d/_secrets/truststore-pass/password" - err = trait.validateCACertConfig() - require.NoError(t, err) -} - func TestApplyJvmTraitWithCustomCACertMountPath(t *testing.T) { trait, environment := createNominalJvmTest(v1.IntegrationKitTypePlatform) trait.CACert = "/etc/camel/conf.d/_secrets/my-ca/ca.crt" @@ -802,3 +784,92 @@ func TestApplyJvmTraitWithCustomCACertMountPath(t *testing.T) { assert.Contains(t, d.Spec.Template.Spec.Containers[0].Args, "-Djavax.net.ssl.trustStore=/custom/truststore/path/truststore.jks") assert.Contains(t, d.Spec.Template.Spec.Containers[0].Args, "-Djavax.net.ssl.trustStorePassword=$(TRUSTSTORE_PASSWORD)") } + +func TestGetAllCACertPaths(t *testing.T) { + trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform) + + trait.CACerts = []string{"/path/to/ca1.crt", "/path/to/ca2.crt"} + trait.CACert = "" + paths := trait.getAllCACertPaths() + assert.Len(t, paths, 2) + assert.Contains(t, paths, "/path/to/ca1.crt") + assert.Contains(t, paths, "/path/to/ca2.crt") + + trait.CACerts = nil + trait.CACert = "/path/to/legacy.crt" + paths = trait.getAllCACertPaths() + assert.Len(t, paths, 1) + assert.Contains(t, paths, "/path/to/legacy.crt") + + trait.CACerts = []string{"/path/to/ca1.crt", "/path/to/ca2.crt"} + trait.CACert = "/path/to/ca3.crt" + paths = trait.getAllCACertPaths() + assert.Len(t, paths, 3) + assert.Contains(t, paths, "/path/to/ca1.crt") + assert.Contains(t, paths, "/path/to/ca2.crt") + assert.Contains(t, paths, "/path/to/ca3.crt") + + trait.CACerts = []string{"/path/to/ca1.crt"} + trait.CACert = "/path/to/ca1.crt" + paths = trait.getAllCACertPaths() + assert.Len(t, paths, 1) + assert.Contains(t, paths, "/path/to/ca1.crt") + + trait.CACerts = nil + trait.CACert = "" + paths = trait.getAllCACertPaths() + assert.Len(t, paths, 0) +} + +func TestHasCACerts(t *testing.T) { + trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform) + + trait.CACerts = nil + trait.CACert = "" + assert.False(t, trait.hasCACerts()) + + trait.CACerts = []string{"/path/to/ca1.crt"} + trait.CACert = "" + assert.True(t, trait.hasCACerts()) + + trait.CACerts = nil + trait.CACert = "/path/to/legacy.crt" + assert.True(t, trait.hasCACerts()) + + trait.CACerts = []string{"/path/to/ca1.crt"} + trait.CACert = "/path/to/ca2.crt" + assert.True(t, trait.hasCACerts()) +} + +func TestHasCustomPassword(t *testing.T) { + trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform) + + trait.CACertPassword = "" + assert.False(t, trait.hasCustomPassword()) + + trait.CACertPassword = "/path/to/password" + assert.True(t, trait.hasCustomPassword()) +} + +func TestGetEffectiveTruststorePassword(t *testing.T) { + trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform) + + trait.CACertPassword = "" + assert.Equal(t, "changeit", trait.getEffectiveTruststorePassword()) + + trait.CACertPassword = "/path/to/password" + assert.Equal(t, "$(cat /path/to/password)", trait.getEffectiveTruststorePassword()) +} + +func TestUseSystemTruststore(t *testing.T) { + trait, _ := createNominalJvmTest(v1.IntegrationKitTypePlatform) + + trait.CACertUseSystemTruststore = nil + assert.False(t, trait.useSystemTruststore()) + + trait.CACertUseSystemTruststore = ptr.To(false) + assert.False(t, trait.useSystemTruststore()) + + trait.CACertUseSystemTruststore = ptr.To(true) + assert.True(t, trait.useSystemTruststore()) +} diff --git a/pkg/trait/mount.go b/pkg/trait/mount.go index 3e25bad0f..4322df614 100644 --- a/pkg/trait/mount.go +++ b/pkg/trait/mount.go @@ -205,7 +205,7 @@ func (t *mountTrait) configureVolumesAndMounts( } // Mount CA cert truststore volume if configured - if ok && jvm.hasCACert() { + if ok && jvm.hasCACerts() { mountPath := jvm.getCACertMountPath() // EmptyDir volume for truststore output
