mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 01:26:11 -08:00
Merge pull request #1248 from adamoutler/Easy-Permissions
Easy permissions
This commit is contained in:
@@ -224,8 +224,8 @@ COPY .devcontainer/resources/devcontainer-overlay/ /
|
|||||||
USER root
|
USER root
|
||||||
# Install common tools, create user, and set up sudo
|
# Install common tools, create user, and set up sudo
|
||||||
RUN apk add --no-cache git nano vim jq php83-pecl-xdebug py3-pip nodejs sudo gpgconf pytest \
|
RUN apk add --no-cache git nano vim jq php83-pecl-xdebug py3-pip nodejs sudo gpgconf pytest \
|
||||||
pytest-cov fish shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx
|
pytest-cov fish shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx \
|
||||||
|
docker-cli-compose
|
||||||
|
|
||||||
RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \
|
RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \
|
||||||
cp -a /usr/lib/php83/modules/. /services/php/modules/ && \
|
cp -a /usr/lib/php83/modules/. /services/php/modules/ && \
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ COPY .devcontainer/resources/devcontainer-overlay/ /
|
|||||||
USER root
|
USER root
|
||||||
# Install common tools, create user, and set up sudo
|
# Install common tools, create user, and set up sudo
|
||||||
RUN apk add --no-cache git nano vim jq php83-pecl-xdebug py3-pip nodejs sudo gpgconf pytest \
|
RUN apk add --no-cache git nano vim jq php83-pecl-xdebug py3-pip nodejs sudo gpgconf pytest \
|
||||||
pytest-cov fish shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx
|
pytest-cov fish shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx \
|
||||||
|
docker-cli-compose
|
||||||
|
|
||||||
RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \
|
RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \
|
||||||
cp -a /usr/lib/php83/modules/. /services/php/modules/ && \
|
cp -a /usr/lib/php83/modules/. /services/php/modules/ && \
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
# --- Color Codes ---
|
# --- Color Codes ---
|
||||||
RED='\033[1;31m'
|
RED='\033[1;31m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
|
MAGENTA='\033[1;35m'
|
||||||
RESET='\033[0m'
|
RESET='\033[0m'
|
||||||
|
|
||||||
# --- Main Logic ---
|
# --- Main Logic ---
|
||||||
@@ -31,19 +32,45 @@ ${NETALERTX_API}
|
|||||||
${NETALERTX_LOG}
|
${NETALERTX_LOG}
|
||||||
${SYSTEM_SERVICES_RUN}
|
${SYSTEM_SERVICES_RUN}
|
||||||
${NETALERTX_CONFIG}
|
${NETALERTX_CONFIG}
|
||||||
$(dirname "${NETALERTX_DB_FILE}")
|
${NETALERTX_CONFIG_FILE}
|
||||||
|
${NETALERTX_DB}
|
||||||
|
${NETALERTX_DB_FILE}
|
||||||
"
|
"
|
||||||
|
|
||||||
# If running as root, fix permissions first
|
# If running as root, fix permissions first
|
||||||
if [ "$(id -u)" -eq 0 ]; then
|
if [ "$(id -u)" -eq 0 ]; then
|
||||||
echo "Running as root. Ensuring correct ownership and permissions..."
|
>&2 printf "%s" "${MAGENTA}"
|
||||||
|
>&2 cat <<'EOF'
|
||||||
|
══════════════════════════════════════════════════════════════════════════════
|
||||||
|
🚨 CRITICAL SECURITY ALERT: NetAlertX is running as ROOT (UID 0)! 🚨
|
||||||
|
|
||||||
# Set ownership to netalertx user and group for all read-write paths
|
This configuration bypasses all built-in security hardening measures.
|
||||||
chown -R netalertx:netalertx ${READ_WRITE_PATHS}
|
You've granted a network monitoring application unrestricted access to
|
||||||
|
your host system. A successful compromise here could jeopardize your
|
||||||
|
entire infrastructure.
|
||||||
|
|
||||||
|
IMMEDIATE ACTION REQUIRED: Switch to the dedicated 'netalertx' user:
|
||||||
|
* Remove any 'user:' directive specifying UID 0 from docker-compose.yml or
|
||||||
|
* switch to the default USER in the image (20211:20211)
|
||||||
|
|
||||||
|
IMPORTANT: This corrective mode automatically adjusts ownership of
|
||||||
|
/app/db and /app/config directories to the netalertx user, ensuring
|
||||||
|
proper operation in subsequent runs.
|
||||||
|
|
||||||
|
Remember: Never operate security-critical tools as root unless you're
|
||||||
|
actively trying to get pwned.
|
||||||
|
══════════════════════════════════════════════════════════════════════════════
|
||||||
|
EOF
|
||||||
|
>&2 printf "%s" "${RESET}"
|
||||||
|
|
||||||
|
# Set ownership to netalertx user for all read-write paths
|
||||||
|
chown -R netalertx ${READ_WRITE_PATHS}
|
||||||
|
|
||||||
# Set directory and file permissions for all read-write paths
|
# Set directory and file permissions for all read-write paths
|
||||||
find ${READ_WRITE_PATHS} -type d -exec chmod 700 {} +
|
find ${READ_WRITE_PATHS} -type d -exec chmod u+rwx {} + 2>/dev/null
|
||||||
find ${READ_WRITE_PATHS} -type f -exec chmod 600 {} +
|
find ${READ_WRITE_PATHS} -type f -exec chmod u+rw {} + 2>/dev/null
|
||||||
|
echo Permissions fixed for read-write paths. Please restart the container as user 20211.
|
||||||
|
sleep infinity & wait $!; exit 211
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Permission Validation ---
|
# --- Permission Validation ---
|
||||||
|
|||||||
@@ -710,7 +710,7 @@ def test_missing_mount_app_db(tmp_path: pathlib.Path) -> None:
|
|||||||
paths = _setup_mount_tree(tmp_path, "missing_mount_app_db")
|
paths = _setup_mount_tree(tmp_path, "missing_mount_app_db")
|
||||||
volumes = _build_volume_args(paths, skip={"app_db"})
|
volumes = _build_volume_args(paths, skip={"app_db"})
|
||||||
# CHANGE: Run as root (0:0) to bypass all permission checks on other mounts.
|
# CHANGE: Run as root (0:0) to bypass all permission checks on other mounts.
|
||||||
result = _run_container("missing-mount-app-db", volumes, user="0:0")
|
result = _run_container("missing-mount-app-db", volumes, user="20211:20211")
|
||||||
# Acknowledge the original intent to check for permission denial (now implicit via root)
|
# Acknowledge the original intent to check for permission denial (now implicit via root)
|
||||||
# _assert_contains(result, "Write permission denied", result.args) # No longer needed, as root user is used
|
# _assert_contains(result, "Write permission denied", result.args) # No longer needed, as root user is used
|
||||||
|
|
||||||
@@ -820,7 +820,7 @@ def test_running_as_root_is_blocked(tmp_path: pathlib.Path) -> None:
|
|||||||
dedicated netalertx user. Warning about security risks, special permission fix mode.
|
dedicated netalertx user. Warning about security risks, special permission fix mode.
|
||||||
Expected: Warning about security risks, guidance to use UID 20211.
|
Expected: Warning about security risks, guidance to use UID 20211.
|
||||||
|
|
||||||
Check script: check-root.sh
|
Check script: check-app-permissions.sh
|
||||||
Sample message: "⚠️ ATTENTION: NetAlertX is running as root (UID 0). This defeats every hardening..."
|
Sample message: "⚠️ ATTENTION: NetAlertX is running as root (UID 0). This defeats every hardening..."
|
||||||
"""
|
"""
|
||||||
paths = _setup_mount_tree(tmp_path, "run_as_root")
|
paths = _setup_mount_tree(tmp_path, "run_as_root")
|
||||||
@@ -828,10 +828,11 @@ def test_running_as_root_is_blocked(tmp_path: pathlib.Path) -> None:
|
|||||||
result = _run_container(
|
result = _run_container(
|
||||||
"run-as-root",
|
"run-as-root",
|
||||||
volumes,
|
volumes,
|
||||||
user="0:0",
|
user="0",
|
||||||
)
|
)
|
||||||
_assert_contains(result, "NetAlertX is running as root", result.args)
|
_assert_contains(result, "NetAlertX is running as ROOT", result.args)
|
||||||
assert result.returncode != 0
|
_assert_contains(result, "Permissions fixed for read-write paths.", result.args)
|
||||||
|
assert result.returncode == 0 # container must be forced to exit 0 by termination after warning
|
||||||
|
|
||||||
|
|
||||||
def test_running_as_uid_1000_warns(tmp_path: pathlib.Path) -> None:
|
def test_running_as_uid_1000_warns(tmp_path: pathlib.Path) -> None:
|
||||||
@@ -852,7 +853,7 @@ def test_running_as_uid_1000_warns(tmp_path: pathlib.Path) -> None:
|
|||||||
volumes,
|
volumes,
|
||||||
user="1000:1000",
|
user="1000:1000",
|
||||||
)
|
)
|
||||||
_assert_contains(result, "NetAlertX is running as UID", result.args)
|
_assert_contains(result, "NetAlertX is running as UID 1000:1000", result.args)
|
||||||
assert result.returncode != 0
|
assert result.returncode != 0
|
||||||
|
|
||||||
|
|
||||||
@@ -885,10 +886,12 @@ def test_missing_app_conf_triggers_seed(tmp_path: pathlib.Path) -> None:
|
|||||||
Container automatically regenerates default configuration on startup.
|
Container automatically regenerates default configuration on startup.
|
||||||
Expected: Automatic regeneration of default configuration.
|
Expected: Automatic regeneration of default configuration.
|
||||||
"""
|
"""
|
||||||
paths = _setup_mount_tree(tmp_path, "missing_app_conf")
|
base = tmp_path / "missing_app_conf_base"
|
||||||
(paths["app_config"] / "app.conf").unlink()
|
paths = _setup_fixed_mount_tree(base)
|
||||||
|
_chown_netalertx(paths["app_config"])
|
||||||
|
(paths["app_config"] / "testfile.txt").write_text("test")
|
||||||
volumes = _build_volume_args(paths)
|
volumes = _build_volume_args(paths)
|
||||||
result = _run_container("missing-app-conf", volumes, user="0:0")
|
result = _run_container("missing-app-conf", volumes)
|
||||||
_assert_contains(result, "Default configuration written to", result.args)
|
_assert_contains(result, "Default configuration written to", result.args)
|
||||||
assert result.returncode != 0
|
assert result.returncode != 0
|
||||||
|
|
||||||
@@ -900,10 +903,12 @@ def test_missing_app_db_triggers_seed(tmp_path: pathlib.Path) -> None:
|
|||||||
Container automatically creates initial database schema on startup.
|
Container automatically creates initial database schema on startup.
|
||||||
Expected: Automatic creation of initial database schema.
|
Expected: Automatic creation of initial database schema.
|
||||||
"""
|
"""
|
||||||
paths = _setup_mount_tree(tmp_path, "missing_app_db")
|
base = tmp_path / "missing_app_db_base"
|
||||||
(paths["app_db"] / "app.db").unlink()
|
paths = _setup_fixed_mount_tree(base)
|
||||||
|
_chown_netalertx(paths["app_db"])
|
||||||
|
(paths["app_db"] / "testfile.txt").write_text("test")
|
||||||
volumes = _build_volume_args(paths)
|
volumes = _build_volume_args(paths)
|
||||||
result = _run_container("missing-app-db", volumes, user="0:0")
|
result = _run_container("missing-app-db", volumes, user="20211:20211")
|
||||||
_assert_contains(result, "Building initial database schema", result.args)
|
_assert_contains(result, "Building initial database schema", result.args)
|
||||||
assert result.returncode != 0
|
assert result.returncode != 0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user