mb-admin/scripts/pma-gateway/create_pma_gateway.sh

246 lines
6.9 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/bin/bash
# ==============================================================================
# Script: create_pma_gateway.sh
# Purpose: Create a time-limited gateway URL for phpMyAdmin on Virtuozzo LLSMP.
# Usage: create_pma_gateway.sh --validity=30 [--slug=myalias]
# Outputs: Prints the generated URL.
# ==============================================================================
set -euo pipefail
SLUG=""
VALIDITY=30 # minutes
for arg in "$@"; do
case $arg in
--slug=*) SLUG="${arg#*=}" ;;
--validity=*) VALIDITY="${arg#*=}" ;;
*) echo "Unknown argument $arg"; exit 1 ;;
esac
done
if [[ -z "$SLUG" ]]; then
SLUG=$(openssl rand -hex 4) # 8-char random
fi
# Determine environment public host (no node prefix)
if [[ -n "${JELASTIC_ENV_DOMAIN:-}" ]]; then
ENV_HOST="$JELASTIC_ENV_DOMAIN"
else
ENV_HOST=$(hostname -f)
ENV_HOST=${ENV_HOST#node*-} # strip nodeXXXX-
fi
PMADB_DIR="/usr/share/phpMyAdmin"
GATEWAY_FILE="$PMADB_DIR/access-db-$SLUG.php"
SECRET_FILE="/var/lib/jelastic/keys/mbadmin_secret"
sudo mkdir -p "$(dirname $SECRET_FILE)"
if [[ ! -f "$SECRET_FILE" ]]; then
sudo sh -c "openssl rand -hex 32 > $SECRET_FILE"
fi
sudo chown litespeed:litespeed "$SECRET_FILE"
sudo chmod 644 "$SECRET_FILE"
SECRET=$(sudo cat "$SECRET_FILE" | xargs)
now=$(date +%s)
expires=$((now + VALIDITY*60))
# token = base64("$SLUG:$expires") . '.' . HMAC_SHA256(secret, data)
data="$SLUG:$expires"
base=$(printf "%s" "$data" | base64 | tr -d '\n')
mac=$(php -r "echo hash_hmac('sha256', '$data', '$SECRET');")
token="$base.$mac"
# Secure the phpMyAdmin vhost with Rewrite Rules to block direct access
VHOST_CONFIG="/usr/share/phpMyAdmin/vhost.conf"
NEEDS_RESTART=0
# If vhost config is missing or empty, recreate it from a known-good default.
if [ ! -s "$VHOST_CONFIG" ]; then
echo "Warning: $VHOST_CONFIG is empty or missing. Recreating from default." >&2
sudo tee "$VHOST_CONFIG" > /dev/null <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<virtualHostConfig>
<docRoot>/usr/share/phpMyAdmin/</docRoot>
<enableGzip>1</enableGzip>
<logging>
<log>
<useServer>0</useServer>
<fileName>$SERVER_ROOT/logs/error.log</fileName>
<logLevel>DEBUG</logLevel>
<rollingSize>10M</rollingSize>
</log>
<accessLog>
<useServer>0</useServer>
<fileName>$SERVER_ROOT/logs/access.log</fileName>
<rollingSize>10M</rollingSize>
<keepDays>30</keepDays>
<compressArchive>0</compressArchive>
</accessLog>
</logging>
<index>
<useServer>0</useServer>
<indexFiles>index.php, index.html</indexFiles>
<autoIndex>0</autoIndex>
<autoIndexURI>/_autoindex/default.php</autoIndexURI>
</index>
<customErrorPages>
<errorPage>
<errCode>404</errCode>
<url>/error404.html</url>
</errorPage>
</customErrorPages>
<htAccess>
<allowOverride>31</allowOverride>
<accessFileName>.htaccess</accessFileName>
</htAccess>
<expires>
<enableExpires>1</enableExpires>
</expires>
<security>
<wpProtectAction>0</wpProtectAction>
<hotlinkCtrl>
<enableHotlinkCtrl>0</enableHotlinkCtrl>
<suffixes>gif, jpeg, jpg</suffixes>
<allowDirectAccess>1</allowDirectAccess>
<onlySelf>1</onlySelf>
</hotlinkCtrl>
<accessControl>
<allow>*</allow>
</accessControl>
<wpProtectLimit>10</wpProtectLimit></security>
<cache>
<storage>
<cacheStorePath>/tmp/lscache/vhosts/$VH_NAME</cacheStorePath>
</storage>
</cache>
<rewrite>
<enable>0</enable>
<logLevel>0</logLevel>
<rules>RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot
RewriteRule ^/nospider/ - [F]</rules>
</rewrite>
<vhssl>
<keyFile>/var/www/ssl/litespeed.key</keyFile>
<certFile>/var/www/ssl/litespeed.crt</certFile>
<certChain>1</certChain>
</vhssl>
<frontPage>
<enable>0</enable>
<disableAdmin>0</disableAdmin>
</frontPage>
<awstats>
<updateMode>0</updateMode>
<workingDir>$VH_ROOT/awstats</workingDir>
<awstatsURI>/awstats/</awstatsURI>
<siteDomain>localhost</siteDomain>
<siteAliases>127.0.0.1 localhost</siteAliases>
<updateInterval>86400</updateInterval>
<updateOffset>0</updateOffset>
</awstats>
</virtualHostConfig>
EOF
NEEDS_RESTART=1
fi
if [ -f "$VHOST_CONFIG" ]; then
MARKER="# PMA Gateway Security Rules"
# If rules are not already in place, add them.
if ! sudo grep -qF "$MARKER" "$VHOST_CONFIG"; then
# Remove any existing rewrite block to ensure a clean state.
sudo sed -i '/\s*<rewrite>/,/<\/rewrite>/d' "$VHOST_CONFIG"
# Define the new rewrite block using a temporary file to avoid escaping issues.
REWRITE_TMP=$(mktemp)
cat > "$REWRITE_TMP" <<'EOF'
<rewrite>
<enable>1</enable>
<logLevel>0</logLevel>
<rules>
# PMA Gateway Security Rules
# Allow access to the gateway scripts themselves
RewriteCond %{REQUEST_URI} ^/access-db-.*\.php$
RewriteRule .* - [L]
# For all other requests, block if the security cookie is not present
RewriteCond %{HTTP_COOKIE} !pma_access_granted
RewriteRule .* - [F,L]
</rules>
</rewrite>
EOF
# Use awk to insert the new block before the </vhssl> tag for robustness
sudo awk -v r="$(cat $REWRITE_TMP)" '{if (/\s*<vhssl>/) print r} {print}' "$VHOST_CONFIG" | sudo tee "$VHOST_CONFIG" > /dev/null
rm -f "$REWRITE_TMP"
NEEDS_RESTART=1
fi
else
echo "Warning: phpMyAdmin vhost config not found at $VHOST_CONFIG. Cannot apply security rules." >&2
fi
sudo tee "$GATEWAY_FILE" >/dev/null <<'PHP'
<?php
// Secure phpMyAdmin gateway auto-generated, do NOT edit manually.
ini_set('session.cookie_httponly', 1);
$param = 'token';
function deny() {
http_response_code(403);
echo 'Access denied';
exit;
}
if (!isset($_GET[$param])) {
deny();
}
$token = $_GET[$param];
if (strpos($token, '.') === false) {
deny();
}
list($base, $sig) = explode('.', $token, 2);
$data = base64_decode($base, true);
if ($data === false) {
deny();
}
if (strpos($data, ':') === false) {
deny();
}
list($slug, $exp) = explode(':', $data, 2);
if (time() > intval($exp)) {
unlink(__FILE__); // Self-destruct if expired
deny();
}
$secret = trim(file_get_contents('/var/lib/jelastic/keys/mbadmin_secret'));
if (!hash_equals($sig, hash_hmac('sha256', $data, $secret))) {
deny();
}
// Issue a short-lived cookie that the rewrite rule looks for.
// This cookie acts as the temporary pass.
setcookie('pma_access_granted', $sig, intval($exp), '/', '', true, true);
header('Location: /');
exit;
?>
PHP
sudo chown litespeed:litespeed "$GATEWAY_FILE"
sudo chmod 644 "$GATEWAY_FILE"
# Restart LiteSpeed if we modified the config
if [[ "${NEEDS_RESTART:-0}" -eq 1 ]]; then
echo "Applying security rules and restarting LiteSpeed..." >&2
if ! sudo systemctl restart lsws; then
echo "Warning: LiteSpeed restart failed. Manual restart may be required." >&2
fi
fi
URL="https://$ENV_HOST:8443/access-db-$SLUG.php?token=$token"
echo "$URL"