At this time only the protocol buffers client supports client certificates. HTTP is not supported.
It is necessary to set up a Root Certificate authority to be able to create and sign certificates.
References:
http://www.freebsdmadeeasy.com/tutorials/web-server/apache-ssl-certs.php
http://pages.cs.wisc.edu/~zmiller/ca-howto/
http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/x160.html
Steps:
- Create openssl configuration file similar to this. This was copied from the "base" openssl configuration
(
/usr/local/openssl/openssl.cnf.sample
on FreeBSD)
HOME = .
RANDFILE = $ENV::HOME/.rnd
oid_section = new_oids
[ new_oids ]
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = .
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.db
new_certs_dir = $dir/newcerts
certificate = $dir/certs/cacert.pem
serial = $dir/serial
crlnumber = $dir/crlnumber
crl = $dir/crl.pem
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand
x509_extensions = usr_cert
name_opt = ca_default
cert_opt = ca_default
default_days = 3650
default_crl_days = 30
default_md = sha1
preserve = no
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
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
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State Name (full name)
stateOrProvinceName_default = WA
localityName = Locality (eg, city)
0.organizationName = Org Name (eg, company)
0.organizationName_default = Basho Technologies
organizationalUnitName = Org Unit Name (eg, section)
organizationalUnitName_default = CliServ
commonName = Common Name
commonName_max = 64
emailAddress = [email protected]
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 = 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
[ tsa ]
default_tsa = tsa_config1
[ tsa_config1 ]
dir = ./demoCA
serial = $dir/tsaserial
crypto_device = builtin
signer_cert = $dir/tsacert.pem
certs = $dir/cacert.pem
signer_key = $dir/private/tsakey.pem
default_policy = tsa_policy1
other_policies = tsa_policy2, tsa_policy3
digests = md5, sha1
accuracy = secs:1, millisecs:500, microsecs:100
clock_precision_digits = 0
ordering = yes
tsa_name = yes
ess_cert_id_chain = no
- Create a directory structure and some files. This is flexible based on your config file:
$ mkdir -p ~/ssl-ca/conf
$ cp openssl.conf ~/ssl-ca/conf
$ mkdir -p ~/ssl-ca/certs
$ mkdir -p ~/ssl-ca/newcerts
$ mkdir -p ~/ssl-ca/private
$ mkdir -p ~/ssl-ca/req
$ touch ssl-ca/index.db
$ touch ssl-ca/index.db.attr
$ echo '1000' > ssl-ca/serial
- Create Root CA key and certificate
$ cd ~/ssl-ca
$ openssl req -new -x509 -days 3650 -extensions v3_ca -keyout private/cakey.pem -out certs/cacert.pem -config conf/openssl.conf
Generating a 2048 bit RSA private key
..........................................................................................................................................................................................+++
......................................................+++
writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
...
...
...
The ssl-ca
directory will now contain the following:
$ find .
.
./private
./private/cakey.pem
./newcerts
./conf
./conf/openssl.conf
./req
./certs
./certs/cacert.pem
./index.db
./serial
./index.db.attr
- Create certificate request for
riakuser
user
The following will create a certificate and specify the cert subject on the command line. Note that the CN
(common name) parameter must match the user name configured via riak-admin security add-user riakuser
[~/ssl-ca]$ openssl req -new -config conf/openssl.conf -nodes -out req/client-certificate-1.pem -keyout private/client-certificate-1-key.pem -subj '/C=US/ST=WA/O=Basho Technologies/OU=CliServ/CN=riakuser/[email protected]'
Generating a 2048 bit RSA private key
.........................................................................+++
....................+++
writing new private key to 'private/client-certificate-1-key.pem'
-----
- Sign certificate request with Root CA
The following uses the -verbose
flag to show extra output, and the -batch
flag to not require any input.
[~/ssl-ca]$ openssl ca -verbose -batch -config conf/openssl.conf -out certs/client-certificate-1.pem -infiles req/client-certificate-1.pem
Using configuration from conf/openssl.conf
Enter pass phrase for ./private/cakey.pem:
0 entries loaded from the database
generating index
message digest is sha1
policy is policy_match
next serial number is 1000
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=US, ST=WA, O=Basho Technologies, OU=CliServ, CN=riakuser/[email protected]
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
00:cb:56:ec:ea:3a:a8:d5:c3:9f:ba:de:1c:fd:9d:
d5:b3:c4:24:f4:11:4e:29:6b:2e:8f:8f:e6:00:88:
fe:ce:dd:59:4e:91:5f:0f:24:b9:37:0e:c2:2e:f0:
60:ee:a1:97:f5:19:01:79:25:d2:9d:06:fb:d6:58:
8e:62:a1:c9:22:7e:88:51:92:58:38:b3:1d:35:04:
14:f6:8e:c3:40:0e:ce:67:92:ef:5d:fd:73:d4:6c:
3d:87:68:0e:22:e3:5e:bf:a5:6b:75:15:df:17:26:
c4:70:f6:7f:71:1e:57:46:38:9d:01:75:3f:00:3c:
b4:6f:eb:13:3e:2d:b5:8b:29:f5:d1:05:36:c6:9c:
96:87:73:e4:7c:69:d9:dd:2d:de:4a:cf:ef:0c:e9:
cb:7f:96:cc:82:df:66:27:b4:b8:54:7d:d1:fd:09:
62:2b:25:d6:b9:36:25:cb:16:ee:e9:89:eb:a1:d2:
66:b6:c7:08:9a:8d:35:aa:4a:12:dd:ab:38:6d:21:
ae:6c:78:af:2b:52:6e:2a:67:0f:a7:72:b7:aa:fd:
95:b0:e7:08:79:85:30:b2:9a:46:31:6e:cf:2c:ec:
06:6a:f4:ca:02:dd:53:80:2c:d8:09:f7:3c:bc:d8:
56:96:3c:ea:36:51:9f:03:b9:bd:38:93:76:38:07:
12:8d
Exponent: 65537 (0x10001)
Attributes:
a0:00
Signature Algorithm: sha1WithRSAEncryption
ae:0c:d7:ff:d2:49:27:3f:80:58:b0:99:59:25:44:72:e1:a7:
42:a8:cd:3d:61:89:17:bf:ce:88:d9:91:b5:cf:75:2f:fd:0d:
d0:01:82:4e:b6:3c:49:fe:f9:0f:65:38:5b:33:fa:ad:d8:d2:
a0:4b:ac:25:2b:ce:67:ae:ca:6f:c7:a8:ca:54:f7:2e:56:42:
25:3f:f3:10:ff:58:81:87:e1:1b:d9:4c:09:1b:9d:8f:b3:e3:
3e:f9:93:fb:77:bb:87:9a:07:38:95:c7:0c:5b:29:a1:41:33:
04:18:d0:10:76:79:1c:da:54:91:3e:39:6f:dd:8a:39:18:59:
e3:2f:6f:fb:f1:bf:f9:1e:be:dd:85:0c:4b:6b:ba:67:44:ff:
ca:64:a4:98:48:28:35:ac:d9:6a:f4:eb:80:b0:19:8e:3d:36:
36:99:73:dc:2b:66:87:09:6b:97:90:e4:19:d3:0d:9c:f6:31:
f3:74:c1:df:90:7a:ce:5d:8f:15:3f:ef:b4:86:45:b6:66:da:
ba:3d:56:a1:4e:df:db:4e:7f:06:1b:e9:c9:f9:a0:52:e4:8b:
95:d7:8f:a1:99:13:69:7d:7c:b4:c4:48:99:0b:bf:36:43:f2:
af:d3:25:1c:17:c2:af:45:8b:f3:e5:f0:1f:5c:42:09:6c:41:
65:a6:99:bc
Check that the request matches the signature
Signature ok
The subject name appears to be ok, checking data base for clashes
Everything appears to be ok, creating and signing the certificate
Successfully added extensions from config
Certificate Details:
Serial Number: 4096 (0x1000)
Validity
Not Before: Feb 24 18:46:10 2014 GMT
Not After : Feb 22 18:46:10 2024 GMT
Subject:
countryName = US
stateOrProvinceName = WA
organizationName = Basho Technologies
organizationalUnitName = CliServ
commonName = riakuser
emailAddress = [email protected]
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
7F:4C:CA:27:04:2C:4A:FB:D3:E3:D9:A0:4E:ED:8A:40:76:32:26:D7
X509v3 Authority Key Identifier:
keyid:38:37:C2:18:BE:CF:34:F1:DF:3D:43:96:10:82:77:9D:8E:AA:CC:4D
Certificate is to be certified until Feb 22 18:46:10 2024 GMT (3650 days)
Write out database with 1 new entries
writing new certificates
writing ./newcerts/1000.pem
Data Base Updated
- Create certificate for Riak server
Assume that the server's host name is riak-node-1
. The following commands will create a certificate that can be used by Riak on that server. The CN
section of the subject must match the FQDN of the server or certificate verification will fail.
[~/ssl-ca]$ openssl req -new -config conf/openssl.conf -nodes -out req/riak-node-1.pem -keyout private/riak-node-1-key.pem -subj '/C=US/ST=WA/O=Basho Technologies/OU=CliServ/CN=riak-node-1/[email protected]'
Generating a 2048 bit RSA private key
......+++
...................+++
writing new private key to 'private/riak-node-1-key.pem'
-----
[~/ssl-ca]$ openssl ca -batch -config conf/openssl.conf -in req/riak-node-1.pem -out certs/riak-node-1-cert.pem
Using configuration from conf/openssl.conf
Enter pass phrase for ./private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 4097 (0x1001)
Validity
Not Before: Feb 24 20:26:44 2014 GMT
Not After : Feb 22 20:26:44 2024 GMT
Subject:
countryName = US
stateOrProvinceName = WA
organizationName = Basho Technologies
organizationalUnitName = CliServ
commonName = riak-node-1
emailAddress = [email protected]
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
DC:F1:64:06:2B:08:69:BE:5A:F8:E7:22:6C:CA:2B:5E:50:8B:56:E1
X509v3 Authority Key Identifier:
keyid:38:37:C2:18:BE:CF:34:F1:DF:3D:43:96:10:82:77:9D:8E:AA:CC:4D
Certificate is to be certified until Feb 22 20:26:44 2024 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated
- Using these certificates for Riak
You will want to generate a server certificate for each node in your Riak cluster (using a CN
that matches each node's host name). Then, copy the generated certificate and the public part of the Root CA to the riak
config directory (/etc/riak
or /usr/local/etc/riak
):
# scp certs/riak-node-1-cert.pem riak-node-1:/etc/riak
# scp certs/cacert.pem riak-node-1:/etc/riak
# scp private/riak-node-1-key.pem riak-node-1:/etc/riak
Then, in /etc/riak/riak.conf
:
ssl.certfile = /etc/riak/riak-node-1-cert.pem
ssl.keyfile = /etc/riak/riak-node-1-key.pem
ssl.cacertfile = /etc/riak/cacert.pem
Once this has been configured on all nodes, do a rolling restart of Riak. Now you can use the client certificate you generated for riakuser
to authenticate.
# riak-admin security add-user riakuser
# riak-admin security add-source riakuser 192.168.1.0/24 certificate
# riak-admin security print-sources
+--------------------+--------------+-----------+----------+
| users | cidr | source | options |
+--------------------+--------------+-----------+----------+
| riakuser |192.168.1.0/24|certificate| [] |
+--------------------+--------------+-----------+----------+
All that remains is to use this certificate via your Riak client. You can specify the full path to your client certificate, associated private key, and CA certificate file via these options:
{cacertfile, File} %% full path to CA cert file (certs/cacert.pem)
{certfile, File} %% full path to client cert (certs/client-certificate-1.pem)
{keyfile, File} %% full path to client cert private key (private/client-certificate-1-key.pem)
Ruby :auth
data:
auth = {
:cert => "/home/lbakken/Projects/basho/CorrugatedIron/tools/test-ca/certs/riakuser-client-cert.pem",
:key => "/home/lbakken/Projects/basho/CorrugatedIron/tools/test-ca/private/riakuser-client-cert-key.pem",
:ca_file => "/home/lbakken/Projects/basho/CorrugatedIron/tools/test-ca/certs/cacert.pem",
:user => "riakuser",
:password => ""
}
c = Riak::Client.new(:host => 'riak-test', :pb_port => 10017, :authentication => auth)