|
| 1 | +#!/bin/bash |
| 2 | +set -e |
| 3 | + |
| 4 | +# ------------------------------- |
| 5 | +# Load .env file if present |
| 6 | +# ------------------------------- |
| 7 | +ENV_FILE=".env" |
| 8 | +if [ -f "$ENV_FILE" ]; then |
| 9 | + # Export variables defined in the .env file. |
| 10 | + # This method assumes no spaces around '=' and no quoted values. |
| 11 | + set -a |
| 12 | + source "$ENV_FILE" |
| 13 | + set +a |
| 14 | + echo "Loaded environment variables from $ENV_FILE." |
| 15 | +fi |
| 16 | + |
| 17 | +# ------------------------------- |
| 18 | +# Check dependencies |
| 19 | +# ------------------------------- |
| 20 | +command -v openssl >/dev/null 2>&1 || { echo "Error: openssl is not installed." >&2; exit 1; } |
| 21 | +command -v keytool >/dev/null 2>&1 || { echo "Error: keytool is not installed." >&2; exit 1; } |
| 22 | + |
| 23 | +# ------------------------------- |
| 24 | +# Set output directory for secrets |
| 25 | +# ------------------------------- |
| 26 | +OUTPUT_DIR="./secrets" |
| 27 | +if [ ! -d "$OUTPUT_DIR" ]; then |
| 28 | + echo "Creating output directory at $OUTPUT_DIR..." |
| 29 | + mkdir -p "$OUTPUT_DIR" |
| 30 | +fi |
| 31 | + |
| 32 | +# ------------------------------- |
| 33 | +# Get hostnames |
| 34 | +# ------------------------------- |
| 35 | +while [[ -z "$HOSTNAMES" ]]; do |
| 36 | + read -p "Enter the hostname(s) (comma separated, e.g., kafka,localhost): " HOSTNAMES |
| 37 | +done |
| 38 | + |
| 39 | +# ------------------------------- |
| 40 | +# Prompt for passwords if not provided in .env |
| 41 | +# ------------------------------- |
| 42 | +# Use CERTIFICATE_PASSWORD from .env for the CA password if set. |
| 43 | +if [ -z "$CERTIFICATE_PASSWORD" ]; then |
| 44 | + read -s -p "Enter CA (Certificate Authority) password: " CA_PASS |
| 45 | + echo |
| 46 | +else |
| 47 | + CA_PASS="$CERTIFICATE_PASSWORD" |
| 48 | +fi |
| 49 | + |
| 50 | +# Use KEYSTORE_PASSWORD from .env for keystore if set. |
| 51 | +if [ -z "$KEYSTORE_PASSWORD" ]; then |
| 52 | + read -s -p "Enter keystore password: " KEYSTORE_PASS |
| 53 | + echo |
| 54 | +else |
| 55 | + KEYSTORE_PASS="$KEYSTORE_PASSWORD" |
| 56 | +fi |
| 57 | + |
| 58 | +# Use TRUSTSTORE_PASSWORD from .env for truststore if set. |
| 59 | +if [ -z "$TRUSTSTORE_PASSWORD" ]; then |
| 60 | + read -s -p "Enter truststore password: " TRUSTSTORE_PASS |
| 61 | + echo |
| 62 | +else |
| 63 | + TRUSTSTORE_PASS="$TRUSTSTORE_PASSWORD" |
| 64 | +fi |
| 65 | + |
| 66 | +# Always prompt for the client certificate export password |
| 67 | +read -s -p "Enter client certificate export password (for PKCS12 file): " CLIENT_PASS |
| 68 | +echo |
| 69 | + |
| 70 | +# ------------------------------- |
| 71 | +# Define filenames (all files will be placed in the OUTPUT_DIR) |
| 72 | +# ------------------------------- |
| 73 | +CA_KEY="${OUTPUT_DIR}/ca.key" |
| 74 | +CA_CERT="${OUTPUT_DIR}/ca.crt" |
| 75 | +CLIENT_KEY="${OUTPUT_DIR}/client.key" |
| 76 | +CLIENT_CSR="${OUTPUT_DIR}/client.csr" |
| 77 | +CLIENT_CERT="${OUTPUT_DIR}/client.crt" |
| 78 | +PKCS12_FILE="${OUTPUT_DIR}/kafka.p12" |
| 79 | +KEYSTORE="${OUTPUT_DIR}/kafka.keystore.jks" |
| 80 | +TRUSTSTORE="${OUTPUT_DIR}/kafka.truststore.jks" |
| 81 | +SAN_FILE="${OUTPUT_DIR}/san.cnf" |
| 82 | + |
| 83 | +# ------------------------------- |
| 84 | +# Backup any existing files |
| 85 | +# ------------------------------- |
| 86 | +for file in "$CA_KEY" "$CA_CERT" "$CLIENT_KEY" "$CLIENT_CSR" "$CLIENT_CERT" "$PKCS12_FILE" "$KEYSTORE" "$TRUSTSTORE"; do |
| 87 | + if [ -f "$file" ]; then |
| 88 | + mv "$file" "${file}.backup_$(date +%Y%m%d%H%M%S)" |
| 89 | + echo "Backed up existing file $file" |
| 90 | + fi |
| 91 | +done |
| 92 | + |
| 93 | +# ------------------------------- |
| 94 | +# Step 1: Generate CA Key and Self-Signed Certificate |
| 95 | +# ------------------------------- |
| 96 | +echo "Generating CA key and self-signed certificate..." |
| 97 | +openssl genrsa -aes256 -passout pass:"$CA_PASS" -out "$CA_KEY" 4096 |
| 98 | +openssl req -x509 -new -key "$CA_KEY" -days 365 -out "$CA_CERT" \ |
| 99 | + -subj "/CN=Certificate Authority" -passin pass:"$CA_PASS" |
| 100 | + |
| 101 | +# ------------------------------- |
| 102 | +# Step 2: Generate Client Key and CSR |
| 103 | +# ------------------------------- |
| 104 | +PRIMARY_HOST=$(echo "$HOSTNAMES" | cut -d',' -f1 | xargs) |
| 105 | +echo "Generating client private key and certificate signing request (CSR)..." |
| 106 | +openssl genrsa -out "$CLIENT_KEY" 4096 |
| 107 | +openssl req -new -key "$CLIENT_KEY" -out "$CLIENT_CSR" -subj "/CN=${PRIMARY_HOST}" |
| 108 | + |
| 109 | +# ------------------------------- |
| 110 | +# Step 3: Create a SAN (Subject Alternative Names) Config File |
| 111 | +# ------------------------------- |
| 112 | +echo "Creating SAN configuration file..." |
| 113 | +cat > "$SAN_FILE" <<EOF |
| 114 | +[ req ] |
| 115 | +distinguished_name = req_distinguished_name |
| 116 | +req_extensions = v3_req |
| 117 | +prompt = no |
| 118 | +
|
| 119 | +[ req_distinguished_name ] |
| 120 | +CN = ${PRIMARY_HOST} |
| 121 | +
|
| 122 | +[ v3_req ] |
| 123 | +subjectAltName = @alt_names |
| 124 | +
|
| 125 | +[ alt_names ] |
| 126 | +EOF |
| 127 | + |
| 128 | +# Append each hostname as a DNS entry |
| 129 | +IFS=',' read -ra HOST_ARR <<< "$HOSTNAMES" |
| 130 | +i=1 |
| 131 | +for host in "${HOST_ARR[@]}"; do |
| 132 | + host=$(echo "$host" | xargs) # trim spaces |
| 133 | + echo "DNS.$i = $host" >> "$SAN_FILE" |
| 134 | + ((i++)) |
| 135 | +done |
| 136 | + |
| 137 | +# ------------------------------- |
| 138 | +# Step 4: Sign the CSR with the CA Key to Generate the Client Certificate |
| 139 | +# ------------------------------- |
| 140 | +echo "Signing the client CSR with the CA key to generate the client certificate..." |
| 141 | +openssl x509 -req -in "$CLIENT_CSR" -CA "$CA_CERT" -CAkey "$CA_KEY" -CAcreateserial \ |
| 142 | + -out "$CLIENT_CERT" -days 365 -extfile "$SAN_FILE" -passin pass:"$CA_PASS" |
| 143 | + |
| 144 | +# ------------------------------- |
| 145 | +# Step 5: Create a PKCS12 File from Client Key and Certificate |
| 146 | +# ------------------------------- |
| 147 | +echo "Creating PKCS12 file from client key and certificate..." |
| 148 | +openssl pkcs12 -export -in "$CLIENT_CERT" -inkey "$CLIENT_KEY" -certfile "$CA_CERT" \ |
| 149 | + -name kafka -out "$PKCS12_FILE" -passout pass:"$CLIENT_PASS" |
| 150 | + |
| 151 | +# ------------------------------- |
| 152 | +# Step 6: Create the Java Keystore (.jks) Using keytool |
| 153 | +# ------------------------------- |
| 154 | +echo "Importing PKCS12 file into Java keystore..." |
| 155 | +keytool -importkeystore \ |
| 156 | + -deststorepass "$KEYSTORE_PASS" -destkeypass "$KEYSTORE_PASS" \ |
| 157 | + -destkeystore "$KEYSTORE" \ |
| 158 | + -srckeystore "$PKCS12_FILE" -srcstoretype PKCS12 -srcstorepass "$CLIENT_PASS" \ |
| 159 | + -alias kafka |
| 160 | + |
| 161 | +# ------------------------------- |
| 162 | +# Step 7: Create the Java Truststore (.jks) and Import the CA Certificate |
| 163 | +# ------------------------------- |
| 164 | +echo "Creating Java truststore and importing CA certificate..." |
| 165 | +keytool -import -file "$CA_CERT" -alias CARoot \ |
| 166 | + -keystore "$TRUSTSTORE" -storepass "$TRUSTSTORE_PASS" -noprompt |
| 167 | + |
| 168 | +# ------------------------------- |
| 169 | +# Cleanup temporary files |
| 170 | +# ------------------------------- |
| 171 | +rm -f "$SAN_FILE" "$CLIENT_CSR" "$PKCS12_FILE" "${OUTPUT_DIR}/ca.srl" |
| 172 | + |
| 173 | +# ------------------------------- |
| 174 | +# Summary of Generated Files |
| 175 | +# ------------------------------- |
| 176 | +echo "----------------------------------------------" |
| 177 | +echo "Certificates and keystores created successfully in $OUTPUT_DIR!" |
| 178 | +echo "Files generated:" |
| 179 | +echo " - CA certificate: $CA_CERT" |
| 180 | +echo " - Client certificate: $CLIENT_CERT" |
| 181 | +echo " - Client private key: $CLIENT_KEY" |
| 182 | +echo " - Java keystore: $KEYSTORE" |
| 183 | +echo " - Java truststore: $TRUSTSTORE" |
| 184 | +echo "----------------------------------------------" |
0 commit comments