diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml deleted file mode 100644 index 0901434386e..00000000000 --- a/.github/workflows/commitlint.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: commit-lint - -on: [push, pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - uses: ahmadnassri/action-commit-lint@v2 - with: - config: conventional diff --git a/build/dockerfiles/deb.Dockerfile b/build/dockerfiles/deb.Dockerfile index a55b3706fcf..c25cbadd5d5 100644 --- a/build/dockerfiles/deb.Dockerfile +++ b/build/dockerfiles/deb.Dockerfile @@ -20,6 +20,7 @@ COPY ${KONG_ARTIFACT_PATH}${KONG_ARTIFACT} /tmp/kong.deb RUN apt-get update \ && apt-get -y upgrade \ && apt-get -y autoremove \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata \ && apt-get install -y --no-install-recommends /tmp/kong.deb \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /tmp/kong.deb \ diff --git a/build/openresty/patches/nginx-1.25.3_03-http_revert_req_body_hardcode_limitation.patch b/build/openresty/patches/nginx-1.25.3_03-http_revert_req_body_hardcode_limitation.patch new file mode 100644 index 00000000000..00a38352402 --- /dev/null +++ b/build/openresty/patches/nginx-1.25.3_03-http_revert_req_body_hardcode_limitation.patch @@ -0,0 +1,320 @@ +diff --git a/bundle/ngx_lua-0.10.26/README.markdown b/bundle/ngx_lua-0.10.26/README.markdown +index d6ec8c9..02eb9af 100644 +--- a/bundle/ngx_lua-0.10.26/README.markdown ++++ b/bundle/ngx_lua-0.10.26/README.markdown +@@ -2722,8 +2722,6 @@ lua_need_request_body + + **phase:** *depends on usage* + +-Due to the stream processing feature of HTTP/2 or HTTP/3, this configuration could potentially block the entire request. Therefore, this configuration is effective only when HTTP/2 or HTTP/3 requests send content-length header. For requests with versions lower than HTTP/2, this configuration can still be used without any problems. +- + Determines whether to force the request body data to be read before running rewrite/access/content_by_lua* or not. The Nginx core does not read the client request body by default and if request body data is required, then this directive should be turned `on` or the [ngx.req.read_body](#ngxreqread_body) function should be called within the Lua code. + + To read the request body data within the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable, +@@ -5426,8 +5424,6 @@ Reads the client request body synchronously without blocking the Nginx event loo + local args = ngx.req.get_post_args() + ``` + +-Due to the stream processing feature of HTTP/2 or HTTP/3, this api could potentially block the entire request. Therefore, this api is effective only when HTTP/2 or HTTP/3 requests send content-length header. For requests with versions lower than HTTP/2, this api can still be used without any problems. +- + If the request body is already read previously by turning on [lua_need_request_body](#lua_need_request_body) or by using other modules, then this function does not run and returns immediately. + + If the request body has already been explicitly discarded, either by the [ngx.req.discard_body](#ngxreqdiscard_body) function or other modules, this function does not run and returns immediately. +@@ -5643,7 +5639,7 @@ Returns a read-only cosocket object that wraps the downstream connection. Only [ + + In case of error, `nil` will be returned as well as a string describing the error. + +-Due to the streaming nature of HTTP2 and HTTP3, this API cannot be used when the downstream connection is HTTP2 and HTTP3. ++**Note:** This method will block while waiting for client request body to be fully received. Block time depends on the [client_body_timeout](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_timeout) directive and maximum body size specified by the [client_max_body_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) directive. If read timeout occurs or client body size exceeds the defined limit, this function will not return and `408 Request Time-out` or `413 Request Entity Too Large` response will be returned to the client instead. + + The socket object returned by this method is usually used to read the current request's body in a streaming fashion. Do not turn on the [lua_need_request_body](#lua_need_request_body) directive, and do not mix this call with [ngx.req.read_body](#ngxreqread_body) and [ngx.req.discard_body](#ngxreqdiscard_body). + +diff --git a/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki b/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki +index 305626c..0db9dd5 100644 +--- a/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki ++++ b/bundle/ngx_lua-0.10.26/doc/HttpLuaModule.wiki +@@ -4741,8 +4741,7 @@ Returns a read-only cosocket object that wraps the downstream connection. Only [ + + In case of error, nil will be returned as well as a string describing the error. + +-Due to the streaming nature of HTTP2 and HTTP3, this API cannot be used when the downstream connection is HTTP2 and HTTP3. +- ++'''Note:''' This method will block while waiting for client request body to be fully received. Block time depends on the [http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_timeout client_body_timeout] directive and maximum body size specified by the [http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size client_max_body_size] directive. If read timeout occurs or client body size exceeds the defined limit, this function will not return and 408 Request Time-out or 413 Request Entity Too Large response will be returned to the client instead. + The socket object returned by this method is usually used to read the current request's body in a streaming fashion. Do not turn on the [[#lua_need_request_body|lua_need_request_body]] directive, and do not mix this call with [[#ngx.req.read_body|ngx.req.read_body]] and [[#ngx.req.discard_body|ngx.req.discard_body]]. + + If any request body data has been pre-read into the Nginx core request header buffer, the resulting cosocket object will take care of this to avoid potential data loss resulting from such pre-reading. +diff --git a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_accessby.c b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_accessby.c +index 2bf40aa..d40eab1 100644 +--- a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_accessby.c ++++ b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_accessby.c +@@ -137,26 +137,6 @@ ngx_http_lua_access_handler(ngx_http_request_t *r) + } + + if (llcf->force_read_body && !ctx->read_body_done) { +- +-#if (NGX_HTTP_V2) +- if (r->main->stream && r->headers_in.content_length_n < 0) { +- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, +- "disable lua_need_request_body, since " +- "http2 read_body may break http2 stream process"); +- goto done; +- } +-#endif +- +-#if (NGX_HTTP_V3) +- if (r->http_version == NGX_HTTP_VERSION_30 +- && r->headers_in.content_length_n < 0) +- { +- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, +- "disable lua_need_request_body, since " +- "http2 read_body may break http2 stream process"); +- goto done; +- } +-#endif + r->request_body_in_single_buf = 1; + r->request_body_in_persistent_file = 1; + r->request_body_in_clean_file = 1; +@@ -174,12 +154,6 @@ ngx_http_lua_access_handler(ngx_http_request_t *r) + } + } + +-#if defined(NGX_HTTP_V3) || defined(NGX_HTTP_V2) +- +-done: +- +-#endif +- + dd("calling access handler"); + return llcf->access_handler(r); + } +diff --git a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_contentby.c b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_contentby.c +index 2014d52..5e2ae55 100644 +--- a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_contentby.c ++++ b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_contentby.c +@@ -196,26 +196,6 @@ ngx_http_lua_content_handler(ngx_http_request_t *r) + } + + if (llcf->force_read_body && !ctx->read_body_done) { +- +-#if (NGX_HTTP_V2) +- if (r->main->stream && r->headers_in.content_length_n < 0) { +- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, +- "disable lua_need_request_body, since " +- "http2 read_body may break http2 stream process"); +- goto done; +- } +-#endif +- +-#if (NGX_HTTP_V3) +- if (r->http_version == NGX_HTTP_VERSION_30 +- && r->headers_in.content_length_n < 0) +- { +- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, +- "disable lua_need_request_body, since " +- "http2 read_body may break http2 stream process"); +- goto done; +- } +-#endif + r->request_body_in_single_buf = 1; + r->request_body_in_persistent_file = 1; + r->request_body_in_clean_file = 1; +@@ -234,12 +214,6 @@ ngx_http_lua_content_handler(ngx_http_request_t *r) + } + } + +-#if defined(NGX_HTTP_V3) || defined(NGX_HTTP_V2) +- +-done: +- +-#endif +- + dd("setting entered"); + + ctx->entered_content_phase = 1; +diff --git a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_req_body.c b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_req_body.c +index 61ab999..5d69735 100644 +--- a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_req_body.c ++++ b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_req_body.c +@@ -85,23 +85,6 @@ ngx_http_lua_ngx_req_read_body(lua_State *L) + return luaL_error(L, "request object not found"); + } + +-/* http2 read body may break http2 stream process */ +-#if (NGX_HTTP_V2) +- if (r->main->stream && r->headers_in.content_length_n < 0) { +- return luaL_error(L, "http2 requests are not supported" +- " without content-length header"); +- } +-#endif +- +-#if (NGX_HTTP_V3) +- if (r->http_version == NGX_HTTP_VERSION_30 +- && r->headers_in.content_length_n < 0) +- { +- return luaL_error(L, "http3 requests are not supported" +- " without content-length header"); +- } +-#endif +- + r->request_body_in_single_buf = 1; + r->request_body_in_persistent_file = 1; + r->request_body_in_clean_file = 1; +@@ -349,23 +332,6 @@ ngx_http_lua_ngx_req_get_body_file(lua_State *L) + return luaL_error(L, "request object not found"); + } + +-/* http2 read body may break http2 stream process */ +-#if (NGX_HTTP_V2) +- if (r->main->stream && r->headers_in.content_length_n < 0) { +- return luaL_error(L, "http2 requests are not supported" +- " without content-length header"); +- } +-#endif +- +-#if (NGX_HTTP_V3) +- if (r->http_version == NGX_HTTP_VERSION_30 +- && r->headers_in.content_length_n < 0) +- { +- return luaL_error(L, "http3 requests are not supported" +- " without content-length header"); +- } +-#endif +- + ngx_http_lua_check_fake_request(L, r); + + if (r->request_body == NULL || r->request_body->temp_file == NULL) { +diff --git a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_rewriteby.c b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_rewriteby.c +index c56bba5..4109f28 100644 +--- a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_rewriteby.c ++++ b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_rewriteby.c +@@ -140,12 +140,7 @@ ngx_http_lua_rewrite_handler(ngx_http_request_t *r) + return NGX_DONE; + } + +-/* http2 read body may break http2 stream process */ +-#if (NGX_HTTP_V2) +- if (llcf->force_read_body && !ctx->read_body_done && !r->main->stream) { +-#else + if (llcf->force_read_body && !ctx->read_body_done) { +-#endif + r->request_body_in_single_buf = 1; + r->request_body_in_persistent_file = 1; + r->request_body_in_clean_file = 1; +diff --git a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_server_rewriteby.c b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_server_rewriteby.c +index 997262e..be86069 100644 +--- a/bundle/ngx_lua-0.10.26/src/ngx_http_lua_server_rewriteby.c ++++ b/bundle/ngx_lua-0.10.26/src/ngx_http_lua_server_rewriteby.c +@@ -102,13 +102,8 @@ ngx_http_lua_server_rewrite_handler(ngx_http_request_t *r) + return NGX_DONE; + } + +-/* TODO: lscf do not have force_read_body +- * http2 read body may break http2 stream process */ +-#if (NGX_HTTP_V2) +- if (llcf->force_read_body && !ctx->read_body_done && !r->main->stream) { +-#else ++ /* TODO: lscf do not have force_read_body */ + if (llcf->force_read_body && !ctx->read_body_done) { +-#endif + r->request_body_in_single_buf = 1; + r->request_body_in_persistent_file = 1; + r->request_body_in_clean_file = 1; +diff --git a/bundle/ngx_lua-0.10.26/t/023-rewrite/request_body.t b/bundle/ngx_lua-0.10.26/t/023-rewrite/request_body.t +index 32c02e1..b867d3a 100644 +--- a/bundle/ngx_lua-0.10.26/t/023-rewrite/request_body.t ++++ b/bundle/ngx_lua-0.10.26/t/023-rewrite/request_body.t +@@ -170,26 +170,3 @@ Expect: 100-Continue + http finalize request: 500, "/echo_body?" a:1, c:2 + http finalize request: 500, "/echo_body?" a:1, c:0 + --- log_level: debug +---- skip_eval: 4:$ENV{TEST_NGINX_USE_HTTP3} +- +- +- +-=== TEST 9: test HTTP2 reading request body was disabled +---- config +- location /echo_body { +- lua_need_request_body on; +- rewrite_by_lua_block { +- ngx.print(ngx.var.request_body or "nil") +- } +- content_by_lua 'ngx.exit(ngx.OK)'; +- } +---- http2 +---- request eval +-"POST /echo_body +-hello\x00\x01\x02 +-world\x03\x04\xff" +---- more_headers +-Content-Length: +---- response_body eval +-"nil" +---- no_error_log +diff --git a/bundle/ngx_lua-0.10.26/t/024-access/request_body.t b/bundle/ngx_lua-0.10.26/t/024-access/request_body.t +index 0aa12c8..fa03195 100644 +--- a/bundle/ngx_lua-0.10.26/t/024-access/request_body.t ++++ b/bundle/ngx_lua-0.10.26/t/024-access/request_body.t +@@ -170,26 +170,3 @@ Expect: 100-Continue + http finalize request: 500, "/echo_body?" a:1, c:2 + http finalize request: 500, "/echo_body?" a:1, c:0 + --- log_level: debug +---- skip_eval: 4:$ENV{TEST_NGINX_USE_HTTP3} +- +- +- +-=== TEST 9: test HTTP2 reading request body was disabled +---- config +- location /echo_body { +- lua_need_request_body on; +- access_by_lua_block { +- ngx.print(ngx.var.request_body or "nil") +- } +- content_by_lua 'ngx.exit(ngx.OK)'; +- } +---- http2 +---- request eval +-"POST /echo_body +-hello\x00\x01\x02 +-world\x03\x04\xff" +---- more_headers +-Content-Length: +---- response_body eval +-"nil" +---- no_error_log +diff --git a/bundle/ngx_lua-0.10.26/t/044-req-body.t b/bundle/ngx_lua-0.10.26/t/044-req-body.t +index f4509e1..da3a28b 100644 +--- a/bundle/ngx_lua-0.10.26/t/044-req-body.t ++++ b/bundle/ngx_lua-0.10.26/t/044-req-body.t +@@ -7,7 +7,7 @@ log_level('warn'); + + repeat_each(2); + +-plan tests => repeat_each() * (blocks() * 4 + 56); ++plan tests => repeat_each() * (blocks() * 4 + 58 ); + + #no_diff(); + no_long_string(); +@@ -1774,23 +1774,3 @@ content length: 5 + --- no_error_log + [error] + [alert] +---- skip_eval: 4:$ENV{TEST_NGINX_USE_HTTP3} +- +- +- +-=== TEST 53: HTTP2 read buffered body was discarded +---- config +- location = /test { +- content_by_lua_block { +- local err = pcall(ngx.req.read_body()) +- ngx.say(err) +- } +- } +---- http2 +---- request +-POST /test +-hello, world +---- more_headers +-Content-Length: +---- error_code: 500 +---- error_log: http2 requests are not supported without content-length header diff --git a/build/package/nfpm.yaml b/build/package/nfpm.yaml index 388b7d0be89..2e0bbf0c691 100644 --- a/build/package/nfpm.yaml +++ b/build/package/nfpm.yaml @@ -42,6 +42,9 @@ contents: dst: /lib/systemd/system/kong.service - src: build/package/kong.logrotate dst: /etc/kong/kong.logrotate + file_info: + mode: 0644 + scripts: postinstall: ./build/package/postinstall.sh replaces: diff --git a/changelog/unreleased/kong/add_tzdata.yml b/changelog/unreleased/kong/add_tzdata.yml new file mode 100644 index 00000000000..91c8df9c2ad --- /dev/null +++ b/changelog/unreleased/kong/add_tzdata.yml @@ -0,0 +1,3 @@ +message: | + Add package `tzdata` to DEB Docker image for convenient timezone setting. +type: dependency diff --git a/changelog/unreleased/kong/fix-file-permission-of-logrotate.yml b/changelog/unreleased/kong/fix-file-permission-of-logrotate.yml new file mode 100644 index 00000000000..2fb24c9e2f5 --- /dev/null +++ b/changelog/unreleased/kong/fix-file-permission-of-logrotate.yml @@ -0,0 +1,3 @@ +message: update file permission of kong.logrotate to 644 +type: bugfix +scope: Core diff --git a/changelog/unreleased/kong/revert-req-body-limitation-patch.yml b/changelog/unreleased/kong/revert-req-body-limitation-patch.yml new file mode 100644 index 00000000000..55da8ff9197 --- /dev/null +++ b/changelog/unreleased/kong/revert-req-body-limitation-patch.yml @@ -0,0 +1,3 @@ +message: revert the hard-coded limitation of the ngx.read_body() API in OpenResty upstreams' new versions when downstream connections are in HTTP/2 or HTTP/3 stream modes. +type: bugfix +scope: Core diff --git a/kong/router/fields.lua b/kong/router/fields.lua index 126bbce671f..4294e84b760 100644 --- a/kong/router/fields.lua +++ b/kong/router/fields.lua @@ -199,6 +199,11 @@ end -- is_http -- stream subsystem needs not to generate func local function get_field_accessor(funcs, field) + local f = FIELDS_FUNCS[field] + if f then + return f + end + error("unknown router matching schema field: " .. field) end @@ -259,7 +264,7 @@ if is_http then get_field_accessor = function(funcs, field) - local f = funcs[field] + local f = FIELDS_FUNCS[field] or funcs[field] if f then return f end @@ -447,8 +452,7 @@ end function _M:get_value(field, params, ctx) - local func = FIELDS_FUNCS[field] or - get_field_accessor(self.funcs, field) + local func = get_field_accessor(self.funcs, field) return func(params, ctx) end diff --git a/scripts/explain_manifest/explain.py b/scripts/explain_manifest/explain.py index d9f807b2dc2..1916401024e 100644 --- a/scripts/explain_manifest/explain.py +++ b/scripts/explain_manifest/explain.py @@ -64,12 +64,14 @@ def __init__(self, path, relpath): # use lstat to get the mode, uid, gid of the symlink itself self.mode = os.lstat(path).st_mode + # unix style mode + self.file_mode = '0' + oct(self.mode & 0o777)[2:] self.uid = os.lstat(path).st_uid self.gid = os.lstat(path).st_gid if not Path(path).is_symlink(): self.size = os.stat(path).st_size - + self._lazy_evaluate_attrs.update({ "binary_content": lambda: open(path, "rb").read(), "text_content": lambda: open(path, "rb").read().decode('utf-8'), @@ -129,7 +131,7 @@ def __init__(self, path, relpath): binary = lief.parse(path) if not binary: # not an ELF file, malformed, etc return - + self.arch = binary.header.machine_type.name for d in binary.dynamic_entries: @@ -152,7 +154,7 @@ def __init__(self, path, relpath): self.version_requirement[f.name] = [LooseVersion( a.name) for a in f.get_auxiliary_symbols()] self.version_requirement[f.name].sort() - + self._lazy_evaluate_attrs.update({ "exported_symbols": self.get_exported_symbols, "imported_symbols": self.get_imported_symbols, diff --git a/scripts/explain_manifest/suites.py b/scripts/explain_manifest/suites.py index 89fb06ecfe2..daed3029939 100644 --- a/scripts/explain_manifest/suites.py +++ b/scripts/explain_manifest/suites.py @@ -19,6 +19,8 @@ def common_suites(expect, libxcrypt_no_obsolete_api: bool = False): expect("/etc/kong/kong.logrotate", "includes logrotate config").exists() + expect("/etc/kong/kong.logrotate", "logrotate config should have 0644 permissions").file_mode.equals("0644") + expect("/usr/local/kong/include/openssl/**.h", "includes OpenSSL headers").exists() # binary correctness diff --git a/t/04-patch/02-ngx-read-body-block.t b/t/04-patch/02-ngx-read-body-block.t new file mode 100644 index 00000000000..a086b125704 --- /dev/null +++ b/t/04-patch/02-ngx-read-body-block.t @@ -0,0 +1,49 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket 'no_plan'; + +repeat_each(2); + +run_tests(); + +__DATA__ + +=== TEST 1: ngx.req.read_body() should work for HTTP2 GET requests that doesn't carry the content-length header +--- config + location = /test { + content_by_lua_block { + local ok, err = pcall(ngx.req.read_body) + ngx.say(ok, " err: ", err) + } + } +--- http2 +--- request +GET /test +hello, world +--- more_headers +Content-Length: +--- response_body +true err: nil +--- no_error_log +[error] +[alert] + +=== TEST 2: ngx.req.read_body() should work for HTTP2 POST requests that doesn't carry the content-length header +--- config + location = /test { + content_by_lua_block { + local ok, err = pcall(ngx.req.read_body) + ngx.say(ok, " err: ", err) + } + } +--- http2 +--- request +POST /test +hello, world +--- more_headers +Content-Length: +--- response_body +true err: nil +--- no_error_log +[error] +[alert] \ No newline at end of file