Difference between revisions of "PKI ACME OpenShift"

From Dogtag
Jump to: navigation, search
m (Overview)
m
Line 7: Line 7:
 
Development branch: https://github.com/edewata/pki/commits/acme
 
Development branch: https://github.com/edewata/pki/commits/acme
  
= Current Issues =
+
= Deployment =
  
* This is still a work in progress.
+
* [https://github.com/dogtagpki/pki/blob/master/docs/installation/acme/Deploying_ACME_on_OpenShift.md Deploying ACME on OpenShift]
 
 
= Certificates =
 
 
 
Prepare an NSS database:
 
 
 
<pre>
 
$ mkdir nssdb
 
$ certutil -N -d nssdb
 
</pre>
 
 
 
Import the certificates into the NSS database.
 
 
 
Export the NSS database into a PKCS #12 file. Store the password in a file.
 
 
 
Encode the files:
 
 
 
<pre>
 
$ PKCS12_FILE=`cat nssdb.p12 | base64 -w0`
 
$ PKCS12_PASSWORD=`cat password.txt | base64 -w0`
 
</pre>
 
 
 
Prepare a file to store the files as a secret (e.g. acme-nssdb.yaml):
 
 
 
<pre>
 
apiVersion: v1
 
kind: Secret
 
type: Opaque
 
metadata:
 
  name: acme-nssdb
 
data:
 
  nssdb.p12: $PKCS12_FILE
 
  password.txt: $PKCS12_PASSWORD
 
</pre>
 
 
 
Then execute the following command:
 
 
 
<pre>
 
$ oc create -f acme-nssdb.yaml
 
</pre>
 
 
 
= Configuration =
 
 
 
Prepare ACME configuration files:
 
* metadata.json
 
* database.json
 
* validators.json
 
* backend.json
 
* password.conf
 
 
 
Encode the files:
 
 
 
<pre>
 
$ METADATA_JSON=`cat metadata.json | base64 -w0`
 
$ DATABASE_JSON=`cat database.json | base64 -w0`
 
$ VALIDATORS_JSON=`cat validators.json | base64 -w0`
 
$ BACKEND_JSON=`cat backend.json | base64 -w0`
 
$ PASSWORD_CONF=`cat password.conf | base64 -w0`
 
</pre>
 
 
 
Prepare a file to store the configuration files as a secret (e.g. acme-conf.yaml):
 
 
 
<pre>
 
apiVersion: v1
 
kind: Secret
 
type: Opaque
 
metadata:
 
  name: acme-conf
 
data:
 
  metadata.json: $METADATA_JSON
 
  database.json: $DATABASE_JSON
 
  validators.json: $VALIDATORS_JSON
 
  backend.json: $BACKEND_JSON
 
  password.conf: $PASSWORD_CONF
 
</pre>
 
 
 
Then execute the following command:
 
 
 
<pre>
 
$ oc create -f acme-conf.yaml
 
</pre>
 
 
 
= Creating Local ACME Instance =
 
 
 
Create Tomcat instance:
 
 
 
<pre>
 
$ pki-server create tomcat@acme
 
</pre>
 
 
 
Deploy ACME web application:
 
 
 
<pre>
 
$ pki-server acme-create -i tomcat@acme
 
$ pki-server acme-deploy -i tomcat@acme
 
</pre>
 
 
 
Then create a backup:
 
 
 
<pre>
 
$ tar czvf acme.tar.gz -C / \
 
    var/lib/tomcats/acme
 
</pre>
 
 
 
= Deploying ACME Image =
 
 
 
To deploy ACME manually:
 
 
 
<pre>
 
apiVersion: v1
 
kind: DeploymentConfig
 
spec:
 
  selector:
 
    app: acme
 
    deploymentconfig: acme
 
  template:
 
    metadata:
 
      labels:
 
        app: acme
 
        deploymentconfig: acme
 
    spec:
 
      containers:
 
        - image: edewata/acme
 
          name: acme
 
          ports:
 
            - containerPort: 8080
 
              protocol: TCP
 
          volumeMounts:
 
            - mountPath: /data
 
              name: data
 
            - mountPath: /var/lib/tomcats/acme/alias
 
              name: acme-nssdb
 
              readOnly: true
 
            - mountPath: /var/lib/tomcats/acme/conf/acme
 
              name: acme-conf
 
              readOnly: true
 
      volumes:
 
        - name: data
 
          persistentVolumeClaim:
 
            claimName: acme
 
        - name: acme-nssdb
 
          secret:
 
            secretName: acme-nssdb
 
        - name: acme-conf
 
          secret:
 
            secretName: acme-conf
 
  triggers:
 
    - type: ConfigChange
 
    - imageChangeParams:
 
        containerNames:
 
          - acme
 
        from:
 
          kind: ImageStreamTag
 
          name: 'acme:latest'
 
      type: ImageChange
 
</pre>
 
 
 
To deploy ACME automatically:
 
 
 
<pre>
 
$ oc new-app edewata/acme:latest --name acme
 
$ oc expose svc/acme --name=acme --hostname=acme.demo.dogtagpki.org
 
</pre>
 
 
 
Add a CNAME DNS record to map to the canonical hostname.
 
 
 
Verify by opening the following URL in a browser:
 
 
 
* http://acme.demo.dogtagpki.org/acme/directory
 
 
 
= Creating ACME Service =
 
 
 
Prepare a configuration file (e.g. acme-svc.yaml):
 
 
 
<pre>
 
apiVersion: v1
 
kind: Service
 
metadata:
 
  labels:
 
    app: acme
 
  name: acme
 
spec:
 
  ports:
 
    - name: 8080-tcp
 
      port: 8080
 
      protocol: TCP
 
      targetPort: 8080
 
    - name: 8443-tcp
 
      port: 8443
 
      protocol: TCP
 
      targetPort: 8443
 
  selector:
 
    app: acme
 
    deploymentconfig: acme
 
  sessionAffinity: None
 
  type: ClusterIP
 
</pre>
 
 
 
Then execute the following command:
 
 
 
<pre>
 
$ oc create -f acme-svc.yaml
 
</pre>
 
 
 
= Creating DNS Record =
 
 
 
Create a CNAME record for the public hostname (e.g. acme.demo.dogtagpki.org) pointing to the router's canonical hostname provided by OpenShift.
 
 
 
= Creating ACME Route =
 
 
 
Prepare a configuration file (e.g. acme-route.yaml):
 
 
 
<pre>
 
apiVersion: v1
 
kind: Route
 
metadata:
 
  labels:
 
    app: acme
 
  name: acme
 
spec:
 
  host: acme.demo.dogtagpki.org
 
  port:
 
    targetPort: 8080-tcp
 
  to:
 
    kind: Service
 
    name: acme
 
    weight: 100
 
  wildcardPolicy: None
 
</pre>
 
 
 
Then execute the following command:
 
 
 
<pre>
 
$ oc create -f acme-route.yaml
 
</pre>
 
 
 
= Generating Internal SSL Certificate =
 
 
 
== Using JSS Connector ==
 
 
 
To generate HTTPS connector:
 
 
 
<pre>
 
$ pki-server http-connector-add -i tomcat@acme \
 
  --port 8443 \
 
  --scheme https \
 
  --secure true \
 
  --sslEnabled true \
 
  --sslProtocol SSL \
 
  Secure
 
$ pki-server http-connector-mod -i tomcat@acme \
 
  --sslImpl org.dogtagpki.tomcat.JSSImplementation \
 
  Secure
 
$ pki-server http-connector-cert-add -i tomcat@acme \
 
  --keyAlias sslserver \
 
  --keystoreType pkcs11 \
 
  --keystoreProvider Mozilla-JSS
 
</pre>
 
 
 
== Using JSSE Connector ==
 
 
 
To generate internal SSL certificate:
 
 
 
<pre>
 
$ openssl req \
 
  -newkey rsa:2048 \
 
  -x509 \
 
  -nodes \
 
  -days 365 \
 
  -subj "/CN=acme.pki-demo.svc" \
 
  -keyout /var/lib/tomcats/acme/conf/sslserver.key \
 
  -out /var/lib/tomcats/acme/conf/sslserver.crt
 
</pre>
 
 
 
To generate HTTPS connector:
 
 
 
<pre>
 
$ pki-server http-connector-add -i tomcat@acme \
 
  --port 8443 \
 
  --scheme https \
 
  --secure true \
 
  --sslEnabled true \
 
  --sslProtocol SSL \
 
  Secure
 
$ pki-server http-connector-cert-add -i tomcat@acme \
 
  --certFile /var/lib/tomcats/acme/conf/sslserver.crt \
 
  --keyFile /var/lib/tomcats/acme/conf/sslserver.key
 
</pre>
 
 
 
= Generating External SSL Certificate =
 
 
 
Run the following command to request a certificate from Let's Encrypt:
 
 
 
<pre>
 
$ certbot certonly --manual -d acme.demo.dogtagpki.org --register-unsafely-without-email
 
</pre>
 
 
 
Create the ACME response:
 
 
 
<pre>
 
$ oc rsh <pod> mkdir -p /var/lib/tomcats/acme/webapps/.well-known/acme-challenge
 
$ oc rsync acme-challenge/ <pod>:/var/lib/tomcats/acme/webapps/.well-known/acme-challenge
 
</pre>
 
 
 
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/acme.demo.dogtagpki.org/fullchain.pem
 
* key: /etc/letsencrypt/live/acme.demo.dogtagpki.org/privkey.pem
 
 
 
= Installing External SSL Certificate =
 
 
 
Remove the current route:
 
 
 
<pre>
 
$ oc delete routes/acme
 
</pre>
 
 
 
Prepare a configuration file (e.g. acme-route-secure.yaml):
 
 
 
<pre>
 
apiVersion: v1
 
kind: Route
 
metadata:
 
  labels:
 
    app: acme
 
  name: acme
 
spec:
 
  host: acme.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: acme
 
    weight: 100
 
  wildcardPolicy: None
 
</pre>
 
 
 
Then execute the following command:
 
 
 
<pre>
 
$ oc create -f acme-route-secure.yaml
 
</pre>
 
 
 
To validate, open https://acme.demo.dogtagpki.org with a browser.
 
 
 
= Updating ACME Image =
 
 
 
To deploy newer ACME image:
 
 
 
<pre>
 
$ oc import-image edewata/acme
 
</pre>
 
 
 
It will automatically respawn the pods with the new image.
 
 
 
= Testing with an ACME Client =
 
 
 
To submit an ACME request:
 
 
 
<pre>
 
$ certbot certonly --manual \
 
    -d server.example.com \
 
    --register-unsafely-without-email \
 
    --preferred-challenges dns \
 
    --server https://acme.demo.dogtagpki.org/acme/directory
 
</pre>
 
  
 
= See Also =
 
= See Also =

Revision as of 19:56, 29 June 2020

Overview

This page describes the process to deploy PKI ACME responder on OpenShift.

Demo: https://acme.demo.dogtagpki.org/acme/directory

Development branch: https://github.com/edewata/pki/commits/acme

Deployment

See Also