feat: Cert generation for multiple xmpp nodes
Cert generation and import scripts now support any number of XMPP servers and use more intuitive naming for the certificates. This will make it easier to move cert generation to other configurations. Maybe promoting this to a top-level script to generate certs in all scenarios.fix-revocation-examples
parent
4c608f22f8
commit
5a595cd864
|
@ -7,6 +7,23 @@ OCSP_URL="http://ocsp.localhost.example:8888"
|
|||
# Base directory for all certificate-related files
|
||||
# All paths in this script will be relative to this directory
|
||||
CERT_DIR="./_data/certs"
|
||||
XMPP_BASE_DIR="./_data/xmpp"
|
||||
|
||||
# Function to check which server directories exist
|
||||
get_server_instances() {
|
||||
local instances=()
|
||||
# Look for numbered directories in the xmpp base directory
|
||||
for dir in "$XMPP_BASE_DIR"/*/; do
|
||||
if [[ -d "$dir" ]]; then
|
||||
# Extract the number from the directory name
|
||||
local num=$(basename "$dir")
|
||||
if [[ "$num" =~ ^[0-9]+$ ]]; then
|
||||
instances+=("$num")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo "${instances[@]}"
|
||||
}
|
||||
|
||||
# Create the PKI directory structure:
|
||||
# We only need:
|
||||
|
@ -53,15 +70,16 @@ openssl x509 -req -in "${CERT_DIR}/ca/intermediate-ca/intermediate.csr" \
|
|||
|
||||
# Function to generate a server certificate and add it to the certificate database
|
||||
# Parameters:
|
||||
# $1: instance number (1 or 2 for xmpp1/xmpp2)
|
||||
# $1: instance number (1, 2, or 3 for xmpp1/xmpp2/xmpp3)
|
||||
generate_server_cert() {
|
||||
local instance=$1
|
||||
local server_name="xmpp${instance}"
|
||||
|
||||
# Generate server private key and CSR
|
||||
openssl genrsa -out "${CERT_DIR}/server${instance}.key" 2048
|
||||
openssl genrsa -out "${CERT_DIR}/${server_name}.key" 2048
|
||||
|
||||
# Create OpenSSL config file for SAN support
|
||||
cat > "${CERT_DIR}/server${instance}.cnf" << EOF
|
||||
cat > "${CERT_DIR}/${server_name}.cnf" << EOF
|
||||
[req]
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
|
@ -72,7 +90,7 @@ C = GB
|
|||
ST = London
|
||||
L = London
|
||||
O = Test Openfire
|
||||
CN = xmpp${instance}.localhost.example
|
||||
CN = ${server_name}.localhost.example
|
||||
|
||||
[v3_req]
|
||||
basicConstraints = CA:FALSE
|
||||
|
@ -81,17 +99,17 @@ extendedKeyUsage = serverAuth
|
|||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = xmpp${instance}.localhost.example
|
||||
DNS.2 = *.xmpp${instance}.localhost.example
|
||||
DNS.1 = ${server_name}.localhost.example
|
||||
DNS.2 = *.${server_name}.localhost.example
|
||||
EOF
|
||||
|
||||
# Generate CSR with the config file
|
||||
openssl req -new -key "${CERT_DIR}/server${instance}.key" \
|
||||
-out "${CERT_DIR}/server${instance}.csr" \
|
||||
-config "${CERT_DIR}/server${instance}.cnf"
|
||||
openssl req -new -key "${CERT_DIR}/${server_name}.key" \
|
||||
-out "${CERT_DIR}/${server_name}.csr" \
|
||||
-config "${CERT_DIR}/${server_name}.cnf"
|
||||
|
||||
# Create OpenSSL config for certificate signing
|
||||
cat > "${CERT_DIR}/server${instance}_sign.cnf" << EOF
|
||||
cat > "${CERT_DIR}/${server_name}_sign.cnf" << EOF
|
||||
basicConstraints = critical,CA:false
|
||||
keyUsage = critical,digitalSignature,keyEncipherment
|
||||
extendedKeyUsage = serverAuth
|
||||
|
@ -99,31 +117,33 @@ subjectAltName = @alt_names
|
|||
authorityInfoAccess = OCSP;URI:${OCSP_URL}
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = xmpp${instance}.localhost.example
|
||||
DNS.2 = *.xmpp${instance}.localhost.example
|
||||
DNS.1 = ${server_name}.localhost.example
|
||||
DNS.2 = *.${server_name}.localhost.example
|
||||
EOF
|
||||
|
||||
# Sign the server certificate with the Intermediate CA
|
||||
openssl x509 -req -in "${CERT_DIR}/server${instance}.csr" \
|
||||
openssl x509 -req -in "${CERT_DIR}/${server_name}.csr" \
|
||||
-CA "${CERT_DIR}/ca/intermediate-ca/intermediate.crt" \
|
||||
-CAkey "${CERT_DIR}/ca/intermediate-ca/private/intermediate.key" -CAcreateserial \
|
||||
-out "${CERT_DIR}/server${instance}.crt" -days 365 \
|
||||
-extfile "${CERT_DIR}/server${instance}_sign.cnf"
|
||||
-out "${CERT_DIR}/${server_name}.crt" -days 365 \
|
||||
-extfile "${CERT_DIR}/${server_name}_sign.cnf"
|
||||
|
||||
# Create the full certificate chain
|
||||
cat "${CERT_DIR}/server${instance}.crt" "${CERT_DIR}/ca/intermediate-ca/intermediate.crt" "${CERT_DIR}/ca/root-ca/ca.crt" > "${CERT_DIR}/chain${instance}.pem"
|
||||
cat "${CERT_DIR}/${server_name}.crt" \
|
||||
"${CERT_DIR}/ca/intermediate-ca/intermediate.crt" \
|
||||
"${CERT_DIR}/ca/root-ca/ca.crt" > "${CERT_DIR}/${server_name}_chain.pem"
|
||||
|
||||
# Add to certificate database
|
||||
SERIAL=$(openssl x509 -in "${CERT_DIR}/server${instance}.crt" -noout -serial | cut -d'=' -f2)
|
||||
SUBJECT=$(openssl x509 -in "${CERT_DIR}/server${instance}.crt" -noout -subject | cut -d'=' -f2-)
|
||||
SERIAL=$(openssl x509 -in "${CERT_DIR}/${server_name}.crt" -noout -serial | cut -d'=' -f2)
|
||||
SUBJECT=$(openssl x509 -in "${CERT_DIR}/${server_name}.crt" -noout -subject | cut -d'=' -f2-)
|
||||
printf 'V\t%s\t\t%s\tunknown\t%s\n' "$(date -u +%y%m%d%H%M%SZ)" "$SERIAL" "$SUBJECT" >> "${CERT_DIR}/ca/intermediate-ca/index.txt"
|
||||
|
||||
# Clean up temporary config files
|
||||
rm -f "${CERT_DIR}/server${instance}.cnf" "${CERT_DIR}/server${instance}_sign.cnf"
|
||||
rm -f "${CERT_DIR}/${server_name}.cnf" "${CERT_DIR}/${server_name}_sign.cnf"
|
||||
|
||||
# Display the certificate's subject and SANs for verification
|
||||
echo "Certificate generated for instance ${instance}:"
|
||||
openssl x509 -in "${CERT_DIR}/server${instance}.crt" -noout -subject -ext subjectAltName
|
||||
echo "Certificate generated for ${server_name}:"
|
||||
openssl x509 -in "${CERT_DIR}/${server_name}.crt" -noout -subject -ext subjectAltName
|
||||
}
|
||||
|
||||
# Generate the OCSP responder certificate
|
||||
|
@ -144,17 +164,36 @@ openssl x509 -req -in "${CERT_DIR}/ca/ocsp-responder/ocsp.csr" \
|
|||
-out "${CERT_DIR}/ca/ocsp-responder/ocsp.crt" -days 365 \
|
||||
-extfile <(printf 'basicConstraints=critical,CA:false\nkeyUsage=critical,digitalSignature\nextendedKeyUsage=OCSPSigning')
|
||||
|
||||
# Generate certificates for both Openfire instances
|
||||
generate_server_cert 1
|
||||
generate_server_cert 2
|
||||
# Get the list of server instances that exist
|
||||
SERVER_INSTANCES=($(get_server_instances))
|
||||
|
||||
if [ ${#SERVER_INSTANCES[@]} -eq 0 ]; then
|
||||
echo "Error: No server directories found in ${XMPP_BASE_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Found server directories for instances: ${SERVER_INSTANCES[*]}"
|
||||
|
||||
# Generate certificates for each existing server instance
|
||||
for instance in "${SERVER_INSTANCES[@]}"; do
|
||||
echo "Generating certificates for xmpp${instance}"
|
||||
generate_server_cert "$instance"
|
||||
done
|
||||
|
||||
# Verify the certificate chain for all generated certificates
|
||||
# This ensures that all certificates are properly signed and trusted
|
||||
echo "Verifying certificates..."
|
||||
openssl verify -CAfile "${CERT_DIR}/ca/root-ca/ca.crt" "${CERT_DIR}/ca/intermediate-ca/intermediate.crt"
|
||||
openssl verify -CAfile <(cat "${CERT_DIR}/ca/root-ca/ca.crt" "${CERT_DIR}/ca/intermediate-ca/intermediate.crt") "${CERT_DIR}/server1.crt"
|
||||
openssl verify -CAfile <(cat "${CERT_DIR}/ca/root-ca/ca.crt" "${CERT_DIR}/ca/intermediate-ca/intermediate.crt") "${CERT_DIR}/server2.crt"
|
||||
openssl verify -CAfile <(cat "${CERT_DIR}/ca/root-ca/ca.crt" "${CERT_DIR}/ca/intermediate-ca/intermediate.crt") "${CERT_DIR}/ca/ocsp-responder/ocsp.crt"
|
||||
|
||||
# Verify each server certificate
|
||||
for instance in "${SERVER_INSTANCES[@]}"; do
|
||||
openssl verify -CAfile <(cat "${CERT_DIR}/ca/root-ca/ca.crt" "${CERT_DIR}/ca/intermediate-ca/intermediate.crt") \
|
||||
"${CERT_DIR}/xmpp${instance}.crt"
|
||||
done
|
||||
|
||||
openssl verify -CAfile <(cat "${CERT_DIR}/ca/root-ca/ca.crt" "${CERT_DIR}/ca/intermediate-ca/intermediate.crt") \
|
||||
"${CERT_DIR}/ca/ocsp-responder/ocsp.crt"
|
||||
|
||||
printf '\nCertificate generation complete.'
|
||||
printf '\nOCSP URL configured as: %s\n\n' "$OCSP_URL"
|
||||
printf '\nOCSP URL configured as: %s\n' "$OCSP_URL"
|
||||
printf 'Generated certificates for servers: %s\n\n' "${SERVER_INSTANCES[*]}"
|
||||
|
|
|
@ -7,17 +7,35 @@ KEYSTORE_PASSWORD="changeit"
|
|||
# Base directory where certificates were generated
|
||||
# This should match the CERT_DIR from the certificate generation script
|
||||
CERT_DIR="./_data/certs"
|
||||
XMPP_BASE_DIR="./_data/xmpp"
|
||||
|
||||
# Function to check which server directories exist
|
||||
get_server_instances() {
|
||||
local instances=()
|
||||
# Look for numbered directories in the xmpp base directory
|
||||
for dir in "$XMPP_BASE_DIR"/*/; do
|
||||
if [[ -d "$dir" ]]; then
|
||||
# Extract the number from the directory name
|
||||
local num=$(basename "$dir")
|
||||
if [[ "$num" =~ ^[0-9]+$ ]]; then
|
||||
instances+=("$num")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo "${instances[@]}"
|
||||
}
|
||||
|
||||
# Function to import certificates and set up keystores/truststores for one Openfire instance
|
||||
# Parameters:
|
||||
# $1: instance number (1 or 2 for xmpp1/xmpp2)
|
||||
# $1: instance number (1, 2, or 3 for xmpp1/xmpp2/xmpp3)
|
||||
import_certificates() {
|
||||
local instance=$1
|
||||
local server_name="xmpp${instance}"
|
||||
|
||||
# Directory where Openfire expects to find its certificates
|
||||
local conf_dir="_data/xmpp/${instance}/conf/security"
|
||||
|
||||
echo "Importing certificates for Openfire instance ${instance}..."
|
||||
echo "Importing certificates for ${server_name}..."
|
||||
|
||||
# Ensure the security directory exists
|
||||
mkdir -p "${conf_dir}"
|
||||
|
@ -25,7 +43,7 @@ import_certificates() {
|
|||
# Remove any existing keystore to start fresh
|
||||
rm -f "${conf_dir}/keystore"
|
||||
|
||||
echo "Creating new keystore for instance ${instance}"
|
||||
echo "Creating new keystore for ${server_name}"
|
||||
# Create a new empty keystore by generating and immediately deleting a temporary keypair
|
||||
# This ensures the keystore is properly initialized with the correct format
|
||||
keytool -genkeypair \
|
||||
|
@ -46,12 +64,12 @@ import_certificates() {
|
|||
# First convert them to PKCS12 format which can be imported into a Java keystore
|
||||
echo "Importing server certificate and private key..."
|
||||
openssl pkcs12 -export \
|
||||
-in "${CERT_DIR}/server${instance}.crt" \
|
||||
-inkey "${CERT_DIR}/server${instance}.key" \
|
||||
-in "${CERT_DIR}/${server_name}.crt" \
|
||||
-inkey "${CERT_DIR}/${server_name}.key" \
|
||||
-chain \
|
||||
-CAfile "${CERT_DIR}/chain${instance}.pem" \
|
||||
-name "xmpp${instance}.localhost.example" \
|
||||
-out "${CERT_DIR}/server${instance}.p12" \
|
||||
-CAfile "${CERT_DIR}/${server_name}_chain.pem" \
|
||||
-name "${server_name}.localhost.example" \
|
||||
-out "${CERT_DIR}/${server_name}.p12" \
|
||||
-password "pass:${KEYSTORE_PASSWORD}"
|
||||
|
||||
# Import the PKCS12 file into the keystore
|
||||
|
@ -59,15 +77,15 @@ import_certificates() {
|
|||
-deststorepass "${KEYSTORE_PASSWORD}" \
|
||||
-destkeypass "${KEYSTORE_PASSWORD}" \
|
||||
-destkeystore "${conf_dir}/keystore" \
|
||||
-srckeystore "${CERT_DIR}/server${instance}.p12" \
|
||||
-srckeystore "${CERT_DIR}/${server_name}.p12" \
|
||||
-srcstoretype PKCS12 \
|
||||
-srcstorepass "${KEYSTORE_PASSWORD}" \
|
||||
-alias "xmpp${instance}.localhost.example"
|
||||
-alias "${server_name}.localhost.example"
|
||||
|
||||
# Create or update truststore
|
||||
# truststore - used by the server to verify other servers
|
||||
if [ ! -f "${conf_dir}/truststore" ]; then
|
||||
echo "Creating new truststore for instance ${instance}"
|
||||
echo "Creating new truststore for ${server_name}"
|
||||
# Initialize a new truststore with a dummy entry
|
||||
keytool -importpass \
|
||||
-keystore "${conf_dir}/truststore" \
|
||||
|
@ -106,21 +124,34 @@ import_certificates() {
|
|||
echo "Intermediate CA already exists in truststore"
|
||||
fi
|
||||
|
||||
echo "Certificate import completed for instance ${instance}"
|
||||
echo "Certificate import completed for ${server_name}"
|
||||
}
|
||||
|
||||
# Main script execution
|
||||
|
||||
echo "Starting certificate import process..."
|
||||
|
||||
# Import certificates for both Openfire instances
|
||||
import_certificates 1
|
||||
import_certificates 2
|
||||
# Get the list of server instances that exist
|
||||
SERVER_INSTANCES=($(get_server_instances))
|
||||
|
||||
if [ ${#SERVER_INSTANCES[@]} -eq 0 ]; then
|
||||
echo "Error: No server directories found in ${XMPP_BASE_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Found server directories for instances: ${SERVER_INSTANCES[*]}"
|
||||
|
||||
# Import certificates for each existing server instance
|
||||
for instance in "${SERVER_INSTANCES[@]}"; do
|
||||
echo "Importing certificates for xmpp${instance}"
|
||||
import_certificates "$instance"
|
||||
done
|
||||
|
||||
# Clean up temporary PKCS12 files that were created during the import process
|
||||
rm -f "${CERT_DIR}"/*.p12
|
||||
|
||||
# Display commands that can be used to verify the keystore contents
|
||||
echo -e "\nTo verify the keystores, run:"
|
||||
echo "keytool -list -keystore _data/xmpp/1/conf/security/keystore -storepass ${KEYSTORE_PASSWORD}"
|
||||
echo "keytool -list -keystore _data/xmpp/1/conf/security/truststore -storepass ${KEYSTORE_PASSWORD}"
|
||||
for instance in "${SERVER_INSTANCES[@]}"; do
|
||||
echo "keytool -list -keystore _data/xmpp/${instance}/conf/security/keystore -storepass ${KEYSTORE_PASSWORD}"
|
||||
echo "keytool -list -keystore _data/xmpp/${instance}/conf/security/truststore -storepass ${KEYSTORE_PASSWORD}"
|
||||
done
|
Loading…
Reference in New Issue