|
#!/usr/bin/env bash |
|
|
|
set -euo pipefail |
|
|
|
############################################################################### |
|
# Usage |
|
############################################################################### |
|
|
|
usage() { |
|
cat <<EOF |
|
Usage: |
|
|
|
Extract certificate, chain and unprotected key: |
|
$0 <pkcs12-file> |
|
|
|
Extract and install certificates: |
|
$0 --install <pkcs12-file> |
|
|
|
Extract, install and create reverse proxy at port 443: |
|
$0 --install <pkcs12-file> <hostname> <target-port> |
|
|
|
Extract, install and create reverse proxy at different port: |
|
$0 --install <pkcs12-file> <hostname> <target-port> <external-port> |
|
|
|
EOF |
|
} |
|
|
|
############################################################################### |
|
# Parameter |
|
############################################################################### |
|
|
|
INSTALL_MODE=false |
|
|
|
if [[ "${1:-}" == "--install" ]]; then |
|
INSTALL_MODE=true |
|
shift |
|
fi |
|
|
|
if [[ $# -ne 1 && $# -ne 3 && $# -ne 4 ]]; then |
|
usage |
|
exit 1 |
|
fi |
|
|
|
P12_FILE="$1" |
|
|
|
if [[ ! -f "$P12_FILE" ]]; then |
|
echo "File not found: $P12_FILE" |
|
exit 1 |
|
fi |
|
|
|
CREATE_VHOST=false |
|
|
|
if [[ $# -ge 3 ]]; then |
|
CREATE_VHOST=true |
|
HOSTNAME="$2" |
|
TARGET_PORT="$3" |
|
EXTERNAL_PORT="${4:-443}" |
|
fi |
|
|
|
if ! $INSTALL_MODE && $CREATE_VHOST; then |
|
echo "Reverse proxy creation requires --install." |
|
usage |
|
exit 1 |
|
fi |
|
|
|
P12_DIR="$(cd "$(dirname "$P12_FILE")" && pwd)" |
|
P12_NAME="$(basename "$P12_FILE")" |
|
P12_BASE="${P12_NAME%.*}" |
|
|
|
OUTPUT_CERT="${P12_DIR}/${P12_BASE}.crt" |
|
OUTPUT_CHAIN="${P12_DIR}/${P12_BASE}-chain.pem" |
|
OUTPUT_KEY="${P12_DIR}/${P12_BASE}.key" |
|
|
|
############################################################################### |
|
# Root Check |
|
############################################################################### |
|
|
|
if $INSTALL_MODE && [[ $EUID -ne 0 ]]; then |
|
echo "Please run as root when using --install." |
|
exit 1 |
|
fi |
|
|
|
############################################################################### |
|
# Password |
|
############################################################################### |
|
|
|
read -rsp "PKCS12 Password: " P12_PASSWORD |
|
echo |
|
|
|
export P12_PASSWORD |
|
|
|
# Prevent interactive prompts when exporting the encrypted private key. |
|
KEY_EXPORT_PASSWORD="mthk-setup" |
|
export KEY_EXPORT_PASSWORD |
|
|
|
############################################################################### |
|
# Workdir |
|
############################################################################### |
|
|
|
TMPDIR="$(mktemp -d)" |
|
trap 'rm -rf "$TMPDIR"' EXIT |
|
|
|
############################################################################### |
|
# Install Paths and Detection |
|
############################################################################### |
|
|
|
if $INSTALL_MODE; then |
|
if [[ -f /etc/debian_version ]]; then |
|
DISTRO="debian" |
|
SSL_CERT_DIR="/etc/ssl/certs" |
|
SSL_KEY_DIR="/etc/ssl/private" |
|
elif [[ -f /etc/redhat-release ]]; then |
|
DISTRO="rhel" |
|
SSL_CERT_DIR="/etc/pki/tls/certs" |
|
SSL_KEY_DIR="/etc/pki/tls/private" |
|
elif grep -qi suse /etc/os-release 2>/dev/null; then |
|
DISTRO="suse" |
|
SSL_CERT_DIR="/etc/ssl/certs" |
|
SSL_KEY_DIR="/etc/ssl/private" |
|
else |
|
echo "Unsupported Linux distribution" |
|
exit 1 |
|
fi |
|
|
|
M2M_CERT="${SSL_CERT_DIR}/mobilithek.info-m2m.crt" |
|
M2M_CHAIN="${SSL_CERT_DIR}/mobilithek.info-ca-chain.pem" |
|
M2M_KEY="${SSL_KEY_DIR}/mobilithek.info-m2m.key" |
|
|
|
WEBSERVER="" |
|
|
|
APACHE_FOUND=false |
|
NGINX_FOUND=false |
|
|
|
if command -v apache2 >/dev/null 2>&1 || command -v httpd >/dev/null 2>&1; then |
|
APACHE_FOUND=true |
|
fi |
|
|
|
if command -v nginx >/dev/null 2>&1; then |
|
NGINX_FOUND=true |
|
fi |
|
|
|
if $CREATE_VHOST; then |
|
if $APACHE_FOUND && $NGINX_FOUND; then |
|
echo |
|
echo "Both Apache and Nginx detected." |
|
echo |
|
|
|
select ws in apache nginx; do |
|
WEBSERVER="$ws" |
|
break |
|
done |
|
elif $APACHE_FOUND; then |
|
WEBSERVER="apache" |
|
elif $NGINX_FOUND; then |
|
WEBSERVER="nginx" |
|
else |
|
echo "Neither Apache nor Nginx found." |
|
exit 1 |
|
fi |
|
fi |
|
fi |
|
|
|
############################################################################### |
|
# Extract Client Certificate |
|
############################################################################### |
|
|
|
echo "Extracting certificate..." |
|
|
|
openssl pkcs12 \ |
|
-in "$P12_FILE" \ |
|
-passin env:P12_PASSWORD \ |
|
-clcerts \ |
|
-nokeys \ |
|
-out "${TMPDIR}/m2m.crt" |
|
|
|
############################################################################### |
|
# Extract Certificate Chain |
|
############################################################################### |
|
|
|
echo "Extracting certificate chain..." |
|
|
|
openssl pkcs12 \ |
|
-in "$P12_FILE" \ |
|
-passin env:P12_PASSWORD \ |
|
-cacerts \ |
|
-nokeys \ |
|
-out "${TMPDIR}/m2m-chain.pem" |
|
|
|
############################################################################### |
|
# Extract Private Key |
|
############################################################################### |
|
|
|
echo "Extracting private key..." |
|
|
|
openssl pkcs12 \ |
|
-in "$P12_FILE" \ |
|
-passin env:P12_PASSWORD \ |
|
-passout env:KEY_EXPORT_PASSWORD \ |
|
-nocerts \ |
|
-out "${TMPDIR}/encrypted.key" |
|
|
|
############################################################################### |
|
# Remove Password |
|
############################################################################### |
|
|
|
echo "Removing passphrase..." |
|
|
|
openssl rsa \ |
|
-in "${TMPDIR}/encrypted.key" \ |
|
-passin env:KEY_EXPORT_PASSWORD \ |
|
-out "${TMPDIR}/m2m.key" |
|
|
|
############################################################################### |
|
# Export |
|
############################################################################### |
|
|
|
echo "Writing extracted files next to PKCS12 file..." |
|
|
|
install -m 644 \ |
|
"${TMPDIR}/m2m.crt" \ |
|
"$OUTPUT_CERT" |
|
|
|
install -m 644 \ |
|
"${TMPDIR}/m2m-chain.pem" \ |
|
"$OUTPUT_CHAIN" |
|
|
|
install -m 600 \ |
|
"${TMPDIR}/m2m.key" \ |
|
"$OUTPUT_KEY" |
|
|
|
############################################################################### |
|
# Install |
|
############################################################################### |
|
|
|
if $INSTALL_MODE; then |
|
echo "Installing certificates..." |
|
|
|
install -o root -g root -m 644 \ |
|
"$OUTPUT_CERT" \ |
|
"$M2M_CERT" |
|
|
|
install -o root -g root -m 644 \ |
|
"$OUTPUT_CHAIN" \ |
|
"$M2M_CHAIN" |
|
|
|
install -o root -g root -m 600 \ |
|
"$OUTPUT_KEY" \ |
|
"$M2M_KEY" |
|
fi |
|
|
|
############################################################################### |
|
# Create VHost |
|
############################################################################### |
|
|
|
if $INSTALL_MODE && $CREATE_VHOST; then |
|
echo "Creating ${WEBSERVER} virtual host..." |
|
|
|
if [[ "$WEBSERVER" == "apache" ]]; then |
|
if [[ "$DISTRO" == "debian" ]]; then |
|
VHOST_FILE="/etc/apache2/sites-available/${HOSTNAME}.conf" |
|
else |
|
VHOST_FILE="/etc/httpd/conf.d/${HOSTNAME}.conf" |
|
fi |
|
|
|
cat > "$VHOST_FILE" <<EOF |
|
Listen ${EXTERNAL_PORT} |
|
|
|
<VirtualHost *:${EXTERNAL_PORT}> |
|
|
|
ServerName ${HOSTNAME} |
|
|
|
SSLEngine on |
|
|
|
SSLCertificateFile ${M2M_CERT} |
|
SSLCertificateKeyFile ${M2M_KEY} |
|
|
|
SSLVerifyClient require |
|
SSLVerifyDepth 5 |
|
|
|
SSLCACertificateFile ${M2M_CHAIN} |
|
|
|
ProxyPreserveHost On |
|
|
|
ProxyPass / http://127.0.0.1:${TARGET_PORT}/ |
|
ProxyPassReverse / http://127.0.0.1:${TARGET_PORT}/ |
|
|
|
ErrorLog \${APACHE_LOG_DIR}/${HOSTNAME}_error.log |
|
CustomLog \${APACHE_LOG_DIR}/${HOSTNAME}_access.log combined |
|
|
|
</VirtualHost> |
|
EOF |
|
|
|
else |
|
if [[ "$DISTRO" == "debian" ]]; then |
|
VHOST_FILE="/etc/nginx/sites-available/${HOSTNAME}.conf" |
|
else |
|
VHOST_FILE="/etc/nginx/conf.d/${HOSTNAME}.conf" |
|
fi |
|
|
|
cat > "$VHOST_FILE" <<EOF |
|
server { |
|
|
|
listen ${EXTERNAL_PORT} ssl; |
|
|
|
server_name ${HOSTNAME}; |
|
|
|
ssl_certificate ${M2M_CERT}; |
|
ssl_certificate_key ${M2M_KEY}; |
|
|
|
ssl_client_certificate ${M2M_CHAIN}; |
|
ssl_verify_client on; |
|
|
|
location / { |
|
|
|
proxy_pass http://127.0.0.1:${TARGET_PORT}; |
|
|
|
proxy_set_header Host \$host; |
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; |
|
proxy_set_header X-Forwarded-Proto \$scheme; |
|
|
|
} |
|
} |
|
EOF |
|
fi |
|
fi |
|
|
|
############################################################################### |
|
# Summary |
|
############################################################################### |
|
|
|
echo |
|
echo "==========================================================" |
|
echo "Operation completed" |
|
echo "==========================================================" |
|
echo |
|
|
|
echo "Extracted Certificate:" |
|
echo " ${OUTPUT_CERT}" |
|
|
|
echo |
|
echo "Extracted Certificate Chain:" |
|
echo " ${OUTPUT_CHAIN}" |
|
|
|
echo |
|
echo "Extracted Private Key (unencrypted):" |
|
echo " ${OUTPUT_KEY}" |
|
|
|
if $INSTALL_MODE; then |
|
echo |
|
echo "Installed Certificate:" |
|
echo " ${M2M_CERT}" |
|
|
|
echo |
|
echo "Installed Certificate Chain:" |
|
echo " ${M2M_CHAIN}" |
|
|
|
echo |
|
echo "Installed Private Key:" |
|
echo " ${M2M_KEY}" |
|
|
|
if $CREATE_VHOST; then |
|
echo |
|
echo "Virtual Host:" |
|
echo " ${VHOST_FILE}" |
|
echo |
|
|
|
if [[ "$WEBSERVER" == "apache" ]]; then |
|
if [[ "$DISTRO" == "debian" ]]; then |
|
cat <<EOF |
|
|
|
Activate Site: |
|
a2enmod ssl |
|
a2enmod proxy |
|
a2enmod proxy_http |
|
|
|
a2ensite ${HOSTNAME} |
|
|
|
Validate: |
|
apachectl configtest |
|
|
|
Reload: |
|
systemctl reload apache2 |
|
|
|
EOF |
|
else |
|
cat <<EOF |
|
|
|
Validate: |
|
apachectl configtest |
|
|
|
Reload: |
|
systemctl reload httpd |
|
|
|
EOF |
|
fi |
|
else |
|
if [[ "$DISTRO" == "debian" ]]; then |
|
cat <<EOF |
|
|
|
Enable Site: |
|
ln -sf \ |
|
/etc/nginx/sites-available/${HOSTNAME}.conf \ |
|
/etc/nginx/sites-enabled/${HOSTNAME}.conf |
|
|
|
Validate: |
|
nginx -t |
|
|
|
Reload: |
|
systemctl reload nginx |
|
|
|
EOF |
|
else |
|
cat <<EOF |
|
|
|
Validate: |
|
nginx -t |
|
|
|
Reload: |
|
systemctl reload nginx |
|
|
|
EOF |
|
fi |
|
fi |
|
fi |
|
fi |