Skip to content

Commit 055caeb

Browse files
committed
adding missing files
Signed-off-by: Eric Bannon <eric.bannon4@gmail.com>
1 parent 8db6d40 commit 055caeb

14 files changed

Lines changed: 983 additions & 0 deletions

File tree

java-fips-bcfks/app/bin/run.sh

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/bin/sh
2+
set -euo pipefail
3+
4+
ts() { date -u +'%Y-%m-%dT%H:%M:%SZ'; }
5+
6+
APP_ROOT="${APP_ROOT:-/app}"
7+
CERT_DIR="${APP_ROOT}/certs"
8+
TMP_DIR="${APP_ROOT}/tmp"
9+
10+
CA_PEM="${CERT_DIR}/ca.crt"
11+
SERVER_CRT="${CERT_DIR}/server.crt"
12+
SERVER_KEY="${CERT_DIR}/server.key"
13+
CHAIN_PEM="${CERT_DIR}/chain.crt" # optional
14+
15+
TRUSTSTORE_PATH="${CERT_DIR}/truststore.bcfks"
16+
KEYSTORE_PATH="${CERT_DIR}/keystore.bcfks"
17+
SERVER_PK8="${CERT_DIR}/server.pk8"
18+
19+
BC_DIR="/usr/share/java/bouncycastle-fips"
20+
BC_JAR="${BC_DIR}/bc-fips.jar"
21+
22+
mkdir -p "${CERT_DIR}" "${TMP_DIR}"
23+
24+
# Providers/module-path only; no java.security append/override
25+
export JDK_JAVA_OPTIONS="--module-path=${BC_DIR} --add-modules=jdk.crypto.ec,jdk.crypto.cryptoki ${JDK_JAVA_OPTIONS:-}"
26+
export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS:-}"
27+
28+
# Optional: enforce approved-only if set via env
29+
if [ -n "${FIPS_APPROVED_ONLY:-}" ]; then
30+
export JAVA_OPTS="${JAVA_OPTS:-} -Dorg.bouncycastle.fips.approved_only=true"
31+
fi
32+
33+
need_openssl() { command -v openssl >/dev/null 2>&1 || { echo "$(ts) ERROR: openssl not found"; exit 1; }; }
34+
need_javac() { command -v javac >/dev/null 2>&1 || { echo "$(ts) ERROR: javac not found"; exit 1; }; }
35+
need_java() { command -v java >/dev/null 2>&1 || { echo "$(ts) ERROR: java not found"; exit 1; }; }
36+
37+
# Strip inherited javax.net.ssl pins to avoid conflicts
38+
_strip_ssl_flags() { sed -E 's/-Djavax\.net\.ssl\.(trust|key)Store(Type|Provider|Password)=[^ ]+//g'; }
39+
[ -n "${JDK_JAVA_OPTIONS:-}" ] && export JDK_JAVA_OPTIONS="$(printf '%s' "${JDK_JAVA_OPTIONS}" | _strip_ssl_flags)"
40+
[ -n "${JAVA_TOOL_OPTIONS:-}" ] && export JAVA_TOOL_OPTIONS="$(printf '%s' "${JAVA_TOOL_OPTIONS}" | _strip_ssl_flags)"
41+
[ -n "${JAVA_OPTS:-}" ] && export JAVA_OPTS="$(printf '%s' "${JAVA_OPTS}" | _strip_ssl_flags)"
42+
43+
# --- Truststore plan ---
44+
TRUSTSTORE_PASSWORD="${TRUSTSTORE_PASSWORD:-}"
45+
if [ -f "${CA_PEM}" ] && { [ "${FORCE_REGEN:-0}" = "1" ] || [ ! -f "${TRUSTSTORE_PATH}" ]; }; then
46+
echo "$(ts) Creating BCFKS truststore (CA only) at ${TRUSTSTORE_PATH}"
47+
: "${TRUSTSTORE_PASSWORD:=$(LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c 32 || true)}"
48+
export TRUSTSTORE_PASSWORD
49+
:> "${TMP_DIR}/.need_makebcfks"
50+
elif [ ! -f "${CA_PEM}" ]; then
51+
echo "$(ts) WARN: ${CA_PEM} not found; no custom CA will be trusted."
52+
fi
53+
54+
# --- Keystore plan ---
55+
KEY_PASSWORD="${KEY_PASSWORD:-}"
56+
if [ -f "${SERVER_CRT}" ] && [ -f "${SERVER_KEY}" ] && { [ "${FORCE_REGEN:-0}" = "1" ] || [ ! -f "${KEYSTORE_PATH}" ]; }; then
57+
echo "$(ts) Creating BCFKS keystore (server cert+key) at ${KEYSTORE_PATH}"
58+
: "${KEY_PASSWORD:=$(LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c 32 || true)}"
59+
export KEY_PASSWORD
60+
need_openssl
61+
if ! grep -q "BEGIN PRIVATE KEY" "${SERVER_KEY}"; then
62+
openssl pkcs8 -topk8 -nocrypt -in "${SERVER_KEY}" -out "${SERVER_PK8}" ${PASSPHRASE:+-passin pass:"${PASSPHRASE}"} 2>/dev/null \
63+
|| { echo "$(ts) ERROR: Failed to convert server.key to PKCS#8; check PASSPHRASE"; exit 1; }
64+
else
65+
cp -f "${SERVER_KEY}" "${SERVER_PK8}"
66+
fi
67+
:> "${TMP_DIR}/.need_makebcfks"
68+
fi
69+
70+
# --- Write .bcfks if needed ---
71+
if [ -f "${TMP_DIR}/.need_makebcfks" ]; then
72+
need_javac; need_java
73+
cat >"${TMP_DIR}/MakeBcfks.java" <<'EOF'
74+
import java.io.InputStream; import java.io.OutputStream; import java.io.IOException;
75+
import java.nio.file.*; import java.security.*; import java.security.cert.*; import java.security.spec.PKCS8EncodedKeySpec;
76+
import java.util.*; public class MakeBcfks {
77+
static final String PROV_NAME="BCFIPS";
78+
static byte[] readAll(String p)throws IOException{return Files.readAllBytes(Paths.get(p));}
79+
static byte[] decodePem(byte[] in,String type){String s=new String(in);String b="-----BEGIN "+type+"-----",e="-----END "+type+"-----";
80+
int i=s.indexOf(b),j=s.indexOf(e); if(i>=0&&j>i){String b64=s.substring(i+b.length(),j).replaceAll("[\\r\\n\\s]","");return Base64.getDecoder().decode(b64);} return in;}
81+
static PrivateKey readPkcs8Key(String path)throws Exception{
82+
byte[] der=decodePem(readAll(path),"PRIVATE KEY"); PKCS8EncodedKeySpec spec=new PKCS8EncodedKeySpec(der);
83+
GeneralSecurityException last=null; for(String alg:new String[]{"RSA","EC","Ed25519","Ed448"}){
84+
try{return KeyFactory.getInstance(alg,PROV_NAME).generatePrivate(spec);}catch(GeneralSecurityException e){last=e;}}
85+
throw (last!=null)?last:new GeneralSecurityException("Unsupported key algorithm");}
86+
static KeyStore newBcfks(char[]pwd)throws Exception{KeyStore ks=KeyStore.getInstance("BCFKS",PROV_NAME); ks.load(null,pwd); return ks;}
87+
public static void main(String[] a)throws Exception{
88+
if(Security.getProvider(PROV_NAME)==null){
89+
Security.addProvider((Provider)Class.forName("org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider").getDeclaredConstructor().newInstance());}
90+
String ca=System.getenv("CA_PEM"), leaf=System.getenv("SERVER_CRT"), chain=System.getenv("CHAIN_PEM"), pk8=System.getenv("SERVER_PK8"),
91+
ts=System.getenv("TRUSTSTORE_PATH"), ks=System.getenv("KEYSTORE_PATH");
92+
char[] tsp=Optional.ofNullable(System.getenv("TRUSTSTORE_PASSWORD")).orElse("").toCharArray();
93+
char[] ksp=Optional.ofNullable(System.getenv("KEY_PASSWORD")).orElse("").toCharArray();
94+
if(ca!=null && Files.isRegularFile(Paths.get(ca)) && !Files.isRegularFile(Paths.get(ts))){
95+
KeyStore T=newBcfks(tsp); CertificateFactory cf=CertificateFactory.getInstance("X.509");
96+
try(InputStream is=Files.newInputStream(Paths.get(ca))){int i=0; for(java.security.cert.Certificate c: cf.generateCertificates(is)){T.setCertificateEntry("ca-"+(i++),c);}}
97+
try(OutputStream os=Files.newOutputStream(Paths.get(ts))){T.store(os,tsp);} System.out.println("Wrote truststore: "+ts);
98+
}
99+
if(leaf!=null && Files.isRegularFile(Paths.get(leaf)) && pk8!=null && Files.isRegularFile(Paths.get(pk8)) && !Files.isRegularFile(Paths.get(ks))){
100+
PrivateKey key=readPkcs8Key(pk8); List<java.security.cert.Certificate> list=new ArrayList<>(); CertificateFactory cf=CertificateFactory.getInstance("X.509");
101+
try(InputStream is=Files.newInputStream(Paths.get(leaf))){list.addAll((Collection<? extends java.security.cert.Certificate>)cf.generateCertificates(is));}
102+
if(chain!=null && Files.isRegularFile(Paths.get(chain))){try(InputStream cs=Files.newInputStream(Paths.get(chain))){list.addAll((Collection<? extends java.security.cert.Certificate>)cf.generateCertificates(cs));}}
103+
KeyStore K=newBcfks(ksp); K.setKeyEntry("app-server",key,ksp,list.toArray(new java.security.cert.Certificate[0]));
104+
try(OutputStream os=Files.newOutputStream(Paths.get(ks))){K.store(os,ksp);} System.out.println("Wrote keystore: "+ks);
105+
}
106+
}
107+
}
108+
EOF
109+
javac -cp "${BC_JAR}" "${TMP_DIR}/MakeBcfks.java"
110+
CA_PEM="${CA_PEM}" SERVER_CRT="${SERVER_CRT}" CHAIN_PEM="${CHAIN_PEM}" \
111+
SERVER_PK8="${SERVER_PK8}" TRUSTSTORE_PATH="${TRUSTSTORE_PATH}" KEYSTORE_PATH="${KEYSTORE_PATH}" \
112+
TRUSTSTORE_PASSWORD="${TRUSTSTORE_PASSWORD:-}" KEY_PASSWORD="${KEY_PASSWORD:-}" \
113+
java -cp "${TMP_DIR}:${BC_JAR}" MakeBcfks
114+
rm -f "${TMP_DIR}/.need_makebcfks" "${SERVER_PK8}" || true
115+
fi
116+
117+
# Pin BCFKS stores at runtime (only if they exist + passwords set)
118+
RUNTIME_PROPS=""
119+
[ -f "${TRUSTSTORE_PATH}" ] && [ -n "${TRUSTSTORE_PASSWORD:-}" ] && RUNTIME_PROPS="${RUNTIME_PROPS} -Djavax.net.ssl.trustStore=${TRUSTSTORE_PATH} -Djavax.net.ssl.trustStoreType=BCFKS -Djavax.net.ssl.trustStoreProvider=BCFIPS -Djavax.net.ssl.trustStorePassword=${TRUSTSTORE_PASSWORD}"
120+
[ -f "${KEYSTORE_PATH}" ] && [ -n "${KEY_PASSWORD:-}" ] && RUNTIME_PROPS="${RUNTIME_PROPS} -Djavax.net.ssl.keyStore=${KEYSTORE_PATH} -Djavax.net.ssl.keyStoreType=BCFKS -Djavax.net.ssl.keyStoreProvider=BCFIPS -Djavax.net.ssl.keyStorePassword=${KEY_PASSWORD}"
121+
122+
echo "$(ts) JAVA_TOOL_OPTIONS=${JAVA_TOOL_OPTIONS}"
123+
[ -n "${TRUSTSTORE_PASSWORD:-}" ] && echo "$(ts) truststore: ${TRUSTSTORE_PATH} (pwd len: ${#TRUSTSTORE_PASSWORD})"
124+
[ -n "${KEY_PASSWORD:-}" ] && echo "$(ts) keystore: ${KEYSTORE_PATH} (pwd len: ${#KEY_PASSWORD})"
125+
126+
APP_JAR="${APP_JAR:-${APP_ROOT}/lib/app.jar}"
127+
if [ -f "$APP_JAR" ]; then
128+
echo "$(ts) Launching Java app: ${APP_JAR}"
129+
exec java ${JAVA_OPTS:-} ${RUNTIME_PROPS} -jar "${APP_JAR}"
130+
else
131+
echo "[WARN] No ${APP_JAR}; sleeping for debug"
132+
exec sleep 600
133+
fi

0 commit comments

Comments
 (0)