diff --git a/.github/scripts/resolve-nginx-ref.sh b/.github/scripts/resolve-nginx-ref.sh new file mode 100644 index 00000000..cd516c4f --- /dev/null +++ b/.github/scripts/resolve-nginx-ref.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -euo pipefail + +VERSION="${NGINX_VERSION:-}" + +if [[ -z "${VERSION}" ]]; then + echo "NGINX_VERSION is not set" >&2 + exit 1 +fi + +echo "Requested NGINX_VERSION=${VERSION}" + +if [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.x$ ]]; then + PREFIX="release-${VERSION%.x}." + REF=$(git ls-remote --tags https://github.com/nginx/nginx.git "refs/tags/${PREFIX}*" \ + | sed -E 's#.*refs/tags/##; s#\^\{\}##' \ + | grep -E "^${PREFIX}[0-9]+$" \ + | sort -V \ + | tail -n 1) +elif [[ "${VERSION}" =~ ^release-[0-9]+\.[0-9]+\.[0-9]+$ || "${VERSION}" == "master" || "${VERSION}" == "main" ]]; then + REF="${VERSION}" +else + echo "Unsupported NGINX_VERSION=${VERSION}" >&2 + echo "Use e.g. 1.30.x, 1.29.x, 1.28.x or exact tag release-1.30.0" >&2 + exit 1 +fi + +if [[ -z "${REF}" ]]; then + echo "No matching Nginx tag found for ${VERSION}" >&2 + exit 1 +fi + +echo "Resolved Nginx ref: ${REF}" +echo "ref=${REF}" >> "${GITHUB_OUTPUT}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 01268470..4fa41c1d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,7 @@ jobs: with: repository: owasp-modsecurity/ModSecurity path: ModSecurity - submodules: true + submodules: recursive fetch-depth: 1 - name: Build libModSecurity working-directory: ModSecurity @@ -274,7 +274,7 @@ jobs: uses: actions/checkout@v4 with: repository: owasp-modsecurity/ModSecurity - submodules: true + submodules: recursive path: nginx/objs/lib/ModSecurity fetch-depth: 1 - name: Setup Conan diff --git a/.github/workflows/test_new.yml b/.github/workflows/test_new.yml new file mode 100644 index 00000000..7a981176 --- /dev/null +++ b/.github/workflows/test_new.yml @@ -0,0 +1,413 @@ +name: Quality Assurance new + +on: + pull_request: + push: + workflow_dispatch: + + +# Default: none +permissions: {} + +jobs: + build-linux: + name: linux-${{ matrix.compiler }}-nginx-${{ matrix.nginx_version }} + permissions: + contents: read + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04] + compiler: [gcc, clang] + nginx_version: ["1.30.x", "1.29.x", "1.28.x"] + env: + NGINX_VERSION: ${{ matrix.nginx_version }} + CC: "/usr/bin/${{ matrix.compiler }}" + CXX: "/usr/bin/${{ matrix.compiler == 'gcc' && 'g' || 'clang' }}++" + COMPDEPS: "${{ matrix.compiler == 'gcc' && 'gcc g++' || 'clang' }}" + steps: + - name: Setup Dependencies + run: | + sudo apt-get update -y -qq + sudo apt-get install -y make autoconf automake pcre2-utils libpcre2-dev libyajl-dev libxml2-dev libmaxminddb-dev libcurl4-gnutls-dev $COMPDEPS + - name: Get libModSecurity source + uses: actions/checkout@v6 + with: + repository: owasp-modsecurity/ModSecurity + path: ModSecurity + submodules: recursive + fetch-depth: 1 + - name: Build libModSecurity + working-directory: ModSecurity + run: | + ./build.sh + ./configure --without-lmdb --prefix=/usr + make -j $(nproc) + sudo make install + - uses: actions/checkout@v6 + with: + path: ModSecurity-nginx + fetch-depth: 1 + - name: Resolve latest Nginx version + id: nginx_ref + shell: bash + run: bash ModSecurity-nginx/.github/scripts/resolve-nginx-ref.sh + + - name: Get Nginx source + uses: actions/checkout@v6 + with: + repository: nginx/nginx + ref: ${{ steps.nginx_ref.outputs.ref }} + path: nginx + fetch-depth: 0 + + - name: Show Nginx source version + working-directory: nginx + shell: bash + run: | + echo "Requested NGINX_VERSION=${NGINX_VERSION}" + echo "Resolved ref=${{ steps.nginx_ref.outputs.ref }}" + echo "Commit=$(git rev-parse HEAD)" + echo "Describe=$(git describe --tags --always)" + grep '#define NGINX_VERSION' src/core/nginx.h || true + + - name: Get Nginx tests + uses: actions/checkout@v6 + with: + repository: nginx/nginx-tests + path: nginx/test + fetch-depth: 0 + + - name: Show Nginx tests version + working-directory: nginx/test + shell: bash + run: | + echo "Commit=$(git rev-parse HEAD)" + echo "Describe=$(git describe --tags --always)" + git log -1 --oneline + - name: Copy ModSecurity-nginx tests to nginx/test + run: | + cp ModSecurity-nginx/tests/* nginx/test + - name: Build nginx with ModSecurity-nginx module + working-directory: nginx + run: | + ./auto/configure --with-ld-opt="-Wl,-rpath,/usr/local/lib" --with-http_v2_module --with-http_auth_request_module --add-module=../ModSecurity-nginx + make + make modules + sudo make install + - name: Run ModSecurity-nginx tests + working-directory: nginx/test + run: | + TEST_NGINX_BINARY=../objs/nginx prove modsecurity*.t + - name: Start Nginx + run: | + sudo mkdir -p /usr/local/nginx/html + sudo cp "${{ github.workspace }}/ModSecurity-nginx/.github/nginx/docs/"* /usr/local/nginx/html/ + sudo /usr/local/nginx/sbin/nginx -c "${{ github.workspace }}/ModSecurity-nginx/.github/nginx/nginx.conf" + - name: Run attack test vhost 1 + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest1" "http://localhost/?q=attack") + if [ "${status}" == "403" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run non-attack test vhost 1 + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest1" "http://localhost/?q=1") + if [ "${status}" == "200" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run attack test vhost 2 + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest2" "http://localhost/?q=attack") + if [ "${status}" == "403" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run non-attack test vhost 2 + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest2" "http://localhost/?q=1") + if [ "${status}" == "200" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run file consistency check 1 + run: | + curl -sS "http://localhost/data50k.json" --output data50k.json + if [ -f data50k.json ]; then + diff data50k.json /usr/local/nginx/html/data50k.json > /dev/null + if [ $? -eq 0 ]; then + echo "OK" + else + echo "FAIL" + exit 2 + fi + else + echo "FAIL" + exit 1 + fi + - name: Run file consistency check 2 + run: | + curl -sS "http://localhost/plugged.png" --output plugged.png + if [ -f plugged.png ]; then + diff plugged.png /usr/local/nginx/html/plugged.png > /dev/null + if [ $? -eq 0 ]; then + echo "OK" + else + echo "FAIL" + exit 2 + fi + else + echo "FAIL" + exit 1 + fi + - name: Check attack log vhost 2 (modsecurity_use_error_log on(default)) + run: | + if ( grep -q "modsectest2" /usr/local/nginx/logs/error.log ); then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Check attack log vhost 3 (modsecurity_use_error_log off) + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsecurity_use_error_log_off" "http://localhost/?q=attack") + if [ "${status}" == "403" ]; then + if ( grep -q "modsecurity_use_error_log_off" /usr/local/nginx/logs/error.log ); then + echo "FAIL" + exit 1 + else + echo "OK" + fi + else + echo "FAIL" + exit 1 + fi + - name: Start Nginx with redir + run: | + sudo killall nginx + sudo /usr/local/nginx/sbin/nginx -c "${{ github.workspace }}/ModSecurity-nginx/.github/nginx/nginx.conf.redir" + - name: Run attack test vhost 1 + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest1" "http://localhost/?q=attack") + if [ "${status}" == "403" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run non-attack test vhost 1 (redir config) + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest1" "http://localhost/?q=1") + if [ "${status}" == "200" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run attack test vhost 2 (redir config) + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest2" "http://localhost/?q=attack") + if [ "${status}" == "403" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run non-attack test vhost 2 (redir config) + run: | + status=$(curl -sSo /dev/null -w %{http_code} -I -X GET -H "Host: modsectest2" "http://localhost/?q=1") + if [ "${status}" == "200" ]; then + echo "OK" + else + echo "FAIL" + exit 1 + fi + - name: Run file consistency check 1 (redir config) + run: | + curl -sS "http://localhost/data50k.json" --output data50k.json + if [ -f data50k.json ]; then + diff data50k.json /usr/local/nginx/html/data50k.json > /dev/null + if [ $? -eq 0 ]; then + ls -l data50k.json /usr/local/nginx/html/data50k.json + echo "OK" + else + echo "FAIL" + exit 2 + fi + else + echo "FAIL" + exit 1 + fi + - name: Run file consistency check 2 (redir config) + run: | + curl -sS "http://localhost/plugged.png" --output plugged.png + if [ -f plugged.png ]; then + diff plugged.png /usr/local/nginx/html/plugged.png > /dev/null + if [ $? -eq 0 ]; then + ls -l plugged.png /usr/local/nginx/html/plugged.png + echo "OK" + else + echo "FAIL" + exit 2 + fi + else + echo "FAIL" + exit 1 + fi + + + build-windows: + name: windows-nginx-${{ matrix.nginx_version }} + runs-on: windows-2025 + strategy: + fail-fast: false + matrix: + nginx_version: ["1.30.x", "1.29.x", "1.28.x"] + env: + NGINX_VERSION: ${{ matrix.nginx_version }} + defaults: + run: + shell: msys2 {0} + steps: + - name: Set up MSVC + uses: ilammy/msvc-dev-cmd@v1 + - name: Set up msys + uses: msys2/setup-msys2@v2 + with: + msystem: UCRT64 + path-type: inherit + - name: Get ModSecurity-nginx workflow scripts + uses: actions/checkout@v6 + with: + path: ModSecurity-nginx + fetch-depth: 1 + - name: Resolve latest Nginx version + id: nginx_ref + shell: bash + run: bash ModSecurity-nginx/.github/scripts/resolve-nginx-ref.sh + + - name: Get Nginx source + uses: actions/checkout@v6 + with: + repository: nginx/nginx + ref: ${{ steps.nginx_ref.outputs.ref }} + path: nginx + fetch-depth: 0 + + - name: Show Nginx source version + working-directory: nginx + shell: bash + run: | + echo "Requested NGINX_VERSION=${NGINX_VERSION}" + echo "Resolved ref=${{ steps.nginx_ref.outputs.ref }}" + echo "Commit=$(git rev-parse HEAD)" + echo "Describe=$(git describe --tags --always)" + grep '#define NGINX_VERSION' src/core/nginx.h || true + + - name: Get Nginx tests + uses: actions/checkout@v6 + with: + repository: nginx/nginx-tests + path: nginx/test + fetch-depth: 0 + + - name: Show Nginx tests version + working-directory: nginx/test + shell: bash + run: | + echo "Commit=$(git rev-parse HEAD)" + echo "Describe=$(git describe --tags --always)" + git log -1 --oneline + - name: Set up third-party libraries + working-directory: nginx + run: | + mkdir objs + mkdir objs/lib + cd objs/lib + wget -q -O - https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.tar.gz | tar -xzf - + wget -q -O - https://www.zlib.net/fossils/zlib-1.3.2.tar.gz | tar -xzf - + wget -q -O - https://www.openssl.org/source/openssl-3.6.2.tar.gz | tar -xzf - + - name: Get libModSecurity source + uses: actions/checkout@v6 + with: + repository: owasp-modsecurity/ModSecurity + submodules: recursive + path: nginx/objs/lib/ModSecurity + fetch-depth: 1 + - name: Setup Conan + shell: cmd + run: | + pip3 install conan --upgrade + conan profile detect + - name: Build libModSecurity + working-directory: nginx/objs/lib/ModSecurity + shell: cmd + run: | + vcbuild.bat + - name: Get ModSecurity-nginx source code + uses: actions/checkout@v6 + with: + path: nginx/objs/lib/ModSecurity-nginx + - name: Copy ModSecurity-nginx tests to nginx/test + working-directory: nginx/test + run: | + cp ../objs/lib/ModSecurity-nginx/tests/* . + - name: Remove /usr/bin/link conflicting with MSVC link.exe + run: | + set -ex + which link + rm /usr/bin/link + - name: Build nginx w/ModSecurity-nginx module + working-directory: nginx + run: | + : # Windows native version of Perl is required by nginx build + export PATH=/c/Strawberry/perl/bin:$PATH + : # Set env variables to point to libModSecurity v3 include & lib directories + export MODSECURITY_INC=objs/lib/ModSecurity/headers + export MODSECURITY_LIB=objs/lib/ModSecurity/build/win32/build/Release + : # Copy libModSecurity.dll to objs dir (to be able to run nginx later) + cp $MODSECURITY_LIB/libModSecurity.dll objs + : # Configure nginx build w/ModSecurity-nginx module + auto/configure \ + --with-cc=cl \ + --with-debug \ + --prefix= \ + --conf-path=conf/nginx.conf \ + --pid-path=logs/nginx.pid \ + --http-log-path=logs/access.log \ + --error-log-path=logs/error.log \ + --sbin-path=nginx.exe \ + --http-client-body-temp-path=temp/client_body_temp \ + --http-proxy-temp-path=temp/proxy_temp \ + --http-fastcgi-temp-path=temp/fastcgi_temp \ + --http-scgi-temp-path=temp/scgi_temp \ + --http-uwsgi-temp-path=temp/uwsgi_temp \ + --with-cc-opt=-DFD_SETSIZE=1024 \ + --with-pcre=objs/lib/pcre2-10.47 \ + --with-zlib=objs/lib/zlib-1.3.2 \ + --with-openssl=objs/lib/openssl-3.6.2 \ + --with-openssl-opt=no-asm \ + --with-http_ssl_module \ + --with-http_v2_module \ + --with-http_auth_request_module \ + --add-module=objs/lib/ModSecurity-nginx + nmake + - name: Run ModSecurity-nginx tests + working-directory: nginx/test + shell: cmd # tests need to run on a "windows" shell + run: | + md temp + set TEMP=temp + set TEST_NGINX_BINARY=..\objs\nginx.exe + prove modsecurity*.t diff --git a/.travis.yml b/.travis.yml index f6e050b5..3cf380db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,12 +12,12 @@ addons: apt: packages: - libyajl-dev - - libgeoip-dev - liblmdb-dev env: - VER_NGINX=1.21.0 - VER_NGINX=1.20.1 + - VER_NGINX=1.29.8 before_script: - cd .. @@ -31,15 +31,14 @@ before_script: - make - sudo make install - cd .. - - wget http://nginx.org/download/nginx-${VER_NGINX}.tar.gz && tar -xf nginx-${VER_NGINX}.tar.gz - - cd nginx-${VER_NGINX} + - git clone --depth 1 --branch release-${VER_NGINX} https://github.com/nginx/nginx.git + - cd nginx - ./configure --with-http_auth_request_module --with-http_v2_module --add-module=../ModSecurity-nginx - make - sudo make install - cd .. - - wget http://hg.nginx.org/nginx-tests/archive/tip.tar.gz - - tar xvzf tip.tar.gz - - cd nginx-tests-* + - git clone --depth 1 https://github.com/nginx/nginx-tests.git + - cd nginx-tests - cp ../ModSecurity-nginx/tests/* . - export TEST_NGINX_BINARY=/usr/local/nginx/sbin/nginx