Monday, 19 October 2026

create mTLS certs - basic steps

 

Mental model (before commands)

1 CA → many leaf certs → pack into .p12/.jks → apps only see store files
CA private key (ca.key) = secret, never shared
CA cert (ca.crt) = public, goes in trust-store (shared client+server)
Leaf private key (.key) = stays with that side
CSR (.csr) = send to CA to sign (not the private key)
Leaf cert (.crt) = CA returns this
Key-store (.p12) = .key + leaf .crt (identity) — private to that side
Trust-store (.p12) = ca.crt only — same file OK on both sides

In real Wipro: company CA plays the role of steps that use ca.key below.
Locally: you are the CA (private CA; root ca.crt is self-signed; leaf certs are CA-signed, not “self-signed leaves”).

Bootstrap like bootstrap-pr.yml only references the packed files (ispKeyStore.p12, ispTrustStore.jks) — not raw .crt/.key.


#1 Create CA (Wipro PKI / you-as-CA for play)

# CA PRIVATE KEY — highly confidential; never put in trust-store or give to apps
openssl genrsa -out ca.key 4096
# CA CERTIFICATE (public) — contains CA public key + identity; root is self-signed
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
-subj "/CN=MyPlayCA" -out ca.crt
FileWhatWho keeps it
ca.key
CA private key
PKI only (in play: you)
ca.crt
CA public cert
Shared into trust-stores

#2 Server identity — key, CSR, CA returns cert

# SERVER PRIVATE KEY — never send to CA
openssl genrsa -out server.key 2048
# CSR = server public key + CN (request for signing). No private key inside.
openssl req -new -key server.key -subj "/CN=localhost" -out server.csr
# CA SIGNS CSR → server.crt
# Play: you sign with ca.key. Real world: send server.csr to Wipro CA; they return server.crt
# (and usually ca.crt / chain). You still keep server.key.
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 825 -sha256
FileRole
server.key
Private key
server.csr
Sent to CA (then can delete)
server.crt
Public certificate CA returned / issued

#3 Client identity — same pattern

openssl genrsa -out client.key 2048
openssl req -new -key client.key -subj "/CN=my-client" -out client.csr
# Play: sign locally. Real: send client.csr → Wipro CA → get client.crt back
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt -days 825 -sha256

Let’s Encrypt would only cover a public server domain flow roughly like #2 — not typical store client certs like #3.


#4 Trust-store — one shared file (CA only)

# Only ca.crt (public). No client/server private keys or leaf identity required.
# Same truststore.p12 can be installed on BOTH client and server when one CA signs both.
keytool -importcert -alias myca -file ca.crt \
-keystore truststore.p12 -storetype PKCS12 -storepass changeit -noprompt

≈ your ispTrustStore.jks (name may be .jks even if type is PKCS12).


#5 Key-stores — you/SRE pack after CA returns .crt

CA does not have to give you .p12; you/SRE build containers:

# server-keystore = server private key + server.crt (+ optional CA chain via -certfile)
openssl pkcs12 -export -inkey server.key -in server.crt -certfile ca.crt \
-out server-keystore.p12 -name server -passout pass:changeit
# client-keystore = client private key + client.crt (+ optional chain)
openssl pkcs12 -export -inkey client.key -in client.crt -certfile ca.crt \
-out client-keystore.p12 -name client -passout pass:changeit

-certfile ca.crt = optional chain inside the key-store; trust-store still needs ca.crt for verifying peers.

≈ your ispKeyStore.p12 (client identity on the store box).


#6 Deploy (out of band — before apps start)

SideFiles to install
Client (CF/DP)
client-keystore.p12 → key-store, truststore.p12 → trust-store
Server (Config Server / gateway)
server-keystore.p12 → key-store, same truststore.p12 → trust-store

Point bootstrap at those paths + passwords (optionally Jasypt ENC(...) + --jasypt.encryptor.password).

No exchange of key-store files between apps at runtime. Handshake sends public certs only; private keys prove possession locally.


#7 Runtime mTLS (what the files are for)

Client opens client-keystore + truststore
Server opens server-keystore + truststore
Client → presents client.crt (from key-store)
Server → checks signature proof + “signed by CA in truststore?”
Server → presents server.crt
Client → checks against same CA in truststore
OK → HTTPS to Config Server

File map (play names → bootstrap names)

GeneratedRoleLike in bootstrap-pr.yml
truststore.p12
Shared CA trust
ispTrustStore.jks
client-keystore.p12
Client identity
ispKeyStore.p12
server-keystore.p12
Server identity
on Config Server / gateway (not in CF bootstrap as server’s own file for config TLS — CF uses client store)
ca.key
Never deployed to stores
Wipro PKI only
*.csr
Temporary
not deployed
loose client.crt
Inside .p12
not referenced in YAML

Who does what (real vs play)

StepPlay (you)Production (Wipro)
Hold ca.key, sign CSRs
You
Wipro CA / PKI
Create .key + .csr
You
SRE / cert process
Return .crt (+ ca.crt)
Your openssl x509
Wipro CA
Build .p12 / .jks
You (pkcs12 / keytool)
SRE
Install on Unix box
You
Install scripts / SRE
App uses stores
Spring TLS config
bootstrap-pr.yml