generate_certs.sh 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #!/usr/bin/env bash
  2. set -eu
  3. KEYSTORE_FILENAME="kafka.keystore.jks"
  4. VALIDITY_IN_DAYS=3650
  5. DEFAULT_TRUSTSTORE_FILENAME="kafka.truststore.jks"
  6. TRUSTSTORE_WORKING_DIRECTORY="truststore"
  7. KEYSTORE_WORKING_DIRECTORY="keystore"
  8. CA_CERT_FILE="ca-cert"
  9. KEYSTORE_SIGN_REQUEST="cert-file"
  10. KEYSTORE_SIGN_REQUEST_SRL="ca-cert.srl"
  11. KEYSTORE_SIGNED_CERT="cert-signed"
  12. export COUNTRY=US
  13. export STATE=IL
  14. export ORGANIZATION_UNIT=SE
  15. export CITY=Chicago
  16. export PASSWORD=secret
  17. COUNTRY=$COUNTRY
  18. STATE=$STATE
  19. OU=$ORGANIZATION_UNIT
  20. CN=kafka0 # COMMON NAME VERIFICATION GOES BRR
  21. LOCATION=$CITY
  22. PASS=$PASSWORD
  23. function file_exists_and_exit() {
  24. echo "'$1' cannot exist. Move or delete it before"
  25. echo "re-running this script."
  26. exit 1
  27. }
  28. if [ -e "$KEYSTORE_WORKING_DIRECTORY" ]; then
  29. file_exists_and_exit $KEYSTORE_WORKING_DIRECTORY
  30. fi
  31. if [ -e "$CA_CERT_FILE" ]; then
  32. file_exists_and_exit $CA_CERT_FILE
  33. fi
  34. if [ -e "$KEYSTORE_SIGN_REQUEST" ]; then
  35. file_exists_and_exit $KEYSTORE_SIGN_REQUEST
  36. fi
  37. if [ -e "$KEYSTORE_SIGN_REQUEST_SRL" ]; then
  38. file_exists_and_exit $KEYSTORE_SIGN_REQUEST_SRL
  39. fi
  40. if [ -e "$KEYSTORE_SIGNED_CERT" ]; then
  41. file_exists_and_exit $KEYSTORE_SIGNED_CERT
  42. fi
  43. echo "Welcome to the Kafka SSL keystore and trust store generator script."
  44. trust_store_file=""
  45. trust_store_private_key_file=""
  46. if [ -e "$TRUSTSTORE_WORKING_DIRECTORY" ]; then
  47. file_exists_and_exit $TRUSTSTORE_WORKING_DIRECTORY
  48. fi
  49. mkdir $TRUSTSTORE_WORKING_DIRECTORY
  50. echo
  51. echo "OK, we'll generate a trust store and associated private key."
  52. echo
  53. echo "First, the private key."
  54. echo
  55. openssl req -new -x509 -keyout $TRUSTSTORE_WORKING_DIRECTORY/ca-key \
  56. -out $TRUSTSTORE_WORKING_DIRECTORY/ca-cert -days $VALIDITY_IN_DAYS -nodes \
  57. -subj "/C=$COUNTRY/ST=$STATE/L=$LOCATION/O=$OU/CN=$CN"
  58. trust_store_private_key_file="$TRUSTSTORE_WORKING_DIRECTORY/ca-key"
  59. echo
  60. echo "Two files were created:"
  61. echo " - $TRUSTSTORE_WORKING_DIRECTORY/ca-key -- the private key used later to"
  62. echo " sign certificates"
  63. echo " - $TRUSTSTORE_WORKING_DIRECTORY/ca-cert -- the certificate that will be"
  64. echo " stored in the trust store in a moment and serve as the certificate"
  65. echo " authority (CA). Once this certificate has been stored in the trust"
  66. echo " store, it will be deleted. It can be retrieved from the trust store via:"
  67. echo " $ keytool -keystore <trust-store-file> -export -alias CARoot -rfc"
  68. echo
  69. echo "Now the trust store will be generated from the certificate."
  70. echo
  71. keytool -keystore $TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME \
  72. -alias CARoot -import -file $TRUSTSTORE_WORKING_DIRECTORY/ca-cert \
  73. -noprompt -dname "C=$COUNTRY, ST=$STATE, L=$LOCATION, O=$OU, CN=$CN" -keypass $PASS -storepass $PASS -storetype JKS
  74. trust_store_file="$TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME"
  75. echo
  76. echo "$TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME was created."
  77. # don't need the cert because it's in the trust store.
  78. rm $TRUSTSTORE_WORKING_DIRECTORY/$CA_CERT_FILE
  79. echo
  80. echo "Continuing with:"
  81. echo " - trust store file: $trust_store_file"
  82. echo " - trust store private key: $trust_store_private_key_file"
  83. mkdir $KEYSTORE_WORKING_DIRECTORY
  84. echo
  85. echo "Now, a keystore will be generated. Each broker and logical client needs its own"
  86. echo "keystore. This script will create only one keystore. Run this script multiple"
  87. echo "times for multiple keystores."
  88. echo
  89. echo " NOTE: currently in Kafka, the Common Name (CN) does not need to be the FQDN of"
  90. echo " this host. However, at some point, this may change. As such, make the CN"
  91. echo " the FQDN. Some operating systems call the CN prompt 'first / last name'"
  92. # To learn more about CNs and FQDNs, read:
  93. # https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/X509ExtendedTrustManager.html
  94. keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME \
  95. -alias localhost -validity $VALIDITY_IN_DAYS -genkey -keyalg RSA \
  96. -noprompt -dname "C=$COUNTRY, ST=$STATE, L=$LOCATION, O=$OU, CN=$CN" -keypass $PASS -storepass $PASS -storetype JKS
  97. echo
  98. echo "'$KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME' now contains a key pair and a"
  99. echo "self-signed certificate. Again, this keystore can only be used for one broker or"
  100. echo "one logical client. Other brokers or clients need to generate their own keystores."
  101. echo
  102. echo "Fetching the certificate from the trust store and storing in $CA_CERT_FILE."
  103. echo
  104. keytool -keystore $trust_store_file -export -alias CARoot -rfc -file $CA_CERT_FILE -keypass $PASS -storepass $PASS
  105. echo
  106. echo "Now a certificate signing request will be made to the keystore."
  107. echo
  108. keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias localhost \
  109. -certreq -file $KEYSTORE_SIGN_REQUEST -keypass $PASS -storepass $PASS
  110. echo
  111. echo "Now the trust store's private key (CA) will sign the keystore's certificate."
  112. echo
  113. openssl x509 -req -CA $CA_CERT_FILE -CAkey $trust_store_private_key_file \
  114. -in $KEYSTORE_SIGN_REQUEST -out $KEYSTORE_SIGNED_CERT \
  115. -days $VALIDITY_IN_DAYS -CAcreateserial \
  116. -extensions kafka -extfile san.cnf
  117. # creates $KEYSTORE_SIGN_REQUEST_SRL which is never used or needed.
  118. echo
  119. echo "Now the CA will be imported into the keystore."
  120. echo
  121. keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias CARoot \
  122. -import -file $CA_CERT_FILE -keypass $PASS -storepass $PASS -noprompt
  123. rm $CA_CERT_FILE # delete the trust store cert because it's stored in the trust store.
  124. echo
  125. echo "Now the keystore's signed certificate will be imported back into the keystore."
  126. echo
  127. keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias localhost -import \
  128. -file $KEYSTORE_SIGNED_CERT -keypass $PASS -storepass $PASS
  129. echo
  130. echo "All done!"
  131. echo
  132. echo "Deleting intermediate files. They are:"
  133. echo " - '$KEYSTORE_SIGN_REQUEST_SRL': CA serial number"
  134. echo " - '$KEYSTORE_SIGN_REQUEST': the keystore's certificate signing request"
  135. echo " (that was fulfilled)"
  136. echo " - '$KEYSTORE_SIGNED_CERT': the keystore's certificate, signed by the CA, and stored back"
  137. echo " into the keystore"
  138. rm $KEYSTORE_SIGN_REQUEST_SRL
  139. rm $KEYSTORE_SIGN_REQUEST
  140. rm $KEYSTORE_SIGNED_CERT