Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

N1QL Support for X.509

DZone's Guide to

N1QL Support for X.509

Couchbase Server has added support for X.509 based client certificate authentication. See where this matters and how to use it.

· Database Zone ·
Free Resource

MariaDB TX, proven in production and driven by the community, is a complete database solution for any and every enterprise — a modern database for modern applications.

Couchbase Server 5.5 adds the support for X.509 based client certificate authentication. Earlier releases already had the support for X.509 certificates which enabled server authentication and encryption for client-server communications. By adding the support for client certificate authentication to the list of authentication methods that Couchbase already supports today (LDAP based authentication and basic authentication), the client-server communication has now become even more secure.

Overview of SSL/TLS Handshake

The SSL/TLS handshake uses a combination of asymmetric encryption, symmetric encryption, and digital certificates to establish trust and secure the communication between a server and a client. The following is an overview of the messages exchanged as part of the handshake procedure:

  • The client sends a "client hello" message, which contains the SSL/TLS version, the cipher suites, and the data compression schemes supported by the client.
  • The server responds with a "server hello" message, where it would indicate SSL/TLS version and the cipher suite to be used. The server would also send its digital certificate and public key. Depending on the mode chosen during server initialization, the server can optionally request for client certificate to mutually authenticate each other.
  • The client then verifies the server's digital certificate by consulting the Certificate Authority. If the verification succeeds, then the client has established trust with the server.
  • The client now sends a random byte string, encrypted using the server's public key, back to the server. This will be used by both parties to generate a shared secret key.
  • If the server has requested a client certificate, the client sends its digital certificate and a random byte string encrypted using the client's private key.
  • If the server had requested a client certificate, then it'll verify the client's digital certificate. If the verification fails, then the session ends. The server, depending on whether the client certificate was requested or not, will now decrypt the random byte string sent by the client using either the server's private key or the client's public key. This random byte will then be used by both parties to generate a shared secret key.
  • The client will send a "client finished" message back to the server which will be encrypted using the shared secret key.
  • The server sends back the "server finished" message back to the client which will also be encrypted using the shared secret key.
  • For the duration of this session, all the subsequent messages will be encrypted using the shared secret key.

Motivation

The motivation to support client certificate authentication in Couchbase Server is to enable a 2-way authentication scheme where both the client and the server mutually establish trust, thereby making the communication more secure. As a client certificate uniquely identifies a client/user, there would be no need to rely on the password based authentication (although some implementations use both to provide a 2-level authentication scheme). Furthermore, by encoding the client/user information into the client certificate, the server can now use this information to tie into the RBAC system for authorization. In essence, client certificates can be used to provide both authentication and authorization while accessing Couchbase Server.

Configuration

In order to configure the client certificates, TLS must first be enabled on Couchbase Server using X.509 certificates. By default, Couchbase Server enables TLS using self-signed certificates but, as a best practice, it’s advised to set up TLS on Couchbase Server using X.509 certificates that are assigned to the organization/customer by a Certificate Authority.

Note that it is common practice for organizations to set up a hierarchy of Certificate Authorities (CAs). The topmost tier being the root CA, which will be typically issued by third-party CA like Verisign. The lower tiers being the intermediate CAs that are in turn issued by their immediate predecessor in the hierarchy. While enabling TLS on Couchbase Server, one of the CAs in the hierarchy will be configured as a Cluster Certificate. This cluster certificate will, in turn, be used to sign all the certificates that are assigned to every node that makes up the Couchbase cluster. More details about TLS support in Couchbase and the instructions to enable it can be found in this article.

Configuring Client Certificate Authentication

Once the server has been configured with X.509 certificates, we can now enable the client certificate authentication and authorization (auth[N | Z]) feature on the server. The following are the three states in which the client certificate auth[N|Z] can be configured:

  • disable: The server doesn’t look for a client certificate while processing the request and uses basic auth[N | Z]. This is the default mode.
  • enable: If the client presents a certificate, the server uses that for auth[N | Z], and if the certificate is either malformed or contains wrong user information, then the request will be failed. However, if the client does not present a certificate, then the server falls back to basic auth.
  • mandatory: The server always expects the client to present a valid client certificate in order to gain access to the resources. If the client doesn’t present a client certificate, then the request will fail.

While generating the client certificate, the user would have encoded user information into one of the following fields in the certificate: commonName or subject alternative name[URI | email | dns].

Now, how will the server know from which field to extract the user information from? That’s where the prefixes field comes in. While configuring the client certificate authentication feature, the administrator must provide information about prefixes, which is an array of {path, prefix, delimiter} triples, that are to be used by the server to extract the user information. The administrator can specify up to 10 such triplets.

The following table explains the intent of each field in a triple:

Field

Description

path

This denotes the field in the X.509 certificate that will be used to extract the username from. If the State setting is either enable or mandatory then this field must be set by the user. It can take the following values:

  1. subject.cn: Refers to the commonName field in the subject section of the certificate.
  2. san.uri: Refers to the URI field in Subject Alternate Names section of the certificate.
  3. san.email: Refers to the email field in Subject Alternate Names section of the certificate.
  4. san.dnsname: Refers to the DNS field in Subject Alternate Names section of the certificate.

prefix

This is an optional field. This denotes the prefix to be ignored from the username read from the Path. If this field is specified and the username doesn’t have the prefix then we move on to the next triple. If it’s empty then we use the entire value found in Path.

delimiter

This is an optional field. Mulitple characters can be configured as the delimiters. After the prefix removal, we pick the characters from the value until a delimiter is encountered and that would be returned as the username. If there is no match against any of delimiters then we return the entire string as the username.

Each triple is processed in the order specified until a match is found. A "match" occurs when we find a name in the client certificate that satisfies path and prefix. The delimiter field does not count for matches, and if the delimiter is not found, we take up to the end of the string.

{
   "state" : "enable",
   "prefixes" : [
       { "path" : "subject.cn", "prefix" : "www.", "delimiter" : "." },
       { "path" : "san.dnsname", "prefix" : "node1.", "delimiter" : "." }
   ]
}


Details about the ways to enable this feature on the server can be found in this article.

Note that the clients of Couchbase Server will be applications/services typically deployed along with the database within the same infrastructure. Hence, from a certificate management perspective, it makes more sense for the IT folks to generate the client certificates using the cluster

This is a certificate that was deployed within Couchbase Server. Hence, Couchbase Server uses the cluster certificate to verify the validity of the client certificates when used.

X.509 Client Certificate auth[N | Z] Behavior

Once the client certificate auth[N | Z] feature is configured, depending on the state, all the web-servers within Couchbase Server will be reconfigured to request a client certificate during the TLS handshake. When a client presents a client certificate while issuing a request, the validation of the client certificate happens as part of TLS handshake. If the validation fails, then the request will be rejected at the TLS level, and typically the error string returned will be “bad certificate.” The TLS layer also provides an alert number associated with it. If the validation succeeds, then the server gets to process the request further.

If the state is set to enable or mandatory, the server tries to get the certificate from the HTTP request object. If the client certificate is missing and the state is enabled, then the server falls back to regular basic-auth. But if the state is mandatory, then the server fails the request.

Once the server gets the client certificate from the request, then the prefix from the configuration is used to extract the username. The server reads the value of the field from the certificate identified by path and then uses the prefix and delimiter settings to extract the username from the value read. The prefix portion of the value is discarded and the substring until the delimiter is returned as the username. If both are undefined, then the entire value is returned as the username. If the prefix is defined but it is not found in the value, then we move on to the next triple. Some of the fields (specifically pertaining to Subject Alternate Names) may have multiple values defined. In such a case, we pick the first value that matches the prefix and delimiter.

Once the username extraction is successful, that is used as a local identity, and the server checks to see if the identity has the required permissions to process the request. If none of the prefixes match or there was a match but the username extracted doesn’t exist or if the username exists but doesn’t have correct permissions, then the request will be failed with an HTTP 401 error.

Running a Query With Client Certificate Auth[N | Z]

After having enabled TLS on the Couchbase server and configured the client certificate auth[N | Z] feature on the server, the following are the steps one would have to follow to run a query using a client certificate.

Generate Client Certificates

As mentioned before, the client certificates need to be signed by the Couchbase cluster certificate. In order to generate a client certificate, we can make use of the directory hierarchy that’s been used to generate the cluster certificate and node certificates (as described in the “Configure X.509 certificates” section of this article).

In our example, the client certificate will be signed by an intermediate CA which in turn will be signed by the root CA (which is also the cluster certificate). Note that in order to generate a certificate with subject alternative name section populated, one would have to supply a configuration file to the OpenSSL command. The following is an example configuration file (let’s call it ssl.conf):

[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions      = req_ext
prompt              = no

[ req_distinguished_name ] 
countryName         = US
stateOrProvinceName = California
localityName        = San Jose
organizationName    = XYZ Inc
commonName          = www.xyz.com

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1   = node1-user1.xyz.com
DNS.2   = node1-user2.xyz.com

Create directories called client_int and client_cert under the SSLCA directory. As a first step, generate the intermediate CA that will be used to sign the client certificate.

$ cd client_int

$ openssl genrsa -out int.key 2048                                                                                                                                              

$ openssl req -new -key int.key -out int.csr -subj '/C=US/O=XYZ/CN=XYZIntCA'                                                                                  

$ cat <<EOF >> ./v3_ca.ext
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
EOF

$ openssl x509 -req -in int.csr -CA ../root/ca.pem -CAkey ../root/ca.key -CAcreateserial-CAserial ../root/rootCA.srl -extfile ./v3_ca.ext -out int.pem -days 365

As a next step, generate the client certificate. Here, it’s assumed that the ssl.conf file is stored in the SSLCA directory. Once the client certificate is generated, combine the client certificate and the intermediate certificate to create a chain. This chain is the one that will be presented when issuing requests to Couchbase Server.

$ cd ../client_cert

$ openssl genrsa -out client.key 2048                                                                                                                                              

$ openssl req -new -key client.key -out client.csr -config ../ssl.conf                                                                                                             

$ openssl x509 -req -in client.csr -CA ../client_int/int.pem -CAkey ../client_int/int.key -CAcreateserial-CAserial ../client_int/intermediateCA.srl -out client.pem -days 365 -extfile ../ssl.conf -extensions req_ext

$ cat client.pem ../client_int/int.pem > chain.pem

Finally, now comes the time to execute a query using just the client certificate. The assumption here is that the command is being executed from the SSLCA directory.

$ curl --cacert ./root/ca.pem
        --cert-type PEM
        --key-type PEM
        --cert ./client_cert/chain.pem
        --key ./client_cert/client.key https://localhost:18093/query/service
        -d "statement=select * from system:keyspaces"

MariaDB AX is an open source database for modern analytics: distributed, columnar and easy to use.

Topics:
x509 certificates ,couchbase ,n1ql ,ssl certificate ,tls security ,database

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}