Nexus Certificate Manager

Migrate existing CM installation to Kubernetes (Helm)

This article describes how to migrate an existing Nexus Certificate Manager (CM) installation to Kubernetes using Helm.

Prerequisites

  • Certificate Manager (CM) is installed with CM version 8.15.x or later.

    • Earlier CM versions are not supported for migration and must be updated before a migration.

  • A supported database server must be installed/available. Access to the database itself and the type of deployment of the database is not part of the scope of this guide.

  • Knowledge or experience of deployment and troubleshooting in Kubernetes.

  • Kubernetes version 1.33.8 or later.

  • License file must be available.

  • Helm version 3.6.2 or later.

  • Kubectl version 1.33.8 or later.

  • Any supported Podman version, Docker version, or other container image build tool, such as Buildah.

  • Administrator's Workbench, Registration Authority, and Certificate Controller clients from CM distributable package.

  • A Kubernetes namespace for the deployment exists and access to it is available, with both kubectl and helm commands configured to use it as the current namespace.

  • Before deploying, verify that the storage class configured for the CF PVCs supports ReadWriteManyaccess mode.

Recommendations

Migration to Kubernetes is an advanced topic and requires analysis of the current configuration and use cases to adapt it to fit well on a Kubernetes deployment. It’s recommended to use the cf-example and pgw-example as a starting point but those charts likely may still need modifications to fully fit all use cases.

  • Configuration files and libraries/addons (such as HSM) can be mounted as volumes to the pods, via ConfigMaps, or Secrets. Libraries or addons which require write access for files (which could be for example a PKCS#11 library writing configuration or logs), may need to be copied to persistent volumes which must then be mounted in each container requiring them.

  • Data such as configuration or libraries should be deployed as read-only data in ConfigMaps or Secrets (by using Helm or kubectl) to the highest extent possible. Removing volumes can lead to loss of data and configuration.

  • It is recommended to keep the Helm deployment/umbrella chart in a version controlled code repository with the exception of configuration files, certificates and keystores, which contain binary data or may hold sensitive data, such as passwords and private keys.

Step-by-step instructions

Deployment directory setup

  • The distributable contains a helm directory where the Helm charts are stored. It contains the following charts:

    • cf

    • cf-example

    • pgw

    • pgw-example

The cf and pgw charts are the base charts. These charts contain the base templates for Certificate Manager and Protocol Gateway application deployment, but do not contain any configuration.

The cf-example and pgw-example charts are the parent charts. The parent charts are example charts with configuration for an initial example deployment, and can be renamed and modified by the customer as needed, with customer specific configuration, trust stores and key stores.

The cf-example and pgw-example charts have explicit dependencies to the cf and pgw base charts in their Chart.yaml files. The path to the base charts must match where the charts are stored on the file system.

Copy all these charts to a suitable location in a host which can reach the targeted Kubernetes-based system.

Once the charts are extracted from the deliverable, the existing configuration to be migrated can be added to the parent charts.

It is recommended to keep the parent charts under a version control system, such as Git. The base charts may also be uploaded to an OCI registry, but they shall not be uploaded to any publicly available registries or repositories.

For deploying both Certificate Manager server and Protocol Gateway at the same time, an umbrella chart may also be defined with both cf-example and pgw-example as dependencies.

See the official Helm documentation for more information.

Load the container images

The container images for CM are located in the images directory within the distributable package.

The images can be read with below commands.

Example using docker, podman and buildah tools:

docker image load --input images/cf-server-image-<version>.tar
docker image load --input images/pgw-image-<version>.tar
podman image load --input images/cf-server-image-<version>.tar
podman image load --input images/pgw-image-<version>.tar
buildah pull docker-archive:images/cf-server-image-<version>.tar
buildah pull docker-archive:images/pgw-image-<version>.tar

If images are stored in private container registries they could be pulled by updating the configuration file values.yaml:

# the image and tag references for the CF image. The image is required to be
# stored in a registry.
image:
  repository: <registry-url>/x-repo
  tag: <version-tag>
  pullPolicy: IfNotPresent

CF and CIS migration initialization

Once extracted from the deliverable, the cf-example chart will contain configuration files and certificates with initial configuration:

├── Chart.yaml
├── files
│   ├── certs
│   │   ├── kek.p12
│   │   ├── pin.p12
│   │   ├── tls.p12
│   │   ├── tcsigner.p12
        ..etc.

│   ├── config
│   │   ├── cis.conf
│   │   ├── cm.conf
        ...etc.

│   ├── inputviews
│   │   ├── ac-iv.conf
│   │   ├── acme-account-reg-search.conf
│   │   ├── acme-prereg-search.conf
        ...etc.

│   ├── keystore
│   ├── license
│   ├── pinprocedures
│   │   ├── generate_puk.conf
        ...etc.

All obfuscated configuration files will require their .seed file to be copied alongside its obfuscated configuration file to the corresponding subdirectory under files in the cf-example Helm chart.

While CM allows for obfuscating new parameters in configuration files it’s not recommended to do so for Kubernetes deployments, because each time the CF pods restart, scale in or are re-deployed, the obfuscation changes are lost. To have a permanent effect, the seed file as well as the configuration file must be copied from the container to the Helm chart configuration, as the Helm chart is the source of the configuration.

Migrating CF and CIS configuration files

  1. Copy any customized PIN procedures from the source CM installation to the cf-example chart:

cp <old CM server dir>/config/pinprocedures/* cf-example/files/pinprocedures/
  1. From the source CM installation, copy all configuration files from the old CM installation directory to the cf-example chart:

cp <old CM server dir>/config/* cf-example/files/config/

If any of the config name contains space characters as in for example ecs template.tpl, replace the space character with two underscore characters, as follows: ecs__template.tpl.

  1. Remove all existing files in the certs directory in cf-example, and then copy all files from the old CM installation certs directory to the cf-example chart.

rm -f cf-example/files/certs/
cp <old CM server dir>/certs/* cf-example/files/certs/
  1. The CIS keystores must be moved to the directory keystore in the cf-example chart as these cannot be backed by a read-only Secret from the chart directly. In a default deployment the commands to move the keystore files would be as follows:

mv cf-example/files/certs/ca.p12 cf-example/files/keystore/
mv cf-example/files/certs/rsapss.p12 cf-example/files/keystore/
mv cf-example/files/certs/dsa.p12 cf-example/files/keystore/
mv cf-example/files/certs/ecdsa.p12 cf-example/files/keystore/
mv cf-example/files/certs/edwards.p12 cf-example/files/keystore/
mv cf-example/files/certs/ml-dsa.p12 cf-example/files/keystore/
mv cf-example/files/certs/pure-slh-dsa.p12 cf-example/files/keystore/
mv cf-example/files/certs/hash-slh-dsa.p12 cf-example/files/keystore/

If any of the keystore files are not found it means such keys were never added. The mv errors can be ignored.

  1. Verify the CIS keystore name and path for cis.crypto.device is correct in cis.conf Migrating CF format files

    example cis.crypto.device.1.file = keystore/ca.p12

Customized certificate format files and other format files require creating additional ConfigMap templates inside cf-example/templates. The ConfigMap templates can be defined in the same way as for example pinprocedures.yaml, and then be mounted to the CF container by using the extraVolumes and extraVolumeMounts parameters in cf-example/values.yaml. The ConfigMap may also be a Secret with type Opaque instead if so desired.

There is an example on how to use the extraVolumes and extraVolumeMounts to mount a ConfigMap as files in the Migrating HSM libraries and configuration section below.

Migrating license files

Copy license files from old CM installation under the license folder cf-example/files/license:

cp <old CM install dir>/config/license/* cf-example/files/license/

CM license file

Place the CM license files under the license folder cf-example/files/license.

Migrating HSM drivers and configuration

Configuring HSM PKCS#11 drivers with CM on Kubernetes may be done in several ways. The most important aspect of it is that CIS and CF can point out the path to the HSM PKCS#11 library file, and also read the corresponding environment variables for locating the configuration file of the HSM PKCS#11 driver.

One way to handle this is to mount a volume in the CF containers containing the configuration for the HSM driver by creating a Secret or ConfigMap with the configuration files into the desired destination directory in the CF container. Then an environment variable is provided with a ConfigMap which points out the location of the HSM configuration files.

The HSM library/driver file is typically too large to deploy via a ConfigMap or a Secret, so it must be copied to the container in some other way. kubectl cp cannot be used because the CF container image lacks the support to use it due to security hardening reasons.

Instead, a Kubernetes Job can be used to deploy a Pod running a temporary container with a suitable temporary image such as busybox. The container in this Pod must mount the drivers subdirectory from the shared volume cf. This way, any files copied to the drivers directory in the temporary Pod will also be reflected in the CF Pod in /opt/drivers.

kubectl can then be used to copy the HSM driver library files to where the drivers sub path is mounted.


Here follows an example for configuring an Utimaco HSM library:

  1. Create the directory example-cf/files/hsm/ and copy the HSM config file to example-cf/files/hsm/cs_pkcs11_R3.cfg.

  2. Create a new ConfigMap template, for example cf-example/templates/hsm-files.yaml, with the content:

apiVersion: v1
kind: ConfigMap
metadata:
  name: hsm-files
binaryData:
  {{- $files := .Files }}
    {{- range $key, $value := .Files.Glob "files/hsm/*" }}
      {{- if hasPrefix "files/hsm/" $key }}
      {{ $key | trimPrefix "files/hsm/" }}: {{ $files.Get $key | b64enc }}
    {{- end }}
  {{- end }}
  1. Create another ConfigMap template for environment variables,cf-example/templates/hsm-config.yaml with the following content:

apiVersion: v1
kind: ConfigMap
metadata:
  name: hsm-env
data:
  CS_PKCS11_R3_CFG: /opt/hsm/cs_pkcs11_R3.cfg
  1. Add volume and volume mount for the hsm-files ConfigMap and environment variables hsm-env in cf-example/values.yaml:

  extraVolumes: 
    - name: hsm-files
      configMap:
        name: hsm-files
        defaultMode: 0555

  extraVolumeMounts:
    - name: hsm-files
      mountPath: /opt/hsm
      readOnly: true

  environment:
    - name: CS_PKCS11_R3_CFG
      valueFrom:
        configMapKeyRef:
          name: hsm-env
          key: CS_PKCS11_R3_CFG

Steps to add the HSM driver:

Copy the HSM driver library inside the CF pod mount path /opt/drivers/ by using a batch job.

  1. Make sure to copy the HSM driver library file libcs_pkcs11_R3.so to the host where kubectl has access to the target Kubernetes environment.

  2. Create a new YAML file, for example copy_job.yaml. Avoid creating the YAML file in any of the Helm charts directories.

  3. Save the YAML file with the below content:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: copy-hsm-driver
    spec:
      template:
        spec:
          containers:
          - name: app
            image: busybox
            command: ["sleep", "600"]
            volumeMounts:
            - mountPath: /opt/drivers
              name: cf
              subPath: drivers
          volumes:
          - name: cf
            persistentVolumeClaim:
              claimName: cf
          restartPolicy: Never
    
  4. Deploy the new YAML file:

    kubectl apply -f copy_job.yaml
    
  5. Run the command to copy the HSM driver library:

    kubectl cp libcs_pkcs11_R3.so copy-hsm-driver-<id>:/opt/drivers/
    
  6. Verify that the HSM driver library is present inside the CF Pods on the path /opt/drivers:

    kubectl exec cm-cf-0 -- ls -la /opt/drivers
    Defaulted container "cf" out of: cf, cf-init (init)
    total 4539
    drwxrwxrwx 2 0 1000       0 Aug 14 08:28 .
    drwxr-xr-x 1 0    0    4096 Aug 14 11:34 ..
    -rwxrwxrwx 1 0 1000 4639392 Aug 14 09:13 libcs_pkcs11_R3.so
    
  7. Delete the copy_job.yaml file.

  8. Delete job.batch/copy-hsm-driver from the namespace:

    kubectl delete job.batch/copy-hsm-driver
    

Device Configurations

  1. Edit cis.conf and make sure that the device configuration points to the HSM library file, as in this example:

;- Examples of PKCS#11 device configurations

cis.crypto.device.10.name = CryptoServer (RSA and RSASSA-PSS)
cis.crypto.device.10.type = PKCS11
cis.crypto.device.10.label = CIS Slot
cis.crypto.device.10.library = /opt/drivers/libcs_pkcs11_R3.so
cis.crypto.device.10.algorithm = RSA
;;cis.crypto.device.10.algorithmOID = RSA
cis.crypto.device.10.keysize = 2048 3072 4096 8192
cis.crypto.device.10.pin = 1234
cis.crypto.device.10.hashInCis = false

The Utimaco HSM driver library file is now present in the path /opt/drivers/libcs_pkcs11_R3.so and can be referenced from cm.conf and cis.conf by specifying this path.

Deploy the CF application

Run the following commands to deploy the cf-example chart:

cd cf-example
helm dependency build
helm install -n <your-namespace> cm .

Monitor the CF Pods and make sure they start up correctly.

kubectl logs <cf-pod> -n <your-namespace>

To forward the port 5009, simply run the below command in a shell:

kubectl port-forward service/cm-cf 5009:5009


PGW migration initialization

Migrating Protocol Gateway requires collecting important files, such as TLS keystores, trust store files and configuration files, such as server.xml.

Migrate PGW configuration

The content from the following directories needed to be added as content for the volumes in the pgw-example chart:

  • PGW configuration which contains the conf and certdir: <pgw_home>/conf

  • Tomcat configuration which contains the TLS and server.xml: <tomcat_home>/conf

When copying files into the chart,

  • Include only the CA certificate, any *.p12 files, and other relevant configuration files that override existing content. Excludelogging.properties; do not override this file in pgw-example/files/conf or pgw-example/files/tomcat

  • Copy <pgw_home>/conf/certdir/* to pgw-example/files/certdir/

  • WebUI is not supported with helm charts for now skip <pgw_home>/conf/Json-template for this version

find <pgw-home>/conf/ -type f -not -name 'logging.properties' -exec cp '{}' 'pgw-example/files/conf/{}' ';'
cp <pgw-home/conf/certdir/* pgw-example/files/certdir/
cp <tomcat-home>/conf/* pgw-example/files/tomcat/

Verify that the connectivity

For connection verify the details in pgw-example/files/conf/cm-gateway.properties are correct.

  • Thecmhost parameter should point to the cmhost=<cf-server-host> ClusterIP load balancing service.

    • example cmhost=cm-cf

  • The officer.keyfile has correct cert path

Make sure that the Tomcat health check valve is configured in server.xml below the Host XML element:

        <Valve className="org.apache.catalina.valves.HealthCheckValve" />

The connectors defined in server.xml must map to the ports defined in the service, which can be seen in the pgw base chartpgw/values.yaml default service ports are 8080, 8443, 8444. If the service or liveness and readiness probe ports are different in the values.yaml, then either they can be overridden in the pgw-example umbrella chart or changed in server.xml to map correctly to those defined on the service, liveness and readiness probes.

Configure HSM with PGW container

Configuring the HSM with PGW can be performed similar to the approach outlined in the section Migrating CF and CIS HSM libraries and configuration above.

Deploy the PGW application

Run the following commands to deploy the pgw-example chart:

cd pgw-example
helm dependency build
helm install -n <your-namespace> pgw .

Monitor the PGW Pods and make sure they start up correctly.

kubectl logs <pgw-pod> -n <your-namespace>

To access the Protocol Gateway ports for testing, forward them by running the below command in a shell:

kubectl port-forward service/pgw 8080:8080 8443:8443 8444:8444


Last updated: