Skip to content

Commit 8143b8a

Browse files
pkalsi97squakez
authored andcommitted
fix(jvm): secure JVM truststore password handling via secret reference
1 parent fdec425 commit 8143b8a

File tree

14 files changed

+290
-17
lines changed

14 files changed

+290
-17
lines changed

docs/modules/traits/pages/jvm.adoc

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ Example: "secret:my-ca-certs" or "secret:my-ca-certs/custom-ca.crt"
7272
| The path where the generated truststore will be mounted
7373
Default: "/etc/camel/conf.d/_truststore"
7474

75+
| jvm.ca-cert-password
76+
| string
77+
| **Required when ca-cert is set.** A secret reference containing the truststore password.
78+
If the secret key is not specified, "password" is used as the default key.
79+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
80+
7581
|===
7682

7783
// End of autogenerated code - DO NOT EDIT! (configuration)
@@ -116,22 +122,34 @@ First, create a Kubernetes Secret containing the CA certificate:
116122
kubectl create secret generic my-private-ca --from-file=ca.crt=/path/to/ca-certificate.pem
117123
----
118124

119-
Then reference the secret when running the integration:
125+
Next, create a Secret containing the truststore password:
126+
127+
[source,console]
128+
----
129+
kubectl create secret generic my-truststore-pwd --from-literal=password=mysecurepassword
130+
----
131+
132+
Then reference both secrets when running the integration:
120133

121134
[source,console]
122135
----
123-
$ kamel run MyRoute.java -t jvm.ca-cert=secret:my-private-ca
136+
$ kamel run MyRoute.java -t jvm.ca-cert=secret:my-private-ca -t jvm.ca-cert-password=secret:my-truststore-pwd
124137
----
125138

126139
If your certificate is stored under a different key in the secret:
127140

128141
[source,console]
129142
----
130-
$ kamel run MyRoute.java -t jvm.ca-cert=secret:my-private-ca/custom-ca.pem
143+
$ kamel run MyRoute.java -t jvm.ca-cert=secret:my-private-ca/custom-ca.pem -t jvm.ca-cert-password=secret:my-truststore-pwd
131144
----
132145

133146
This will automatically:
134147

135148
1. Mount the CA certificate secret
136149
2. Generate a JVM truststore using an init container
137150
3. Configure the JVM to use the generated truststore via `-Djavax.net.ssl.trustStore`
151+
4. Inject the truststore password securely as an environment variable from your secret
152+
153+
NOTE: The `ca-cert-password` option is **required** when using `ca-cert`. The password is never exposed in command-line arguments - it is injected as an environment variable from the secret.
154+
155+

e2e/common/traits/jvm_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,17 @@ func TestJVMTrait(t *testing.T) {
102102
err = CreatePlainTextSecret(t, ctx, ns, "test-ca-cert", caCertData)
103103
require.NoError(t, err)
104104

105+
passwordData := make(map[string]string)
106+
passwordData["password"] = "test-password-123"
107+
err = CreatePlainTextSecret(t, ctx, ns, "test-ca-password", passwordData)
108+
require.NoError(t, err)
109+
105110
name := RandomizedSuffixName("cacert")
106111
g.Expect(KamelRun(t, ctx, ns,
107112
"./files/Java.java",
108113
"--name", name,
109114
"-t", "jvm.ca-cert=secret:test-ca-cert",
115+
"-t", "jvm.ca-cert-password=secret:test-ca-password",
110116
).Execute()).To(Succeed())
111117

112118
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning))

helm/camel-k/crds/camel-k-crds.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4731,6 +4731,12 @@ spec:
47314731
The path where the generated truststore will be mounted
47324732
Default: "/etc/camel/conf.d/_truststore"
47334733
type: string
4734+
caCertPassword:
4735+
description: |-
4736+
Required when caCert is set. A secret reference containing the truststore password.
4737+
If the secret key is not specified, "password" is used as the default key.
4738+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
4739+
type: string
47344740
classpath:
47354741
description: Additional JVM classpath (use `Linux` classpath
47364742
separator)
@@ -7134,6 +7140,12 @@ spec:
71347140
The path where the generated truststore will be mounted
71357141
Default: "/etc/camel/conf.d/_truststore"
71367142
type: string
7143+
caCertPassword:
7144+
description: |-
7145+
Required when caCert is set. A secret reference containing the truststore password.
7146+
If the secret key is not specified, "password" is used as the default key.
7147+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
7148+
type: string
71377149
classpath:
71387150
description: Additional JVM classpath (use `Linux` classpath
71397151
separator)
@@ -9439,6 +9451,12 @@ spec:
94399451
The path where the generated truststore will be mounted
94409452
Default: "/etc/camel/conf.d/_truststore"
94419453
type: string
9454+
caCertPassword:
9455+
description: |-
9456+
Required when caCert is set. A secret reference containing the truststore password.
9457+
If the secret key is not specified, "password" is used as the default key.
9458+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
9459+
type: string
94429460
classpath:
94439461
description: Additional JVM classpath (use `Linux` classpath
94449462
separator)
@@ -11721,6 +11739,12 @@ spec:
1172111739
The path where the generated truststore will be mounted
1172211740
Default: "/etc/camel/conf.d/_truststore"
1172311741
type: string
11742+
caCertPassword:
11743+
description: |-
11744+
Required when caCert is set. A secret reference containing the truststore password.
11745+
If the secret key is not specified, "password" is used as the default key.
11746+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
11747+
type: string
1172411748
classpath:
1172511749
description: Additional JVM classpath (use `Linux` classpath
1172611750
separator)
@@ -20837,6 +20861,12 @@ spec:
2083720861
The path where the generated truststore will be mounted
2083820862
Default: "/etc/camel/conf.d/_truststore"
2083920863
type: string
20864+
caCertPassword:
20865+
description: |-
20866+
Required when caCert is set. A secret reference containing the truststore password.
20867+
If the secret key is not specified, "password" is used as the default key.
20868+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
20869+
type: string
2084020870
classpath:
2084120871
description: Additional JVM classpath (use `Linux` classpath
2084220872
separator)
@@ -23073,6 +23103,12 @@ spec:
2307323103
The path where the generated truststore will be mounted
2307423104
Default: "/etc/camel/conf.d/_truststore"
2307523105
type: string
23106+
caCertPassword:
23107+
description: |-
23108+
Required when caCert is set. A secret reference containing the truststore password.
23109+
If the secret key is not specified, "password" is used as the default key.
23110+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
23111+
type: string
2307623112
classpath:
2307723113
description: Additional JVM classpath (use `Linux` classpath
2307823114
separator)
@@ -33551,6 +33587,12 @@ spec:
3355133587
The path where the generated truststore will be mounted
3355233588
Default: "/etc/camel/conf.d/_truststore"
3355333589
type: string
33590+
caCertPassword:
33591+
description: |-
33592+
Required when caCert is set. A secret reference containing the truststore password.
33593+
If the secret key is not specified, "password" is used as the default key.
33594+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
33595+
type: string
3355433596
classpath:
3355533597
description: Additional JVM classpath (use `Linux` classpath
3355633598
separator)
@@ -35719,6 +35761,12 @@ spec:
3571935761
The path where the generated truststore will be mounted
3572035762
Default: "/etc/camel/conf.d/_truststore"
3572135763
type: string
35764+
caCertPassword:
35765+
description: |-
35766+
Required when caCert is set. A secret reference containing the truststore password.
35767+
If the secret key is not specified, "password" is used as the default key.
35768+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
35769+
type: string
3572235770
classpath:
3572335771
description: Additional JVM classpath (use `Linux` classpath
3572435772
separator)

pkg/apis/camel/v1/trait/jvm.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,8 @@ type JVMTrait struct {
4848
// The path where the generated truststore will be mounted
4949
// Default: "/etc/camel/conf.d/_truststore"
5050
CACertMountPath string `json:"caCertMountPath,omitempty" property:"ca-cert-mount-path"`
51+
// Required when caCert is set. A secret reference containing the truststore password.
52+
// If the secret key is not specified, "password" is used as the default key.
53+
// Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
54+
CACertPassword string `json:"caCertPassword,omitempty" property:"ca-cert-password"`
5155
}

pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,12 @@ spec:
14821482
The path where the generated truststore will be mounted
14831483
Default: "/etc/camel/conf.d/_truststore"
14841484
type: string
1485+
caCertPassword:
1486+
description: |-
1487+
Required when caCert is set. A secret reference containing the truststore password.
1488+
If the secret key is not specified, "password" is used as the default key.
1489+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
1490+
type: string
14851491
classpath:
14861492
description: Additional JVM classpath (use `Linux` classpath
14871493
separator)
@@ -3885,6 +3891,12 @@ spec:
38853891
The path where the generated truststore will be mounted
38863892
Default: "/etc/camel/conf.d/_truststore"
38873893
type: string
3894+
caCertPassword:
3895+
description: |-
3896+
Required when caCert is set. A secret reference containing the truststore password.
3897+
If the secret key is not specified, "password" is used as the default key.
3898+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
3899+
type: string
38883900
classpath:
38893901
description: Additional JVM classpath (use `Linux` classpath
38903902
separator)

pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,12 @@ spec:
13501350
The path where the generated truststore will be mounted
13511351
Default: "/etc/camel/conf.d/_truststore"
13521352
type: string
1353+
caCertPassword:
1354+
description: |-
1355+
Required when caCert is set. A secret reference containing the truststore password.
1356+
If the secret key is not specified, "password" is used as the default key.
1357+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
1358+
type: string
13531359
classpath:
13541360
description: Additional JVM classpath (use `Linux` classpath
13551361
separator)
@@ -3632,6 +3638,12 @@ spec:
36323638
The path where the generated truststore will be mounted
36333639
Default: "/etc/camel/conf.d/_truststore"
36343640
type: string
3641+
caCertPassword:
3642+
description: |-
3643+
Required when caCert is set. A secret reference containing the truststore password.
3644+
If the secret key is not specified, "password" is used as the default key.
3645+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
3646+
type: string
36353647
classpath:
36363648
description: Additional JVM classpath (use `Linux` classpath
36373649
separator)

pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8164,6 +8164,12 @@ spec:
81648164
The path where the generated truststore will be mounted
81658165
Default: "/etc/camel/conf.d/_truststore"
81668166
type: string
8167+
caCertPassword:
8168+
description: |-
8169+
Required when caCert is set. A secret reference containing the truststore password.
8170+
If the secret key is not specified, "password" is used as the default key.
8171+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
8172+
type: string
81678173
classpath:
81688174
description: Additional JVM classpath (use `Linux` classpath
81698175
separator)
@@ -10400,6 +10406,12 @@ spec:
1040010406
The path where the generated truststore will be mounted
1040110407
Default: "/etc/camel/conf.d/_truststore"
1040210408
type: string
10409+
caCertPassword:
10410+
description: |-
10411+
Required when caCert is set. A secret reference containing the truststore password.
10412+
If the secret key is not specified, "password" is used as the default key.
10413+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
10414+
type: string
1040310415
classpath:
1040410416
description: Additional JVM classpath (use `Linux` classpath
1040510417
separator)

pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8220,6 +8220,12 @@ spec:
82208220
The path where the generated truststore will be mounted
82218221
Default: "/etc/camel/conf.d/_truststore"
82228222
type: string
8223+
caCertPassword:
8224+
description: |-
8225+
Required when caCert is set. A secret reference containing the truststore password.
8226+
If the secret key is not specified, "password" is used as the default key.
8227+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
8228+
type: string
82238229
classpath:
82248230
description: Additional JVM classpath (use `Linux` classpath
82258231
separator)
@@ -10388,6 +10394,12 @@ spec:
1038810394
The path where the generated truststore will be mounted
1038910395
Default: "/etc/camel/conf.d/_truststore"
1039010396
type: string
10397+
caCertPassword:
10398+
description: |-
10399+
Required when caCert is set. A secret reference containing the truststore password.
10400+
If the secret key is not specified, "password" is used as the default key.
10401+
Example: "secret:my-truststore-password" or "secret:my-truststore-password/mykey"
10402+
type: string
1039110403
classpath:
1039210404
description: Additional JVM classpath (use `Linux` classpath
1039310405
separator)

pkg/trait/init_containers.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type containerTask struct {
4242
image string
4343
command string
4444
isSidecar bool
45+
env []corev1.EnvVar
4546
}
4647

4748
type initContainersTrait struct {
@@ -100,14 +101,20 @@ func (t *initContainersTrait) Configure(e *Environment) (bool, *TraitCondition,
100101
secretKey = "ca.crt"
101102
}
102103

104+
secretName, secretKey2, err := jvm.getTrustStorePasswordSecretRef()
105+
if err != nil {
106+
return false, nil, err
107+
}
108+
103109
keytoolCmd := fmt.Sprintf(
104-
"keytool -importcert -noprompt -alias custom-ca -storepass %s -keystore %s -file /etc/secrets/cacert/%s",
105-
getTrustStorePassword(e.Integration.Name), jvm.getTrustStorePath(), secretKey,
110+
"keytool -importcert -noprompt -alias custom-ca -storepass:env %s -keystore %s -file /etc/secrets/cacert/%s",
111+
truststorePasswordEnvVar, jvm.getTrustStorePath(), secretKey,
106112
)
107113
caCertTask := containerTask{
108114
name: "generate-truststore",
109115
image: defaults.BaseImage(),
110116
command: keytoolCmd,
117+
env: []corev1.EnvVar{getTrustStorePasswordEnvVar(secretName, secretKey2)},
111118
}
112119
t.tasks = append(t.tasks, caCertTask)
113120
}
@@ -156,6 +163,7 @@ func (t *initContainersTrait) configureContainers(containers *[]corev1.Container
156163
Name: task.name,
157164
Image: task.image,
158165
Command: splitContainerCommand(task.command),
166+
Env: task.env,
159167
}
160168
if task.isSidecar {
161169
initCont.RestartPolicy = ptr.To(corev1.ContainerRestartPolicyAlways)

pkg/trait/init_containers_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,8 @@ func TestApplyInitContainerWithCACert(t *testing.T) {
393393
Spec: v1.IntegrationSpec{
394394
Traits: v1.Traits{
395395
JVM: &trait.JVMTrait{
396-
CACert: "secret:my-ca-secret",
396+
CACert: "secret:my-ca-secret",
397+
CACertPassword: "secret:my-ca-password",
397398
},
398399
},
399400
},

0 commit comments

Comments
 (0)