PKI CA OpenShift - dogtagpki/pki GitHub Wiki

Table of Contents

Overview

This page describes the procedure to deploy a PKI instance on OpenShift.

Current Issues

  • This is still a work in progress.
  • The PKI instance cannot be created in OpenShift yet. The instance needs to be created locally then uploaded to OpenShift.
  • The database configuration needs to be updated.
  • The auth-method.properties needs to be fixed.
  • The SSL certificate needs to be regenerated.
  • Log files need to be cleaned up.

Creating Local PKI Instance

Create a PKI instance in the local machine.

Then create a backup:

$ pki-server stop
$ tar czvf pki-tomcat.tar.gz -C / \
    etc/pki/pki-tomcat \
    etc/sysconfig/pki-tomcat \
    etc/sysconfig/pki/tomcat/pki-tomcat \
    etc/systemd/system/pki-tomcatd.target.wants/[email protected] \
    var/lib/pki/pki-tomcat \
    var/log/pki/pki-tomcat

Put the pki-tomcat.tar.gz in a backup dir.

Creating Persistent Storage

Prepare a configuration file (e.g. pki-pvc.yaml):

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pki
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

Then execute the following command:

$ oc create -f pki-pvc.yaml

Uploading PKI Instance Files

Deploy a temporary application (e.g. Fedora OpenShift).

Mount the storage into the application's pod into /data.

Upload the backup file:

$ oc rsync <backup dir> <pod>:/data

Open a remote shell:

$ oc rsh <pod>

Execute the following commands:

$ cd /data
$ tar xvf pki-tomcat.tar.gz
$ rm pki-tomcat.tar.gz

Edit /data/var/lib/pki/pki-tomcat/conf/ca/CS.cfg:

internaldb.ldapconn.host=ds.pki-demo.svc
internaldb.ldapconn.port=10389

Unmount the storage. The temporary application can be undeployed as well.

Dockerfile

FROM fedora:30

EXPOSE 8080 8443

RUN dnf install -y dnf-plugins-core && dnf copr enable -y edewata/pki
RUN dnf install -y abrt-java-connector dogtag-pki && dnf clean all

RUN ln -s /data/var/lib/pki/pki-tomcat/conf /var/lib/pki/pki-tomcat/conf && \
    ln -s /data/etc/sysconfig/pki-tomcat /etc/sysconfig/pki-tomcat && \
    ln -s /data/etc/sysconfig/pki/tomcat/pki-tomcat /etc/sysconfig/pki/tomcat/pki-tomcat && \
    ln -s /data/etc/systemd/system/pki-tomcatd.target.wants/[email protected] \
          /etc/systemd/system/pki-tomcatd.target.wants/[email protected] && \
    ln -s /data/var/lib/pki/pki-tomcat /var/lib/pki/pki-tomcat && \
    ln -s /data/var/log/pki/pki-tomcat /var/log/pki/pki-tomcat

USER pkiuser

VOLUME /data

CMD [ "pki-server", "run", "--as-current-user", "--debug" ]

Building Container Image

$ docker build -t pki .

Publishing Container Image

$ docker tag pki:latest <username>/pki:latest
$ docker push <username>/pki:latest

Available Images

Creating PKI Image Stream

Prepare a configuration file (e.g. pki-is.yaml):

apiVersion: v1
kind: ImageStream
metadata:
  labels:
    app: ca
  name: pki
spec:
  lookupPolicy:
    local: false
  tags:
    - from:
        kind: DockerImage
        name: 'edewata/pki:latest'
      name: latest
      referencePolicy:
        type: Source

Then execute the following command:

$ oc create -f pki-is.yaml

Creating PKI Application

Prepare a configuration file (e.g. pki-dc.yaml):

apiVersion: v1
kind: DeploymentConfig
metadata:
  labels:
    app: pki
  name: pki
spec:
  selector:
    app: pki
    deploymentconfig: pki
  template:
    metadata:
      labels:
        app: pki
        deploymentconfig: pki
    spec:
      containers:
        - image: edewata/pki
          name: pki
          ports:
            - containerPort: 8080
              protocol: TCP
          volumeMounts:
            - mountPath: /data
              name: data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pki
  test: false
  triggers:
    - type: ConfigChange
    - imageChangeParams:
        automatic: true
        containerNames:
          - pki
        from:
          kind: ImageStreamTag
          name: 'pki:latest'
      type: ImageChange

Then execute the following command:

$ oc create -f pki-dc.yaml

Starting PKI Application

$ oc scale dc pki --replicas=1

Generating Internal SSL Certificate

Generate a new CSR for the PKI service (e.g. pki.pki-demo.svc):

$ cd /var/lib/pki/pki-tomcat/conf/alias
$ openssl rand -out noise.bin 2048
$ echo Secret.123 > password.txt
$ certutil -R \
 -d . \
 -f password.txt \
 -z noise.bin \
 -k rsa \
 -g 2048 \
 -Z SHA256 \
 -s "CN=pki.pki-demo.svc,O=EXAMPLE" \
 --keyUsage critical,dataEncipherment,keyEncipherment,digitalSignature \
 --extKeyUsage serverAuth \
 -o sslserver.csr.der
$ openssl req -inform der -in sslserver.csr.der -out sslserver.csr

Get the SKID and OCSP URL from the CA signing certificate:

$ pki-server cert-export ca_signing --cert-file ca_signing.crt
$ openssl x509 -text -noout -in ca_signing.crt
$ SKID=0x`openssl x509 -text -noout -in ca_signing.crt | grep "keyid:" | sed -e 's/ *keyid://g' -e 's/://g'`
$ OCSP=http://pki.pki-demo.svc:8080/ca/ocsp

Issue a new certificate for the SSL server certificate:

$ echo -e "y\n${SKID}\n\n\nn\n2\n7\n${OCSP}\n\n\n\n" | \
 certutil -C \
 -d . \
 -f password.txt \
 -m $RANDOM \
 -a \
 -i sslserver.csr \
 -o sslserver.crt \
 -c "ca_signing" \
 -v 12 \
 -3 \
 --extAIA \
 --keyUsage critical,dataEncipherment,keyEncipherment,digitalSignature \
 --extKeyUsage serverAuth

Replace the server certificate:

$ certutil -F -d . -f password.txt -n "sslserver"
$ certutil -A -d . -f password.txt -n "sslserver" -i sslserver.crt -t ",,"

Restarting PKI Application

$ oc scale dc pki --replicas=0
$ sleep 10
$ oc scale dc pki --replicas=1

Creating PKI Service

Prepare a configuration file (e.g. pki-svc.yaml):

apiVersion: v1
kind: Service
metadata:
  labels:
    app: pki
  name: pki
spec:
  ports:
    - name: 8080-tcp
      port: 8080
      protocol: TCP
      targetPort: 8080
    - name: 8443-tcp
      port: 8443
      protocol: TCP
      targetPort: 8443
  selector:
    app: pki
    deploymentconfig: pki
  sessionAffinity: None
  type: ClusterIP

Then execute the following command:

$ oc create -f pki-svc.yaml

Creating DNS Record

Create a CNAME record for the public hostname (e.g. pki.demo.dogtagpki.org) pointing to the router's canonical hostname provided by OpenShift.

Creating PKI Route

Prepare a configuration file (e.g. pki-route.yaml):

apiVersion: v1
kind: Route
metadata:
  labels:
    app: pki
  name: pki
spec:
  host: pki.demo.dogtagpki.org
  port:
    targetPort: 8080-tcp
  to:
    kind: Service
    name: pki
    weight: 100
  wildcardPolicy: None

Then execute the following command:

$ oc create -f pki-route.yaml

Generating External SSL Certificate

Run the following command to request a certificate from Let's Encrypt:

$ certbot certonly --manual -d pki.demo.dogtagpki.org --register-unsafely-without-email

Create the ACME response:

$ oc rsh <pod> mkdir -p /var/lib/pki/pki-tomcat/webapps/.well-known/acme-challenge
$ oc rsync acme-challenge/ <pod>:/var/lib/pki/pki-tomcat/webapps/.well-known/acme-challenge

Create an unsecure HTTP route for port 8080 of the PKI CA service, then complete the ACME validation. The results will be stored in:

  • certificate: /etc/letsencrypt/live/pki.demo.dogtagpki.org/fullchain.pem
  • key: /etc/letsencrypt/live/pki.demo.dogtagpki.org/privkey.pem

Installing External SSL Certificate

Remove the current route:

$ oc delete routes/pki

Prepare a configuration file (e.g. pki-route-secure.yaml):

apiVersion: v1
kind: Route
metadata:
  labels:
    app: pki
  name: pki
spec:
  host: pki.demo.dogtagpki.org
  port:
    targetPort: 8443-tcp
  tls:
    caCertificate: |-
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    certificate: |-
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    destinationCACertificate: |-
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    insecureEdgeTerminationPolicy: Redirect
    key: |-
      -----BEGIN PRIVATE KEY-----
      ...
      -----END PRIVATE KEY-----
    termination: reencrypt
  to:
    kind: Service
    name: pki
    weight: 100
  wildcardPolicy: None

Then execute the following command:

$ oc create -f pki-route-secure.yaml

To validate, open https://pki.demo.dogtagpki.org with a browser.

Updating Container Image

If newer container image is available, it can be deployed with the following command:

$ oc import-image <username>/ca

See Also

⚠️ **GitHub.com Fallback** ⚠️