Encryption (SSL)

Encryption solves the problem of the man in the middle (MITM) attack. That’s because your packets, while being routed to your destination, travel your network and hop from machines to machines. If your data is PLAINTEXT, any of these routers could read the content of the data you’re sending.

encryption

After Encryption is enabled and SSL certificates being carefully setup, your data is now encrypted and securely transmitted over the network. With SSL, only the first and the final machine possess the ability to decrypt the packet being sent.

Steps to generate SSL certificates

1. Generate SSL key and certificate for each node

The first step of deploying one or more nodes with the SSL support is to generate the key and the certificate for each machine in the cluster. You can use Java’s keytool utility to accomplish this task. We will generate the key into a temporary keystore initially so that we can export and sign it later with CA.

keytool -genkey -keyalg RSA -keystore {keystore-name}.jks -storepass {store-password} -keypass {key-password} -validity {validity} -alias {alias-name} -dname CN={node-fqdn}
You need to specify six parameters in the above command

The following command can be run afterwards to verify the contents of the generated certificate:

keytool -list -v -keystore {keystore-name}.jks

2. Creating your own CA (Certificate Authority)

After the first step, each machine in the cluster has a public-private key pair, and a certificate to identify the machine. The certificate, however, is unsigned, which means that an attacker can create such a certificate to pretend to be any machine.

Therefore, it is important to prevent forged certificates by signing them for each machine in the cluster. A certificate authority (CA) is responsible for signing certificates. CA works likes a government that issues passports—the government stamps (signs) each passport so that the passport becomes difficult to forge. Other governments verify the stamps to ensure the passport is authentic. Similarly, the CA signs the certificates, and the cryptography guarantees that a signed certificate is computationally difficult to forge. Thus, as long as the CA is a genuine and trusted authority, the clients have high assurance that they are connecting to the authentic machines.

openssl req -new -x509 -keyout ca-key -out ca-cert -days {validity} -passout pass:{ca-pass} -subj "/CN={sever-fqdn}"
You need to specify three parameters in the above command

3. Create a Truststore

In contrast to the keystore in step 1 that stores each machine’s own identity, the truststore of a client stores all the certificates that the client should trust. Importing a certificate into one’s truststore also means trusting all certificates that are signed by that certificate. As the analogy above, trusting the government (CA) also means trusting all passports (certificates) that it has issued.

This attribute is called the chain of trust, and it is particularly useful when deploying SSL on a large cluster. You can sign all certificates in the cluster with a single CA, and have all machines share the same truststore that trusts the CA. That way all machines can authenticate all other machines.

Add the generated CA to the clients’ truststore so that the clients can trust this CA.

keytool -keystore {truststore-name}.jks -storepass {store-pass} -alias CARoot -import -file ca-cert -noprompt
You need to specify two parameters in the above command

4. Signing the certificate

The next step is to sign all certificates generated by step 1 with the CA generated in step 2.

First, you need to export the certificate from the keystore:

keytool -keystore {keystore-name}.jks -certreq -file cert-file -storepass {store-pass} -keypass {key-pass} -alias {node-alias}
You need to specify five parameters in the above command

Then sign it with the CA:

openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days {validity} -CAcreateserial -passin pass:{ca-pass}
You need to specify six parameters in the above command

5. Import Signed Certificate

Finally, you need to import both the certificate of the CA and the signed certificate into the keystore:

keytool -keystore {keystore-name}.jks -storepass {store-pass} -keypass {key-pass} -alias CARoot -import -file ca-cert -noprompt

keytool -keystore {keystore-name}.jks -storepass {store-pass} -keypass {key-pass} -alias {node-alias} -import -file cert-signed -noprompt
You need to specify six parameters in the above command

Here is an example of a bash script with all above steps. Note that one of the commands assumes a password of test1234, so either use that password or edit the command before running it.

Generate Certificate Script
#!/bin/bash
PASSWORD=test1234
VALIDITY=365
CN=node.domain.com
KEYSTORE_ALIAS=node
CA_ALIAS=CARoot

# for server

# generating CA
openssl req -new -x509 -keyout ca-key -out ca-cert -days $VALIDITY -passout pass:$PASSWORD -subj /CN=$CN
# generating server keystore
keytool -genkey -keyalg RSA -keystore kafka.server.keystore.jks -validity $VALIDITY -storepass $PASSWORD -keypass $PASSWORD -alias $KEYSTORE_ALIAS -dname CN=$CN
# generating server truststore and importing CA certificate in it
keytool -keystore kafka.server.truststore.jks -storepass $PASSWORD -alias $CA_ALIAS -import -file ca-cert -noprompt
# exporting server certificate from server keystore
keytool -keystore kafka.server.keystore.jks -certreq -file cert-file -alias $KEYSTORE_ALIAS -storepass $PASSWORD -keypass $PASSWORD
# signing server certificate with CA
openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days $VALIDITY -CAcreateserial -passin pass:$PASSWORD
# importing CA certificate in server keystore
keytool -keystore kafka.server.keystore.jks -alias $CA_ALIAS -import -file ca-cert -storepass $PASSWORD -keypass $PASSWORD -noprompt
# importing Signed server certificate in server keystore
keytool -keystore kafka.server.keystore.jks -alias $KEYSTORE_ALIAS -import -file cert-signed -storepass $PASSWORD -keypass $PASSWORD -noprompt