From ce8bb53bc88e07e0434e8df424018be449dd2915 Mon Sep 17 00:00:00 2001 From: Adam Outler Date: Wed, 22 Oct 2025 19:48:58 -0400 Subject: [PATCH] Refine devcontainer setup and docker tests --- .devcontainer/Dockerfile | 22 +++--- .devcontainer/devcontainer.json | 3 + .../resources/devcontainer-Dockerfile | 14 ++-- .devcontainer/scripts/setup.sh | 47 ++++++++++++ test/docker_tests/README.md | 39 ++++++++++ .../dockerfiles/no-error-compose.yml | 76 +++++++++++++++++++ 6 files changed, 182 insertions(+), 19 deletions(-) create mode 100644 test/docker_tests/README.md create mode 100755 test/docker_tests/dockerfiles/no-error-compose.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3e0c7324..fddc5803 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -# DO NOT MODIFY THIS FILE DIRECTLY. IT IS AUTO-GENERATED BY .devcontainer/scripts/generate-dockerfile.sh +# DO NOT MODIFY THIS FILE DIRECTLY. IT IS AUTO-GENERATED BY .devcontainer/scripts/generate-configs.sh # ---/Dockerfile--- # The NetAlertX Dockerfile has 3 stages: @@ -103,7 +103,6 @@ ENV PORT=20211 ENV NETALERTX_DEBUG=0 ENV VENDORSPATH=/app/back/ieee-oui.txt ENV VENDORSPATH_NEWEST=/services/run/tmp/ieee-oui.txt -ENV PYTHONPATHPATH="${NETALERTX_APP}:${VIRTUAL_ENV}/bin:${PATH}" ENV ENVIRONMENT=alpine ENV READ_ONLY_USER=readonly READ_ONLY_GROUP=readonly ENV NETALERTX_USER=netalertx NETALERTX_GROUP=netalertx @@ -146,13 +145,14 @@ RUN apk add libcap && \ setcap cap_net_raw,cap_net_admin+eip /usr/bin/arp-scan && \ setcap cap_net_raw,cap_net_admin,cap_net_bind_service+eip /usr/bin/nbtscan && \ setcap cap_net_raw,cap_net_admin+eip /usr/bin/traceroute && \ - setcap cap_net_raw,cap_net_admin+eip ${VIRTUAL_ENV_BIN}/scapy && \ + setcap cap_net_raw,cap_net_admin+eip $(readlink -f ${VIRTUAL_ENV_BIN}/python) && \ /bin/sh /build/init-nginx.sh && \ /bin/sh /build/init-php-fpm.sh && \ /bin/sh /build/init-crond.sh && \ /bin/sh /build/init-backend.sh && \ rm -rf /build && \ - apk del libcap + apk del libcap && \ + date +%s > ${NETALERTX_FRONT}/buildtimestamp.txt ENTRYPOINT ["/bin/sh","/entrypoint.sh"] @@ -218,19 +218,17 @@ ENV PORT=20211 ENV NETALERTX_DEBUG=1 ENV PYDEVD_DISABLE_FILE_VALIDATION=1 COPY .devcontainer/resources/devcontainer-overlay/ / - +USER root # 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 pytest-cov fish shfmt sudo +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 + RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \ cp -a /usr/lib/php83/modules/. /services/php/modules/ && \ echo "${NETALERTX_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers -# Install debugpy in the virtualenv if present, otherwise into system python3 -RUN /bin/sh -c '(/opt/venv/bin/python3 -m pip install --no-cache-dir debugpy) || (python3 -m pip install --no-cache-dir debugpy) || true' && \ - mkdir /workspaces && \ +RUN mkdir /workspaces && \ install -d -o netalertx -g netalertx -m 777 /services/run/logs && \ install -d -o netalertx -g netalertx -m 777 /app/run/tmp/client_body && \ - sed -i -e 's|:/app:|:/workspaces:|' /etc/passwd && \ - python -m pip install -U pytest pytest-cov - + sed -i -e 's|:/app:|:/workspaces:|' /etc/passwd +USER netalertx ENTRYPOINT ["/bin/sh","-c","sleep infinity"] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e947a3fa..3cbfd89e 100755 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -23,6 +23,9 @@ // even within this container and connect to them as needed. // "--network=host", ], + "mounts": [ + "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" //used for testing various conditions in docker + ], // ATTENTION: If running with --network=host, COMMENT `forwardPorts` OR ELSE THERE WILL BE NO WEBUI! "forwardPorts": [20211, 20212, 5678], "portsAttributes": { // the ports we care about diff --git a/.devcontainer/resources/devcontainer-Dockerfile b/.devcontainer/resources/devcontainer-Dockerfile index 28fd8c38..1952b816 100755 --- a/.devcontainer/resources/devcontainer-Dockerfile +++ b/.devcontainer/resources/devcontainer-Dockerfile @@ -15,19 +15,19 @@ ENV PORT=20211 ENV NETALERTX_DEBUG=1 ENV PYDEVD_DISABLE_FILE_VALIDATION=1 COPY .devcontainer/resources/devcontainer-overlay/ / - +USER root # 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 pytest-cov fish shfmt github-cli +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 + RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \ cp -a /usr/lib/php83/modules/. /services/php/modules/ && \ echo "${NETALERTX_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers -# Install debugpy in the virtualenv if present, otherwise into system python3 -RUN /bin/sh -c '(/opt/venv/bin/python3 -m pip install --no-cache-dir debugpy) || (python3 -m pip install --no-cache-dir debugpy) || true' && \ - mkdir /workspaces && \ +RUN mkdir /workspaces && \ install -d -o netalertx -g netalertx -m 777 /services/run/logs && \ install -d -o netalertx -g netalertx -m 777 /app/run/tmp/client_body && \ sed -i -e 's|:/app:|:/workspaces:|' /etc/passwd && \ - python -m pip install -U pytest pytest-cov - + find /opt/venv -type d -exec chmod o+rw {} + && \ + pip install pytest docker +USER netalertx ENTRYPOINT ["/bin/sh","-c","sleep infinity"] diff --git a/.devcontainer/scripts/setup.sh b/.devcontainer/scripts/setup.sh index 2ee40c96..bac5a49f 100755 --- a/.devcontainer/scripts/setup.sh +++ b/.devcontainer/scripts/setup.sh @@ -25,11 +25,52 @@ export PORT=20211 export SOURCE_DIR="/workspaces/NetAlertX" +ensure_docker_socket_access() { + local socket="/var/run/docker.sock" + if [ ! -S "${socket}" ]; then + echo "docker socket not present; skipping docker group configuration" + return + fi + + local sock_gid + sock_gid=$(stat -c '%g' "${socket}" 2>/dev/null || true) + if [ -z "${sock_gid}" ]; then + echo "unable to determine docker socket gid; skipping docker group configuration" + return + fi + + local group_entry="" + if command -v getent >/dev/null 2>&1; then + group_entry=$(getent group "${sock_gid}" 2>/dev/null || true) + else + group_entry=$(grep -E ":${sock_gid}:" /etc/group 2>/dev/null || true) + fi + + local group_name="" + if [ -n "${group_entry}" ]; then + group_name=$(echo "${group_entry}" | cut -d: -f1) + else + group_name="docker-host" + sudo addgroup -g "${sock_gid}" "${group_name}" 2>/dev/null || group_name=$(grep -E ":${sock_gid}:" /etc/group | head -n1 | cut -d: -f1) + fi + + if [ -z "${group_name}" ]; then + echo "failed to resolve group for docker socket gid ${sock_gid}; skipping docker group configuration" + return + fi + + if ! id -nG netalertx | tr ' ' '\n' | grep -qx "${group_name}"; then + sudo addgroup netalertx "${group_name}" 2>/dev/null || true + fi +} + + main() { echo "=== NetAlertX Development Container Setup ===" killall php-fpm83 nginx crond python3 2>/dev/null sleep 1 echo "Setting up ${SOURCE_DIR}..." + ensure_docker_socket_access sudo chown $(id -u):$(id -g) /workspaces sudo chmod 755 /workspaces configure_source @@ -102,6 +143,12 @@ configure_source() { killall python3 &>/dev/null sleep 0.2 done + sudo chmod 777 /opt/venv/lib/python3.12/site-packages/ && \ + pip install --no-cache-dir debugpy docker && \ + sudo chmod 005 /opt/venv/lib/python3.12/site-packages/ + sudo chmod 666 /var/run/docker.sock + + echo " -> Updating build timestamp" date +%s > ${NETALERTX_FRONT}/buildtimestamp.txt } diff --git a/test/docker_tests/README.md b/test/docker_tests/README.md new file mode 100644 index 00000000..f8eb6b65 --- /dev/null +++ b/test/docker_tests/README.md @@ -0,0 +1,39 @@ +# Alpine Docker tests + +This is intended to be run as Root user as permissions are altered. It will create and analyze the results of various configurations on containers. The test craeates a container, logs the results, terminates the container, then starts the next test +0. No errors on startup + 1. missing config/db generation + 2. After config/db generation +1. root user mount on + 1. /app/db + 2. /app/config + 3. /app/log + 4. /app/api + 5. /services/config/nginx/conf.active + 6. /services/run/ +2. 000 permissions on + 1. /app/db + 2. /app/db/app.db + 3. /app/config + 4. /app/config/app.conf + 5. /app/log + 6. /app/api + 7. /services/config/nginx/conf.active + 8. /services/run/ +3. Container read-only missing mounts + 1. /app/db + 2. /app/config + 3. /app/log + 4. /app/api + 5. /services/config/nginx/conf.active + 6. /services/run/ +4. Custom port/listen address without /services/config/nginx/conf.active mount +5. Missing cap NET_ADMIN, NET_RAW, NET_BIND_SERVICE +6. Run as Root user +7. Run as user 1000 +8. Run without network_mode host +9. Missing /app/config/app.conf +10. Missing /app/db/app.db +11. Ramdisk mounted on + 1. /app/config + 2. /app/db \ No newline at end of file diff --git a/test/docker_tests/dockerfiles/no-error-compose.yml b/test/docker_tests/dockerfiles/no-error-compose.yml new file mode 100755 index 00000000..70787a74 --- /dev/null +++ b/test/docker_tests/dockerfiles/no-error-compose.yml @@ -0,0 +1,76 @@ +services: + netalertx: + network_mode: host # Use host networking for ARP scanning and other services + build: + context: . # Build context is the current directory + dockerfile: Dockerfile # Specify the Dockerfile to use + image: netalertx:latest + container_name: netalertx # The name when you docker contiainer ls + read_only: true # Make the container filesystem read-only + cap_drop: # Drop all capabilities for enhanced security + - ALL + cap_add: # Add only the necessary capabilities + - NET_ADMIN # Required for ARP scanning + - NET_RAW # Required for raw socket operations + - NET_BIND_SERVICE # Required to bind to privileged ports (nbtscan) + + volumes: + - type: volume + source: netalertx_config + target: /app/config + read_only: false + + - type: volume + source: netalertx_db + target: /app/db + read_only: false + + - type: bind + source: /etc/localtime + target: /etc/localtime + read_only: true + + # Use a custom Enterprise-configured nginx config for ldap or other settings + # - /custom-enterprise.conf:/services/config/nginx/conf.active/netalertx.conf:ro + + # Test your plugin on the production container + # - /path/on/host:/app/front/plugins/custom + + # Retain logs - comment out tmpfs /app/log if you want to retain logs between container restarts + # - /path/on/host/log:/app/log + + # Tempfs mounts for writable directories in a read-only container and improve system performance + tmpfs: + # Speed up logging. This can be commented out to retain logs between container restarts + - "/app/log:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime" + # Speed up API access as frontend/backend API is very chatty + - "/app/api:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,sync,noatime,nodiratime" + # Required for customization of the nginx listen addr/port without rebuilding the container + - "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime" + # /services/config/nginx/conf.d is required for nginx and php to start + - "/services/run:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime" + # /tmp is required by php for session save this should be reworked to /services/run/tmp + - "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime" + environment: + LISTEN_ADDR: 0.0.0.0 # Listen for connections on all interfaces + PORT: 20211 # Application port + GRAPHQL_PORT: 20212 # GraphQL API port + ALWAYS_FRESH_INSTALL: false # Set to true to reset your config and database on each container start + NETALERTX_DEBUG: 0 # 0=kill all services and restart if any dies. 1 keeps running dead services. + + # Resource limits to prevent resource exhaustion + mem_limit: 2048m + mem_reservation: 1024m + cpus: 4 + pids_limit: 512 + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + restart: unless-stopped + +volumes: + netalertx_config_test: + netalertx_db_test: +