diff --git a/.devcontainer/resources/devcontainer-Dockerfile b/.devcontainer/resources/devcontainer-Dockerfile index 3bb285ce..a8acadbd 100755 --- a/.devcontainer/resources/devcontainer-Dockerfile +++ b/.devcontainer/resources/devcontainer-Dockerfile @@ -6,6 +6,8 @@ FROM runner AS netalertx-devcontainer ENV INSTALL_DIR=/app + + ENV PYTHONPATH=/workspaces/NetAlertX/test:/workspaces/NetAlertX/server:/app:/app/server:/opt/venv/lib/python3.12/site-packages ENV PATH=/services:${PATH} ENV PHP_INI_SCAN_DIR=/services/config/php/conf.d:/etc/php83/conf.d @@ -15,10 +17,11 @@ ENV NETALERTX_DEBUG=1 COPY .devcontainer/resources/devcontainer-overlay/ / # 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 +RUN apk add --no-cache git nano vim jq php83-pecl-xdebug py3-pip nodejs sudo gpgconf pytest pytest-cov fish shfmt sudo 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/ && \ + 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 && \ diff --git a/Dockerfile b/Dockerfile index 14ec0b72..2ca01c21 100755 --- a/Dockerfile +++ b/Dockerfile @@ -83,13 +83,13 @@ 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 +ENV LANG=C.UTF-8 - -RUN apk add --no-cache bash mtr libbsd zip lsblk sudo tzdata curl arp-scan iproute2 \ - iproute2-ss nmap nmap-scripts traceroute nbtscan net-tools net-snmp-tools bind-tools awake \ - ca-certificates sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session python3 \ - envsubst nginx sudo shadow && \ +RUN apk add --no-cache bash mtr libbsd zip lsblk tzdata curl arp-scan iproute2 iproute2-ss nmap \ + nmap-scripts traceroute nbtscan net-tools net-snmp-tools bind-tools awake ca-certificates \ + sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session python3 envsubst \ + nginx shadow && \ rm -Rf /var/cache/apk/* && \ rm -Rf /etc/nginx && \ addgroup -g 20211 ${NETALERTX_GROUP} && \ @@ -124,19 +124,17 @@ RUN apk add libcap && \ /bin/sh /build/init-backend.sh && \ rm -rf /build && \ apk del libcap - -# set netalertx to allow sudoers for any command, no password -RUN echo "${NETALERTX_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers - -ENTRYPOINT ["/bin/sh","-c","sleep infinity"] +ENTRYPOINT ["/bin/sh","/entrypoint.sh"] # Final hardened stage to improve security by setting least possible permissions and removing sudo access. # When complete, if the image is compromised, there's not much that can be done with it. # This stage is separate from Runner stage so that devcontainer can use the Runner stage. FROM runner AS hardened +ENV UMASK=0077 + # Create readonly user and group with no shell access. # Readonly user marks folders that are created by NetAlertX, but should not be modified. # AI may claim this is stupid, but it's actually least possible permissions as @@ -159,9 +157,9 @@ RUN chown -R ${READ_ONLY_USER}:${READ_ONLY_GROUP} ${READ_ONLY_FOLDERS} && \ chmod 005 /entrypoint.sh ${SYSTEM_SERVICES}/*.sh -# remove sudoers, sudo, alpine installers pacakges, and all users and groups except +# remove sudoers, alpine installers pacakges, and all users and groups except # readonly and netalertx -RUN apk del sudo apk-tools && \ +RUN apk del apk-tools && \ rm -rf /var/cache/apk/* && \ rm -Rf /etc/sudoers.d/* /etc/shadow /etc/gshadow /etc/sudoers \ /lib/apk /lib/firmware /lib/modules-load.d /lib/sysctl.d /mnt /home/ /root \ @@ -175,4 +173,3 @@ USER netalertx HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD /services/healthcheck.sh -ENTRYPOINT [ "/bin/sh", "/entrypoint.sh" ] diff --git a/Dockerfile.debian b/Dockerfile.debian index 8ca524f7..3def1a0b 100755 --- a/Dockerfile.debian +++ b/Dockerfile.debian @@ -9,6 +9,9 @@ # - read-only filesystem # - no sudo access # - least possible permissions on all files and folders +# - Root user has all permissions revoked and is unused +# - Secure umask applied so files are owner-only by default +# - non-privileged user runs the application # - no shell access for non-privileged users # - no unnecessary packages or services # - reduced capabilities diff --git a/docker-compose.hardened.yaml b/docker-compose.hardened.yaml deleted file mode 100644 index 42ddc5aa..00000000 --- a/docker-compose.hardened.yaml +++ /dev/null @@ -1,41 +0,0 @@ -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 - security_opt: # Security options for the container - - no-new-privileges:true # Prevent privilege escalation - - seccomp:unconfined # Use unconfined seccomp profile (adjust as needed) - volumes: - - netalertx_config:/app/config - - netalertx_db:/app/db - - /etc/localtime:/etc/localtime:ro - - tmpfs: - - "/app/api:uid=20211,gid=20211,mode=700" - - "/app/log:uid=20211,gid=20211,mode=700" - - "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=700" - - "/services/run:uid=20211,gid=20211,mode=700" - - "/tmp:mode=700" - - - environment: - NETALERTX_MODE: hardened - PORT: 20211 - GRAPHQL_PORT: 25378 - ALWAYS_FRESH_INSTALL: false - restart: unless-stopped - -volumes: - netalertx_config: - netalertx_db: - diff --git a/docker-compose.unproxied.yaml b/docker-compose.unproxied.yaml deleted file mode 100644 index 892b4b41..00000000 --- a/docker-compose.unproxied.yaml +++ /dev/null @@ -1,21 +0,0 @@ -version: '3.8' - -services: - netalertx: - build: - context: . - dockerfile: Dockerfile - image: netalertx:latest - container_name: netalertx_unproxied - read_only: true - tmpfs: - - /etc/nginx/conf.d - - /var/cache/nginx - - /var/run - - /app/log - - /tmp - network_mode: "host" - environment: - - NETALERTX_MODE=unproxied - - GRAPHQL_PORT=20212 - restart: unless-stopped diff --git a/docker-compose.yml b/docker-compose.yml index ef5d279f..f504f55e 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,40 +1,62 @@ services: netalertx: - network_mode: host # Use host networking for ARP scanning and other services + 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 + 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 + 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 - security_opt: # Security options for the container - - no-new-privileges:true # Prevent privilege escalation - - seccomp:unconfined # Use unconfined seccomp profile (adjust as needed) + cap_add: # Add only the necessary capabilities + - NET_ADMIN # Required for ARP scanning + - NET_RAW # Required for raw socket operations + security_opt: # Security options for the container + - no-new-privileges:true # Prevent privilege escalation volumes: - netalertx_config:/app/config # Store your NetAlertX config - netalertx_db:/app/db # Store your NetAlertX devices and settings - /etc/localtime:/etc/localtime:ro # Use your system clock inside the container (read-only) - #- /path/on/host:/app/front/plugins/custom # Test your plugin on the production container - + + # Additional Volume Examples below + + # 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 # by providing a clean R/W filesystem each container start and reducing disk I/O. + # Temp mounts are noexec, nosuid, and nodev for security. tmpfs: - - "/app/api:uid=20211,gid=20211,mode=700" - - "/app/log:uid=20211,gid=20211,mode=700" - - "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=700" - - "/services/run:uid=20211,gid=20211,mode=700" + - "/app/api:uid=20211,gid=20211,mode=700,noexec,nosuid,nodev" + - "/app/log:uid=20211,gid=20211,mode=700,noexec,nosuid,nodev" + - "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=700,noexec,nosuid,nodev" + - "/services/run:uid=20211,gid=20211,mode=700,noexec,nosuid,nodev" environment: - LISTEN_ADDR: 0.0.0.0 - PORT: 20211 - GRAPHQL_PORT: 20212 - NETALERTX_MODE: hardened - ALWAYS_FRESH_INSTALL: false - NETALERTX_DEBUG: 0 + 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: