How to generate self-signed TLS certificates

The Aerospike Knowledge Base has moved to https://support.aerospike.com. Content on https://discuss.aerospike.com is being migrated to either https://support.aerospike.com or https://docs.aerospike.com. Maintenance on articles stored in this repository ceased on December 31st 2022 and this article may be stale. If you have any questions, please do not hesitate to raise a case via https://support.aerospike.com.

How to generate self-signed TLS certificates

Prerequisites

Create basic folder hierarchy

$ sudo -i
$ mkdir /root/CA
$ cd /root/CA
$ mkdir newcerts private
$ touch index.txt
$ echo -n 01 > serial
$ export tlsname="tls1"

Create a custom openssl.cnf

This step is to create a small and sane openssl.cnf, as to not rely on the provided global one that would differ per version and OS.

cat <<'EOF' > /root/CA/openssl.cnf
dir			= .

[ req ]
default_bits  	    = 2048  		# Size of keys
default_keyfile     = key.pem		# name of generated keys
default_md          = sha256		# message digest algorithm
string_mask         = nombstr		# permitted characters
distinguished_name  = req_distinguished_name
req_extensions      = v3_req

[ req_distinguished_name ]
# Variable name		        Prompt string
#----------------------   ----------------------------------
0.organizationName        = Organization Name (company)
organizationalUnitName    = Organizational Unit Name (department, division)
emailAddress              = Email Address
emailAddress_max          = 40
localityName              = Locality Name (city, district)
stateOrProvinceName       = State or Province Name (full name)
countryName               = Country Name (2 letter code)
countryName_min           = 2
countryName_max           = 2
commonName                = Common Name (hostname, IP, or your name)
commonName_max            = 64

# Default values for the above, for consistency and less typing.
# Variable name			  Value
#------------------------------	  ------------------------------
0.organizationName_default         = Aerospike
organizationalUnitName_default     = Support
emailAddress_default               = noreply@example.com
localityName_default               = London
stateOrProvinceName_default	   = London
countryName_default		   = GB
commonName_default                 = DefaultCommonName

[ v3_ca ]
basicConstraints	= CA:TRUE
subjectKeyIdentifier	= hash
authorityKeyIdentifier	= keyid:always,issuer:always
subjectAltName = IP:127.0.0.1

[ v3_req ]
basicConstraints	= CA:FALSE
subjectKeyIdentifier	= hash
subjectAltName = @alt_names

[alt_names]
DNS.1   = TLSNAME
IP.1 = 127.0.0.1

[ ca ]
default_ca		= CA_default

[ CA_default ]
serial			= $dir/serial
database		= $dir/index.txt
new_certs_dir		= $dir/newcerts
certificate		= $dir/cacert.pem
private_key		= $dir/private/cakey.pem
default_days		= 365
default_md		= sha256
preserve		= no
email_in_dn		= no
nameopt			= default_ca
certopt			= default_ca
policy			= policy_match

[ policy_match ]
countryName		= match
stateOrProvinceName	= match
organizationName	= match
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional
EOF

sed -i "s/TLSNAME/$tlsname/g" /root/CA/openssl.cnf

Create CA certificate and private key

$ cd /root/CA
$ openssl req -new -nodes -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 3650 -config ./openssl.cnf -subj "/C=GB/ST=London/L=London/O=Aerospike/CN=$tlsname"

Create the server certificates

Generate a certificate signing request (CSR)

The name you use in “Common Name” field will later be used in aerospike.conf as tls-name.

$ cd /root/CA
$ openssl req -new -nodes -extensions v3_req -out req.pem -config ./openssl.cnf -subj "/C=GB/ST=London/L=London/O=Aerospike/CN=$tlsname"

Sign the certificate

$ cd /root/CA
$ openssl ca -batch -extensions v3_req -out cert.pem -config ./openssl.cnf -infiles req.pem

Copy the certificate to Aerospike directory

$ mkdir -p /etc/aerospike/ssl/$tlsname
$ cp cert.pem /etc/aerospike/ssl/$tlsname
$ cp cacert.pem /etc/aerospike/ssl/$tlsname
$ cp key.pem /etc/aerospike/ssl/$tlsname

Copy the certificate to other nodes

Copy /etc/aeropsike/ssl/$tlsname directory to all other nodes in the cluster to use the same certificates.

Define tls-name in aerospike.conf

Add the following to the ‘network’ stanza in the aerospike.conf, replacing with the chosen tlsname in step 1.

tls tls1 {
    cert-file /etc/aerospike/ssl/tls1/cert.pem
    key-file /etc/aerospike/ssl/tls1/key.pem
    ca-file /etc/aerospike/ssl/tls1/cacert.pem
}

Generate more certificates if needed

If you want to use separate tls certificate for clients, fabric and heartbeat messages, follow the above “Create the server certificates” section again, changing the ‘server.*’ file names to another certificate name. Be sure to use a unique tlsname as well.

Enable use of TLS in service (client), fabric and/or heartbeat messages

Follow configuration reference for the ‘service’, ‘heartbeat’ and ‘fabric’ stanzas in aerospike.conf as specified here

To check details of an existing certificate

$ openssl x509 -in certs/server.crt -noout -text

Note on mutual authentication

The above will allow the fabric, heartbeat node-to-node authentication as well as server to authenticate to client (client to verify server). If you need the client to authenticate to server (server to verify client), you can for example:

  1. Generate another certificate using the “Create the server certificate” section above, calling it for example ‘client’
  2. In the ‘service’ stanza, change the ‘tls-authenticate-client false’ to ‘tls-authenticate-client ’

Example network stanza with tls enabled:

network {
    tls tls1 {
        cert-file /etc/aerospike/ssl/tls1/cert.pem
        key-file /etc/aerospike/ssl/tls1/key.pem
        ca-file /etc/aerospike/ssl/tls1/cacert.pem
    }
    service {
        # address any
        # port 3000
        tls-port 4333
        tls-address any
        tls-authenticate-client false
        tls-name tls1
    }
    heartbeat {
        mode mesh
        tls-port 3012
        tls-name tls1
        tls-mesh-seed-address-port IP_OF_ANOTHER_NODE 3012
        interval 150
        timeout 10
    }
    fabric {
        # port 3001
        tls-port 3011
        tls-name tls1
    }
    info {
        port 3003
    }
}

Test

The below test will work for both: mutual auth with server cert and server-side only auth. If using a separate client certificate, replace the server key and cert with client ones.

$ aql -h 127.0.0.1:tls1:4333 --tls-enable --tls-cafile=/etc/aerospike/ssl/tls1/cacert.pem --tls-keyfile=/etc/aerospike/ssl/tls1/key.pem --tls-certfile=/etc/aerospike/ssl/tls1/cert.pem
Seed:         127.0.0.1:tls1:4333
User:         None
Config File:  /etc/aerospike/astools.conf /root/.aerospike/astools.conf 
Aerospike Query Client
Version 3.15.3.14
C Client Version 4.3.12
Copyright 2012-2017 Aerospike. All rights reserved.
aql> select * from test
0 rows in set (0.205 secs)

OK

aql> exit

Keywords

GENERATE OPENSSL CERTIFICATE CERT KEY CSR SELF-SIGNED

Timestamp

October 2018

1 Like