diff --git a/images/nginx/rootfs/build.sh b/images/nginx/rootfs/build.sh index 3baf775fca..e011816463 100755 --- a/images/nginx/rootfs/build.sh +++ b/images/nginx/rootfs/build.sh @@ -32,9 +32,6 @@ export MORE_HEADERS_VERSION=v0.37 # Check for recent changes: https://github.com/atomx/nginx-http-auth-digest/compare/v1.0.0...atomx:master export NGINX_DIGEST_AUTH=v1.0.0 -# Check for recent changes: https://github.com/yaoweibin/ngx_http_substitutions_filter_module/compare/v0.6.4...master -export NGINX_SUBSTITUTIONS=e12e965ac1837ca709709f9a26f572a54d83430e - # Check for recent changes: https://github.com/SpiderLabs/ModSecurity-nginx/compare/v1.0.3...master export MODSECURITY_VERSION=v1.0.3 @@ -106,6 +103,9 @@ export OPENTELEMETRY_CPP_VERSION="v1.11.0" # Check on https://github.com/open-telemetry/opentelemetry-proto export OPENTELEMETRY_PROTO_VERSION="v1.1.0" +# Check for recent changes: https://github.com/nginx/njs/compare/0.8.7...master +export NJS_VERSION="0.8.7" + export BUILD_PATH=/tmp/build ARCH=$(uname -m) @@ -213,9 +213,6 @@ get_src 0c0d2ced2ce895b3f45eb2b230cd90508ab2a773299f153de14a43e44c1209b3 \ get_src f09851e6309560a8ff3e901548405066c83f1f6ff88aa7171e0763bd9514762b \ "https://github.com/atomx/nginx-http-auth-digest/archive/$NGINX_DIGEST_AUTH.tar.gz" "nginx-http-auth-digest" -get_src a98b48947359166326d58700ccdc27256d2648218072da138ab6b47de47fbd8f \ - "https://github.com/yaoweibin/ngx_http_substitutions_filter_module/archive/$NGINX_SUBSTITUTIONS.tar.gz" "ngx_http_substitutions_filter_module" - get_src 32a42256616cc674dca24c8654397390adff15b888b77eb74e0687f023c8751b \ "https://github.com/SpiderLabs/ModSecurity-nginx/archive/$MODSECURITY_VERSION.tar.gz" "ModSecurity-nginx" @@ -414,6 +411,12 @@ Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf " > /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf +# checkout njs module +cd "$BUILD_PATH" +git clone -n https://github.com/nginx/njs +cd njs/ +git checkout $NJS_VERSION + # build nginx cd "$BUILD_PATH/nginx-$NGINX_VERSION" @@ -474,10 +477,10 @@ WITH_MODULES=" \ --add-module=$BUILD_PATH/ngx_devel_kit \ --add-module=$BUILD_PATH/set-misc-nginx-module \ --add-module=$BUILD_PATH/headers-more-nginx-module \ - --add-module=$BUILD_PATH/ngx_http_substitutions_filter_module \ --add-module=$BUILD_PATH/lua-nginx-module \ --add-module=$BUILD_PATH/stream-lua-nginx-module \ --add-module=$BUILD_PATH/lua-upstream-nginx-module \ + --add-module=$BUILD_PATH/njs/nginx \ --add-dynamic-module=$BUILD_PATH/nginx-http-auth-digest \ --add-dynamic-module=$BUILD_PATH/ModSecurity-nginx \ --add-dynamic-module=$BUILD_PATH/ngx_http_geoip2_module \ diff --git a/rootfs/etc/nginx/js/nginx/ngx_conf_rewrite_auth.js b/rootfs/etc/nginx/js/nginx/ngx_conf_rewrite_auth.js new file mode 100644 index 0000000000..aa45fe2cae --- /dev/null +++ b/rootfs/etc/nginx/js/nginx/ngx_conf_rewrite_auth.js @@ -0,0 +1,7 @@ +const crypto = require('crypto'); + +function cache_key(req) { + return crypto.createHash('sha1').update(req.variables.tmp_cache_key).digest('base64'); +} + +export default { cache_key }; diff --git a/rootfs/etc/nginx/js/nginx/ngx_srv_redirect.js b/rootfs/etc/nginx/js/nginx/ngx_srv_redirect.js new file mode 100644 index 0000000000..da1942bc8e --- /dev/null +++ b/rootfs/etc/nginx/js/nginx/ngx_srv_redirect.js @@ -0,0 +1,16 @@ +function srv_redirect(req) { + const redirectTo = req.variables.tmp_redirect_to; + + const requestUri = req.variables.request_uri.replace(/\/$/, ''); + + const useForwardedHeaders = req.variables.forwarded_headers + const xForwardedProto = req.variables.http_x_forwarded_proto; + const xForwardedPort = req.variables.http_x_forwarded_port; + + const redirectScheme = useForwardedHeaders && xForwardedProto ? xForwardedProto : req.variables.scheme; + const redirectPort = useForwardedHeaders && xForwardedPort ? xForwardedPort : req.variables.server_port; + + return `${redirectScheme}://${redirectTo}:${redirectPort}${requestUri}`; +} + +export default { srv_redirect }; \ No newline at end of file diff --git a/rootfs/etc/nginx/template/nginx.tmpl b/rootfs/etc/nginx/template/nginx.tmpl index ad41ec7ee7..91387530da 100644 --- a/rootfs/etc/nginx/template/nginx.tmpl +++ b/rootfs/etc/nginx/template/nginx.tmpl @@ -74,6 +74,12 @@ http { init_worker_by_lua_file /etc/nginx/lua/ngx_conf_init_worker.lua; + js_import /etc/nginx/js/nginx/ngx_conf_rewrite_auth.js; + js_import /etc/nginx/js/nginx/ngx_srv_redirect.js; + + js_set $njs_cache_key ngx_conf_rewrite_auth.cache_key; + js_set $njs_srv_redirect ngx_srv_redirect.srv_redirect; + {{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}} {{/* we use the value of the real IP for the geo_ip module */}} {{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIP }} @@ -572,9 +578,10 @@ http { } {{ end }} - set_by_lua_file $redirect_to /etc/nginx/lua/nginx/ngx_srv_redirect.lua {{ $redirect.To }}; + set $tmp_redirect_to '{{ $redirect.To }}'; + set $tmp_forwarded_headers '{{ $cfg.UseForwardedHeaders }}'; - return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; + return {{ $all.Cfg.HTTPRedirectCode }} $njs_srv_redirect; } ## end server {{ $redirect.From }} {{ end }} @@ -988,9 +995,6 @@ stream { {{ if $externalAuth.AuthCacheKey }} set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; - set $cache_key ''; - - rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua; proxy_cache auth_cache; @@ -998,7 +1002,7 @@ stream { proxy_cache_valid {{ $dur }}; {{- end }} - proxy_cache_key "$cache_key"; + proxy_cache_key "$njs_cache_key"; {{ end }} # ngx_auth_request module overrides variables in the parent request, diff --git a/test/e2e/annotations/auth.go b/test/e2e/annotations/auth.go index ddda1dce5f..51561fe658 100644 --- a/test/e2e/annotations/auth.go +++ b/test/e2e/annotations/auth.go @@ -21,7 +21,6 @@ import ( "fmt" "net/http" "net/url" - "regexp" "strings" "golang.org/x/crypto/bcrypt" @@ -341,11 +340,9 @@ var _ = framework.DescribeAnnotation("auth-*", func() { ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations) f.EnsureIngress(ing) - cacheRegex := regexp.MustCompile(`\$cache_key.*foo`) - f.WaitForNginxServer(host, func(server string) bool { - return cacheRegex.MatchString(server) && + return strings.Contains(server, "proxy_cache_key \"$njs_cache_key\";") && strings.Contains(server, `proxy_cache_valid 200 202 401 30m;`) }) }) diff --git a/test/e2e/annotations/fromtowwwredirect.go b/test/e2e/annotations/fromtowwwredirect.go index a3fb3b9b5d..5d4e7af0ef 100644 --- a/test/e2e/annotations/fromtowwwredirect.go +++ b/test/e2e/annotations/fromtowwwredirect.go @@ -49,7 +49,7 @@ var _ = framework.DescribeAnnotation("from-to-www-redirect", func() { f.WaitForNginxConfiguration( func(cfg string) bool { return strings.Contains(cfg, `server_name www.fromtowwwredirect.bar.com;`) && - strings.Contains(cfg, `return 308 $redirect_to;`) + strings.Contains(cfg, `return 308 $njs_srv_redirect;`) }) ginkgo.By("sending request to www.fromtowwwredirect.bar.com") @@ -88,7 +88,7 @@ var _ = framework.DescribeAnnotation("from-to-www-redirect", func() { f.WaitForNginxServer(toHost, func(server string) bool { return strings.Contains(server, fmt.Sprintf(`server_name %v;`, toHost)) && - strings.Contains(server, `return 308 $redirect_to;`) + strings.Contains(server, `return 308 $njs_srv_redirect;`) }) ginkgo.By("sending request to www should redirect to domain") diff --git a/test/e2e/settings/global_external_auth.go b/test/e2e/settings/global_external_auth.go index f589a63e94..be717ab455 100644 --- a/test/e2e/settings/global_external_auth.go +++ b/test/e2e/settings/global_external_auth.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "net/http" - "regexp" "strings" "github.com/onsi/ginkgo/v2" @@ -169,11 +168,9 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() { globalExternalAuthURLSetting: globalExternalAuthURL, }) - cacheRegex := regexp.MustCompile(`\$cache_key.*foo`) - f.WaitForNginxServer(host, func(server string) bool { - return cacheRegex.MatchString(server) && + return strings.Contains(server, "proxy_cache_key \"$njs_cache_key\";") && strings.Contains(server, `proxy_cache_valid 200 201 401 30m;`) })