diff --git a/Makefile b/Makefile index fa8b972df8bd..9650979071ca 100644 --- a/Makefile +++ b/Makefile @@ -247,7 +247,6 @@ install: runtime $(ENV_INSTALL) -d /usr/local/apisix/conf/cert $(ENV_INSTALL) conf/mime.types /usr/local/apisix/conf/mime.types $(ENV_INSTALL) conf/config.yaml /usr/local/apisix/conf/config.yaml - $(ENV_INSTALL) conf/config-default.yaml /usr/local/apisix/conf/config-default.yaml $(ENV_INSTALL) conf/debug.yaml /usr/local/apisix/conf/debug.yaml $(ENV_INSTALL) conf/cert/* /usr/local/apisix/conf/cert/ diff --git a/README.md b/README.md index 62e8bc3aa9c4..4cb9180e2034 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The technical architecture of Apache APISIX: ## Community -- [Kindly Write a Review](https://www.g2.com/products/apache-apisix/reviews) +- [Kindly Write a Review](https://www.g2.com/products/apache-apisix/reviews) for APISIX in G2. - Mailing List: Mail to dev-subscribe@apisix.apache.org, follow the reply to subscribe to the mailing list. - Slack Workspace - [invitation link](https://apisix.apache.org/slack) (Please open an [issue](https://apisix.apache.org/docs/general/submit-issue) if this link is expired), and then join the #apisix channel (Channels -> Browse channels -> search for "apisix"). - ![Twitter Follow](https://img.shields.io/twitter/follow/ApacheAPISIX?style=social) - follow and interact with us using hashtag `#ApacheAPISIX` @@ -71,7 +71,8 @@ A/B testing, canary release, blue-green deployment, limit rate, defense against - Proxy Websocket - Proxy Protocol - HTTP(S) Forward Proxy - - [SSL](docs/en/latest/certificate.md): Dynamically load an SSL certificate. + - [SSL](docs/en/latest/certificate.md): Dynamically load an SSL certificate + - [HTTP/3 with QUIC](docs/en/latest/http3.md) - **Full Dynamic** @@ -134,7 +135,7 @@ A/B testing, canary release, blue-green deployment, limit rate, defense against - [Global Rule](docs/en/latest/terminology/global-rule.md): Allows to run any plugin for all request, eg: limit rate, IP filter etc. - High performance: The single-core QPS reaches 18k with an average delay of fewer than 0.2 milliseconds. - [Fault Injection](docs/en/latest/plugins/fault-injection.md) - - [REST Admin API](docs/en/latest/admin-api.md): Using the REST Admin API to control Apache APISIX, which only allows 127.0.0.1 access by default, you can modify the `allow_admin` field in `conf/config.yaml` to specify a list of IPs that are allowed to call the Admin API. Also, note that the Admin API uses key auth to verify the identity of the caller. **The `admin_key` field in `conf/config.yaml` needs to be modified before deployment to ensure security**. + - [REST Admin API](docs/en/latest/admin-api.md): Using the REST Admin API to control Apache APISIX, which only allows 127.0.0.1 access by default, you can modify the `allow_admin` field in `conf/config.yaml` to specify a list of IPs that are allowed to call the Admin API. Also, note that the Admin API uses key auth to verify the identity of the caller. - External Loggers: Export access logs to external log management tools. ([HTTP Logger](docs/en/latest/plugins/http-logger.md), [TCP Logger](docs/en/latest/plugins/tcp-logger.md), [Kafka Logger](docs/en/latest/plugins/kafka-logger.md), [UDP Logger](docs/en/latest/plugins/udp-logger.md), [RocketMQ Logger](docs/en/latest/plugins/rocketmq-logger.md), [SkyWalking Logger](docs/en/latest/plugins/skywalking-logger.md), [Alibaba Cloud Logging(SLS)](docs/en/latest/plugins/sls-logger.md), [Google Cloud Logging](docs/en/latest/plugins/google-cloud-logging.md), [Splunk HEC Logging](docs/en/latest/plugins/splunk-hec-logging.md), [File Logger](docs/en/latest/plugins/file-logger.md), [SolarWinds Loggly Logging](docs/en/latest/plugins/loggly.md), [TencentCloud CLS](docs/en/latest/plugins/tencent-cloud-cls.md)). - [ClickHouse](docs/en/latest/plugins/clickhouse-logger.md): push logs to ClickHouse. - [Elasticsearch](docs/en/latest/plugins/elasticsearch-logger.md): push logs to Elasticsearch. @@ -192,12 +193,6 @@ Using AWS's eight-core server, APISIX's QPS reaches 140,000 with a latency of on [APISIX also works perfectly in AWS graviton3 C7g.](https://apisix.apache.org/blog/2022/06/07/installation-performance-test-of-apigateway-apisix-on-aws-graviton3) -## Contributor Over Time - -> [visit here](https://www.apiseven.com/contributor-graph) to generate Contributor Over Time. - -[![Contributor over time](https://contributor-graph-api.apiseven.com/contributors-svg?repo=apache/apisix)](https://www.apiseven.com/en/contributor-graph?repo=apache/apisix) - ## User Stories - [European eFactory Platform: API Security Gateway – Using APISIX in the eFactory Platform](https://www.efactory-project.eu/post/api-security-gateway-using-apisix-in-the-efactory-platform) @@ -232,15 +227,6 @@ A wide variety of companies and organizations use APISIX API Gateway for researc - XPENG - Zoom -## Landscape - -

-   -

-APISIX enriches the -CNCF API Gateway Landscape. -

- ## Logos - [Apache APISIX logo(PNG)](https://github.com/apache/apisix/tree/master/logos/apache-apisix.png) diff --git a/apisix/cli/config.lua b/apisix/cli/config.lua new file mode 100644 index 000000000000..94843621a74b --- /dev/null +++ b/apisix/cli/config.lua @@ -0,0 +1,364 @@ +-- +-- 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. +-- + +local table_conact = table.concat + +local _M = { + apisix = { + node_listen = { 9080 }, + enable_admin = true, + enable_dev_mode = false, + enable_reuseport = true, + show_upstream_status_in_response_header = false, + enable_ipv6 = true, + enable_http2 = true, + enable_server_tokens = true, + extra_lua_path = "", + extra_lua_cpath = "", + proxy_cache = { + cache_ttl = "10s", + zones = { + { + name = "disk_cache_one", + memory_size = "50m", + disk_size = "1G", + disk_path = "/tmp/disk_cache_one", + cache_levels = "1:2" + }, + { + name = "memory_cache", + memory_size = "50m" + } + } + }, + delete_uri_tail_slash = false, + normalize_uri_like_servlet = false, + router = { + http = "radixtree_host_uri", + ssl = "radixtree_sni" + }, + proxy_mode = "http", + resolver_timeout = 5, + enable_resolv_search_opt = true, + ssl = { + enable = true, + listen = { { + port = 9443, + enable_http3 = false + } }, + ssl_protocols = "TLSv1.2 TLSv1.3", + ssl_ciphers = table_conact({ + "ECDHE-ECDSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES256-GCM-SHA384", "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-CHACHA20-POLY1305", "ECDHE-RSA-CHACHA20-POLY1305", + "DHE-RSA-AES128-GCM-SHA256", "DHE-RSA-AES256-GCM-SHA384", + }, ":"), + ssl_session_tickets = false + }, + enable_control = true, + disable_sync_configuration_during_start = false, + data_encryption = { + enable_encrypt_fields = true, + keyring = { "qeddd145sfvddff3", "edd1c9f0985e76a2" } + }, + events = { + module = "lua-resty-events" + } + }, + nginx_config = { + error_log = "logs/error.log", + error_log_level = "warn", + worker_processes = "auto", + enable_cpu_affinity = false, + worker_rlimit_nofile = 20480, + worker_shutdown_timeout = "240s", + max_pending_timers = 16384, + max_running_timers = 4096, + event = { + worker_connections = 10620 + }, + meta = { + lua_shared_dict = { + ["prometheus-metrics"] = "15m" + } + }, + stream = { + enable_access_log = false, + access_log = "logs/access_stream.log", + -- luacheck: push max code line length 300 + access_log_format = "$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time", + -- luacheck: pop + access_log_format_escape = "default", + lua_shared_dict = { + ["etcd-cluster-health-check-stream"] = "10m", + ["lrucache-lock-stream"] = "10m", + ["plugin-limit-conn-stream"] = "10m", + ["worker-events-stream"] = "10m", + ["tars-stream"] = "1m" + } + }, + main_configuration_snippet = "", + http_configuration_snippet = "", + http_server_configuration_snippet = "", + http_server_location_configuration_snippet = "", + http_admin_configuration_snippet = "", + http_end_configuration_snippet = "", + stream_configuration_snippet = "", + http = { + enable_access_log = true, + access_log = "logs/access.log", + access_log_buffer = 16384, + -- luacheck: push max code line length 300 + access_log_format = + '$remote_addr - $remote_user [$time_local] $http_host "$request" $status $body_bytes_sent $request_time "$http_referer" "$http_user_agent" $upstream_addr $upstream_status $upstream_response_time "$upstream_scheme://$upstream_host$upstream_uri"', + -- luacheck: pop + access_log_format_escape = "default", + keepalive_timeout = "60s", + client_header_timeout = "60s", + client_body_timeout = "60s", + client_max_body_size = 0, + send_timeout = "10s", + underscores_in_headers = "on", + real_ip_header = "X-Real-IP", + real_ip_recursive = "off", + real_ip_from = { "127.0.0.1", "unix:" }, + proxy_ssl_server_name = true, + upstream = { + keepalive = 320, + keepalive_requests = 1000, + keepalive_timeout = "60s" + }, + charset = "utf-8", + variables_hash_max_size = 2048, + lua_shared_dict = { + ["internal-status"] = "10m", + ["plugin-limit-req"] = "10m", + ["plugin-limit-count"] = "10m", + ["prometheus-metrics"] = "10m", + ["plugin-limit-conn"] = "10m", + ["upstream-healthcheck"] = "10m", + ["worker-events"] = "10m", + ["lrucache-lock"] = "10m", + ["balancer-ewma"] = "10m", + ["balancer-ewma-locks"] = "10m", + ["balancer-ewma-last-touched-at"] = "10m", + ["plugin-limit-req-redis-cluster-slot-lock"] = "1m", + ["plugin-limit-count-redis-cluster-slot-lock"] = "1m", + ["plugin-limit-conn-redis-cluster-slot-lock"] = "1m", + tracing_buffer = "10m", + ["plugin-api-breaker"] = "10m", + ["etcd-cluster-health-check"] = "10m", + discovery = "1m", + jwks = "1m", + introspection = "10m", + ["access-tokens"] = "1m", + ["ext-plugin"] = "1m", + tars = "1m", + ["cas-auth"] = "10m", + ["ocsp-stapling"] = "10m" + } + } + }, + graphql = { + max_size = 1048576 + }, + plugins = { + "real-ip", + "ai", + "client-control", + "proxy-control", + "request-id", + "zipkin", + "ext-plugin-pre-req", + "fault-injection", + "mocking", + "serverless-pre-function", + "cors", + "ip-restriction", + "ua-restriction", + "referer-restriction", + "csrf", + "uri-blocker", + "request-validation", + "chaitin-waf", + "multi-auth", + "openid-connect", + "cas-auth", + "authz-casbin", + "authz-casdoor", + "wolf-rbac", + "ldap-auth", + "hmac-auth", + "basic-auth", + "jwt-auth", + "jwe-decrypt", + "key-auth", + "consumer-restriction", + "forward-auth", + "opa", + "authz-keycloak", + "proxy-cache", + "body-transformer", + "proxy-mirror", + "proxy-rewrite", + "workflow", + "api-breaker", + "limit-conn", + "limit-count", + "limit-req", + "gzip", + "server-info", + "traffic-split", + "redirect", + "response-rewrite", + "degraphql", + "kafka-proxy", + "grpc-transcode", + "grpc-web", + "http-dubbo", + "public-api", + "prometheus", + "datadog", + "loki-logger", + "elasticsearch-logger", + "echo", + "loggly", + "http-logger", + "splunk-hec-logging", + "skywalking-logger", + "google-cloud-logging", + "sls-logger", + "tcp-logger", + "kafka-logger", + "rocketmq-logger", + "syslog", + "udp-logger", + "file-logger", + "clickhouse-logger", + "tencent-cloud-cls", + "inspect", + "example-plugin", + "aws-lambda", + "azure-functions", + "openwhisk", + "openfunction", + "serverless-post-function", + "ext-plugin-post-req", + "ext-plugin-post-resp", + }, + stream_plugins = { "ip-restriction", "limit-conn", "mqtt-proxy", "syslog" }, + plugin_attr = { + ["log-rotate"] = { + timeout = 10000, + interval = 3600, + max_kept = 168, + max_size = -1, + enable_compression = false + }, + skywalking = { + service_name = "APISIX", + service_instance_name = "APISIX Instance Name", + endpoint_addr = "http://127.0.0.1:12800", + report_interval = 3 + }, + opentelemetry = { + trace_id_source = "x-request-id", + resource = { + ["service.name"] = "APISIX" + }, + collector = { + address = "127.0.0.1:4318", + request_timeout = 3, + request_headers = { + Authorization = "token" + } + }, + batch_span_processor = { + drop_on_queue_full = false, + max_queue_size = 1024, + batch_timeout = 2, + inactive_timeout = 1, + max_export_batch_size = tonumber(os.getenv("OTEL_BSP_MAX_EXPORT_BATCH_SIZE")) or 16 + }, + set_ngx_var = false + }, + prometheus = { + export_uri = "/apisix/prometheus/metrics", + metric_prefix = "apisix_", + enable_export_server = true, + export_addr = { + ip = "127.0.0.1", + port = 9091 + } + }, + ["server-info"] = { + report_ttl = 60 + }, + ["dubbo-proxy"] = { + upstream_multiplex_count = 32 + }, + ["proxy-mirror"] = { + timeout = { + connect = "60s", + read = "60s", + send = "60s" + } + }, + inspect = { + delay = 3, + hooks_file = "/usr/local/apisix/plugin_inspect_hooks.lua" + }, + zipkin = { + set_ngx_var = false + } + }, + deployment = { + role = "traditional", + role_traditional = { + config_provider = "etcd" + }, + admin = { + admin_key_required = true, + admin_key = { + { + name = "admin", + key = "", + role = "admin" + } + }, + enable_admin_cors = true, + allow_admin = { "127.0.0.0/24" }, + admin_listen = { + ip = "0.0.0.0", + port = 9180 + }, + admin_api_version = "v3" + }, + etcd = { + host = { "http://127.0.0.1:2379" }, + prefix = "/apisix", + timeout = 30, + watch_timeout = 50, + startup_retry = 2, + tls = { + verify = true + } + } + } +} + +return _M diff --git a/apisix/cli/file.lua b/apisix/cli/file.lua index c01736d16180..86cdd7b8566b 100644 --- a/apisix/cli/file.lua +++ b/apisix/cli/file.lua @@ -18,6 +18,7 @@ local yaml = require("lyaml") local profile = require("apisix.core.profile") local util = require("apisix.cli.util") +local default_conf = require("apisix.cli.config") local dkjson = require("dkjson") local pairs = pairs @@ -228,18 +229,7 @@ function _M.read_yaml_conf(apisix_home) profile.apisix_home = apisix_home .. "/" end - local local_conf_path = profile:yaml_path("config-default") - local default_conf_yaml, err = util.read_file(local_conf_path) - if not default_conf_yaml then - return nil, err - end - - local default_conf = yaml.load(default_conf_yaml) - if not default_conf then - return nil, "invalid config-default.yaml file" - end - - local_conf_path = profile:customized_yaml_path() + local local_conf_path = profile:customized_yaml_path() if not local_conf_path then local_conf_path = profile:yaml_path("config") end diff --git a/conf/config-default.yaml b/conf/config.yaml.example old mode 100755 new mode 100644 similarity index 99% rename from conf/config-default.yaml rename to conf/config.yaml.example index 225f41dbb116..5a490a4bb4b3 --- a/conf/config-default.yaml +++ b/conf/config.yaml.example @@ -647,10 +647,10 @@ deployment: # Deployment configurations name: admin # admin: write access to configurations. key: '' # Set API key for the admin of Admin API. role: admin - - - name: viewer # viewer: read-only to configurations. - key: 4054f7cf07e344346cd3f287985e76a2 # Set API key for the viewer of Admin API. - role: viewer + # - + # name: viewer # viewer: read-only to configurations. + # key: 4054f7cf07e344346cd3f287985e76a2 # Set API key for the viewer of Admin API. + # role: viewer enable_admin_cors: true # Enable Admin API CORS response header `Access-Control-Allow-Origin`. allow_admin: # Limit Admin API access by IP addresses. diff --git a/docs/en/latest/deployment-modes.md b/docs/en/latest/deployment-modes.md index 90ae0cded0ea..016473db2131 100644 --- a/docs/en/latest/deployment-modes.md +++ b/docs/en/latest/deployment-modes.md @@ -267,6 +267,26 @@ plugins: #END ``` +### How to configure Plugin Configs + +```yml +plugin_configs: + - + id: 1 + plugins: + response-rewrite: + body: "hello\n" +routes: + - id: 1 + uri: /hello + plugin_config_id: 1 + upstream: + nodes: + "127.0.0.1:1980": 1 + type: roundrobin +#END +``` + ### How to enable SSL ```yml diff --git a/t/APISIX.pm b/t/APISIX.pm index 698326b4a8b2..50f7cfaecab6 100644 --- a/t/APISIX.pm +++ b/t/APISIX.pm @@ -79,11 +79,14 @@ if ($custom_dns_server) { my $events_module = $ENV{TEST_EVENTS_MODULE} // "lua-resty-events"; -my $default_yaml_config = read_file("conf/config-default.yaml"); -# enable example-plugin as some tests require it -$default_yaml_config =~ s/#- example-plugin/- example-plugin/; -$default_yaml_config =~ s/enable_export_server: true/enable_export_server: false/; -$default_yaml_config =~ s/module: lua-resty-events/module: $events_module/; +my $test_default_config = <<_EOC_; + -- read the default configuration, modify it, and the Lua package + -- cache will persist it for loading by other entrypoints + -- it is used to replace the test::nginx implementation + local default_config = require("apisix.cli.config") + default_config.plugin_attr.prometheus.enable_export_server = false + default_config.apisix.events.module = "$events_module" +_EOC_ my $user_yaml_config = read_file("conf/config.yaml"); my $ssl_crt = read_file("t/certs/apisix.crt"); @@ -429,6 +432,7 @@ _EOC_ $stream_config .= <<_EOC_; init_by_lua_block { + $test_default_config $stream_init_by_lua_block $stream_extra_init_by_lua } @@ -621,6 +625,7 @@ _EOC_ $dubbo_upstream init_by_lua_block { + $test_default_config $init_by_lua_block } @@ -912,8 +917,6 @@ _EOC_ $user_files .= <<_EOC_; >>> ../conf/$debug_file $user_debug_config ->>> ../conf/config-default.yaml -$default_yaml_config >>> ../conf/$config_file $yaml_config >>> ../conf/cert/apisix.crt diff --git a/t/admin/plugins-reload.t b/t/admin/plugins-reload.t index df891279d36b..336723146ce6 100644 --- a/t/admin/plugins-reload.t +++ b/t/admin/plugins-reload.t @@ -45,7 +45,7 @@ location /t { ngx.status = code ngx.say(org_body) - ngx.sleep(0.2) + ngx.sleep(1) } } --- request @@ -70,7 +70,7 @@ location /t { content_by_lua_block { local core = require "apisix.core" local config_util = require("apisix.core.config_util") - ngx.sleep(0.5) -- make sure the sync happened when admin starts is already finished + ngx.sleep(1) -- make sure the sync happened when admin starts is already finished local before_reload = true local plugins_conf, err @@ -88,7 +88,7 @@ location /t { error("failed to create etcd instance for fetching /plugins : " .. err) end - ngx.sleep(0.5) + ngx.sleep(1) local data = [[ deployment: diff --git a/t/cli/test_validate_config.sh b/t/cli/test_validate_config.sh index 0379b986c5b2..0f8a09a43c2d 100755 --- a/t/cli/test_validate_config.sh +++ b/t/cli/test_validate_config.sh @@ -99,26 +99,6 @@ make stop echo "passed: allow configuring address in stream_proxy" -sed -i 's/^ \(node_listen:\)/ #\1/g' conf/config-default.yaml -sed -i 's/^ \(- 9080\)/ #\1/g' conf/config-default.yaml -sed -i 's/^ # \(node_listen: 9080\)/ \1/g' conf/config-default.yaml - -echo ' -apisix: - node_listen: - - 9080 - - 9081 -' > conf/config.yaml - -out=$(make init 2>&1 || true) -if ! echo "$out"; then - echo "failed: allow configuring node_listen as a number in the default config" - exit 1 -fi -git checkout conf/config-default.yaml - -echo "passed: allow configuring node_listen as a number in the default config" - # apisix test git checkout conf/config.yaml diff --git a/t/core/etcd-mtls.t b/t/core/etcd-mtls.t index 3300aae42639..3ff25715f2ec 100644 --- a/t/core/etcd-mtls.t +++ b/t/core/etcd-mtls.t @@ -82,12 +82,8 @@ deployment: } --- request GET /t ---- grep_error_log eval -qr/init_by_lua:\d+: \S+/ ---- grep_error_log_out -init_by_lua:12: ab -init_by_lua:19: 200 -init_by_lua:26: 404 +--- error_log eval +qr/init_by_lua:\d+: ab/ and qr/init_by_lua:\d+: 200/ and qr/init_by_lua:\d+: 404/ @@ -136,12 +132,8 @@ deployment: ngx.say("ok") } --- stream_enable ---- grep_error_log eval -qr/init_by_lua:\d+: \S+/ ---- grep_error_log_out -init_by_lua:12: ab -init_by_lua:19: 200 -init_by_lua:26: 404 +--- error_log eval +qr/init_by_lua:\d+: ab/ and qr/init_by_lua:\d+: 200/ and qr/init_by_lua:\d+: 404/ @@ -286,5 +278,5 @@ deployment: } --- request GET /t ---- error_log -init_by_lua:11: ab +--- error_log eval +qr/init_by_lua:\d+: ab/ diff --git a/utils/check-lua-code-style.sh b/utils/check-lua-code-style.sh index 59fe473e4250..5296e75812b9 100755 --- a/utils/check-lua-code-style.sh +++ b/utils/check-lua-code-style.sh @@ -21,7 +21,7 @@ set -ex luacheck -q apisix t/lib -find apisix -name '*.lua' ! -wholename 'apisix/cli/ngx_tpl.lua' -exec ./utils/lj-releng {} + > \ +find apisix -name '*.lua' ! -wholename 'apisix/cli/ngx_tpl.lua' ! -wholename 'apisix/cli/config.lua' -exec ./utils/lj-releng {} + > \ /tmp/check.log 2>&1 || (cat /tmp/check.log && exit 1) grep -E "ERROR.*.lua:" /tmp/check.log > /tmp/error.log || true