Using OpenShift 4 As A Certificates CA

Why this Article

Today the very basic of securing your application is running it with a TLS encryption. When running the application on top of OpenShift we can utilized the Kubernetes Abilities and sign the application certificate when the CA is already part of OpenShift.

What do we need ?

Openshift, That is it…. well almost we do need to create the CSR and the KEY. For that we need to create an answer file and use openssl to generate the 2 files.

Getting Started

The steps for generating the Certificate are simple. First we will generate the key and the the answer file for the CSR followed by the CSR. Once the two files are obtained we will create the “CertificateSigningRequest” resource and sign the certificate.

OpenSSL

First (as root) let’s make sure the package is installed on the server :

# dnf install -y openssl
$ openssl genrsa -out tls.key 2048

Answer file (Option 1)

to generate the answer file I will first export our URL short name (the first part of the FQDN) and then the domain with environment variables :

# export DOMAIN="<my.long.and-annoying.really-long.domain.me>"
# export SHORT_NAME="<the name>"
$ cat > ${SHORT_NAME}_answer.txt << EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = req_ext
req_extensions = req_ext
distinguished_name = dn
[ dn ]
C=US
ST=New York
L=New York
O=MyOrg
OU=MyOrgUnit
emailAddress=me@working.me
CN = ${SHORT_NAME}
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = ${SHORT_NAME}
DNS.2 = ${SHORT_NAME}.${DOMAIN}
EOF
# openssl req -new -key tls.key -out tls.csr -config <( cat ${SHORT_NAME}_answer.txt )

One liner (Option 2)

We will first export our URL short name (the first part of the FQDN) and then the domain with environment variables :

# export DOMAIN="<my.short.name>"
# export SHORT_NAME="<the name>"
# openssl req -new -key tls.key -out tls.csr -subj "/CN=${SHORT_NAME}.${DOMAIN}/O=devops/O=My Org/C=US/ST=New York/L=New York"  -addext "subjectAltName = DNS:${SHORT_NAME},DNS:${SHORT_NAME}.${DOMAIN}"

Signing the CSR

(From the Official Kubernetes page) : “The CertificateSigningRequest resource type allows a client to ask for an X.509 certificate be issued, based on a signing request. The CertificateSigningRequest object includes a PEM-encoded PKCS#10 signing request in the spec.request field. The CertificateSigningRequest denotes the signer (the recipient that the request is being made to) using the spec.signerName field. Note that spec.signerName is a required key after API version certificates.k8s.io/v1. In Kubernetes v1.22 and later, clients may optionally set the spec.expirationSeconds field to request a particular lifetime for the issued certificate. The minimum valid value for this field is 600, i.e. ten minutes.”

# CERT_BASE64=$(cat tls.csr | base64 -w0) 
# cat > tls-csr.yaml << EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: ${SHORT_NAME}
spec:
request: ${CERT_BASE64}
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 7776000 # three months
usages:
- client auth
EOF
  • expirationSeconds could be made longer (i.e. 15552000 for half a year ) or shorter (i.e. 3600 for one hour)
  • request is the base64 encoded value of the CSR file content.
# oc apply -f tls-csr.yaml
# oc get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
my-cert 17s kubernetes.io/kube-apiserver-client system:admin Pending
# oc adm certificate approve my-cert
certificatesigningrequest.certificates.k8s.io/my-cert approved
# oc get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
my-cert 2m51s kubernetes.io/kube-apiserver-client system:admin Approved,Issued
# oc get csr my-cert -o jsonpath='{.status.certificate}' | base64 -d
-----BEGIN CERTIFICATE-----
.....
-----END CERTIFICATE-----

CA certificate

For the last part we need to extract our CA certificate which OpenShift had used to sign the certificate. On Openshift there is a simple config map which contains all of the necessary CAs :

# oc get secret csr-signer -n openshift-kube-controller-manager-operator -o template='{{ index .data "tls.crt"}}' | base64 -d > route-ca.crt

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store