88551536e6
Amp-Thread-ID: https://ampcode.com/threads/T-019cc404-c628-759e-a50b-f5eeea35b91f Co-authored-by: Amp <amp@ampcode.com>
683 lines
19 KiB
Bash
683 lines
19 KiB
Bash
#!/bin/bash
|
|
|
|
################################################
|
|
#### SSL Certificate Deployer ####
|
|
#### Deploy certs to multiple services ####
|
|
#### ####
|
|
#### Author: Phil Connor ####
|
|
#### License: MIT ####
|
|
#### Contact: contact@mylinux.work ####
|
|
#### Version: 1.00-030326 ####
|
|
################################################
|
|
|
|
set -o pipefail
|
|
|
|
SCRIPT_NAME=$(basename "$0")
|
|
readonly SCRIPT_NAME
|
|
|
|
# Runtime variables
|
|
CERT_FILE=""
|
|
KEY_FILE=""
|
|
CA_FILE=""
|
|
TARGETS=""
|
|
DRY_RUN=false
|
|
BACKUP=false
|
|
DEBUG=${DEBUG:-}
|
|
|
|
handle_error() {
|
|
local exit_code=$1
|
|
local line_number=$2
|
|
echo "Error: $SCRIPT_NAME failed at line $line_number with exit code $exit_code" >&2
|
|
exit "$exit_code"
|
|
}
|
|
|
|
trap 'handle_error $? $LINENO' ERR
|
|
|
|
debug_echo() {
|
|
if [[ -n "$DEBUG" ]]; then
|
|
echo "[DEBUG] $*" >&2
|
|
fi
|
|
}
|
|
|
|
info() {
|
|
echo "[INFO] $*"
|
|
}
|
|
|
|
warn() {
|
|
echo "[WARN] $*" >&2
|
|
}
|
|
|
|
error() {
|
|
echo "[ERROR] $*" >&2
|
|
}
|
|
|
|
show_help() {
|
|
cat << EOF
|
|
Usage: $SCRIPT_NAME [OPTIONS]
|
|
|
|
Deploy SSL certificates to multiple service targets in a single run.
|
|
|
|
OPTIONS:
|
|
--cert FILE Path to the SSL certificate file (required)
|
|
--key FILE Path to the SSL private key file (required)
|
|
--ca FILE Path to the CA bundle file (optional)
|
|
--targets LIST Comma-separated list of targets (required)
|
|
--dry-run Show what would be done without making changes
|
|
--backup Backup existing certificates before overwriting
|
|
--help, -h Show this help message
|
|
|
|
SUPPORTED TARGETS:
|
|
nginx Copy cert+key to /etc/nginx/ssl/, reload nginx
|
|
apache Copy cert+key to /etc/httpd/ssl/ or /etc/apache2/ssl/, reload
|
|
postfix Update TLS cert/key in main.cf, reload postfix
|
|
dovecot Update ssl_cert/ssl_key in dovecot config, reload dovecot
|
|
artifactory Import cert into Artifactory Java keystore, restart
|
|
bitbucket Import cert into Bitbucket Java keystore, restart
|
|
jira Import cert into Jira Java keystore, restart
|
|
haproxy Concatenate cert+key into PEM at /etc/haproxy/certs/, reload
|
|
system Update system CA trust store
|
|
|
|
ENVIRONMENT VARIABLES:
|
|
DEBUG Enable debug output when set
|
|
|
|
EXAMPLES:
|
|
$SCRIPT_NAME --cert server.crt --key server.key --targets nginx,haproxy
|
|
$SCRIPT_NAME --cert server.crt --key server.key --ca ca-bundle.crt --targets apache,postfix,dovecot
|
|
$SCRIPT_NAME --cert server.crt --key server.key --targets artifactory,bitbucket,jira --backup
|
|
$SCRIPT_NAME --cert server.crt --key server.key --targets system --dry-run
|
|
DEBUG=1 $SCRIPT_NAME --cert server.crt --key server.key --targets nginx
|
|
EOF
|
|
}
|
|
|
|
validate_cert_key_match() {
|
|
local cert="$1"
|
|
local key="$2"
|
|
|
|
local cert_modulus
|
|
cert_modulus=$(openssl x509 -noout -modulus -in "$cert" 2>/dev/null | openssl md5)
|
|
local key_modulus
|
|
key_modulus=$(openssl rsa -noout -modulus -in "$key" 2>/dev/null | openssl md5)
|
|
|
|
if [[ "$cert_modulus" != "$key_modulus" ]]; then
|
|
error "Certificate and key do not match (modulus mismatch)"
|
|
debug_echo "Cert modulus: $cert_modulus"
|
|
debug_echo "Key modulus: $key_modulus"
|
|
return 1
|
|
fi
|
|
|
|
debug_echo "Certificate and key match"
|
|
return 0
|
|
}
|
|
|
|
backup_file() {
|
|
local file="$1"
|
|
if [[ -f "$file" ]]; then
|
|
local backup_name
|
|
backup_name="${file}.bak.$(date +%Y%m%d%H%M%S)"
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would backup $file -> $backup_name"
|
|
else
|
|
cp -a "$file" "$backup_name"
|
|
info "Backed up $file -> $backup_name"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
copy_file() {
|
|
local src="$1"
|
|
local dest="$2"
|
|
|
|
if [[ "$BACKUP" == true ]]; then
|
|
backup_file "$dest"
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would copy $src -> $dest"
|
|
else
|
|
cp -a "$src" "$dest"
|
|
chmod 600 "$dest"
|
|
info "Copied $src -> $dest"
|
|
fi
|
|
}
|
|
|
|
reload_service() {
|
|
local service="$1"
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would reload $service"
|
|
else
|
|
if systemctl is-active --quiet "$service" 2>/dev/null; then
|
|
systemctl reload "$service"
|
|
info "Reloaded $service"
|
|
else
|
|
warn "Service $service is not active, skipping reload"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
restart_service() {
|
|
local service="$1"
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would restart $service"
|
|
else
|
|
systemctl restart "$service"
|
|
info "Restarted $service"
|
|
fi
|
|
}
|
|
|
|
get_keystore_password() {
|
|
local password_url="$1"
|
|
local storepass=""
|
|
|
|
# Try Vault HTTP API first if URL provided
|
|
if [[ -n "$password_url" ]]; then
|
|
debug_echo "Retrieving keystore password from $password_url"
|
|
storepass=$(curl -sf -X GET "$password_url" 2>/dev/null | jq -r '.data.password // empty' 2>/dev/null || true)
|
|
fi
|
|
|
|
# Fall back to Vault CLI
|
|
if [[ -z "$storepass" ]]; then
|
|
debug_echo "Falling back to Vault CLI for keystore password"
|
|
storepass=$(vault kv get -field=password secret/keystore 2>/dev/null || true)
|
|
fi
|
|
|
|
# Fall back to default
|
|
if [[ -z "$storepass" ]]; then
|
|
debug_echo "Using default keystore password"
|
|
storepass="changeit"
|
|
fi
|
|
|
|
echo "$storepass"
|
|
}
|
|
|
|
find_java_keystore() {
|
|
local -n java_bin_ref=$1
|
|
local -n keystore_ref=$2
|
|
|
|
# Common Java installation paths
|
|
local java_paths=(
|
|
"/opt/jfrog/artifactory/app/third-party/java"
|
|
"/mnt/ebs/bitbucket/*/jre"
|
|
"/mnt/ebs/jira/jre"
|
|
"/usr/lib/jvm/java-*-openjdk"
|
|
"/usr/lib/jvm/default-java"
|
|
"/opt/java"
|
|
"/usr/java/latest"
|
|
)
|
|
|
|
# Check JAVA_HOME first
|
|
if [[ -n "${JAVA_HOME:-}" && -x "$JAVA_HOME/bin/keytool" ]]; then
|
|
java_bin_ref="$JAVA_HOME/bin"
|
|
keystore_ref="$JAVA_HOME/lib/security/cacerts"
|
|
if [[ -f "$keystore_ref" ]]; then
|
|
debug_echo "Found Java via JAVA_HOME: $java_bin_ref"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Search common paths with glob expansion
|
|
for path_pattern in "${java_paths[@]}"; do
|
|
for java_dir in $path_pattern; do
|
|
if [[ -d "$java_dir" ]]; then
|
|
local bin_dir="$java_dir/bin"
|
|
local cacerts="$java_dir/lib/security/cacerts"
|
|
|
|
if [[ -x "$bin_dir/keytool" && -f "$cacerts" ]]; then
|
|
java_bin_ref="$bin_dir"
|
|
keystore_ref="$cacerts"
|
|
debug_echo "Found Java at: $java_dir"
|
|
return 0
|
|
fi
|
|
fi
|
|
done
|
|
done
|
|
|
|
# Fallback: try system keytool
|
|
if command -v keytool >/dev/null 2>&1; then
|
|
java_bin_ref="$(dirname "$(command -v keytool)")"
|
|
# Try common system keystore locations
|
|
local system_keystores=(
|
|
"/etc/ssl/certs/java/cacerts"
|
|
"/usr/lib/jvm/default-java/lib/security/cacerts"
|
|
"/etc/pki/ca-trust/extracted/java/cacerts"
|
|
)
|
|
for ks in "${system_keystores[@]}"; do
|
|
if [[ -f "$ks" ]]; then
|
|
keystore_ref="$ks"
|
|
debug_echo "Found system Java at: $java_bin_ref"
|
|
return 0
|
|
fi
|
|
done
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
deploy_java_keystore() {
|
|
local keystore="$1"
|
|
local java_bin="$2"
|
|
local alias_name="$3"
|
|
local vault_url="$4"
|
|
local service_name="$5"
|
|
|
|
local storepass
|
|
storepass=$(get_keystore_password "$vault_url")
|
|
|
|
if [[ "$BACKUP" == true ]]; then
|
|
backup_file "$keystore"
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would delete alias '$alias_name' from keystore $keystore"
|
|
info "[DRY RUN] Would import $CERT_FILE into keystore $keystore"
|
|
info "[DRY RUN] Would restart $service_name"
|
|
else
|
|
"$java_bin/keytool" -delete -alias "$alias_name" -keystore "$keystore" -storepass "$storepass" 2>/dev/null || true
|
|
"$java_bin/keytool" -import -noprompt -alias "$alias_name" -keystore "$keystore" -file "$CERT_FILE" -storepass "$storepass"
|
|
info "Imported certificate into $keystore"
|
|
restart_service "$service_name"
|
|
fi
|
|
}
|
|
|
|
# ---- Target handlers ----
|
|
|
|
deploy_nginx() {
|
|
info "Deploying to nginx..."
|
|
local ssl_dir="/etc/nginx/ssl"
|
|
|
|
if [[ "$DRY_RUN" != true ]]; then
|
|
mkdir -p "$ssl_dir"
|
|
fi
|
|
|
|
copy_file "$CERT_FILE" "$ssl_dir/server.crt"
|
|
copy_file "$KEY_FILE" "$ssl_dir/server.key"
|
|
|
|
if [[ -n "$CA_FILE" ]]; then
|
|
copy_file "$CA_FILE" "$ssl_dir/ca-bundle.crt"
|
|
fi
|
|
|
|
reload_service nginx
|
|
}
|
|
|
|
deploy_apache() {
|
|
info "Deploying to apache..."
|
|
local ssl_dir=""
|
|
|
|
if [[ -d "/etc/httpd" ]]; then
|
|
ssl_dir="/etc/httpd/ssl"
|
|
elif [[ -d "/etc/apache2" ]]; then
|
|
ssl_dir="/etc/apache2/ssl"
|
|
else
|
|
error "Could not detect Apache configuration directory"
|
|
return 1
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" != true ]]; then
|
|
mkdir -p "$ssl_dir"
|
|
fi
|
|
|
|
copy_file "$CERT_FILE" "$ssl_dir/server.crt"
|
|
copy_file "$KEY_FILE" "$ssl_dir/server.key"
|
|
|
|
if [[ -n "$CA_FILE" ]]; then
|
|
copy_file "$CA_FILE" "$ssl_dir/ca-bundle.crt"
|
|
fi
|
|
|
|
# Detect and reload the correct service
|
|
if systemctl list-units --type=service --all 2>/dev/null | grep -q "httpd.service"; then
|
|
reload_service httpd
|
|
elif systemctl list-units --type=service --all 2>/dev/null | grep -q "apache2.service"; then
|
|
reload_service apache2
|
|
else
|
|
warn "Could not detect Apache service name"
|
|
fi
|
|
}
|
|
|
|
deploy_postfix() {
|
|
info "Deploying to postfix..."
|
|
local main_cf="/etc/postfix/main.cf"
|
|
|
|
if [[ ! -f "$main_cf" ]]; then
|
|
error "Postfix main.cf not found at $main_cf"
|
|
return 1
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would update smtpd_tls_cert_file in $main_cf to $CERT_FILE"
|
|
info "[DRY RUN] Would update smtpd_tls_key_file in $main_cf to $KEY_FILE"
|
|
info "[DRY RUN] Would reload postfix"
|
|
else
|
|
if [[ "$BACKUP" == true ]]; then
|
|
backup_file "$main_cf"
|
|
fi
|
|
|
|
if grep -q "^smtpd_tls_cert_file" "$main_cf"; then
|
|
sed -i "s|^smtpd_tls_cert_file.*|smtpd_tls_cert_file = $CERT_FILE|" "$main_cf"
|
|
else
|
|
echo "smtpd_tls_cert_file = $CERT_FILE" >> "$main_cf"
|
|
fi
|
|
|
|
if grep -q "^smtpd_tls_key_file" "$main_cf"; then
|
|
sed -i "s|^smtpd_tls_key_file.*|smtpd_tls_key_file = $KEY_FILE|" "$main_cf"
|
|
else
|
|
echo "smtpd_tls_key_file = $KEY_FILE" >> "$main_cf"
|
|
fi
|
|
|
|
info "Updated $main_cf with certificate paths"
|
|
reload_service postfix
|
|
fi
|
|
}
|
|
|
|
deploy_dovecot() {
|
|
info "Deploying to dovecot..."
|
|
local dovecot_conf=""
|
|
|
|
if [[ -f "/etc/dovecot/conf.d/10-ssl.conf" ]]; then
|
|
dovecot_conf="/etc/dovecot/conf.d/10-ssl.conf"
|
|
elif [[ -f "/etc/dovecot/dovecot.conf" ]]; then
|
|
dovecot_conf="/etc/dovecot/dovecot.conf"
|
|
else
|
|
error "Could not find dovecot configuration"
|
|
return 1
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would update ssl_cert in $dovecot_conf to <$CERT_FILE"
|
|
info "[DRY RUN] Would update ssl_key in $dovecot_conf to <$KEY_FILE"
|
|
info "[DRY RUN] Would reload dovecot"
|
|
else
|
|
if [[ "$BACKUP" == true ]]; then
|
|
backup_file "$dovecot_conf"
|
|
fi
|
|
|
|
if grep -q "^ssl_cert" "$dovecot_conf"; then
|
|
sed -i "s|^ssl_cert.*|ssl_cert = <$CERT_FILE|" "$dovecot_conf"
|
|
else
|
|
echo "ssl_cert = <$CERT_FILE" >> "$dovecot_conf"
|
|
fi
|
|
|
|
if grep -q "^ssl_key" "$dovecot_conf"; then
|
|
sed -i "s|^ssl_key.*|ssl_key = <$KEY_FILE|" "$dovecot_conf"
|
|
else
|
|
echo "ssl_key = <$KEY_FILE" >> "$dovecot_conf"
|
|
fi
|
|
|
|
info "Updated $dovecot_conf with certificate paths"
|
|
reload_service dovecot
|
|
fi
|
|
}
|
|
|
|
deploy_artifactory() {
|
|
info "Deploying to artifactory..."
|
|
local java_bin="/opt/jfrog/artifactory/app/third-party/java/bin"
|
|
local keystore="/opt/jfrog/artifactory/app/third-party/java/lib/security/cacerts"
|
|
|
|
if [[ ! -x "$java_bin/keytool" || ! -f "$keystore" ]]; then
|
|
debug_echo "Artifactory default paths not found, searching for Java"
|
|
if ! find_java_keystore java_bin keystore; then
|
|
error "Could not find Java keytool or keystore for Artifactory"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
deploy_java_keystore "$keystore" "$java_bin" "ssl-cert" "" "artifactory"
|
|
}
|
|
|
|
deploy_bitbucket() {
|
|
info "Deploying to bitbucket..."
|
|
local java_bin=""
|
|
local keystore=""
|
|
|
|
# Check app-specific paths first with glob
|
|
for bb_dir in /mnt/ebs/bitbucket/*/jre; do
|
|
if [[ -d "$bb_dir" && -x "$bb_dir/bin/keytool" && -f "$bb_dir/lib/security/cacerts" ]]; then
|
|
java_bin="$bb_dir/bin"
|
|
keystore="$bb_dir/lib/security/cacerts"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [[ -z "$java_bin" || -z "$keystore" ]]; then
|
|
debug_echo "Bitbucket default paths not found, searching for Java"
|
|
if ! find_java_keystore java_bin keystore; then
|
|
error "Could not find Java keytool or keystore for Bitbucket"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
deploy_java_keystore "$keystore" "$java_bin" "ssl-cert" "" "atlbitbucket"
|
|
}
|
|
|
|
deploy_jira() {
|
|
info "Deploying to jira..."
|
|
local java_bin="/mnt/ebs/jira/jre/bin"
|
|
local keystore="/mnt/ebs/jira/jre/lib/security/cacerts"
|
|
|
|
if [[ ! -x "$java_bin/keytool" || ! -f "$keystore" ]]; then
|
|
debug_echo "Jira default paths not found, searching for Java"
|
|
if ! find_java_keystore java_bin keystore; then
|
|
error "Could not find Java keytool or keystore for Jira"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
deploy_java_keystore "$keystore" "$java_bin" "ssl-cert" "" "jira"
|
|
}
|
|
|
|
deploy_haproxy() {
|
|
info "Deploying to haproxy..."
|
|
local cert_dir="/etc/haproxy/certs"
|
|
local pem_file="$cert_dir/server.pem"
|
|
|
|
if [[ "$DRY_RUN" != true ]]; then
|
|
mkdir -p "$cert_dir"
|
|
fi
|
|
|
|
if [[ "$BACKUP" == true ]]; then
|
|
backup_file "$pem_file"
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would concatenate $CERT_FILE + $KEY_FILE -> $pem_file"
|
|
info "[DRY RUN] Would reload haproxy"
|
|
else
|
|
cat "$CERT_FILE" "$KEY_FILE" > "$pem_file"
|
|
chmod 600 "$pem_file"
|
|
info "Created combined PEM at $pem_file"
|
|
reload_service haproxy
|
|
fi
|
|
}
|
|
|
|
deploy_system() {
|
|
info "Deploying to system CA trust store..."
|
|
|
|
if [[ -z "$CA_FILE" && -z "$CERT_FILE" ]]; then
|
|
error "No certificate or CA bundle provided for system trust store"
|
|
return 1
|
|
fi
|
|
|
|
local cert_to_install="${CA_FILE:-$CERT_FILE}"
|
|
|
|
if command -v update-ca-trust >/dev/null 2>&1; then
|
|
# RHEL/CentOS/Fedora/Rocky/Alma
|
|
local trust_dir="/etc/pki/ca-trust/source/anchors"
|
|
local cert_name
|
|
cert_name=$(basename "$cert_to_install")
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would copy $cert_to_install -> $trust_dir/$cert_name"
|
|
info "[DRY RUN] Would run update-ca-trust"
|
|
else
|
|
copy_file "$cert_to_install" "$trust_dir/$cert_name"
|
|
update-ca-trust
|
|
info "Updated system CA trust store (RHEL-based)"
|
|
fi
|
|
elif command -v update-ca-certificates >/dev/null 2>&1; then
|
|
# Debian/Ubuntu
|
|
local trust_dir="/usr/local/share/ca-certificates"
|
|
local cert_name
|
|
cert_name=$(basename "$cert_to_install")
|
|
# Debian requires .crt extension
|
|
cert_name="${cert_name%.*}.crt"
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "[DRY RUN] Would copy $cert_to_install -> $trust_dir/$cert_name"
|
|
info "[DRY RUN] Would run update-ca-certificates"
|
|
else
|
|
copy_file "$cert_to_install" "$trust_dir/$cert_name"
|
|
update-ca-certificates
|
|
info "Updated system CA trust store (Debian-based)"
|
|
fi
|
|
else
|
|
error "Could not find update-ca-trust or update-ca-certificates"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
parse_arguments() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--cert)
|
|
CERT_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--key)
|
|
KEY_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--ca)
|
|
CA_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--targets)
|
|
TARGETS="$2"
|
|
shift 2
|
|
;;
|
|
--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
--backup)
|
|
BACKUP=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
*)
|
|
error "Unknown option: $1"
|
|
show_help >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
validate_inputs() {
|
|
if [[ -z "$CERT_FILE" ]]; then
|
|
error "Certificate file is required (--cert)"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "$KEY_FILE" ]]; then
|
|
error "Key file is required (--key)"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "$TARGETS" ]]; then
|
|
error "At least one target is required (--targets)"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$CERT_FILE" ]]; then
|
|
error "Certificate file not found: $CERT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$KEY_FILE" ]]; then
|
|
error "Key file not found: $KEY_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -n "$CA_FILE" && ! -f "$CA_FILE" ]]; then
|
|
error "CA bundle file not found: $CA_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
if ! openssl x509 -noout -text -in "$CERT_FILE" >/dev/null 2>&1; then
|
|
error "Invalid certificate file: $CERT_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
if ! openssl rsa -noout -check -in "$KEY_FILE" >/dev/null 2>&1; then
|
|
error "Invalid key file: $KEY_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
if ! validate_cert_key_match "$CERT_FILE" "$KEY_FILE"; then
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
deploy_target() {
|
|
local target="$1"
|
|
|
|
case "$target" in
|
|
nginx) deploy_nginx ;;
|
|
apache) deploy_apache ;;
|
|
postfix) deploy_postfix ;;
|
|
dovecot) deploy_dovecot ;;
|
|
artifactory) deploy_artifactory ;;
|
|
bitbucket) deploy_bitbucket ;;
|
|
jira) deploy_jira ;;
|
|
haproxy) deploy_haproxy ;;
|
|
system) deploy_system ;;
|
|
*)
|
|
error "Unknown target: $target"
|
|
error "Valid targets: nginx, apache, postfix, dovecot, artifactory, bitbucket, jira, haproxy, system"
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main() {
|
|
parse_arguments "$@"
|
|
validate_inputs
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
info "Running in DRY RUN mode — no changes will be made"
|
|
fi
|
|
|
|
local failed=0
|
|
local succeeded=0
|
|
|
|
IFS=',' read -ra target_list <<< "$TARGETS"
|
|
for target in "${target_list[@]}"; do
|
|
# Trim whitespace
|
|
target=$(echo "$target" | tr -d '[:space:]')
|
|
info "--- Deploying to target: $target ---"
|
|
|
|
if deploy_target "$target"; then
|
|
((succeeded++))
|
|
info "Target $target: OK"
|
|
else
|
|
((failed++))
|
|
error "Target $target: FAILED"
|
|
fi
|
|
echo
|
|
done
|
|
|
|
info "Deployment complete: $succeeded succeeded, $failed failed"
|
|
|
|
if [[ $failed -gt 0 ]]; then
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Execute main function if script is run directly
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
main "$@"
|
|
fi
|