11.4. Certificate Operations

This section will describe how to manage the HTTPS certificates that dr-provision uses for the API port and the HTTPS static file port.

11.4.1. API Certificate Management

In dr-provision versions earlier than 4.6.0, API certificates can only be managed via the –tls-cert and –tls-key startup options.

In dr-provision versions 4.6.0 and later, the –tls-cert and –tls-key startup options are only used for loading certificates at initial startup time. After that, you must use the drpcli system certs or drpcli files certs commands to manage the TLS certificate that the API uses.

11.4.1.1. Get API Certificates

You can fetch the current TLS certificate and private key that the API uses with:

drpcli system certs get server.crt server.key

This will retrieve the TLS certificate and private key that the API is using, and saves them in x.509 DER encoded form.

11.4.1.2. Set API Certificates

You can update the TLS certificate and private key that the API will use for new connections with:

drpcli system certs set server.crt server.key

This will upload the X.509 DER encoded certificate and private key to dr-provision, which (assuming that they are valid) will be used for any new connections. Additionally, the new certs will be applied cluster-wide if running in an HA cluster.

11.4.2. Static Certificate Management (4.7.0 and higher)

dr-provision 4.7.0 and higher have a static HTTPS server that will be used as an alternative to serving static files over HTTP whenever feasible. It uses the –static-tls-cert and –static-tls-key startup options to load the static HTTPS certs initially. Afterwards, the drpcli files certs commands will manage the static HTTPS certificates in the same way the drpcli system certs commands manage the API certs.

11.4.3. Client Certificate Authoriation (v4.10.3 and higher)

dr-provision 4.10.3 and higher has the ability to authenticate with Client Certificates. The server allows for client certificates and if present will use the CommonName field of the Subject of the Certificate as the user requesting access.

The only requirement is that the client certificates MUST be signed by an authority in the chain of the server’s current certificate. This prevents Certs used for other applications or services to enable things in DRP.

If a User is not found that matches the CommonName, the request will be failed and audited as an forbidden request. It the User is found, the Roles and Tenant associated with that user will be used.

A User is NOT required to exist that matches the CommonName if the certificate contains additional RackN-specific extensions. The certificate can specify the desired access controls and this allows for custom operations with an undefined User. The CommonName will be used as the principal for normal operations and auditing.

The following extensions are allowed:

  • 1.3.6.1.4.1.59257.1.1 - This ASN1 string specifies a JSON claims list.

    1.3.6.1.4.1.59257.1.1=ASN1:UTF8String:[ { \"scope\": \"machines\", \"action\": \"*\", \"specific\": \"*\" } ]
    

This is an example for an openssl extensions file that would be passed to the CA signing operation. These MUST be done on the CSR signing side. Extensions are not passed from the CSR to the final certificate.

  • 1.3.6.1.4.1.59257.1.2 - This ASN1 string specifies a comma-separated list of Roles

    1.3.6.1.4.1.59257.1.2=ASN1:UTF8String:operator
    

This is an example for an openssl extensions file that would be passed to the CA signing operation. These MUST be done on the CSR signing side. Extensions are not passed from the CSR to the final certificate.

This is an exmaple of an OpenSSL extensions file that could be used to generate a client certificate.

basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
1.3.6.1.4.1.59257.1.2=ASN1:UTF8String:readonly
1.3.6.1.4.1.59257.1.1=ASN1:UTF8String:[ { \"scope\": \"machines\", \"action\": \"*\", \"specific\": \"*\" } ]

The following commands for Linux OpenSSL could be used to sign/create a client key. This assumes that your openssl configuration has access to your CA Key and CA Certificate. This will create a certificate for client-1.

mkdir -p client_certs
CL=client-1
cat >client_certs/${CL}_ext.cnf <<EOF
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
1.3.6.1.4.1.59257.1.2=ASN1:UTF8String:readonly
1.3.6.1.4.1.59257.1.1=ASN1:UTF8String:[ { \"scope\": \"machines\", \"action\": \"*\", \"specific\": \"*\" } ]
EOF
openssl req -nodes -newkey rsa:4096 -keyout client_certs/${CL}.key.pem -out client_certs/${CL}.csr -subj "/C=US/ST=TX/L=Austin/O=RackN/OU=Engineering/CN=${CL}/emailAddress=support@rackn.com"
openssl ca -extfile client_certs/${CL}_ext.cnf -days 1650 -notext -batch -in client_certs/${CL}.csr -out client_certs/${CL}.cert.pem

To generate a Certificate without Authorizations, remove the two lines with 1.3.6.1.3 from the extensions file.

11.4.4. Mutual TLS Setup

The following script can be used to setup MTLS. It will create a CA certificate (self-signed). It will then create client and server certificates that can be used. Everything will be stored under the mtls directory.

It requires Linux and has been tested with default OpenSSL configuration on Ubunut 20.04.

#!/usr/bin/env bash

set -e
set -x

IP1=$1
DNS1=$2

# Start with config file from bottom
mkdir mtls
cd mtls
mkdir demoCA server_certs client_certs demoCA/private demoCA/newcerts
echo 01 > demoCA/serial
touch demoCA/index.txt

# Build CA
openssl req -nodes -newkey rsa:4096 -keyout demoCA/private/cakey.pem -new -x509 -out demoCA/cacert.pem -subj "/C=US/ST=TX/L=Austin/O=RackN/OU=Engineering/CN=ca-server/emailAddress=support@rackn.com"
openssl x509 -in demoCA/cacert.pem -out demoCA/cacert.pem -outform PEM

# Create empty extent
cat >client_certs/client-1_ext.cnf <<EOF
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
EOF

cp client_certs/client-1_ext.cnf client_certs/client-2_ext.cnf
cat >>client_certs/client-2_ext.cnf <<EOF
1.3.6.1.4.1.59257.1.2=ASN1:UTF8String:readonly
EOF

cp client_certs/client-1_ext.cnf client_certs/client-3_ext.cnf
cat >>client_certs/client-3_ext.cnf <<-EOF
1.3.6.1.4.1.59257.1.1=ASN1:UTF8String:[ { \"scope\": \"machines\", \"action\": \"*\", \"specific\": \"*\" } ]
EOF

cp client_certs/client-1_ext.cnf client_certs/client-4_ext.cnf
cat >>client_certs/client-4_ext.cnf <<-EOF
1.3.6.1.4.1.59257.1.1=ASN1:UTF8String:[ { \"scope\": \"machines\", \"action\": \"*\", \"specific\": \"*\" } ]
1.3.6.1.4.1.59257.1.2=ASN1:UTF8String:readonly
EOF

cp client_certs/client-1_ext.cnf client_certs/client-5_ext.cnf

for CL in client-1 client-2 client-3 client-4 client-5 ; do
  openssl req -nodes -newkey rsa:4096 -keyout client_certs/${CL}.key.pem -out client_certs/${CL}.csr -subj "/C=US/ST=TX/L=Austin/O=RackN/OU=Engineering/CN=${CL}/emailAddress=support@rackn.com"
  openssl ca -extfile client_certs/${CL}_ext.cnf -days 1650 -notext -batch -in client_certs/${CL}.csr -out client_certs/${CL}.cert.pem
done


# Make Server certs

# Onny config piece is DNS name and IP address
cat >server_certs/server_ext.cnf <<EOF
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = ${IP1}
IP.2 = 127.0.0.1
DNS.1 = ${DNS1}
DNS.2 = localhost
EOF

openssl req -nodes -newkey rsa:4096 -keyout server_certs/server.key.pem -out server_certs/server.csr -subj "/C=US/ST=TX/L=Austin/O=RackN/OU=Engineering/CN=server/emailAddress=support@rackn.com"
openssl ca -extfile server_certs/server_ext.cnf -days 1650 -notext -batch -in server_certs/server.csr -out server_certs/server.cert.pem

To Use, save the script as setup-mtls.sh. The script requires the IP address of the system and the name of the system. The server certificate will be generated with server as the CN, but additional names and IPs are added.

The script can be run as:

chmod +x setup-mtls.sh
./setup-mtls.sh 1.2.3.4 myhost.company.com

The following files are used for the RackN client and server.

  • mtls/demoCA/cacert.pem - the CA Certificate for validation. This is used by dr-provision and drpcli to validate certificates.

  • mtls/server_certs/server.key.pem - The Server’s key file

  • mtls/server_certs/server.cert.pem - The Server’s cert file

  • mtls/client_certs/client-##.key.pem - The Client’s key file

  • mtls/client_certs/client-##.cert.pem - The Client’s cert file

There are 5 certs generated for clients.

  • client-1 - CN = client1 and NO extensions

  • client-2 - CN = client2 and a Roles extension of read-only (requires ux-views plugin)

  • client-3 - CN = client3 and a Claims extension of access to machines.

  • client-4 - CN = client4 and both the above extensions

  • client-5 - CN = client5 and NO extentions

To use client-1 and client-5, you will need to create a User in the system for access.

To use the server certificate and key use the commands above to load the certificates. The server will use the system default location for CA certficates. Additionally, the server can be started with the SSL_CERT_FILE environment variable to point at the specific CA certificate or the SSL_CERT_DIR environment variable to point to a complete directory of certificates. These will override the system level locations.

For client certificate usage, drpcli has additional flags, drpclirc, and environment variable support to specify the client certificate file and key file.

The client by default does NOT verify the certficate of the server. This can be turned on by adding an additional flag. The client will attempt to use the system enabled certificates, but an additional flag is added to allow for the specification of the CA certificate.