diff --git a/.github/workflows/gm-cron.yaml b/.github/workflows/gm-cron.yaml.disabled similarity index 100% rename from .github/workflows/gm-cron.yaml rename to .github/workflows/gm-cron.yaml.disabled diff --git a/.github/workflows/gm.yml b/.github/workflows/gm.yml.disabled similarity index 100% rename from .github/workflows/gm.yml rename to .github/workflows/gm.yml.disabled diff --git a/.requirements b/.requirements index b5d22118a3c4..bbfa42c49801 100644 --- a/.requirements +++ b/.requirements @@ -17,4 +17,4 @@ APISIX_PACKAGE_NAME=apisix -APISIX_RUNTIME=1.1.1 +APISIX_RUNTIME=1.2.0 diff --git a/Makefile b/Makefile index 1482198f022f..ff50ca881219 100644 --- a/Makefile +++ b/Makefile @@ -312,6 +312,9 @@ install: runtime $(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/plugins/limit-conn $(ENV_INSTALL) apisix/plugins/limit-conn/*.lua $(ENV_INST_LUADIR)/apisix/plugins/limit-conn/ + $(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/plugins/limit-req + $(ENV_INSTALL) apisix/plugins/limit-req/*.lua $(ENV_INST_LUADIR)/apisix/plugins/limit-req/ + $(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/plugins/limit-count $(ENV_INSTALL) apisix/plugins/limit-count/*.lua $(ENV_INST_LUADIR)/apisix/plugins/limit-count/ diff --git a/apisix-master-0.rockspec b/apisix-master-0.rockspec index 90327d61b262..91e6b541c4d2 100644 --- a/apisix-master-0.rockspec +++ b/apisix-master-0.rockspec @@ -79,7 +79,7 @@ dependencies = { "nanoid = 0.1-1", "lua-resty-mediador = 0.1.2-1", "lua-resty-ldap = 0.1.0-0", - "lua-resty-t1k = 1.1.0", + "lua-resty-t1k = 1.1.1", "brotli-ffi = 0.3-1", "lua-ffi-zlib = 0.6-0" } diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua index d4d78a2197d8..121f39f0501f 100644 --- a/apisix/cli/ngx_tpl.lua +++ b/apisix/cli/ngx_tpl.lua @@ -628,12 +628,15 @@ http { {% end %} server { + {% if enable_http2 then %} + http2 on; + {% end %} {% for _, item in ipairs(node_listen) do %} - listen {* item.ip *}:{* item.port *} default_server {% if item.enable_http2 then %} http2 {% end %} {% if enable_reuseport then %} reuseport {% end %}; + listen {* item.ip *}:{* item.port *} default_server {% if enable_reuseport then %} reuseport {% end %}; {% end %} {% if ssl.enable then %} {% for _, item in ipairs(ssl.listen) do %} - listen {* item.ip *}:{* item.port *} ssl default_server {% if item.enable_http2 then %} http2 {% end %} {% if enable_reuseport then %} reuseport {% end %}; + listen {* item.ip *}:{* item.port *} ssl default_server {% if enable_reuseport then %} reuseport {% end %}; {% end %} {% end %} {% if proxy_protocol and proxy_protocol.listen_http_port then %} diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua index 836c87bce521..918d1c81bdfb 100644 --- a/apisix/cli/ops.lua +++ b/apisix/cli/ops.lua @@ -413,6 +413,7 @@ Please modify "admin_key" in conf/config.yaml . end end + local enable_http2_global = false local node_listen = {} -- listen in http, support multiple ports and specific IP, compatible with the original style if type(yaml_conf.apisix.node_listen) == "number" then @@ -443,6 +444,9 @@ Please modify "admin_key" in conf/config.yaml . if enable_http2 == nil then enable_http2 = false end + if enable_http2 == true then + enable_http2_global = true + end listen_table_insert(node_listen, "http", ip, port, enable_http2, enable_ipv6) @@ -473,12 +477,16 @@ Please modify "admin_key" in conf/config.yaml . if enable_http2 == nil then enable_http2 = false end + if enable_http2 == true then + enable_http2_global = true + end listen_table_insert(ssl_listen, "https", ip, port, enable_http2, enable_ipv6) end yaml_conf.apisix.ssl.listen = ssl_listen + yaml_conf.apisix.enable_http2 = enable_http2_global if yaml_conf.apisix.ssl.ssl_trusted_certificate ~= nil then local cert_path = yaml_conf.apisix.ssl.ssl_trusted_certificate diff --git a/apisix/core/config_etcd.lua b/apisix/core/config_etcd.lua index eebf74eee71e..c1ea323db9da 100644 --- a/apisix/core/config_etcd.lua +++ b/apisix/core/config_etcd.lua @@ -227,7 +227,7 @@ local function do_run_watch(premature) log.warn("watch canceled by etcd, res: ", inspect(res)) if res.result.compact_revision then watch_ctx.rev = tonumber(res.result.compact_revision) - log.warn("etcd compacted, compact_revision=", watch_ctx.rev) + log.error("etcd compacted, compact_revision=", watch_ctx.rev) produce_res(nil, "compacted") end cancel_watch(http_cli) @@ -629,7 +629,7 @@ local function sync_data(self) if not dir_res then if err == "compacted" then self.need_reload = true - log.warn("waitdir [", self.key, "] err: ", err, + log.error("waitdir [", self.key, "] err: ", err, ", will read the configuration again via readdir") return false end diff --git a/apisix/core/request.lua b/apisix/core/request.lua index aa9dd03bf7bc..0c614edf1b20 100644 --- a/apisix/core/request.lua +++ b/apisix/core/request.lua @@ -282,6 +282,15 @@ function _M.get_body(max_size, ctx) end end + -- check content-length header for http2/http3 + do + local var = ctx and ctx.var or ngx.var + local content_length = tonumber(var.http_content_length) + if (var.server_protocol == "HTTP/2.0" or var.server_protocol == "HTTP/3.0") + and not content_length then + return nil, "HTTP2/HTTP3 request without a Content-Length header" + end + end req_read_body() local req_body = req_get_body_data() diff --git a/apisix/discovery/consul/init.lua b/apisix/discovery/consul/init.lua index a1e537a53829..a6139993dc14 100644 --- a/apisix/discovery/consul/init.lua +++ b/apisix/discovery/consul/init.lua @@ -45,6 +45,7 @@ local next = next local all_services = core.table.new(0, 5) local default_service local default_weight +local sort_type local skip_service_map = core.table.new(0, 1) local dump_params @@ -339,6 +340,25 @@ local function watch_result_is_valid(watch_type, index, catalog_index, health_in end +local function combine_sort_nodes_cmp(left, right) + if left.host ~= right.host then + return left.host < right.host + end + + return left.port < right.port +end + + +local function port_sort_nodes_cmp(left, right) + return left.port < right.port +end + + +local function host_sort_nodes_cmp(left, right) + return left.host < right.host +end + + function _M.connect(premature, consul_server, retry_delay) if premature then return @@ -489,6 +509,7 @@ function _M.connect(premature, consul_server, retry_delay) if is_not_empty(result.body) then -- add services to table local nodes = up_services[service_name] + local nodes_uniq = {} for _, node in ipairs(result.body) do if not node.Service then goto CONTINUE @@ -500,12 +521,29 @@ function _M.connect(premature, consul_server, retry_delay) nodes = core.table.new(1, 0) up_services[service_name] = nodes end - -- add node to nodes table - core.table.insert(nodes, { - host = svc_address, - port = tonumber(svc_port), - weight = default_weight, - }) + -- not store duplicate service IDs. + local service_id = svc_address .. ":" .. svc_port + if not nodes_uniq[service_id] then + -- add node to nodes table + core.table.insert(nodes, { + host = svc_address, + port = tonumber(svc_port), + weight = default_weight, + }) + nodes_uniq[service_id] = true + end + end + if nodes then + if sort_type == "port_sort" then + core.table.sort(nodes, port_sort_nodes_cmp) + + elseif sort_type == "host_sort" then + core.table.sort(nodes, host_sort_nodes_cmp) + + elseif sort_type == "combine_sort" then + core.table.sort(nodes, combine_sort_nodes_cmp) + + end end up_services[service_name] = nodes end @@ -592,6 +630,7 @@ function _M.init_worker() log.notice("consul_conf: ", json_delay_encode(consul_conf, true)) default_weight = consul_conf.weight + sort_type = consul_conf.sort_type -- set default service, used when the server node cannot be found if consul_conf.default_service then default_service = consul_conf.default_service diff --git a/apisix/discovery/consul/schema.lua b/apisix/discovery/consul/schema.lua index d7cf2954abf3..5d6fc641e85b 100644 --- a/apisix/discovery/consul/schema.lua +++ b/apisix/discovery/consul/schema.lua @@ -44,6 +44,11 @@ return { wait = 60, } }, + sort_type = { + type = "string", + enum = {"origin", "host_sort", "port_sort", "combine_sort"}, + default = "origin", + }, skip_services = { type = "array", minItems = 1, diff --git a/apisix/plugins/cors.lua b/apisix/plugins/cors.lua index 94f54683ef55..869775e5ffeb 100644 --- a/apisix/plugins/cors.lua +++ b/apisix/plugins/cors.lua @@ -341,15 +341,32 @@ function _M.header_filter(conf, ctx) local req_origin = ctx.original_request_origin -- If allow_origins_by_regex is not nil, should be matched to it only local allow_origins - if conf.allow_origins_by_regex == nil then - allow_origins = process_with_allow_origins( - TYPE_ACCESS_CONTROL_ALLOW_ORIGIN, conf.allow_origins, ctx, req_origin + local allow_origins_local = false + if conf.allow_origins_by_metadata then + allow_origins = process_with_allow_origins_by_metadata( + TYPE_ACCESS_CONTROL_ALLOW_ORIGIN, conf.allow_origins_by_metadata, ctx, req_origin ) + if not match_origins(req_origin, allow_origins) then + if conf.allow_origins and conf.allow_origins ~= "*" then + allow_origins_local = true + end + end else - allow_origins = process_with_allow_origins_by_regex( - TYPE_ACCESS_CONTROL_ALLOW_ORIGIN, conf.allow_origins_by_regex, - conf, ctx, req_origin - ) + allow_origins_local = true + end + if conf.allow_origins_by_regex == nil then + if allow_origins_local then + allow_origins = process_with_allow_origins( + TYPE_ACCESS_CONTROL_ALLOW_ORIGIN, conf.allow_origins, ctx, req_origin + ) + end + else + if allow_origins_local then + allow_origins = process_with_allow_origins_by_regex( + TYPE_ACCESS_CONTROL_ALLOW_ORIGIN, conf.allow_origins_by_regex, + conf, ctx, req_origin + ) + end end if not match_origins(req_origin, allow_origins) then allow_origins = process_with_allow_origins_by_metadata( diff --git a/apisix/plugins/ext-plugin/init.lua b/apisix/plugins/ext-plugin/init.lua index 424f29dc4f9b..2631afd36fb3 100644 --- a/apisix/plugins/ext-plugin/init.lua +++ b/apisix/plugins/ext-plugin/init.lua @@ -935,13 +935,14 @@ end local runner local function setup_runner(cmd) - runner = spawn_proc(cmd) ngx_timer_at(0, function(premature) if premature then return end + runner = spawn_proc(cmd) + while not exiting() do while true do -- drain output @@ -968,7 +969,6 @@ local function setup_runner(cmd) end runner = nil - local ok, err = events:post(events_list._source, events_list.runner_exit) if not ok then core.log.error("post event failure with ", events_list._source, ", error: ", err) diff --git a/apisix/plugins/openid-connect.lua b/apisix/plugins/openid-connect.lua index 28af0e933e2e..435cf63631e9 100644 --- a/apisix/plugins/openid-connect.lua +++ b/apisix/plugins/openid-connect.lua @@ -72,6 +72,15 @@ local schema = { description = "the key used for the encrypt and HMAC calculation", minLength = 16, }, + cookie = { + type = "object", + properties = { + lifetime = { + type = "integer", + description = "it holds the cookie lifetime in seconds in the future", + } + } + } }, required = {"secret"}, additionalProperties = false, diff --git a/ci/centos7-ci.sh b/ci/centos7-ci.sh index 344552e9f4ef..044c6239d3ce 100755 --- a/ci/centos7-ci.sh +++ b/ci/centos7-ci.sh @@ -44,10 +44,7 @@ install_dependencies() { yum install -y yum-utils && yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo yum install -y openresty-pcre-devel openresty-zlib-devel - export runtime_version=${APISIX_RUNTIME} - wget "https://raw.githubusercontent.com/api7/apisix-build-tools/apisix-runtime/${APISIX_RUNTIME}/build-apisix-runtime.sh" - chmod +x build-apisix-runtime.sh - ./build-apisix-runtime.sh latest + install_apisix_runtime curl -o /usr/local/openresty/openssl3/ssl/openssl.cnf \ https://raw.githubusercontent.com/api7/apisix-build-tools/apisix-runtime/${APISIX_RUNTIME}/conf/openssl3/openssl.cnf diff --git a/ci/common.sh b/ci/common.sh index 9aa132af1c06..7e9f65e385b6 100644 --- a/ci/common.sh +++ b/ci/common.sh @@ -75,6 +75,13 @@ install_curl () { curl -V } +install_apisix_runtime() { + export runtime_version=${APISIX_RUNTIME} + wget "https://raw.githubusercontent.com/api7/apisix-build-tools/apisix-runtime/${APISIX_RUNTIME}/build-apisix-runtime.sh" + chmod +x build-apisix-runtime.sh + ./build-apisix-runtime.sh latest +} + install_grpcurl () { # For more versions, visit https://github.com/fullstorydev/grpcurl/releases GRPCURL_VERSION="1.8.5" diff --git a/ci/linux-install-openresty.sh b/ci/linux-install-openresty.sh index 8d24334173e9..f55bb114095f 100755 --- a/ci/linux-install-openresty.sh +++ b/ci/linux-install-openresty.sh @@ -51,10 +51,7 @@ if [ "$OPENRESTY_VERSION" == "source" ]; then fi fi -export runtime_version=${APISIX_RUNTIME} -wget "https://raw.githubusercontent.com/api7/apisix-build-tools/apisix-runtime/${APISIX_RUNTIME}/build-apisix-runtime.sh" -chmod +x build-apisix-runtime.sh -./build-apisix-runtime.sh latest +install_apisix_runtime if [ ! "$ENABLE_FIPS" == "true" ]; then curl -o /usr/local/openresty/openssl3/ssl/openssl.cnf \ diff --git a/ci/pod/docker-compose.first.yml b/ci/pod/docker-compose.first.yml index aee79a8387c7..622360638a00 100644 --- a/ci/pod/docker-compose.first.yml +++ b/ci/pod/docker-compose.first.yml @@ -55,6 +55,48 @@ services: networks: consul_net: + ## Consul cluster + consul_node_1: + image: consul:1.7 + restart: unless-stopped + ports: + - "9500:8500" + - "8300:8300" + - "8301:8301" + - "8302:8302" + - "9600:8600" + command: [ "consul", "agent", "-server", "-bootstrap-expect=1", "-bind", "0.0.0.0", "-client", "0.0.0.0", "-node", "node-1", "-log-level", "info", "-data-dir=/consul/data", "-enable-script-checks" ] + networks: + consul_cluster_net: + aliases: + - consul.cluster + + consul_node_2: + image: consul:1.7 + restart: unless-stopped + environment: + - CONSUL_BIND_INTERFACE=eth0 + ports: + - "9501:8500" + command: [ "consul", "agent", "-server", "-bind", "0.0.0.0", "-client", "0.0.0.0", "-retry-join", "consul.cluster", "-node", "node-2", "-log-level", "info", "-data-dir=/consul/data", "-enable-script-checks" ] + networks: + consul_cluster_net: + aliases: + - consul.cluster + + consul_node_3: + image: consul:1.7 + restart: unless-stopped + environment: + - CONSUL_BIND_INTERFACE=eth0 + ports: + - "9502:8500" + command: [ "consul", "agent", "-server", "-bind", "0.0.0.0", "-client", "0.0.0.0", "-retry-join", "consul.cluster", "-node", "node-3", "-log-level", "info", "-data-dir=/consul/data", "-enable-script-checks" ] + networks: + consul_cluster_net: + aliases: + - consul.cluster + ## Nacos cluster nacos_auth: hostname: nacos1 @@ -246,5 +288,6 @@ services: networks: + consul_cluster_net: consul_net: nacos_net: diff --git a/ci/redhat-ci.sh b/ci/redhat-ci.sh index c10e047d4a48..e6a50e2b6ebe 100755 --- a/ci/redhat-ci.sh +++ b/ci/redhat-ci.sh @@ -38,10 +38,7 @@ install_dependencies() { yum install -y yum-utils && yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo yum install -y openresty-pcre-devel openresty-zlib-devel - export runtime_version=${APISIX_RUNTIME} - wget "https://raw.githubusercontent.com/api7/apisix-build-tools/apisix-runtime/${APISIX_RUNTIME}/build-apisix-runtime.sh" - chmod +x build-apisix-runtime.sh - ./build-apisix-runtime.sh latest + install_apisix_runtime curl -o /usr/local/openresty/openssl3/ssl/openssl.cnf \ https://raw.githubusercontent.com/api7/apisix-build-tools/apisix-runtime/${APISIX_RUNTIME}/conf/openssl3/openssl.cnf diff --git a/docs/en/latest/discovery/consul.md b/docs/en/latest/discovery/consul.md index 85e6b9ba2c8b..1f230eddf37b 100644 --- a/docs/en/latest/discovery/consul.md +++ b/docs/en/latest/discovery/consul.md @@ -47,6 +47,7 @@ discovery: weight: 1 # default 1 fetch_interval: 5 # default 3 sec, only take effect for keepalive: false way keepalive: true # default true, use the long pull way to query consul servers + sort_type: "origin" # default origin default_service: # you can define default service when missing hit host: "127.0.0.1" port: 20999 @@ -73,6 +74,13 @@ The `keepalive` has two optional values: - `true`, default and recommend value, use the long pull way to query consul servers - `false`, not recommend, it would use the short pull way to query consul servers, then you can set the `fetch_interval` for fetch interval +The `sort_type` has four optional values: + +- `origin`, not sorting +- `host_sort`, sort by host +- `port_sort`, sort by port +- `combine_sort`, with the precondition that hosts are ordered, ports are also ordered. + #### Dump Data When we need reload `apisix` online, as the `consul` module maybe loads data from CONSUL slower than load routes from ETCD, and would get the log at the moment before load successfully from consul: diff --git a/docs/en/latest/plugin-develop.md b/docs/en/latest/plugin-develop.md index 1b674303ecfe..014939a51270 100644 --- a/docs/en/latest/plugin-develop.md +++ b/docs/en/latest/plugin-develop.md @@ -341,7 +341,7 @@ If none of the keys in `keyring` can decrypt the data, the original data is used Determine which phase to run, generally access or rewrite. If you don't know the [OpenResty lifecycle](https://github.com/openresty/lua-nginx-module/blob/master/README.markdown#directives), it's recommended to know it in advance. For example key-auth is an authentication plugin, thus the authentication should be completed before forwarding the request to any upstream service. Therefore, the plugin must be executed in the rewrite phases. -In APISIX, only the authentication logic can be run in the rewrite phase. Other logic needs to run before proxy should be in access phase. +Similarly, if you want to modify or process the response body or headers you can do that in the `body_filter` or in the `header_filter` phases respectively. The following code snippet shows how to implement any logic relevant to the plugin in the OpenResty log phase. diff --git a/docs/en/latest/plugins/api-breaker.md b/docs/en/latest/plugins/api-breaker.md index 64b80c97657d..d0478b1c91da 100644 --- a/docs/en/latest/plugins/api-breaker.md +++ b/docs/en/latest/plugins/api-breaker.md @@ -80,7 +80,7 @@ curl "http://127.0.0.1:9180/apisix/admin/routes/1" \ "127.0.0.1:1980": 1 } }, - "uri": "/hello", + "uri": "/hello" }' ``` diff --git a/docs/en/latest/plugins/ext-plugin-post-resp.md b/docs/en/latest/plugins/ext-plugin-post-resp.md index 1692eacb79ab..5a240c7fd5e2 100644 --- a/docs/en/latest/plugins/ext-plugin-post-resp.md +++ b/docs/en/latest/plugins/ext-plugin-post-resp.md @@ -33,12 +33,7 @@ The `ext-plugin-post-resp` Plugin is for running specific external Plugins in th The `ext-plugin-post-resp` plugin will be executed after the request gets a response from the upstream. -After enabling this plugin, APISIX will use the [lua-resty-http](https://github.com/api7/lua-resty-http) library to make requests to the upstream, this results in: - -- [proxy-control](./proxy-control.md) plugin is not available -- [proxy-mirror](./proxy-mirror.md) plugin is not available -- [proxy-cache](./proxy-cache.md) plugin is not available -- [mTLS Between APISIX and Upstream](../mtls.md#mtls-between-apisix-and-upstream) function is not available yet +This plugin uses [lua-resty-http](https://github.com/api7/lua-resty-http) library under the hood to send requests to the upstream, due to which the [proxy-control](./proxy-control.md), [proxy-mirror](./proxy-mirror.md), and [proxy-cache](./proxy-cache.md) plugins are not available to be used alongside this plugin. Also, [mTLS Between APISIX and Upstream](../mtls.md#mtls-between-apisix-and-upstream) is not yet supported. See [External Plugin](../external-plugin.md) to learn more. diff --git a/docs/en/latest/plugins/openid-connect.md b/docs/en/latest/plugins/openid-connect.md index 1fcba8811d8f..103c7c0265bb 100644 --- a/docs/en/latest/plugins/openid-connect.md +++ b/docs/en/latest/plugins/openid-connect.md @@ -61,6 +61,8 @@ description: OpenID Connect allows the client to obtain user information from th | set_refresh_token_header | boolean | False | false | | When set to true and a refresh token object is available, sets it in the `X-Refresh-Token` request header. | | session | object | False | | | When bearer_only is set to false, openid-connect will use Authorization Code flow to authenticate on the IDP, so you need to set the session-related configuration. | | session.secret | string | True | Automatic generation | 16 or more characters | The key used for session encrypt and HMAC operation. | +| session.cookie | object | False | | | | +| session.cookie.lifetime | integer | False | 3600 | | it holds the cookie lifetime in seconds in the future. By default this is set to 3,600 seconds. This can be configured with Nginx set $session_cookie_lifetime 3600;. This does not set cookie's expiration time on session only (by default) cookies, but it is used if the cookies are configured persistent with session.cookie.persistent == true. | | unauth_action | string | False | "auth" | ["auth","deny","pass"] | Specify the response type on unauthenticated requests. "auth" redirects to identity provider, "deny" results in a 401 response, "pass" will allow the request without authentication. | | proxy_opts | object | False | | | HTTP proxy that the OpenID provider is behind. | | proxy_opts.http_proxy | string | False | | http://proxy-server:port | HTTP proxy server address. | diff --git a/docs/en/latest/plugins/ua-restriction.md b/docs/en/latest/plugins/ua-restriction.md index 8438553dc962..c55ba973d2ff 100644 --- a/docs/en/latest/plugins/ua-restriction.md +++ b/docs/en/latest/plugins/ua-restriction.md @@ -39,11 +39,11 @@ A common scenario is to set crawler rules. `User-Agent` is the identity of the c | bypass_missing | boolean | False | false | | When set to `true`, bypasses the check when the `User-Agent` header is missing. | | allowlist | array[string] | False | | | List of allowed `User-Agent` headers. | | denylist | array[string] | False | | | List of denied `User-Agent` headers. | -| message | string | False | "Not allowed" | [1, 1024] | Message with the reason for denial to be added to the response. | +| message | string | False | "Not allowed" | | Message with the reason for denial to be added to the response. | :::note -Both `allowlist` and `denylist` can't be used at the same time. +`allowlist` and `denylist` can't be configured at the same time. ::: @@ -64,45 +64,25 @@ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13 "plugins": { "ua-restriction": { "bypass_missing": true, - "allowlist": [ - "my-bot1", - "(Baiduspider)/(\\d+)\\.(\\d+)" - ], "denylist": [ "my-bot2", "(Twitterspider)/(\\d+)\\.(\\d+)" - ] + ], + "message": "Do you want to do something bad?" } } }' ``` -You can also configure the Plugin to respond with a custom rejection message: - -```json -"plugins": { - "ua-restriction": { - "denylist": [ - "my-bot2", - "(Twitterspider)/(\\d+)\\.(\\d+)" - ], - "message": "Do you want to do something bad?" - } -} -``` - ## Example usage -After you have configured the Plugin as shown above, you can make a normal request which will get accepted: +Send a request to the route: ```shell curl http://127.0.0.1:9080/index.html -i ``` -```shell -HTTP/1.1 200 OK -... -``` +You should receive an `HTTP/1.1 200 OK` response. Now if the `User-Agent` header is in the `denylist` i.e the bot User-Agent: @@ -110,10 +90,10 @@ Now if the `User-Agent` header is in the `denylist` i.e the bot User-Agent: curl http://127.0.0.1:9080/index.html --header 'User-Agent: Twitterspider/2.0' ``` -```shell -HTTP/1.1 403 Forbidden -... -{"message":"Not allowed"} +You should receive an `HTTP/1.1 403 Forbidden` response with the following message: + +```text +{"message":"Do you want to do something bad?"} ``` ## Delete Plugin diff --git a/docs/en/latest/plugins/workflow.md b/docs/en/latest/plugins/workflow.md index 6448d0224156..48fa0963d92e 100644 --- a/docs/en/latest/plugins/workflow.md +++ b/docs/en/latest/plugins/workflow.md @@ -126,24 +126,24 @@ HTTP/1.1 403 Forbidden **Example 2: if the request uri is `/hello/v2/appid`, the `workflow` plugin would execute the `limit-count` plugin** ```shell -curl http://127.0.0.1:0080/hello/v2/appid -i +curl http://127.0.0.1:9080/hello/v2/appid -i HTTP/1.1 200 OK ``` ```shell -curl http://127.0.0.1:0080/hello/v2/appid -i +curl http://127.0.0.1:9080/hello/v2/appid -i HTTP/1.1 200 OK ``` ```shell -curl http://127.0.0.1:0080/hello/v2/appid -i +curl http://127.0.0.1:9080/hello/v2/appid -i HTTP/1.1 429 Too Many Requests ``` **Example 3: if the request can not match any `case` in the `rules`, the `workflow` plugin would do nothing** ```shell -curl http://127.0.0.1:0080/hello/fake -i +curl http://127.0.0.1:9080/hello/fake -i HTTP/1.1 200 OK ``` diff --git a/docs/zh/latest/plugins/openid-connect.md b/docs/zh/latest/plugins/openid-connect.md index bdcd22530c09..f09e1707ddfe 100644 --- a/docs/zh/latest/plugins/openid-connect.md +++ b/docs/zh/latest/plugins/openid-connect.md @@ -60,6 +60,8 @@ description: OpenID Connect(OIDC)是基于 OAuth 2.0 的身份认证协议 | set_refresh_token_header | boolean | 否 | false | | 当设置为 `true` 并且刷新令牌可用时,则会将该属性设置在`X-Refresh-Token`请求头中。 | | session | object | 否 | | | 当设置 bearer_only 为 false 时,openid-connect 插件将使用 Authorization Code 在 IDP 上进行认证,因此你必须设置 session 相关设置。 | | session.secret | string | 是 | 自动生成 | 16 个以上字符 | 用于 session 加密和 HMAC 计算的密钥。 | +| session.cookie | object | False | | | | +| session.cookie.lifetime | integer | False | 3600 | | 用于设置 cookie 的生命周期,以秒为单位。默认设置为 3600 秒。这可以通过 Nginx `set $session_cookie_lifetime 3600` 来配置。在默认情况下不会影响会话 cookie 的过期时间,但如果通过 session.cookie.persistent == true 配置了持久化的 cookie,则会使用该值。另请参阅有关 ssl_session_timeout 的说明。 | | unauth_action | string | False | "auth" | ["auth","deny","pass"] | 指定未经身份验证的请求的响应类型。 `auth` 重定向到身份提供者,`deny` 导致 401 响应,`pass` 将允许请求而无需身份验证。 | | proxy_opts | object | 否 | | | OpenID 服务器前面的 HTTP 代理服务器。 | | proxy_opts | object | 否 | | | 用来访问身份认证服务器的代理服务器。 | diff --git a/docs/zh/latest/plugins/ua-restriction.md b/docs/zh/latest/plugins/ua-restriction.md index e65a55a890fa..eedcd015ae1c 100644 --- a/docs/zh/latest/plugins/ua-restriction.md +++ b/docs/zh/latest/plugins/ua-restriction.md @@ -38,7 +38,7 @@ description: 本文介绍了 Apache APISIX ua-restriction 插件的使用方法 | --------- | ------------- | ------ | ------ | ------ | -------------------------------- | | allowlist | array[string] | 否 | | | 加入白名单的 `User-Agent`。 | | denylist | array[string] | 否 | | | 加入黑名单的 `User-Agent`。 | -| message | string | 否 | "Not allowed" | [1, 1024] | 当未允许的 `User-Agent` 访问时返回的信息。 | +| message | string | 否 | "Not allowed" | | 当未允许的 `User-Agent` 访问时返回的信息。 | | bypass_missing | boolean | 否 | false | | 当设置为 `true` 时,如果 `User-Agent` 请求头不存在或格式有误时,将绕过检查。 | :::note @@ -64,33 +64,16 @@ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13 "plugins": { "ua-restriction": { "bypass_missing": true, - "allowlist": [ - "my-bot1", - "(Baiduspider)/(\\d+)\\.(\\d+)" - ], "denylist": [ "my-bot2", "(Twitterspider)/(\\d+)\\.(\\d+)" - ] + ], + "message": "Do you want to do something bad?" } } }' ``` -当未允许的 `User-Agent` 访问时,默认返回 `{"message":"Not allowed"}`。如果你想使用自定义的 `message`,可以在 `plugins` 部分进行配置: - -```json -"plugins": { - "ua-restriction": { - "denylist": [ - "my-bot2", - "(Twitterspider)/(\\d+)\\.(\\d+)" - ], - "message": "Do you want to do something bad?" - } -} -``` - ## 测试插件 通过上述命令启用插件后,你可以先发起一个简单的请求测试: @@ -99,12 +82,7 @@ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13 curl http://127.0.0.1:9080/index.html -i ``` -返回的 HTTP 响应头中带有 `200` 状态码,代表请求成功: - -```shell -HTTP/1.1 200 OK -... -``` +你应当收到 `HTTP/1.1 200 OK` 的响应,表示请求成功。 接下来,请求的同时指定处于 `denylist` 中的 `User-Agent`,如 `Twitterspider/2.0`: @@ -112,12 +90,10 @@ HTTP/1.1 200 OK curl http://127.0.0.1:9080/index.html --header 'User-Agent: Twitterspider/2.0' ``` -返回的 HTTP 响应头中带有 `403` 状态码,请求失败,代表插件生效: +你应当收到 `HTTP/1.1 403 Forbidden` 的响应和以下报错,表示请求失败,代表插件生效: -```shell -HTTP/1.1 403 Forbidden -... -{"message":"Not allowed"} +```text +{"message":"Do you want to do something bad?"} ``` ## 删除插件 diff --git a/docs/zh/latest/plugins/workflow.md b/docs/zh/latest/plugins/workflow.md index 0c7228a9e904..51ed1b32a7ba 100644 --- a/docs/zh/latest/plugins/workflow.md +++ b/docs/zh/latest/plugins/workflow.md @@ -126,17 +126,17 @@ HTTP/1.1 403 Forbidden **示例 2: 如果请求的 uri 是 `/hello/v2/appid`,则执行 `limit-count` 插件,限制请求的数量为 2,时间窗口为 60 秒,如果超过限制数量,则返回给客户端状态码 `429`** ```shell -curl http://127.0.0.1:0080/hello/v2/appid -i +curl http://127.0.0.1:9080/hello/v2/appid -i HTTP/1.1 200 OK ``` ```shell -curl http://127.0.0.1:0080/hello/v2/appid -i +curl http://127.0.0.1:9080/hello/v2/appid -i HTTP/1.1 200 OK ``` ```shell -curl http://127.0.0.1:0080/hello/v2/appid -i +curl http://127.0.0.1:9080/hello/v2/appid -i HTTP/1.1 429 Too Many Requests ``` diff --git a/docs/zh/latest/tutorials/client-to-apisix-mtls.md b/docs/zh/latest/tutorials/client-to-apisix-mtls.md index 0999ab65a3db..7d018089e0ef 100644 --- a/docs/zh/latest/tutorials/client-to-apisix-mtls.md +++ b/docs/zh/latest/tutorials/client-to-apisix-mtls.md @@ -233,7 +233,7 @@ curl http://127.0.0.1:9180/apisix/admin/ssls/1 \ ] } }' - +``` 2. 如果没提供客户端证书,而 URI 又不在白名单内,会得到 HTTP 400 响应。 @@ -296,7 +296,7 @@ curl https://admin.apisix.dev:9443/uuid -v \

Powered by APISIX.

* Connection #0 to host admin.apisix.dev left intact - +``` 3. 虽然没提供客户端证书,但是 URI 在白名单内,请求会被成功处理和响应。 diff --git a/t/APISIX.pm b/t/APISIX.pm index 9a98176c36ec..be640c2bc98a 100644 --- a/t/APISIX.pm +++ b/t/APISIX.pm @@ -726,7 +726,8 @@ _EOC_ $config .= <<_EOC_; $ipv6_listen_conf - listen 1994 ssl http2; + listen 1994 ssl; + http2 on; ssl_certificate cert/apisix.crt; ssl_certificate_key cert/apisix.key; lua_ssl_trusted_certificate cert/apisix.crt; diff --git a/t/cli/test_main.sh b/t/cli/test_main.sh index 3b0cab766d59..1835ef5bbe27 100755 --- a/t/cli/test_main.sh +++ b/t/cli/test_main.sh @@ -152,7 +152,7 @@ if [ $count_http_specific_ip -ne 2 ]; then exit 1 fi -count_http_specific_ip_and_enable_http2=`grep -c "listen 127.0.0..:908. default_server http2" conf/nginx.conf || true` +count_http_specific_ip_and_enable_http2=`grep -c "http2 on" conf/nginx.conf || true` if [ $count_http_specific_ip_and_enable_http2 -ne 1 ]; then echo "failed: failed to support specific IP and enable http2 listen in http" exit 1 @@ -164,7 +164,7 @@ if [ $count_https_specific_ip -ne 2 ]; then exit 1 fi -count_https_specific_ip_and_enable_http2=`grep -c "listen 127.0.0..:944. ssl default_server http2" conf/nginx.conf || true` +count_https_specific_ip_and_enable_http2=`grep -c "http2 on" conf/nginx.conf || true` if [ $count_https_specific_ip_and_enable_http2 -ne 1 ]; then echo "failed: failed to support specific IP and enable http2 listen in https" exit 1 diff --git a/t/core/json.t b/t/core/json.t index 6966f914cf6e..a7caf8daedc8 100644 --- a/t/core/json.t +++ b/t/core/json.t @@ -132,12 +132,15 @@ qr/\{"b":\{"a":\{"b":"table: 0x[\w]+"\}\}\}/ local core = require("apisix.core") local data = core.json.decode('{"arr":[]}') ngx.say(core.json.encode(data)) + local data = { arr = setmetatable({}, core.json.array_mt)} + ngx.say(core.json.encode(data)) local data = core.json.decode('{"obj":{}}') ngx.say(core.json.encode(data)) } } --- response_body {"arr":[]} +{"arr":[]} {"obj":{}} diff --git a/t/discovery/consul2.t b/t/discovery/consul2.t new file mode 100644 index 000000000000..841ef5026e6d --- /dev/null +++ b/t/discovery/consul2.t @@ -0,0 +1,292 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +use t::APISIX 'no_plan'; + +repeat_each(1); +log_level('info'); +no_root_location(); +no_shuffle(); + + +add_block_preprocessor(sub { + my ($block) = @_; + + my $http_config = $block->http_config // <<_EOC_; + + server { + listen 20999; + + location / { + content_by_lua_block { + ngx.say("missing consul services") + } + } + } + + server { + listen 30511; + + location /hello { + content_by_lua_block { + ngx.say("server 1") + } + } + } + server { + listen 30512; + + location /hello { + content_by_lua_block { + ngx.say("server 2") + } + } + } + server { + listen 30513; + + location /hello { + content_by_lua_block { + ngx.say("server 3") + } + } + } + server { + listen 30514; + + location /hello { + content_by_lua_block { + ngx.say("server 4") + } + } + } +_EOC_ + + $block->set_value("http_config", $http_config); +}); + +our $yaml_config = <<_EOC_; +apisix: + node_listen: 1984 + enable_control: true + control: + ip: 127.0.0.1 + port: 9090 +deployment: + role: data_plane + role_data_plane: + config_provider: yaml +discovery: + consul: + servers: + - "http://127.0.0.1:8500" + - "http://127.0.0.1:8600" + skip_services: + - "service_c" + timeout: + connect: 1000 + read: 1000 + wait: 60 + weight: 1 + fetch_interval: 1 + keepalive: true + default_service: + host: "127.0.0.1" + port: 20999 + metadata: + fail_timeout: 1 + weight: 1 + max_fails: 1 +_EOC_ + + +run_tests(); + +__DATA__ + +=== TEST 1: sanity +--- config +location /consul1 { + rewrite ^/consul1/(.*) /v1/agent/service/$1 break; + proxy_pass http://127.0.0.1:9500; +} + +location /consul2 { + rewrite ^/consul2/(.*) /v1/agent/service/$1 break; + proxy_pass http://127.0.0.1:9501; +} +location /consul3 { + rewrite ^/consul3/(.*) /v1/agent/service/$1 break; + proxy_pass http://127.0.0.1:9502; +} +--- pipelined_requests eval +[ + "PUT /consul1/deregister/service_a1", + "PUT /consul1/deregister/service_b1", + "PUT /consul1/deregister/service_a2", + "PUT /consul1/deregister/service_b2", + "PUT /consul1/deregister/service_a3", + "PUT /consul1/deregister/service_a4", + "PUT /consul2/deregister/service_a1", + "PUT /consul2/deregister/service_a2", + "PUT /consul3/deregister/service_a1", + "PUT /consul3/deregister/service_a2", + "PUT /consul1/register\n" . "{\"ID\":\"service_a1\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30511,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul1/register\n" . "{\"ID\":\"service_a2\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30512,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul1/register\n" . "{\"ID\":\"service_a3\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"localhost\",\"Port\":30511,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul1/register\n" . "{\"ID\":\"service_a4\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"localhost\",\"Port\":30512,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul2/register\n" . "{\"ID\":\"service_a1\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30511,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul2/register\n" . "{\"ID\":\"service_a2\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30512,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul3/register\n" . "{\"ID\":\"service_a1\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30511,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul3/register\n" . "{\"ID\":\"service_a2\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30512,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", +] +--- error_code eval +[200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200] + + + +=== TEST 2: show dump services without duplicates +--- yaml_config +apisix: + node_listen: 1984 + enable_control: true +discovery: + consul: + servers: + - "http://127.0.0.1:9500" + dump: + path: "consul.dump" + load_on_init: false +--- config + location /t { + content_by_lua_block { + local json = require("toolkit.json") + local t = require("lib.test_admin") + ngx.sleep(2) + + local code, body, res = t.test('/v1/discovery/consul/show_dump_file', + ngx.HTTP_GET) + local entity = json.decode(res) + ngx.say(json.encode(entity.services)) + } + } +--- timeout: 3 +--- request +GET /t +--- response_body +{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"localhost","port":30512,"weight":1}]} + + + +=== TEST 3: show dump services with host_sort +--- yaml_config +apisix: + node_listen: 1984 + enable_control: true +discovery: + consul: + servers: + - "http://127.0.0.1:9500" + sort_type: host_sort + dump: + path: "consul.dump" + load_on_init: false +--- config + location /t { + content_by_lua_block { + local json = require("toolkit.json") + local t = require("lib.test_admin") + ngx.sleep(2) + + local code, body, res = t.test('/v1/discovery/consul/show_dump_file', + ngx.HTTP_GET) + local entity = json.decode(res) + ngx.say(json.encode(entity.services)) + } + } +--- timeout: 3 +--- request +GET /t +--- response_body +{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"localhost","port":30512,"weight":1}]} + + + +=== TEST 4: show dump services with port sort +--- yaml_config +apisix: + node_listen: 1984 + enable_control: true +discovery: + consul: + servers: + - "http://127.0.0.1:9500" + sort_type: port_sort + dump: + path: "consul.dump" + load_on_init: false +--- config + location /t { + content_by_lua_block { + local json = require("toolkit.json") + local t = require("lib.test_admin") + ngx.sleep(2) + + local code, body, res = t.test('/v1/discovery/consul/show_dump_file', + ngx.HTTP_GET) + local entity = json.decode(res) + ngx.say(json.encode(entity.services)) + } + } +--- timeout: 3 +--- request +GET /t +--- response_body +{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30512,"weight":1}]} + + + +=== TEST 5: show dump services with combine sort +--- yaml_config +apisix: + node_listen: 1984 + enable_control: true +discovery: + consul: + servers: + - "http://127.0.0.1:9500" + sort_type: combine_sort + dump: + path: "consul.dump" + load_on_init: false +--- config + location /t { + content_by_lua_block { + local json = require("toolkit.json") + local t = require("lib.test_admin") + ngx.sleep(2) + + local code, body, res = t.test('/v1/discovery/consul/show_dump_file', + ngx.HTTP_GET) + local entity = json.decode(res) + ngx.say(json.encode(entity.services)) + } + } +--- timeout: 3 +--- request +GET /t +--- response_body +{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"localhost","port":30512,"weight":1}]} diff --git a/t/plugin/azure-functions.t b/t/plugin/azure-functions.t index 2ab2f91178cb..72f9bbc6b2f7 100644 --- a/t/plugin/azure-functions.t +++ b/t/plugin/azure-functions.t @@ -189,6 +189,8 @@ X-Extra-Header: MUST --- http2 --- request GET /azure +--- more_headers +Content-Length: 0 --- response_body faas invoked @@ -208,6 +210,8 @@ server: APISIX/2.10.2 --- http2 --- request HEAD /azure +--- more_headers +Content-Length: 0 --- response_headers Connection: Upgrade: @@ -456,3 +460,51 @@ invocation /api/http/trigger successful } --- response_body invocation /api successful + + + +=== TEST 14: create route with azure-function plugin enabled +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "azure-functions": { + "function_uri": "http://localhost:8765/httptrigger" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1982": 1 + }, + "type": "roundrobin" + }, + "uri": "/azure" + }]] + ) + + if code >= 300 then + ngx.status = code + ngx.say("fail") + return + end + + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 15: http2 failed to check response body and headers +--- http2 +--- request +GET /azure +--- error_code: 400 +--- error_log +HTTP2/HTTP3 request without a Content-Length header, diff --git a/t/plugin/cors3.t b/t/plugin/cors3.t index ae68dec3f549..94e861091575 100644 --- a/t/plugin/cors3.t +++ b/t/plugin/cors3.t @@ -351,3 +351,72 @@ Access-Control-Allow-Headers: * Access-Control-Expose-Headers: * Access-Control-Max-Age: 5 Access-Control-Allow-Credentials: + + + +=== TEST 13: set route (allow_origins_by_metadata specified and allow_origins * is invalid while set allow_origins_by_metadata) +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "cors": { + "allow_origins": "*", + "allow_origins_by_metadata": ["key_1"] + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 14: origin not match because allow_origins * invalid +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: http://foo.example.org +--- response_body +hello world +--- response_headers +Access-Control-Allow-Origin: +Access-Control-Allow-Methods: +Access-Control-Allow-Headers: +Access-Control-Expose-Headers: +Access-Control-Max-Age: +Access-Control-Allow-Credentials: + + + +=== TEST 15: origin matches with first allow_origins_by_metadata +--- request +GET /hello HTTP/1.1 +--- more_headers +Origin: https://domain.com +--- response_body +hello world +--- response_headers +Access-Control-Allow-Origin: https://domain.com +Access-Control-Allow-Methods: * +Access-Control-Allow-Headers: * +Access-Control-Expose-Headers: * +Access-Control-Max-Age: 5 +Access-Control-Allow-Credentials: diff --git a/t/plugin/openid-connect6.t b/t/plugin/openid-connect6.t new file mode 100644 index 000000000000..6497f3baa67f --- /dev/null +++ b/t/plugin/openid-connect6.t @@ -0,0 +1,157 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +use t::APISIX 'no_plan'; + +log_level('debug'); +repeat_each(1); +no_long_string(); +no_root_location(); +# no_shuffle(); + +add_block_preprocessor(sub { + my ($block) = @_; + + if ((!defined $block->error_log) && (!defined $block->no_error_log)) { + $block->set_value("no_error_log", "[error]"); + } + + if (!defined $block->request) { + $block->set_value("request", "GET /t"); + } +}); + +run_tests(); + +__DATA__ + +=== TEST 1: Check configuration of cookie +--- config + location /t { + content_by_lua_block { + local test_cases = { + { + client_id = "course_management", + client_secret = "tbsmDOpsHwdgIqYl2NltGRTKzjIzvEmT", + discovery = "http://127.0.0.1:8080/realms/University/.well-known/openid-configuration", + session = { + secret = "6S8IO+Pydgb33LIor8T9ClER0T/sglFAjClFeAF3RsY=", + cookie = { + lifetime = 86400 + } + } + }, + } + local plugin = require("apisix.plugins.openid-connect") + for _, case in ipairs(test_cases) do + local ok, err = plugin.check_schema(case) + ngx.say(ok and "done" or err) + end + } + } +--- response_body +done + + + +=== TEST 2: Set up new route access the auth server +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "openid-connect": { + "discovery": "http://127.0.0.1:8080/realms/University/.well-known/openid-configuration", + "realm": "University", + "client_id": "course_management", + "client_secret": "d1ec69e9-55d2-4109-a3ea-befa071579d5", + "redirect_uri": "http://127.0.0.1:]] .. ngx.var.server_port .. [[/authenticated", + "ssl_verify": false, + "bearer_only" : false, + "timeout": 10, + "introspection_endpoint_auth_method": "client_secret_post", + "required_scopes": ["profile"], + "introspection_endpoint_auth_method": "client_secret_post", + "introspection_endpoint": "http://127.0.0.1:8080/realms/University/protocol/openid-connect/token/introspect", + "set_access_token_header": true, + "access_token_in_authorization_header": false, + "set_id_token_header": true, + "set_userinfo_header": true, + "set_refresh_token_header": true, + "session": { + "secret": "jwcE5v3pM9VhqLxmxFOH9uZaLo8u7KQK", + "cookie": { + "lifetime": 86400 + } + } + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/*" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- response_body +passed + + + +=== TEST 3: Call to route to get session +--- config + location /t { + content_by_lua_block { + local http = require "resty.http" + local login_keycloak = require("lib.keycloak").login_keycloak + local concatenate_cookies = require("lib.keycloak").concatenate_cookies + + local current_time = os.time() + local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello" + + local res, err = login_keycloak(uri, "teacher@gmail.com", "123456") + if err then + ngx.status = 500 + ngx.say(err) + return + end + + local cookie_str = concatenate_cookies(res.headers['Set-Cookie']) + local parts = {} + for part in string.gmatch(cookie_str, "[^|]+") do + table.insert(parts, part) + end + local target_number = tonumber(parts[2], 10) - 86400 + -- ngx.say(target_number, current_time) + if target_number >= current_time then + ngx.say("passed") + end + } + } +--- response_body +passed diff --git a/t/plugin/proxy-rewrite2.t b/t/plugin/proxy-rewrite2.t index a519968ba7d1..7096e4aad249 100644 --- a/t/plugin/proxy-rewrite2.t +++ b/t/plugin/proxy-rewrite2.t @@ -202,7 +202,7 @@ GET /echo X-Forwarded-Proto: http X-Forwarded-Proto: grpc --- response_headers -X-Forwarded-Proto: http +X-Forwarded-Proto: http, grpc