From a2809a6148f5e0bccfa5d225b4fa20b0e935fb8e Mon Sep 17 00:00:00 2001 From: Lubomir Stanko Date: Mon, 22 Apr 2024 12:03:36 +0200 Subject: [PATCH] Update local development to use prebuilt anzusystems node docker image --- .env.dist | 2 +- .env.docker.dist | 4 +- .github/workflows/node.yml | 40 ++--- docker-compose.yml | 6 +- docker/app/local/Dockerfile | 142 ++---------------- .../local/{usr/local => }/bin/start-command | 0 .../app/local/etc/nginx/conf.d/default.conf | 35 ----- docker/app/local/etc/nginx/nginx.conf | 39 ----- .../local/etc/supervisor/conf.d/nginx.conf | 13 -- .../app/local/etc/supervisor/supervisord.conf | 23 --- docker/app/local/usr/local/bin/fix-user | 95 ------------ src/util/user-token-verifier.ts | 4 +- 12 files changed, 44 insertions(+), 359 deletions(-) rename docker/app/local/{usr/local => }/bin/start-command (100%) delete mode 100644 docker/app/local/etc/nginx/conf.d/default.conf delete mode 100644 docker/app/local/etc/nginx/nginx.conf delete mode 100644 docker/app/local/etc/supervisor/conf.d/nginx.conf delete mode 100644 docker/app/local/etc/supervisor/supervisord.conf delete mode 100755 docker/app/local/usr/local/bin/fix-user diff --git a/.env.dist b/.env.dist index c922d19..2545729 100644 --- a/.env.dist +++ b/.env.dist @@ -8,7 +8,7 @@ PUBSUB_TOPIC=notification_server_internal APP_INSTANCE_NAME=notification-local -WEBSOCKET_SERVER_PORT=3005 +WEBSOCKET_SERVER_PORT=3010 WEBSOCKET_SERVER_CORS=^http://[a-zA-Z0-9-_.]+.anzusystems.localhost(:\d{2,4})?$ SSO_JWT_COOKIES=anz_jp,anz_js diff --git a/.env.docker.dist b/.env.docker.dist index 952b1d5..5acaa52 100644 --- a/.env.docker.dist +++ b/.env.docker.dist @@ -1,7 +1,9 @@ ### Docker configuration + # Docker Nginx setup +NGINX_PROXYPASS_CONFIG=true NGINX_PORT=8490 -NGINX_UPSTREAM_WEBSOCKET_PORT=3410 +NGINX_UPSTREAM_WEBSOCKET_PORT=3010 # Docker Node setup DOCKER_NODE_AUTOSTART=true diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index 12b6aa8..4e32b08 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -1,34 +1,40 @@ name: CI for AnzuSystems Notification-Server by Petit Press a.s. (www.sme.sk) on: + push: + branches: + - '**' pull_request: branches: - main +permissions: + contents: read # to fetch code (actions/checkout) + jobs: - build: + lint: strategy: matrix: - node-version: - - '20' - platform: - - ubuntu-latest - - name: Node ${{ matrix.node-version }} on ${{ matrix.platform }} - runs-on: ${{ matrix.platform }} + include: + - node-version: 20 + docker-image: anzusystems/node:1.0.0-node20 + + name: Node ${{ matrix.node-version }} + runs-on: ubuntu-latest + container: ${{ matrix.docker-image }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v3 + - name: Cache Yarn packages + id: yarn-cache + uses: actions/cache@v3 with: - node-version: ${{ matrix.node-version }} - cache: 'yarn' - cache-dependency-path: 'yarn.lock' - - - name: Enable corepack - run: corepack enable + path: node_modules + key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock', '*/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- - name: Install dependencies run: yarn install --immutable diff --git a/docker-compose.yml b/docker-compose.yml index 87d018e..332fdeb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,15 +9,15 @@ services: dockerfile: docker/app/local/Dockerfile environment: - VIRTUAL_HOST=notification-server.anzusystems.local - - VIRTUAL_PORT=8080 + - VIRTUAL_PORT=${NGINX_PORT:-8490} env_file: - .env.docker.dist - .env.docker.local volumes: - ".:/var/www/html:cached" ports: - - ${NGINX_PORT:-8490}:8080 - - ${NGINX_UPSTREAM_WEBSOCKET_PORT:-3410}:3005 + - ${NGINX_PORT:-8490}:${NGINX_PORT:-8490} + - ${NGINX_UPSTREAM_WEBSOCKET_PORT:-3010}:${NGINX_UPSTREAM_WEBSOCKET_PORT:-3010} hostname: notification-server.anzusystems.local networks: anzusystems_network: diff --git a/docker/app/local/Dockerfile b/docker/app/local/Dockerfile index 1edeac1..257a3da 100644 --- a/docker/app/local/Dockerfile +++ b/docker/app/local/Dockerfile @@ -1,137 +1,19 @@ -FROM node:20-bookworm-slim +FROM anzusystems/node:1.0.0-node20-nginx -# ---------------------------------------------------------------------------------------------------------------------- -# ENVIRONMENT VARIABLES -# ---------------------------------------------------------------------------------------------------------------------- +# +### Basic arguments and variables ARG DOCKER_USER ARG DOCKER_USER_ID ARG DOCKER_GROUP_ID -# Versions -# Nginx version -ENV NGINX_VERSION=1.24.0 \ - NGINX_NJS_VERSION=0.8.1 \ - NGINX_PKG_RELEASE=1~bookworm \ -# Supervisor version - SUPERVISOR_VERSION=4.2.5 \ - SUPERVISOR_PKG_RELEASE=1 \ -# NPM version - NPM_VERSION=10.2.1 \ -# Yarn version - DOCKER_YARN_VERSION=4.0.1 -# Common environment variables -ENV CONTAINER_STOP_LOG_FILE="/var/www/html/var/log/container_stop.log" \ - COREPACK_HOME="/usr/lib/node/corepack" \ - MAIN_TERMINATED_FILE="/var/www/html/var/log/main-terminated" \ - NPM_CONFIG_LOGLEVEL=notice \ - YARN_CACHE_FOLDER="/var/cache/yarn" \ - YARN_ENABLE_TELEMETRY=0 \ - # Unset yarn version - it could break things - YARN_VERSION= -# Packages -ENV RUN_DEPS="ca-certificates \ - curl \ - g++ \ - gcc \ - gettext-base \ - git \ - gnupg \ - less \ - logrotate \ - lsb-release \ - make \ - openssh-client \ - procps \ - vim \ - wget" - -# ---------------------------------------------------------------------------------------------------------------------- -# PACKAGES -# ---------------------------------------------------------------------------------------------------------------------- -RUN apt-get update && \ - apt-get install -y \ - ${RUN_DEPS} \ - supervisor=${SUPERVISOR_VERSION}-${SUPERVISOR_PKG_RELEASE} && \ -# Cleanup - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# ---------------------------------------------------------------------------------------------------------------------- -# NPM + YARN -# Install static npm and yarn version -# ---------------------------------------------------------------------------------------------------------------------- -RUN npm install --location=global npm@${NPM_VERSION} && \ - mkdir -p ${COREPACK_HOME} && \ - corepack prepare yarn@${DOCKER_YARN_VERSION} --activate && \ - corepack enable - -# ---------------------------------------------------------------------------------------------------------------------- -# NGINX -# ---------------------------------------------------------------------------------------------------------------------- -RUN NGINX_KEYRING=/usr/share/keyrings/nginx-archive-keyring.gpg && \ - NGINX_REPO=nginx && \ - echo "deb [signed-by=${NGINX_KEYRING}] http://nginx.org/packages/debian $(lsb_release -cs) ${NGINX_REPO}" > /etc/apt/sources.list.d/${NGINX_REPO}.list && \ - curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor > ${NGINX_KEYRING} && \ - apt-get update && \ - apt-get install --no-install-recommends --no-install-suggests -y \ - nginx=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - nginx-module-xslt=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - nginx-module-geoip=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - nginx-module-image-filter=${NGINX_VERSION}-${NGINX_PKG_RELEASE} \ - nginx-module-njs=${NGINX_VERSION}+${NGINX_NJS_VERSION}-${NGINX_PKG_RELEASE} && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# ---------------------------------------------------------------------------------------------------------------------- -# USER SETUP -# ---------------------------------------------------------------------------------------------------------------------- -RUN ln -sf /dev/stdout /var/log/nginx/access.log && \ - ln -sf /dev/stderr /var/log/nginx/error.log && \ - mkdir -p /run/nginx && \ - chown node:node -R \ - /etc/nginx \ - /run/nginx \ - /var/log/nginx && \ - sed -i 's/^#alias l/alias l/g' /home/node/.bashrc && \ - echo "update-notifier=false" > /home/node/.npmrc && \ - mkdir -p \ - ${YARN_CACHE_FOLDER} \ - /var/cache/nginx \ - /usr/local/lib/node_modules \ - /var/run/supervisor \ - /var/www/html/var && \ - chown node:node -R \ - ${COREPACK_HOME} \ - ${YARN_CACHE_FOLDER} \ - /etc/nginx \ - /home/node/.npmrc \ - /run/nginx \ - /usr/local/bin \ - /usr/local/lib/node_modules \ - /var/cache/nginx \ - /var/log/nginx \ - /var/run/supervisor \ - /var/www/html - -# ---------------------------------------------------------------------------------------------------------------------- -# RUN CONFIGURATION -# ---------------------------------------------------------------------------------------------------------------------- -COPY --chown=node:node ./docker/app/local/etc /etc -COPY --chown=node:node ./docker/app/local/usr /usr - -# ---------------------------------------------------------------------------------------------------------------------- -# PERMISSIONS FIX -# ---------------------------------------------------------------------------------------------------------------------- -# Change USER_ID and GROUP_ID for nonroot container user if needed and install mysql-client +# +### Copy configuration files in to the container +COPY --chown=node:node docker/app/local/bin /usr/local/bin/ +COPY --chown=node:node docker/app/local/etc /etc +# +### Change USER_ID and GROUP_ID for nonroot container user if needed +USER root RUN fix-user ${DOCKER_USER} node ${DOCKER_USER_ID} ${DOCKER_GROUP_ID} - -# ---------------------------------------------------------------------------------------------------------------------- -# RUN -# Run setup and entrypoint start -# ---------------------------------------------------------------------------------------------------------------------- -WORKDIR /var/www/html +# +### Basic user setup and start USER node - -EXPOSE 3005 8080 - -# Start CMD ["start-command"] diff --git a/docker/app/local/usr/local/bin/start-command b/docker/app/local/bin/start-command similarity index 100% rename from docker/app/local/usr/local/bin/start-command rename to docker/app/local/bin/start-command diff --git a/docker/app/local/etc/nginx/conf.d/default.conf b/docker/app/local/etc/nginx/conf.d/default.conf deleted file mode 100644 index 8622c23..0000000 --- a/docker/app/local/etc/nginx/conf.d/default.conf +++ /dev/null @@ -1,35 +0,0 @@ -map $http_upgrade $connection_upgrade { - '' close; - default upgrade; -} - -upstream websocket { - server 127.0.0.1:3005; -} - -server { - listen 8080; - - sendfile off; - client_max_body_size 1m; - large_client_header_buffers 4 16k; - - #App paths - location /ws { - proxy_pass http://websocket; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $host; - - # Custom nginx response headers - proxy_hide_header X-Robots-Tag; - add_header 'X-Robots-Tag' 'noindex, nofollow, noarchive, nosnippet' always; - add_header 'X-XSS-Protection' '1; mode=block' always; - add_header 'X-Content-Type-Options' 'nosniff' always; - } - - location ~ /\.ht { - deny all; - } -} diff --git a/docker/app/local/etc/nginx/nginx.conf b/docker/app/local/etc/nginx/nginx.conf deleted file mode 100644 index be3efbb..0000000 --- a/docker/app/local/etc/nginx/nginx.conf +++ /dev/null @@ -1,39 +0,0 @@ -worker_processes 1; -worker_rlimit_nofile 65535; - -error_log /var/log/nginx/error.log warn; -pid /run/nginx/nginx.pid; - -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" $status ' - '$body_bytes_sent' - 'B ' - '$request_time' - 's ' - '"$http_referer" "$http_user_agent" "$http_x_forwarded_for" "$http_x_forwarded_proto"'; - client_body_temp_path /tmp/client_temp; - proxy_temp_path /tmp/proxy_temp_path; - fastcgi_temp_path /tmp/fastcgi_temp; - uwsgi_temp_path /tmp/uwsgi_temp; - scgi_temp_path /tmp/scgi_temp; - - access_log /var/log/nginx/access.log main; - - server_tokens off; - keepalive_timeout 650; - keepalive_requests 10000; - sendfile on; - - gzip on; - gzip_proxied any; - gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; - - include /etc/nginx/conf.d/*.conf; -} diff --git a/docker/app/local/etc/supervisor/conf.d/nginx.conf b/docker/app/local/etc/supervisor/conf.d/nginx.conf deleted file mode 100644 index 5fe4411..0000000 --- a/docker/app/local/etc/supervisor/conf.d/nginx.conf +++ /dev/null @@ -1,13 +0,0 @@ -[program:nginx] -command=/usr/sbin/nginx -g "daemon off;" -autostart=true -autorestart=unexpected -# Expect 0 exit code returned when stopping the container -exitcodes=0 -priority=10 -stdout_events_enabled=true -stderr_events_enabled=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 diff --git a/docker/app/local/etc/supervisor/supervisord.conf b/docker/app/local/etc/supervisor/supervisord.conf deleted file mode 100644 index dae2dc2..0000000 --- a/docker/app/local/etc/supervisor/supervisord.conf +++ /dev/null @@ -1,23 +0,0 @@ -[unix_http_server] -file=/var/run/supervisor/supervisor.sock -chmod=0700 -username=docker -password=docker - -[supervisorctl] -serverurl=unix:///var/run/supervisor/supervisor.sock -username=docker -password=docker - -[supervisord] -nodaemon=true -logfile=/dev/stdout -logfile_maxbytes=0 -pidfile=/var/run/supervisor/supervisord.pid -loglevel=info - -[rpcinterface:supervisor] -supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface - -[include] -files = /etc/supervisor/conf.d/*.conf diff --git a/docker/app/local/usr/local/bin/fix-user b/docker/app/local/usr/local/bin/fix-user deleted file mode 100755 index 3f61b69..0000000 --- a/docker/app/local/usr/local/bin/fix-user +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash -# -# Corrects UID and GID for container user according to host UID and GID if needed -# -# #1 Example: UID 1000 and GID 1000: -# ./fix-user test user 1000 1000 -# - 'user' has UID 1000 and GID 1000 by default - nothing will happen -# -# #2 Example: UID 501 (not exists in docker image) and GID 501 (not exists in docker image): -# ./fix-user test user 501 501 -# - 'user' UID will change to 501 -# - 'user' GID will change to 501 -# -# #3 Example: UID 35 (exists in docker image as 'games') and GID 100 (exists in docker image as 'users'): -# ./fix-user test user 35 100 -# - 'games' UID will change to random free UID (1100-2000) to release UID 35 -# - 'user' UID will change to 35 -# - adds user 'user' to group 'users' - -HOST_USER=$1 -CONTAINER_USER_NAME=$2 -HOST_USER_ID=$3 -HOST_GROUP_ID=$4 -# User name which exists under hosts user id -EXISTING_CONTAINER_USER_NAME=$(getent passwd "${HOST_USER_ID}" | cut -d: -f1) -EXISTING_CONTAINER_NEW_USER_ID="" -# Group name which exists under hosts group id -EXISTING_CONTAINER_GROUP_NAME=$(getent group "${HOST_GROUP_ID}" | cut -d: -f1) -# User ID of the container user -CONTAINER_USER_ID=$(id -u "${CONTAINER_USER_NAME}") -# Group ID and group name of the container user -CONTAINER_GROUP_ID=$(id -g "${CONTAINER_USER_NAME}") -CONTAINER_GROUP_NAME=$(getent group "${CONTAINER_GROUP_ID}" | cut -d: -f1) -FINAL_GROUP_NAME=${EXISTING_CONTAINER_GROUP_NAME} -SYSTEM_FOLDERS=" \ - ${COREPACK_HOME} \ - ${YARN_CACHE_FOLDER} \ - /etc/nginx \ - /home/node \ - /run/nginx \ - /usr/local/lib/node_modules \ - /usr/local/log \ - /var/log/nginx \ - /var/run/supervisor \ - /var/www/html \ -" - -# Skip this script if the host user is root -if [ "$HOST_USER" == "root" ]; then - exit 0 -fi - -# Final group name to be used will be container group if no other group exists with the host group ID -if [ -z "${FINAL_GROUP_NAME}" ]; then - FINAL_GROUP_NAME=${CONTAINER_GROUP_NAME} -fi - -# Generate new user ID to be used for existing container user -while [ -n "$(getent passwd "${EXISTING_CONTAINER_NEW_USER_ID}")" ]; do - EXISTING_CONTAINER_NEW_USER_ID=$(shuf -i 1100-2000 -n 1) -done - -# Change user ID for container user if needed -if [ -z "${EXISTING_CONTAINER_USER_NAME}" ] && [ ! "${CONTAINER_USER_ID}" == "${HOST_USER_ID}" ]; then - echo "Changing '${CONTAINER_USER_NAME}' user ID ${CONTAINER_USER_ID} to ${HOST_USER_ID}" - usermod -u "${HOST_USER_ID}" "${CONTAINER_USER_NAME}" -fi - -# Change user ID for existing container user and container user if needed -if [ -n "${EXISTING_CONTAINER_USER_NAME}" ] && [ ! "${EXISTING_CONTAINER_USER_NAME}" == "${CONTAINER_USER_NAME}" ]; then - echo "Changing '${EXISTING_CONTAINER_USER_NAME}' user ID ${HOST_USER_ID} to ${EXISTING_CONTAINER_NEW_USER_ID}" - usermod -u "${EXISTING_CONTAINER_NEW_USER_ID}" "${EXISTING_CONTAINER_USER_NAME}" 2>&1 - echo "Changing '${CONTAINER_USER_NAME}' user ID ${CONTAINER_USER_ID} to ${HOST_USER_ID}" - usermod -u "${HOST_USER_ID}" "${CONTAINER_USER_NAME}" -fi - -# Change group ID for container group name if needed -if [ "${FINAL_GROUP_NAME}" == "${CONTAINER_GROUP_NAME}" ] && [ ! "${CONTAINER_GROUP_ID}" == "${HOST_GROUP_ID}" ]; then - echo "Changing '${FINAL_GROUP_NAME}' group ID ${CONTAINER_GROUP_ID} to ${HOST_GROUP_ID}" - groupmod -g "${HOST_GROUP_ID}" "${FINAL_GROUP_NAME}" - find / -group "${CONTAINER_GROUP_ID}" -exec chgrp -h "${HOST_GROUP_ID}" {} \; -fi - -# Assign correct group for existing container user name if needed -if [ ! "${FINAL_GROUP_NAME}" == "${CONTAINER_GROUP_NAME}" ]; then - echo "Adding user with UID ${HOST_USER_ID} (${CONTAINER_USER_NAME}) to group with GID ${HOST_GROUP_ID} (${FINAL_GROUP_NAME})" - usermod -a -G "${FINAL_GROUP_NAME}" "${CONTAINER_USER_NAME}" 2>&1 -fi - -echo "Setting up system user permissions (${CONTAINER_USER_NAME}:${FINAL_GROUP_NAME})" -for folder in ${SYSTEM_FOLDERS}; do - if [ -d "$folder" ]; then - chown "${CONTAINER_USER_NAME}":"${FINAL_GROUP_NAME}" -R "$folder" - fi -done diff --git a/src/util/user-token-verifier.ts b/src/util/user-token-verifier.ts index bf33f71..555718a 100644 --- a/src/util/user-token-verifier.ts +++ b/src/util/user-token-verifier.ts @@ -15,10 +15,10 @@ export function verifyAuthorization(request: IncomingMessage, logger: AppLogger) throw new Error('Invalid JWT token') } - logger.debug('Verifying authorization tokens...', { jwt: jwtRaw, pubCert: Config.getJwtPublicKey() }) + logger.debug('Verifying authorization tokens...', {jwt: jwtRaw, pubCert: Config.getJwtPublicKey()}) return jwt.verify(jwtRaw, Config.getJwtPublicKey(), { algorithms: [Config.getJwtAlgorithm()], - allowInvalidAsymmetricKeyTypes: true + allowInvalidAsymmetricKeyTypes: true, }) as IUserToken }