Skip to content

Commit 8bbd870

Browse files
committed
refactor: move truststore creation script to separate Java file
Move inline jshell script to a proper Java file (qtodo-truststore.java) loaded via ConfigMap. This improves code clarity and maintainability. Changes: - Add charts/qtodo/files/qtodo-truststore.java with proper Java class - Add truststore-script-configmap.yaml to load the Java file - Update app-deployment.yaml to use 'java /usr/local/bin/qtodo-truststore.java' - Update superlinter.yml to exclude the Java file from linting Suggested-by: Manuel Lorenzo <[email protected]> Signed-off-by: Min Zhang <[email protected]>
1 parent a3430d4 commit 8bbd870

File tree

4 files changed

+123
-58
lines changed

4 files changed

+123
-58
lines changed

.github/workflows/superlinter.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ jobs:
3232
DEFAULT_BRANCH: main
3333
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3434
# Exclude bash scripts with Helm templating (they contain {{ }} syntax)
35-
FILTER_REGEX_EXCLUDE: .*\.sh\.tpl$
35+
# Exclude qtodo-truststore.java (default package, no package-info.java needed)
36+
FILTER_REGEX_EXCLUDE: .*\.sh\.tpl$|.*qtodo-truststore\.java$
3637
# These are the validation we disable atm
3738
VALIDATE_ANSIBLE: false
3839
VALIDATE_BASH: false
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import java.io.FileInputStream;
2+
import java.io.FileOutputStream;
3+
import java.io.InputStream;
4+
import java.security.KeyStore;
5+
import java.security.cert.Certificate;
6+
import java.security.cert.CertificateFactory;
7+
import java.util.Collection;
8+
9+
/**
10+
* Utility class for importing CA certificates from a PEM bundle into a PKCS12
11+
* truststore.
12+
*/
13+
public final class QtodoTruststore {
14+
/** Conversion factor from milliseconds to seconds. */
15+
private static final double MILLISECONDS_TO_SECONDS = 1000.0;
16+
17+
private QtodoTruststore() {
18+
// Utility class - prevent instantiation
19+
}
20+
21+
/**
22+
* Main entry point for the truststore import utility.
23+
*
24+
* @param args Command line arguments (not used)
25+
* @throws Exception if certificate import fails
26+
*/
27+
public static void main(final String[] args) throws Exception {
28+
long startTime = System.currentTimeMillis();
29+
30+
// Get environment variables
31+
String bundlePath = System.getenv("CA_BUNDLE");
32+
String p12Path = System.getenv("TRUSTSTORE_PATH");
33+
String password = System.getenv("TRUSTSTORE_PASSWORD");
34+
35+
// Validate required environment variables
36+
boolean missingVars = false;
37+
if (bundlePath == null || bundlePath.isEmpty()) {
38+
System.err.println(
39+
"ERROR: CA_BUNDLE environment variable is not set");
40+
missingVars = true;
41+
}
42+
if (p12Path == null || p12Path.isEmpty()) {
43+
System.err.println(
44+
"ERROR: TRUSTSTORE_PATH environment variable is not set");
45+
missingVars = true;
46+
}
47+
if (password == null || password.isEmpty()) {
48+
System.err.println(
49+
"ERROR: TRUSTSTORE_PASSWORD environment variable "
50+
+ "is not set");
51+
missingVars = true;
52+
}
53+
54+
if (missingVars) {
55+
System.exit(1);
56+
}
57+
58+
System.out.println("Converting CA bundle to PKCS12 truststore...");
59+
System.out.println(" CA bundle: " + bundlePath);
60+
System.out.println(" Output: " + p12Path);
61+
62+
// Create empty PKCS12 keystore
63+
KeyStore keyStore = KeyStore.getInstance("PKCS12");
64+
keyStore.load(null, password.toCharArray());
65+
66+
// Load certificates from PEM bundle
67+
CertificateFactory certFactory =
68+
CertificateFactory.getInstance("X.509");
69+
Collection<? extends Certificate> certs;
70+
71+
try (InputStream fis = new FileInputStream(bundlePath)) {
72+
certs = certFactory.generateCertificates(fis);
73+
}
74+
75+
// Import each certificate
76+
int count = 0;
77+
for (Certificate cert : certs) {
78+
String alias = "ztvp-ca-" + String.format("%03d", count);
79+
keyStore.setCertificateEntry(alias, cert);
80+
count++;
81+
}
82+
83+
// Save the keystore
84+
try (FileOutputStream fos = new FileOutputStream(p12Path)) {
85+
keyStore.store(fos, password.toCharArray());
86+
}
87+
88+
long elapsed = System.currentTimeMillis() - startTime;
89+
System.out.println("Successfully imported " + count
90+
+ " certificates into PKCS12 truststore");
91+
System.out.println("Completed in "
92+
+ (elapsed / MILLISECONDS_TO_SECONDS) + " seconds");
93+
}
94+
}

charts/qtodo/templates/app-deployment.yaml

Lines changed: 11 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -33,64 +33,13 @@ spec:
3333
image: registry.redhat.io/ubi9/openjdk-17:latest
3434
imagePullPolicy: IfNotPresent
3535
command:
36-
- /bin/bash
37-
- -c
38-
- |
39-
set -e
40-
echo "Converting CA bundle to PKCS12 truststore using Java KeyStore API..."
41-
42-
# Validate password is provided
43-
if [ -z "$TRUSTSTORE_PASSWORD" ]; then
44-
echo "ERROR: TRUSTSTORE_PASSWORD not set"
45-
exit 1
46-
fi
47-
48-
CA_BUNDLE="/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"
49-
TRUSTSTORE_PATH="/run/secrets/truststore/truststore.p12"
50-
51-
# Verify CA bundle exists
52-
if [ ! -f "$CA_BUNDLE" ]; then
53-
echo "ERROR: CA bundle not found at $CA_BUNDLE"
54-
exit 1
55-
fi
56-
57-
# Count certificates in bundle
58-
CERT_COUNT=$(grep -c "BEGIN CERTIFICATE" "$CA_BUNDLE" || echo "0")
59-
echo "Found $CERT_COUNT certificates in CA bundle"
60-
61-
# Use jshell to bulk-import all certificates (single JVM, much faster than keytool loop)
62-
jshell -R-Dpassword="$TRUSTSTORE_PASSWORD" -R-Dbundle="$CA_BUNDLE" -R-Doutput="$TRUSTSTORE_PATH" <<'JSHELL'
63-
import java.security.*;
64-
import java.security.cert.*;
65-
import java.io.*;
66-
import java.nio.file.*;
67-
68-
String password = System.getProperty("password");
69-
String bundlePath = System.getProperty("bundle");
70-
String outputPath = System.getProperty("output");
71-
72-
KeyStore ks = KeyStore.getInstance("PKCS12");
73-
ks.load(null, password.toCharArray());
74-
75-
CertificateFactory cf = CertificateFactory.getInstance("X.509");
76-
byte[] pemBytes = Files.readAllBytes(Path.of(bundlePath));
77-
78-
var certs = cf.generateCertificates(new ByteArrayInputStream(pemBytes));
79-
int i = 0;
80-
for (var cert : certs) {
81-
ks.setCertificateEntry("ztvp-ca-" + String.format("%03d", i++), cert);
82-
}
83-
84-
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
85-
ks.store(fos, password.toCharArray());
86-
}
87-
System.out.println("Imported " + i + " certificates into PKCS12 truststore");
88-
/exit
89-
JSHELL
90-
91-
echo "Successfully created PKCS12 truststore"
92-
ls -lh "$TRUSTSTORE_PATH"
36+
- java
37+
- /usr/local/bin/qtodo-truststore.java
9338
env:
39+
- name: CA_BUNDLE
40+
value: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
41+
- name: TRUSTSTORE_PATH
42+
value: /run/secrets/truststore/truststore.p12
9443
- name: TRUSTSTORE_PASSWORD
9544
valueFrom:
9645
secretKeyRef:
@@ -102,6 +51,8 @@ spec:
10251
readOnly: true
10352
- name: truststore
10453
mountPath: /run/secrets/truststore
54+
- name: qtodo-truststore-java
55+
mountPath: /usr/local/bin
10556
- name: wait-for-keycloak
10657
image: registry.redhat.io/openshift4/ose-tools-rhel9:latest
10758
imagePullPolicy: IfNotPresent
@@ -335,4 +286,7 @@ spec:
335286
defaultMode: 420
336287
- name: truststore
337288
emptyDir: {}
289+
- name: qtodo-truststore-java
290+
configMap:
291+
name: qtodo-truststore-java
338292
{{- end }}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{{- if and .Values.app.spire.enabled .Values.app.truststore.enabled }}
2+
---
3+
apiVersion: v1
4+
kind: ConfigMap
5+
metadata:
6+
name: qtodo-truststore-java
7+
namespace: qtodo
8+
annotations:
9+
argocd.argoproj.io/sync-wave: '10'
10+
labels:
11+
app: qtodo
12+
app.kubernetes.io/component: truststore-init
13+
data:
14+
qtodo-truststore.java: |
15+
{{- .Files.Get "files/qtodo-truststore.java" | nindent 4 }}
16+
{{- end }}

0 commit comments

Comments
 (0)