function make_ca() { # Use the provided directory argument or default to AZURITE_DIR if not provided local CERT_DIR="$1" if [[ -z "$CERT_DIR" || ! -d "$CERT_DIR" ]]; then echo "ERROR: Certificate directory $CERT_DIR does not exist." return 1 fi # Generate CA certificate and key if they don't exist if [[ ! -f "$CERT_DIR/ca_cert.pem" || ! -f "$CERT_DIR/ca_key.pem" ]]; then echo "Generating CA certificate and key..." if ! openssl req \ -x509 \ -newkey rsa:4096 \ -keyout "$CERT_DIR/ca_key.pem" \ -out "$CERT_DIR/ca_cert.pem" \ -days 3650 \ -nodes \ -subj "/CN=Azurite CA" \ -text \ -addext "basicConstraints=critical,CA:TRUE,pathlen:0"; then echo "ERROR: Failed to generate CA certificate and key." >&2 return 1 fi fi return 0 } function _is_ip() { if [[ "$1" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then return 0 else return 1 fi } function _is_dns() { if [[ "$1" =~ ^[a-z0-9-]+(\.[a-z0-9-]+)*$ ]]; then return 0 else return 1 fi } function make_server_cert() { local CERT_DIR="$1" local CERT_SUBJECT_NAME="$2" shift 2 if [[ -z "$CERT_DIR" || ! -d "$CERT_DIR" ]]; then echo "ERROR: Certificate directory $CERT_DIR does not exist." return 1 fi if [[ -z "$CERT_SUBJECT_NAME" ]]; then echo "ERROR: Subject name is required." >&2 return 1 fi if ! _is_dns "$CERT_SUBJECT_NAME"; then echo "ERROR: Invalid subject name '$CERT_SUBJECT_NAME'. Must be a valid DNS name." >&2 return 1 fi if [[ ! -f "$CERT_DIR/ca_cert.pem" || ! -f "$CERT_DIR/ca_key.pem" ]]; then echo "ERROR: CA certificate and key not found in $CERT_DIR. Please call make_ca first." >&2 return 1 fi # Calculate the "account" name from the subject name, the hostname part before the first dot local CERT_NAME="${CERT_SUBJECT_NAME%%.*}" # Start with the subjectAltName extension containing the main DNS name local SANS=("DNS:${CERT_SUBJECT_NAME}") # Combine the remaining arguments into a single string for the subjectAltName extension while [[ $# -gt 0 ]]; do if _is_ip "$1"; then SANS+=("IP:$1") elif _is_dns "$1"; then SANS+=("DNS:$1") else echo "ERROR: Invalid SAN entry '$1'" >&2 return 1 fi shift done # Join the SAN entries with commas for the OpenSSL command local SANS_EXT="subjectAltName=$(IFS=,; echo "${SANS[*]}")" echo "Generating server certificate for '$CERT_SUBJECT_NAME' with SANs:" for san in "${SANS[@]}"; do echo " - $san" done # Generate server certificate and key if they don't exist if [[ ! -f "$CERT_DIR/${CERT_NAME}_cert.pem" || ! -f "$CERT_DIR/${CERT_NAME}_key.pem" ]]; then echo "Generating server certificate and key..." if ! openssl req \ -newkey rsa:4096 \ -keyout "$CERT_DIR/${CERT_NAME}_key.pem" \ -nodes \ -subj "/CN=${CERT_SUBJECT_NAME}" \ -addext "basicConstraints=critical,CA:FALSE" \ -addext "keyUsage=digitalSignature,keyEncipherment" \ -addext "extendedKeyUsage=serverAuth,clientAuth" \ -addext "$SANS_EXT" \ | openssl x509 \ -req \ -CA "$CERT_DIR/ca_cert.pem" \ -CAkey "$CERT_DIR/ca_key.pem" \ -set_serial "0x$(openssl rand -hex 16)" \ -copy_extensions copyall \ -days 365 \ -text \ -out "$CERT_DIR/${CERT_NAME}_cert.pem"; then echo "ERROR: Failed to generate server certificate and key." >&2 return 1 fi fi return 0 } function make_pfx() { local CERT_DIR="$1" local CERT_NAME="$2" local PFX_PASSWORD="${3:-}" if [[ -z "$CERT_DIR" || ! -d "$CERT_DIR" ]]; then echo "ERROR: Certificate directory $CERT_DIR does not exist." return 1 fi if [[ -z "$CERT_NAME" ]]; then echo "ERROR: Certificate name is required." >&2 return 1 fi if [[ ! -f "$CERT_DIR/${CERT_NAME}_cert.pem" || ! -f "$CERT_DIR/${CERT_NAME}_key.pem" ]]; then echo "ERROR: Server certificate and key not found in $CERT_DIR. Please call make_server_cert first." >&2 return 1 fi if [[ ! -f "$CERT_DIR/ca_cert.pem" || ! -f "$CERT_DIR/ca_key.pem" ]]; then echo "ERROR: CA certificate and key not found in $CERT_DIR. Please call make_ca first." >&2 return 1 fi if [[ -z "$PFX_PASSWORD" ]]; then PFX_PASSWORD="changeit" fi if [[ ! -f "$CERT_DIR/${CERT_NAME}.pfx" ]]; then echo -n "Generating PKCS#12 (PFX) file..." if ! openssl pkcs12 \ -export -out "$CERT_DIR/${CERT_NAME}.pfx" \ -inkey "$CERT_DIR/${CERT_NAME}_key.pem" \ -in "$CERT_DIR/${CERT_NAME}_cert.pem" \ -certfile "$CERT_DIR/ca_cert.pem" \ -password pass:"$PFX_PASSWORD"; then echo "ERROR: Failed to generate PKCS#12 (PFX) file." >&2 return 1 fi echo "done." else echo "PKCS#12 (PFX) file already exists, aborting generation." return 1 fi return 0 }