Security

Riak 2.0 supports authentication and authorization over encrypted channels via OpenSSL. This is useful to prevent accidental collisions between environments (e.g., pointing application software under active development at the production cluster) and offers protection against some malicious attacks, although Riak still should not be exposed directly to any unsecured network.

Several important caveats when enabling security:

  • There is no support yet for auditing. This is on the roadmap for a future release.
  • Two deprecated features will not work if security is enabled: link walking and Riak Search 1.0.
  • There are restrictions on Erlang modules exposed to MapReduce jobs when security is enabled.
  • Enabling security requires applications be designed to transition gracefully based on the server response or applications will need to be halted before security is enabled and brought back online with support for the new security features.

Server Configuration

The server must first be configured to enable security, users and security sources must be created, permissions applied and the correct certificates must be installed. An overview can be found at Authentication and Authorization.

Client Configuration

Note

OpenSSL 1.0.1g or later (or patched version built after 2014-04-01) is required for pyOpenSSL, which is used for secure transport in the Riak client. Earlier versions may not support TLS 1.2, the recommended security protocol.

On the client, simply create a SecurityCreds object with just a username, password and CA Certificate file. That would then need to be passed into the RiakClient initializer:

creds = SecurityCreds('riakuser',
                      'riakpass',
                      cacert_file='/path/to/ca.crt')
client = RiakClient(credentials=creds)

The credentials argument of a RiakClient constructor is a SecurityCreds object. If you specify a dictionary instead, it will be turned into this type:

creds = {'username': 'riakuser',
         'password': 'riakpass',
         'cacert_file': '/path/to/ca.crt'}
client = RiakClient(credentials=creds)

Note

A Certifying Authority (CA) Certificate must always be supplied to SecurityCreds by specifying the path to a CA certificate file via the cacert_file argument or by setting the cacert argument to an OpenSSL.crypto.X509 object. This mitigates MITM (man-in-the-middle) attacks by ensuring correct certificate validation.

Authentication Types

Trust and PAM Authentication

The most basic authentication would be Trust-based Authentication which is done exclusively on the server side by adding the appropriate trust security source:

riak-admin security add-source all 127.0.0.1/32 trust

PAM-based Authentication is another server-side solution which can be added by a pam security source with the name of the service:

riak-admin security add-source all 127.0.0.1/32 pam service=riak_pam

Even if you are using Trust authentication or the PAM module doesn’t require a password, you must supply one to the client API. From the client’s perspective, these are equivalent to Password authentication.

Password Authentication

The next level of security would be simply a username and password for Password-based Authentication. The server needs to first have a user and a password security source:

riak-admin security add-user riakuser password=captheorem4life
riak-admin security add-source riakuser 127.0.0.1/32 password

On the client, simply create a SecurityCreds object or dict with just a username and password. That would then need to be passed into the RiakClient initializer:

creds = {'username': 'riakuser',
         'password': 'riakpass',
         'cacert_file': '/path/to/ca.crt'}
client = RiakClient(credentials=creds)
myBucket = client.bucket('test')
val1 = "#SeanCribbsHoldingThings"
key1 = myBucket.new('hashtag', data=val1)
key1.store()

Client Certificate Authentication

If you are using the Protocol Buffers transport you could also add a layer of security by using Certificate-based Authentication. This time the server requires a certificate security source:

riak-admin security add-source riakuser 127.0.0.1/32 certificate

When the certificate source is used, the Riak username must match the common name, aka CN, that you specified when you generated your certificate. You can add a certificate source to any number of clients.

The SecurityCreds must then include the include a client certificate file and a private key file, too:

creds = {'username': 'riakuser',
         'password': 'riakpass',
         'cacert_file': '/path/to/ca.crt',
         'cert_file': '/path/to/client.crt',
         'pkey_file': '/path/to/client.key'}

Note

Username and password are still required for certificate-based authentication, although the password is ignored.

Optionally, the certificate or private key may be supplied as a string:

with open('/path/to/client.key', 'r') as f:
    preloaded_pkey = f.read()
with open('/path/to/client.crt', 'r') as f:
    preloaded_cert = f.read()
creds = {'username': 'riakuser',
         'password': 'riakpass',
         'cert': preloaded_cert,
         'pkey': prelocated_pkey}

Additional options

Certificate revocation lists

Another security option available is a Certificate Revocation List (CRL). It lists server certificates which, for whatever reason, are no longer valid. For example, it is discovered that the certificate authority (CA) had improperly issued a certificate, or if a private-key is thought to have been compromised. The most common reason for revocation is the user no longer being in sole possession of the private key (e.g., the token containing the private key has been lost or stolen):

creds = {'username': 'riakuser',
         'password': 'riakpass',
         'cacert_file': '/path/to/ca.crt',
         'crl_file': '/path/to/server.crl'}

Cipher options

The last interesting setting on SecurityCreds is the ciphers option which is a colon-delimited list of supported ciphers for encryption:

creds = {'username': 'riakuser',
         'password': 'riakpass',
         'ciphers': 'ECDHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA'}

A more detailed discussion can be found at Security Ciphers.

SecurityCreds object