mirror of
https://github.com/retspen/webvirtcloud
synced 2026-10-18 00:50:07 +00:00
fix(security): resolve reviewer findings on secret key baking, host symlinks, and injection safety
- Prevent baking SECRET_KEY into Docker image during collectstatic - Persist runtime SECRET_KEY in data/secret_key volume or read from environment - Remove sed-based injection of CSRF_TRUSTED_ORIGINS in favor of native os.getenv - Avoid overwriting system python3 symlink on SUSE; auto-detect python 3.10+ binaries - Make /etc/hosts entry in installer idempotent - Add security notice regarding compute node VNC/SPICE port firewall isolation
This commit is contained in:
parent
b1a843e846
commit
7435d66492
5 changed files with 42 additions and 58 deletions
10
Dockerfile
10
Dockerfile
|
|
@ -42,15 +42,11 @@ RUN python3 -m venv --system-site-packages venv && \
|
|||
# Copy application source
|
||||
COPY . /srv/webvirtcloud
|
||||
|
||||
# Setup build-time settings, run collectstatic, and set permissions
|
||||
# Run collectstatic with temporary dummy key, then remove temporary settings file
|
||||
RUN . venv/bin/activate && \
|
||||
if [ ! -f webvirtcloud/settings.py ]; then \
|
||||
cp webvirtcloud/settings.py.template webvirtcloud/settings.py && \
|
||||
python3 -c 'import secrets; print(secrets.token_urlsafe(50))' > /tmp/secret_key && \
|
||||
sed -i "s|^SECRET_KEY = .*|SECRET_KEY = \"$(cat /tmp/secret_key)\"|" webvirtcloud/settings.py && \
|
||||
rm -f /tmp/secret_key; \
|
||||
fi && \
|
||||
python3 manage.py collectstatic --noinput && \
|
||||
SECRET_KEY="build-dummy-key-only-for-collectstatic" python3 manage.py collectstatic --noinput && \
|
||||
rm -f webvirtcloud/settings.py && \
|
||||
chown -R www-data:www-data /srv/webvirtcloud
|
||||
|
||||
# Setup Nginx
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -170,21 +170,17 @@ sudo systemctl restart nginx supervisord
|
|||
# 1. Install system prerequisites (Python 3.11 stack and C bindings)
|
||||
sudo zypper --non-interactive install -y git hostname python311 python311-base python311-devel python311-pip python311-libvirt-python python311-lxml python311-ldap libvirt-devel cyrus-sasl-devel libopenssl-devel gcc pkg-config nginx
|
||||
|
||||
# Ensure python3 points to Python 3.11
|
||||
sudo ln -sf /usr/bin/python3.11 /usr/bin/python3
|
||||
sudo ln -sf /usr/bin/pip3.11 /usr/bin/pip3
|
||||
|
||||
# 2. Clone repository to /srv/webvirtcloud
|
||||
sudo git clone https://github.com/retspen/webvirtcloud /srv/webvirtcloud
|
||||
cd /srv/webvirtcloud
|
||||
|
||||
# 3. Configure settings
|
||||
cp webvirtcloud/settings.py.template webvirtcloud/settings.py
|
||||
SECRET_KEY=$(python3 conf/runit/secret_generator.py)
|
||||
SECRET_KEY=$(python3.11 conf/runit/secret_generator.py)
|
||||
sed -i "s|^SECRET_KEY = .*|SECRET_KEY = \"${SECRET_KEY}\"|" webvirtcloud/settings.py
|
||||
|
||||
# 4. Create virtual environment and install dependencies
|
||||
python3 -m venv --system-site-packages venv
|
||||
python3.11 -m venv --system-site-packages venv
|
||||
source venv/bin/activate
|
||||
pip install -r conf/requirements.txt
|
||||
|
||||
|
|
@ -251,10 +247,9 @@ python manage.py runserver 0.0.0.0:8000
|
|||
```bash
|
||||
# 1. Install system prerequisites
|
||||
sudo zypper --non-interactive install -y git hostname python311 python311-base python311-devel python311-pip python311-libvirt-python python311-lxml python311-ldap libvirt-devel cyrus-sasl-devel libopenssl-devel gcc pkg-config
|
||||
sudo ln -sf /usr/bin/python3.11 /usr/bin/python3
|
||||
|
||||
# 2. Create virtual environment with system site packages
|
||||
python3 -m venv --system-site-packages .venv
|
||||
python3.11 -m venv --system-site-packages .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
# 3. Install Python dependencies
|
||||
|
|
@ -263,7 +258,7 @@ pip install -r dev/requirements.txt
|
|||
|
||||
# 4. Initialize configuration and run local dev server
|
||||
cp webvirtcloud/settings.py.template webvirtcloud/settings.py
|
||||
sed -i -E 's/SECRET_KEY = .*/SECRET_KEY = "'$(python3 conf/runit/secret_generator.py)'"/' webvirtcloud/settings.py
|
||||
sed -i -E 's/SECRET_KEY = .*/SECRET_KEY = "'$(python3.11 conf/runit/secret_generator.py)'"/' webvirtcloud/settings.py
|
||||
python manage.py migrate
|
||||
python manage.py runserver 0.0.0.0:8000
|
||||
```
|
||||
|
|
@ -326,6 +321,9 @@ sudo dnf install -y dmidecode && sudo systemctl restart libvirtd
|
|||
sudo zypper install -y dmidecode && sudo systemctl restart libvirtd
|
||||
```
|
||||
|
||||
> **Security Notice (Compute Node Firewall):**
|
||||
> Libvirt compute nodes listen on VNC/SPICE ports (`5900`–`65535`) to allow WebVirtCloud to proxy graphical consoles. Ensure your firewall (`ufw`, `firewalld`, or `iptables`) restricts these ports to accept connections **only** from the WebVirtCloud panel IP, and never exposes them directly to public networks.
|
||||
|
||||
---
|
||||
|
||||
## Configuration & Operational Notes
|
||||
|
|
|
|||
|
|
@ -11,22 +11,13 @@ if [ ! -f "$APP_DIR/webvirtcloud/settings.py" ]; then
|
|||
cp "$APP_DIR/webvirtcloud/settings.py.template" "$APP_DIR/webvirtcloud/settings.py"
|
||||
fi
|
||||
|
||||
# Set SECRET_KEY if placeholder exists
|
||||
if grep -q 'SECRET_KEY = ""' "$APP_DIR/webvirtcloud/settings.py" || grep -q "SECRET_KEY = ''" "$APP_DIR/webvirtcloud/settings.py"; then
|
||||
KEY="${SECRET_KEY:-$("$APP_DIR/venv/bin/python3" -c 'import secrets; print(secrets.token_urlsafe(50))')}"
|
||||
sed -i "s|^SECRET_KEY = .*|SECRET_KEY = \"${KEY}\"|" "$APP_DIR/webvirtcloud/settings.py"
|
||||
fi
|
||||
|
||||
# Configure CSRF_TRUSTED_ORIGINS if environment variable is set
|
||||
if [ -n "$CSRF_TRUSTED_ORIGINS" ]; then
|
||||
echo "* Setting CSRF_TRUSTED_ORIGINS from environment..."
|
||||
origins=""
|
||||
IFS=',' read -ra ADDR <<< "$CSRF_TRUSTED_ORIGINS"
|
||||
for o in "${ADDR[@]}"; do
|
||||
clean_o=$(echo "$o" | xargs)
|
||||
[ -n "$clean_o" ] && origins="${origins}'${clean_o}', "
|
||||
done
|
||||
sed -i "s|^CSRF_TRUSTED_ORIGINS = .*|CSRF_TRUSTED_ORIGINS = [ ${origins} ]|" "$APP_DIR/webvirtcloud/settings.py"
|
||||
# Ensure SECRET_KEY is persisted across container restarts if not supplied via environment
|
||||
if [ -z "$SECRET_KEY" ]; then
|
||||
if [ ! -s "$DATA_DIR/secret_key" ]; then
|
||||
echo "* Generating fresh random SECRET_KEY..."
|
||||
"$APP_DIR/venv/bin/python3" -c 'import secrets; print(secrets.token_urlsafe(50))' > "$DATA_DIR/secret_key"
|
||||
chmod 600 "$DATA_DIR/secret_key"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Persist SQLite database in DATA_DIR
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ readonly APP_REPO_URL="${APP_REPO_URL:-https://github.com/retspen/webvirtcloud.g
|
|||
readonly APP_NAME="webvirtcloud"
|
||||
readonly APP_PATH="/srv/$APP_NAME"
|
||||
|
||||
readonly PYTHON="python3"
|
||||
PYTHON="python3"
|
||||
|
||||
progress () {
|
||||
spin[0]="-"
|
||||
|
|
@ -238,26 +238,26 @@ run_as_app_user () {
|
|||
}
|
||||
|
||||
check_python () {
|
||||
# dynamically find python >= 3.10 if default python3 is older
|
||||
for py_bin in python3.11 python3.12 python3.13 python3.10 python3; do
|
||||
if command -v "$py_bin" >/dev/null 2>&1; then
|
||||
if "$py_bin" -c 'import sys; sys.exit(0 if sys.version_info >= (3, 10) else 1)' >/dev/null 2>&1; then
|
||||
PYTHON="$py_bin"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# check if python3 is installed.
|
||||
if ! hash "$PYTHON" 2>/dev/null; then
|
||||
echo "Python3 is not installed. Please install Python3 and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check if python3 version is grater than 3.10 amd set it as default
|
||||
# check if python3 version is greater than 3.10
|
||||
if ! "$PYTHON" -c 'import sys; assert sys.version_info >= (3, 10)' >/dev/null 2>&1; then
|
||||
echo "Your Python version is less than 3.10. This script requires Python 3.10 or greater."
|
||||
echo "Please install Python 3.10 or greater and set it as the default version."
|
||||
echo "Use update-alternatives command to set default python version to latest."
|
||||
echo "For example: sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1"
|
||||
echo "Then run this script again."
|
||||
echo "Do not forget to install pip3 and python3-devel for python3.10 or later."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check if pip3 is installed
|
||||
if ! hash pip3 2>/dev/null; then
|
||||
echo "pip3 is not installed. Please install pip3 and try again."
|
||||
echo "Please install Python 3.10 or greater (such as python311) and try again."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
|
@ -367,7 +367,9 @@ set_hosts () {
|
|||
echo "* Setting up hosts file."
|
||||
local hname
|
||||
hname="$(hostname 2>/dev/null || uname -n)"
|
||||
if ! grep -q "$fqdn" /etc/hosts 2>/dev/null; then
|
||||
echo >> /etc/hosts "127.0.0.1 $hname $fqdn"
|
||||
fi
|
||||
}
|
||||
|
||||
restart_supervisor () {
|
||||
|
|
@ -750,16 +752,6 @@ case $distro in
|
|||
fi
|
||||
install_packages
|
||||
|
||||
# Ensure python3 and pip3 point to python 3.11+ if installed
|
||||
if command -v python3.11 >/dev/null 2>&1; then
|
||||
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 2>/dev/null || true
|
||||
ln -sf /usr/bin/python3.11 /usr/bin/python3
|
||||
if command -v pip3.11 >/dev/null 2>&1; then
|
||||
update-alternatives --install /usr/bin/pip3 pip3 /usr/bin/pip3.11 1 2>/dev/null || true
|
||||
ln -sf /usr/bin/pip3.11 /usr/bin/pip3
|
||||
fi
|
||||
fi
|
||||
|
||||
set_hosts
|
||||
|
||||
# Supervisor on SUSE (available as python3-supervisor, supervisor, or via pip)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,14 @@ from pathlib import Path
|
|||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
SECRET_KEY = ""
|
||||
SECRET_KEY = os.getenv("SECRET_KEY", "")
|
||||
if not SECRET_KEY:
|
||||
secret_file = BASE_DIR / "data" / "secret_key"
|
||||
if secret_file.exists():
|
||||
try:
|
||||
SECRET_KEY = secret_file.read_text().strip()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue