123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- #!/usr/bin/env bash
- set -eu
- KEYSTORE_FILENAME="kafka.keystore.jks"
- VALIDITY_IN_DAYS=3650
- DEFAULT_TRUSTSTORE_FILENAME="kafka.truststore.jks"
- TRUSTSTORE_WORKING_DIRECTORY="truststore"
- KEYSTORE_WORKING_DIRECTORY="keystore"
- CA_CERT_FILE="ca-cert"
- KEYSTORE_SIGN_REQUEST="cert-file"
- KEYSTORE_SIGN_REQUEST_SRL="ca-cert.srl"
- KEYSTORE_SIGNED_CERT="cert-signed"
- export COUNTRY=US
- export STATE=IL
- export ORGANIZATION_UNIT=SE
- export CITY=Chicago
- export PASSWORD=secret
- COUNTRY=$COUNTRY
- STATE=$STATE
- OU=$ORGANIZATION_UNIT
- CN=kafka0 # COMMON NAME VERIFICATION GOES BRR
- LOCATION=$CITY
- PASS=$PASSWORD
- function file_exists_and_exit() {
- echo "'$1' cannot exist. Move or delete it before"
- echo "re-running this script."
- exit 1
- }
- if [ -e "$KEYSTORE_WORKING_DIRECTORY" ]; then
- file_exists_and_exit $KEYSTORE_WORKING_DIRECTORY
- fi
- if [ -e "$CA_CERT_FILE" ]; then
- file_exists_and_exit $CA_CERT_FILE
- fi
- if [ -e "$KEYSTORE_SIGN_REQUEST" ]; then
- file_exists_and_exit $KEYSTORE_SIGN_REQUEST
- fi
- if [ -e "$KEYSTORE_SIGN_REQUEST_SRL" ]; then
- file_exists_and_exit $KEYSTORE_SIGN_REQUEST_SRL
- fi
- if [ -e "$KEYSTORE_SIGNED_CERT" ]; then
- file_exists_and_exit $KEYSTORE_SIGNED_CERT
- fi
- echo "Welcome to the Kafka SSL keystore and trust store generator script."
- trust_store_file=""
- trust_store_private_key_file=""
- if [ -e "$TRUSTSTORE_WORKING_DIRECTORY" ]; then
- file_exists_and_exit $TRUSTSTORE_WORKING_DIRECTORY
- fi
- mkdir $TRUSTSTORE_WORKING_DIRECTORY
- echo
- echo "OK, we'll generate a trust store and associated private key."
- echo
- echo "First, the private key."
- echo
- openssl req -new -x509 -keyout $TRUSTSTORE_WORKING_DIRECTORY/ca-key \
- -out $TRUSTSTORE_WORKING_DIRECTORY/ca-cert -days $VALIDITY_IN_DAYS -nodes \
- -subj "/C=$COUNTRY/ST=$STATE/L=$LOCATION/O=$OU/CN=$CN"
- trust_store_private_key_file="$TRUSTSTORE_WORKING_DIRECTORY/ca-key"
- echo
- echo "Two files were created:"
- echo " - $TRUSTSTORE_WORKING_DIRECTORY/ca-key -- the private key used later to"
- echo " sign certificates"
- echo " - $TRUSTSTORE_WORKING_DIRECTORY/ca-cert -- the certificate that will be"
- echo " stored in the trust store in a moment and serve as the certificate"
- echo " authority (CA). Once this certificate has been stored in the trust"
- echo " store, it will be deleted. It can be retrieved from the trust store via:"
- echo " $ keytool -keystore <trust-store-file> -export -alias CARoot -rfc"
- echo
- echo "Now the trust store will be generated from the certificate."
- echo
- keytool -keystore $TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME \
- -alias CARoot -import -file $TRUSTSTORE_WORKING_DIRECTORY/ca-cert \
- -noprompt -dname "C=$COUNTRY, ST=$STATE, L=$LOCATION, O=$OU, CN=$CN" -keypass $PASS -storepass $PASS -storetype JKS
- trust_store_file="$TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME"
- echo
- echo "$TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME was created."
- # don't need the cert because it's in the trust store.
- rm $TRUSTSTORE_WORKING_DIRECTORY/$CA_CERT_FILE
- echo
- echo "Continuing with:"
- echo " - trust store file: $trust_store_file"
- echo " - trust store private key: $trust_store_private_key_file"
- mkdir $KEYSTORE_WORKING_DIRECTORY
- echo
- echo "Now, a keystore will be generated. Each broker and logical client needs its own"
- echo "keystore. This script will create only one keystore. Run this script multiple"
- echo "times for multiple keystores."
- echo
- echo " NOTE: currently in Kafka, the Common Name (CN) does not need to be the FQDN of"
- echo " this host. However, at some point, this may change. As such, make the CN"
- echo " the FQDN. Some operating systems call the CN prompt 'first / last name'"
- # To learn more about CNs and FQDNs, read:
- # https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/X509ExtendedTrustManager.html
- keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME \
- -alias localhost -validity $VALIDITY_IN_DAYS -genkey -keyalg RSA \
- -noprompt -dname "C=$COUNTRY, ST=$STATE, L=$LOCATION, O=$OU, CN=$CN" -keypass $PASS -storepass $PASS -storetype JKS
- echo
- echo "'$KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME' now contains a key pair and a"
- echo "self-signed certificate. Again, this keystore can only be used for one broker or"
- echo "one logical client. Other brokers or clients need to generate their own keystores."
- echo
- echo "Fetching the certificate from the trust store and storing in $CA_CERT_FILE."
- echo
- keytool -keystore $trust_store_file -export -alias CARoot -rfc -file $CA_CERT_FILE -keypass $PASS -storepass $PASS
- echo
- echo "Now a certificate signing request will be made to the keystore."
- echo
- keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias localhost \
- -certreq -file $KEYSTORE_SIGN_REQUEST -keypass $PASS -storepass $PASS
- echo
- echo "Now the trust store's private key (CA) will sign the keystore's certificate."
- echo
- openssl x509 -req -CA $CA_CERT_FILE -CAkey $trust_store_private_key_file \
- -in $KEYSTORE_SIGN_REQUEST -out $KEYSTORE_SIGNED_CERT \
- -days $VALIDITY_IN_DAYS -CAcreateserial \
- -extensions kafka -extfile san.cnf
- # creates $KEYSTORE_SIGN_REQUEST_SRL which is never used or needed.
- echo
- echo "Now the CA will be imported into the keystore."
- echo
- keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias CARoot \
- -import -file $CA_CERT_FILE -keypass $PASS -storepass $PASS -noprompt
- rm $CA_CERT_FILE # delete the trust store cert because it's stored in the trust store.
- echo
- echo "Now the keystore's signed certificate will be imported back into the keystore."
- echo
- keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias localhost -import \
- -file $KEYSTORE_SIGNED_CERT -keypass $PASS -storepass $PASS
- echo
- echo "All done!"
- echo
- echo "Deleting intermediate files. They are:"
- echo " - '$KEYSTORE_SIGN_REQUEST_SRL': CA serial number"
- echo " - '$KEYSTORE_SIGN_REQUEST': the keystore's certificate signing request"
- echo " (that was fulfilled)"
- echo " - '$KEYSTORE_SIGNED_CERT': the keystore's certificate, signed by the CA, and stored back"
- echo " into the keystore"
- rm $KEYSTORE_SIGN_REQUEST_SRL
- rm $KEYSTORE_SIGN_REQUEST
- rm $KEYSTORE_SIGNED_CERT
|