Simple backend service to view incoming(ssl client) certificate
Turn on peer certificate verification in openssl server
During a PoC we did for mTLS in our api gateway, we wanted a backend service to check and see the certificate passed by the gateway to the backend.
Looked in to multiple approaches like doing it via different web services (python, springboot, nodejs etc) and came across this blog post and it triggered the idea to use openssl server for this purpose.
We could not use a public endpoint for this purpose since the outbound traffic to public internet was blocked. And we wanted this service in the form of a kubernetes pod as our gateways were running inside a k8s cluster.
I liked using the openssl server because it was simple and easy. You dont have to write any java/python etc code. You just need any docker image with openssl installed.
Local Server
If you want to try this locally you will have to run below commands
Generate the cert for the server
openssl req -new -x509 -nodes -out /home/server.crt -keyout /home/server.key -days 3650 -subj '/CN=opensslserver.testing.com'
Start openssl server
Please note that -Verify or -verify parameter is needed to verify the peer/client certificate.
openssl s_server -accept 8443 -cert /home/server.crt -key /home/server.key -Verify 1 -state -debug -www
Now the server should be listening to port 8443 for https requests.
Docker
As I mentioned above, for this purpose you just need any linux distribution with openssl installed. You could use any docker image like alpine,ubuntu,redhat etc.
docker run -d -p 8443:8443 alpine sh -c "apk add openssl; openssl req -new -x509 -nodes -out /home/server.crt -keyout /home/server.key -days 3650 -subj '/CN=opensslserver.testing.com'; openssl s_server -accept 8443 -cert /home/server.crt -key /home/server.key -Verify 1 -state -debug -www"
If your container runtime doesnt have permissions to write files to the host system, then create the certificates manually in your host file system and mount to the docker container as a volume (pass -v <hostpath>:<containerpath> to the docker run command)
Kubernetes
kubectl run openssl-server --image alpine -- "apk add openssl; openssl req -new -x509 -nodes -out /home/server.crt -keyout /home/server.key -days 3650 -subj '/CN=opensslserver.testing.com'; openssl s_server -accept 8443 -cert /home/server.crt -key /home/server.key -Verify 1 -state -debug -www"
If your kubernetes cluster has restricted permissions(where pods arent allowed to write files to host system) you will not be able to create the certs or install openssl during the container startup. Then you can create a docker image with openssl installed on top of a vanila alpine,ubuntu,redhat image.
FROM alpine:3.5
# install openssl and some helpful tools
RUN apk add --no-cache vim curl openssl wget
## And create self-signed ssl keys for test purposes (bind mount proper ones to running container)
RUN openssl req -new -x509 -nodes -out /home/server.crt -keyout /home/server.key -days 3650 -subj '/CN=opensslserver.testing.com'
##
CMD openssl s_server -accept 8443 -cert /home/server.crt -key /home/server.key -Verify 1 -state -debug -www
# http and httpd ports. You can map these to whatever host ports you want with -p
EXPOSE 8443
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: opensslserver
name: opensslserver
spec:
replicas: 1
selector:
matchLabels:
app: opensslserver
strategy: { }
template:
metadata:
labels:
app: opensslserver
spec:
containers:
- name: opensslserver
image: <the image you built with above Dockerfile>
ports:
- containerPort: 8443
protocol: TCP
Testing
I used postman to test these. From postman you can attach client certificate to a request. You receive a response with the client secret you attached in the request like below.
Cheers!!!