Skip to content

Commit d466fb0

Browse files
committed
generic bcfks script
Signed-off-by: Eric Bannon <eric.bannon4@gmail.com>
1 parent 055caeb commit d466fb0

1 file changed

Lines changed: 168 additions & 0 deletions

File tree

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#!/bin/sh
2+
set -euo pipefail
3+
4+
ts() { date -u +'%Y-%m-%dT%H:%M:%SZ'; }
5+
log() { echo "$(ts) $*"; }
6+
7+
# =============================================================================
8+
# Config (override via env)
9+
# =============================================================================
10+
OUT_DIR="${OUT_DIR:-/app/ssl}"
11+
TMP_DIR="${TMP_DIR:-/tmp/fips-ssl}"
12+
13+
TRUSTSTORE="${TRUSTSTORE:-${OUT_DIR}/truststore.bcfks}"
14+
KEYSTORE="${KEYSTORE:-${OUT_DIR}/keystore.bcfks}"
15+
16+
TRUSTSTORE_PASSWORD="${TRUSTSTORE_PASSWORD:-changeit}"
17+
KEYSTORE_PASSWORD="${KEYSTORE_PASSWORD:-changeit}"
18+
19+
BC_DIR="${BC_DIR:-/usr/share/java/bouncycastle-fips}"
20+
BC_JAR="${BC_JAR:-${BC_DIR}/bc-fips.jar}"
21+
22+
ENFORCE_APPROVED_ONLY="${ENFORCE_APPROVED_ONLY:-1}"
23+
24+
# Local identity (only needed if you want a server cert)
25+
SERVER_ALIAS="${SERVER_ALIAS:-server}"
26+
SERVER_DNAME="${SERVER_DNAME:-CN=localhost}"
27+
SERVER_SAN="${SERVER_SAN:-dns:localhost,ip:127.0.0.1}"
28+
29+
KEYALG="${KEYALG:-RSA}"
30+
KEYSIZE="${KEYSIZE:-2048}"
31+
VALIDITY_DAYS="${VALIDITY_DAYS:-825}"
32+
33+
# =============================================================================
34+
# Validate environment
35+
# =============================================================================
36+
command -v keytool >/dev/null || { log "ERROR: keytool not found"; exit 1; }
37+
[ -f "${BC_JAR}" ] || { log "ERROR: bc-fips.jar not found"; exit 1; }
38+
39+
mkdir -p "${OUT_DIR}" "${TMP_DIR}"
40+
41+
# =============================================================================
42+
# Locate JDK cacerts
43+
# =============================================================================
44+
find_cacerts() {
45+
for p in \
46+
"${JAVA_HOME:-}/lib/security/cacerts" \
47+
/usr/lib/jvm/default-jvm/lib/security/cacerts \
48+
/usr/lib/jvm/java-*/lib/security/cacerts \
49+
/etc/ssl/certs/java/cacerts; do
50+
[ -f "$p" ] && echo "$p" && return 0
51+
done
52+
return 1
53+
}
54+
55+
CACERTS="$(find_cacerts || true)"
56+
[ -n "${CACERTS}" ] || { log "ERROR: JDK cacerts not found"; exit 1; }
57+
log "Using JDK cacerts: ${CACERTS}"
58+
59+
# =============================================================================
60+
# keytool wrapper (BC-FIPS)
61+
# =============================================================================
62+
run_keytool() {
63+
env -u JAVA_TOOL_OPTIONS -u JDK_JAVA_OPTIONS \
64+
JAVA_TOOL_OPTIONS="--module-path=${BC_DIR} --add-modules=jdk.crypto.ec,jdk.crypto.cryptoki" \
65+
keytool \
66+
-providername BCFIPS \
67+
-providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider \
68+
-providerpath "${BC_JAR}" \
69+
"$@"
70+
}
71+
72+
# =============================================================================
73+
# 1️⃣ Create empty BCFKS truststore
74+
# =============================================================================
75+
if [ ! -f "${TRUSTSTORE}" ]; then
76+
log "Creating empty BCFKS truststore"
77+
run_keytool -genkeypair \
78+
-alias __bootstrap__ \
79+
-dname "CN=bootstrap" \
80+
-keyalg RSA -keysize 2048 \
81+
-keystore "${TRUSTSTORE}" \
82+
-storetype BCFKS \
83+
-storepass "${TRUSTSTORE_PASSWORD}" \
84+
-keypass "${TRUSTSTORE_PASSWORD}" \
85+
-validity 1
86+
run_keytool -delete \
87+
-alias __bootstrap__ \
88+
-keystore "${TRUSTSTORE}" \
89+
-storetype BCFKS \
90+
-storepass "${TRUSTSTORE_PASSWORD}"
91+
fi
92+
93+
# =============================================================================
94+
# 2️⃣ Import ALL public CA certs from JDK cacerts
95+
# =============================================================================
96+
log "Importing JDK public CA certificates into BCFKS truststore"
97+
98+
keytool -list -cacerts -storepass changeit \
99+
| awk -F, '/trustedCertEntry/ {print $1}' \
100+
| while read -r alias; do
101+
[ -n "$alias" ] || continue
102+
CRT="${TMP_DIR}/${alias}.crt"
103+
if keytool -exportcert -rfc \
104+
-cacerts \
105+
-storepass changeit \
106+
-alias "$alias" \
107+
-file "$CRT" 2>/dev/null; then
108+
run_keytool -importcert -noprompt \
109+
-alias "jdk-${alias}" \
110+
-file "$CRT" \
111+
-keystore "${TRUSTSTORE}" \
112+
-storetype BCFKS \
113+
-storepass "${TRUSTSTORE_PASSWORD}" \
114+
>/dev/null 2>&1 || true
115+
fi
116+
done
117+
118+
# =============================================================================
119+
# 3️⃣ Create BCFKS keystore (server identity)
120+
# =============================================================================
121+
if [ ! -f "${KEYSTORE}" ]; then
122+
log "Creating BCFKS keystore"
123+
run_keytool -genkeypair \
124+
-alias "${SERVER_ALIAS}" \
125+
-dname "${SERVER_DNAME}" \
126+
-ext "SAN=${SERVER_SAN}" \
127+
-keyalg "${KEYALG}" \
128+
-keysize "${KEYSIZE}" \
129+
-validity "${VALIDITY_DAYS}" \
130+
-keystore "${KEYSTORE}" \
131+
-storetype BCFKS \
132+
-storepass "${KEYSTORE_PASSWORD}" \
133+
-keypass "${KEYSTORE_PASSWORD}"
134+
fi
135+
136+
# =============================================================================
137+
# 4️⃣ Sanity checks
138+
# =============================================================================
139+
run_keytool -list \
140+
-keystore "${TRUSTSTORE}" \
141+
-storetype BCFKS \
142+
-storepass "${TRUSTSTORE_PASSWORD}" >/dev/null
143+
144+
run_keytool -list \
145+
-keystore "${KEYSTORE}" \
146+
-storetype BCFKS \
147+
-storepass "${KEYSTORE_PASSWORD}" >/dev/null
148+
149+
log "BCFKS truststore and keystore ready"
150+
151+
# =============================================================================
152+
# 5️⃣ Optional output: JVM flags for runtime
153+
# =============================================================================
154+
echo
155+
echo "Recommended JVM flags:"
156+
echo "--module-path=${BC_DIR} --add-modules=jdk.crypto.ec,jdk.crypto.cryptoki \\"
157+
[ "${ENFORCE_APPROVED_ONLY}" = "1" ] && \
158+
echo "-Dorg.bouncycastle.fips.approved_only=true \\"
159+
cat <<EOF
160+
-Djavax.net.ssl.trustStore=${TRUSTSTORE}
161+
-Djavax.net.ssl.trustStoreType=BCFKS
162+
-Djavax.net.ssl.trustStoreProvider=BCFIPS
163+
-Djavax.net.ssl.trustStorePassword=${TRUSTSTORE_PASSWORD}
164+
-Djavax.net.ssl.keyStore=${KEYSTORE}
165+
-Djavax.net.ssl.keyStoreType=BCFKS
166+
-Djavax.net.ssl.keyStoreProvider=BCFIPS
167+
-Djavax.net.ssl.keyStorePassword=${KEYSTORE_PASSWORD}
168+
EOF

0 commit comments

Comments
 (0)