Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: nginx module more headers #310

Merged
merged 10 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/verifyimage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,11 @@ jobs:
- name: Verify ${{ matrix.target }}
run: |
[ $(docker inspect ${{ matrix.target }}-test --format='{{.State.Running}}') = 'true' ]
if grep -q "nginx "<<< "${{ matrix.target }}"; then
curl -q -D headers.txt http://localhost:8080/?test=../../etc/passwd
grep -q "HTTP/1.1 403 Forbidden" headers.txt
grep -q "Access-Control-Allow-Origin: *" headers.txt
grep -q "Access-Control-Max-Age: 3600" headers.txt
grep -q "Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS" headers.txt
grep -q "Access-Control-Allow-Headers: *" headers.txt
fi
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,12 @@ These variables are common to image variants and will set defaults based on the

### Nginx ENV Variables

<!-- temporarily hidden -->
<!-- | CORS_HEADER_403_ALLOW_ORIGIN | The value of the [Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) header for `403` responses. Determines which origins can access the response. (Default: `"*"`). |
| CORS_HEADER_403_ALLOW_METHODS | The value of the [Access-Control-Request-Method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Method) header for `403` responses. Determines the allowed request methods for the resource. Default: `"GET, POST, PUT, DELETE, OPTIONS"` |
| CORS_HEADER_403_CONTENT_TYPE | The value of the `Content-Type` header for `403` responses. Default: (`"text/plain"`) |
| CORS_HEADER_403_MAX_AGE | The value of the [Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age) header for `403` responses. The number of seconds that preflight requests for this resource may be cached by the browser. (Default: `3600`) | -->

| Name | Description|
| -------- | ------------------------------------------------------------------- |
| CORS_HEADER_403_ALLOW_ORIGIN | The value of the [Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) header for `403` responses. Determines which origins can access the response. (Default: `"*"`). |
| CORS_HEADER_403_ALLOW_METHODS | The value of the [Access-Control-Request-Method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Method) header for `403` responses. Determines the allowed request methods for the resource. Default: `"GET, POST, PUT, DELETE, OPTIONS"` |
| CORS_HEADER_403_CONTENT_TYPE | The value of the `Content-Type` header for `403` responses. Default: (`"text/plain"`) |
| CORS_HEADER_403_MAX_AGE | The value of the [Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age) header for `403` responses. The number of seconds that preflight requests for this resource may be cached by the browser. (Default: `3600`) |
| DNS_SERVER | A string indicating the name servers used to resolve names of upstream servers into addresses. For localhost backend this value should not be defined (Default: _not defined_) |
| KEEPALIVE_TIMEOUT | Number of seconds for a keep-alive client connection to stay open on the server side (Default: `60s`) |
| NGINX_ALWAYS_TLS_REDIRECT | A string value indicating if http should redirect to https (Allowed values: `on`, `off`. Default: `off`) |
Expand Down
14 changes: 12 additions & 2 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ variable "REPOS" {
]
}

variable "nginx-dynamic-modules" {
# List of dynamic modules to include in the nginx build
default = [
"owasp-modsecurity/ModSecurity-nginx",
"openresty/headers-more-nginx-module"
]
}

function "major" {
params = [version]
result = split(".", version)[0]
Expand Down Expand Up @@ -139,8 +147,9 @@ target "nginx" {
inherits = ["platforms-base"]
dockerfile="nginx/Dockerfile"
args = {
NGINX_VERSION = "${nginx-version}"
LUA_MODULES = join(" ", lua-modules-debian)
NGINX_VERSION = "${nginx-version}"
NGINX_DYNAMIC_MODULES = join(" ", nginx-dynamic-modules)
}
tags = concat(tag("nginx"),
vtag("${crs-version}", "nginx")
Expand All @@ -151,8 +160,9 @@ target "nginx-alpine" {
inherits = ["platforms-base"]
dockerfile="nginx/Dockerfile-alpine"
args = {
NGINX_VERSION = "${nginx-version}"
LUA_MODULES = join(" ", lua-modules-alpine)
NGINX_DYNAMIC_MODULES = join(" ", nginx-dynamic-modules)
NGINX_VERSION = "${nginx-version}"
}
tags = concat(tag("nginx-alpine"),
vtag("${crs-version}", "nginx-alpine")
Expand Down
22 changes: 15 additions & 7 deletions nginx/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ FROM nginxinc/nginx-unprivileged:${NGINX_VERSION} AS build
ARG MODSEC3_VERSION="n/a"
ARG LMDB_VERSION="n/a"
ARG LUA_VERSION="n/a"
ARG NGINX_DYNAMIC_MODULES="n/a"

USER root

Expand Down Expand Up @@ -43,6 +44,7 @@ RUN set -eux; \
make -C lmdb/libraries/liblmdb install; \
strip /usr/local/lib/liblmdb*.so*


RUN set -eux; \
git clone https://github.com/owasp-modsecurity/ModSecurity --branch "v${MODSEC3_VERSION}" --depth 1 --recursive; \
cd ModSecurity; \
Expand All @@ -54,16 +56,22 @@ RUN set -eux; \
make install; \
strip /usr/local/modsecurity/lib/lib*.so*

# We use master
# Build modules
RUN set -eux; \
git clone -b master --depth 1 https://github.com/owasp-modsecurity/ModSecurity-nginx.git; \
curl -sSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -o nginx-${NGINX_VERSION}.tar.gz; \
modules=""; \
for module in ${NGINX_DYNAMIC_MODULES}; \
fzipi marked this conversation as resolved.
Show resolved Hide resolved
fzipi marked this conversation as resolved.
Show resolved Hide resolved
do \
repo=$(echo "${module}" | awk -F'/' '{print $2}'); \
git clone -b master --depth 1 "https://github.com/${module}.git" ; \
modules="${modules} --add-dynamic-module=../${repo}"; \
done; \
curl -sSL "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" -o nginx-${NGINX_VERSION}.tar.gz; \
tar -xzf nginx-${NGINX_VERSION}.tar.gz; \
cd ./nginx-${NGINX_VERSION}; \
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx; \
./configure --with-compat ${modules}; \
make modules; \
strip objs/ngx_http_modsecurity_module.so; \
cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/; \
strip objs/*.so; \
cp objs/*.so /etc/nginx/modules/; \
mkdir /etc/modsecurity.d; \
curl -sSL https://raw.githubusercontent.com/owasp-modsecurity/ModSecurity/v3/master/unicode.mapping \
-o /etc/modsecurity.d/unicode.mapping
Expand Down Expand Up @@ -197,7 +205,7 @@ ENV \
BLOCKING_PARANOIA=1

COPY --from=build /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/
COPY --from=build /etc/nginx/modules/ngx_http_modsecurity_module.so /etc/nginx/modules/ngx_http_modsecurity_module.so
COPY --from=build /etc/nginx/modules/*.so /etc/nginx/modules/
COPY --from=build /usr/local/lib/liblmdb.so /usr/local/lib/
COPY --from=build /usr/share/TLS/dhparam-* /etc/ssl/certs/
COPY --from=build /etc/modsecurity.d/unicode.mapping /etc/modsecurity.d/unicode.mapping
Expand Down
21 changes: 15 additions & 6 deletions nginx/Dockerfile-alpine
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ FROM nginxinc/nginx-unprivileged:${NGINX_VERSION}-alpine AS build

ARG MODSEC3_VERSION="n/a"
ARG LUA_VERSION="n/a"
ARG NGINX_DYNAMIC_MODULES="n/a"

USER root

Expand Down Expand Up @@ -51,14 +52,22 @@ RUN set -eux; \
make install; \
strip /usr/local/modsecurity/lib/lib*.so*

# We use master
# Build modules
RUN set -eux; \
git clone -b master --depth 1 https://github.com/owasp-modsecurity/ModSecurity-nginx.git; \
curl -sSL http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xzf -; \
modules=""; \
for module in ${NGINX_DYNAMIC_MODULES}; \
fzipi marked this conversation as resolved.
Show resolved Hide resolved
fzipi marked this conversation as resolved.
Show resolved Hide resolved
do \
repo=$(echo "${module}" | awk -F'/' '{print $2}'); \
git clone -b master --depth 1 "https://github.com/${module}.git" ; \
modules="${modules} --add-dynamic-module=../${repo}"; \
done; \
curl -sSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -o nginx-${NGINX_VERSION}.tar.gz; \
tar -xzf nginx-${NGINX_VERSION}.tar.gz; \
cd ./nginx-${NGINX_VERSION}; \
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx; \
./configure --with-compat ${modules}; \
make modules; \
cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/; \
strip objs/*.so; \
cp objs/*.so /etc/nginx/modules/; \
mkdir /etc/modsecurity.d; \
curl -sSL https://raw.githubusercontent.com/owasp-modsecurity/ModSecurity/v3/master/unicode.mapping \
-o /etc/modsecurity.d/unicode.mapping
Expand Down Expand Up @@ -191,7 +200,7 @@ ENV \
BLOCKING_PARANOIA=1

COPY --from=build /usr/local/modsecurity/lib/libmodsecurity.so.${MODSEC3_VERSION} /usr/local/modsecurity/lib/
COPY --from=build /etc/nginx/modules/ngx_http_modsecurity_module.so /etc/nginx/modules/ngx_http_modsecurity_module.so
COPY --from=build /etc/nginx/modules/*.so /etc/nginx/modules/
COPY --from=build /usr/share/TLS/dhparam-* /etc/ssl/certs/
COPY --from=build /etc/modsecurity.d/unicode.mapping /etc/modsecurity.d/unicode.mapping
COPY --from=crs_release /opt/owasp-crs /opt/owasp-crs
Expand Down
4 changes: 2 additions & 2 deletions nginx/templates/conf.d/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ server {
return 301 https://$host$request_uri;
}

include includes/cors.conf;
include includes/proxy_backend.conf;

index index.html index.htm;
Expand Down Expand Up @@ -62,8 +63,7 @@ server {
location / {
client_max_body_size 0;

# temporarily disabled, since the upstream image doesn't include the required module
# include includes/cors.conf;
include includes/cors.conf;
include includes/proxy_backend.conf;

index index.html index.htm;
Expand Down
10 changes: 5 additions & 5 deletions nginx/templates/includes/cors.conf.template
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
more_set_headers -s 403 'Content-Type' '${CORS_HEADER_403_CONTENT_TYPE}';
more_set_headers -s 403 'Access-Control-Allow-Origin' '${CORS_HEADER_403_ALLOW_ORIGIN}';
more_set_headers -s 403 'Access-Control-Max-Age' '${CORS_HEADER_403_MAX_AGE}';
more_set_headers -s 403 'Access-Control-Allow-Methods' '${CORS_HEADER_403_ALLOW_METHODS}';
more_set_headers 'Access-Control-Allow-Headers' '${CORS_HEADER_ACCESS_CONTROL_ALLOW_HEADERS}';
more_set_headers -s 403 'Content-Type: ${CORS_HEADER_403_CONTENT_TYPE}';
more_set_headers -s 403 'Access-Control-Allow-Origin: ${CORS_HEADER_403_ALLOW_ORIGIN}';
more_set_headers -s 403 'Access-Control-Max-Age: ${CORS_HEADER_403_MAX_AGE}';
more_set_headers -s 403 'Access-Control-Allow-Methods: ${CORS_HEADER_403_ALLOW_METHODS}';
more_set_headers 'Access-Control-Allow-Headers: ${CORS_HEADER_ACCESS_CONTROL_ALLOW_HEADERS}';
3 changes: 1 addition & 2 deletions nginx/templates/nginx.conf.template
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
load_module modules/ngx_http_modsecurity_module.so;
# allows to add cors headers when replying with 403
# temporarily disabled, since the upstream image doesn't include the module
# load_module modules/ngx_http_headers_more_filter_module.so;
load_module modules/ngx_http_headers_more_filter_module.so;

worker_processes auto;
pid /tmp/nginx.pid;
Expand Down
Loading