How to generate a self-signed TLS certificates


#1

How to generate a self-signed TLS certificates

Prerequisites

Create basic folder hierarchy

$ sudo su -
$ mkdir /root/ca
$ cd /root/ca
$ mkdir certs crl newcerts private
$ chmod 700 private
$ touch index.txt
$ echo 1000 > serial

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
HOME                    = .
RANDFILE                = $ENV::HOME/.rnd
[ ca ]
default_ca      = CA_default            # The default ca section
[ CA_default ]
dir             = /root/ca              # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
new_certs_dir   = $dir/newcerts         # default place for new certs.
certificate     = $dir/certs/ca.crt     # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/ca.key   # The private key
RANDFILE        = $dir/private/.rand    # private random number file
x509_extensions = usr_cert              # The extensions to add to the cert
name_opt        = ca_default            # Subject Name options
cert_opt        = ca_default            # Certificate field options
default_days    = 365                   # how long to certify for
default_crl_days= 30                    # how long before next CRL
default_md      = default               # use public key default MD
preserve        = no                    # keep passed DN ordering
policy          = policy_match
[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
[ req ]
default_bits            = 2048
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
attributes              = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert
string_mask = utf8only
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = UK
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = London
localityName                    = Locality Name (eg, city)
localityName_default            = London
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Aerospike
organizationalUnitName          = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName                      = Common Name (aerospike tls-name)
commonName_max                  = 64
emailAddress                    = Email Address
emailAddress_max                = 64
[ req_attributes ]
challengePassword               = A challenge password
challengePassword_min           = 4
challengePassword_max           = 20
unstructuredName                = An optional company name
[ usr_cert ]
basicConstraints=CA:FALSE
nsComment                       = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ proxy_cert_ext ]
basicConstraints=CA:FALSE
nsComment                       = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
EOF

Create CA certificate and private key

$ cd /root/ca
$ openssl req -config openssl.cnf -new -x509 -days 1825 -extensions v3_ca -keyout private/ca.key -out certs/ca.crt

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 -config openssl.cnf -new -nodes -days 365 -keyout private/server.key -out server.csr

Sign the certificate

$ cd /root/ca
$ openssl ca -config openssl.cnf -policy policy_anything -out certs/server.crt -infiles server.csr

Define tls-name in aerospike.conf

Add the following to the ‘network’ stanza in the aerospike.conf, replacing with the chosen “Common Name”

tls <tlsname> {
    cert-file /root/ca/certs/server.crt
    ca-file /root/ca/certs/ca.crt
    key-file /root/ca/private/server.key
}

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 “Common Name” 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. Add the 'tls ’ stanza as defined above for the client
  3. In the ‘service’ stanza, change the ‘tls-authenticate-client false’ to 'tls-authenticate-client ’

Example network stanza with tls enabled:

network {
	tls server {
    	cert-file /root/ca/certs/server.crt
    	ca-file /root/ca/certs/ca.crt
    	key-file /root/ca/private/server.key
	}
	tls client {
    	cert-file /root/ca/certs/client.crt
    	ca-file /root/ca/certs/ca.crt
    	key-file /root/ca/private/client.key
	}
    service {
            tls-port 4333
            tls-address any
            tls-name server
            tls-authenticate-client client
    }

    heartbeat {
            mode mesh
            tls-port 3012
            tls-name server
            tls-mesh-seed-address-port 10.0.3.172 3012
            tls-mesh-seed-address-port 10.0.3.210 3012

            # To use unicast-mesh heartbeats, remove the 3 lines above, and see
            # aerospike_mesh.conf for alternative.

            interval 150
            timeout 10
    }

    fabric {
            tls-port 3011
            tls-name server
    }

    info {
            port 3003
    }
}

Test

The following test will work as the client can verify the server.crt it will receive from the server against the CA (server->client check), and the client presents the correct ‘client’ certificate for the server to verify the client against.

$ aql -h 127.0.0.1:server:4333 --tls-enable --tls-cafile=/root/ca/certs/ca.crt --tls-keyfile=/root/ca/private/client.key --tls-certfile=/root/ca/certs/client.crt
Seed:         127.0.0.1:server: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

The following test will fail as only the ‘client’ certificate is allowed, therefore authenticating with another one (e.g. server, since it was at hand) will not work:

aql -h 127.0.0.1:server:4333 --tls-enable --tls-cafile=/root/ca/certs/ca.crt --tls-keyfile=/root/ca/private/server.key --tls-certfile=/root/ca/certs/server.crt 
Seed:         127.0.0.1:server:4333
User:         None
Config File:  /etc/aerospike/astools.conf /root/.aerospike/astools.conf 
2018-10-04 13:57:58 WARN SSL_connect failed: error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error
2018-10-04 13:57:58 WARN Failed to connect to seed 127.0.0.1 4333. AEROSPIKE_ERR_CONNECTION Socket connect failed: 127.0.0.1:4333
Error -10: Failed to connect

Keywords

GENERATE OPENSSL CERTIFICATE CERT KEY CSR SELF-SIGNED

Timestamp

10/4/2018