This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 089e8a218 feat(deployment): support connecting to etcd via https
(#7269)
089e8a218 is described below
commit 089e8a2181cb9872e1be239cafdb60b4f930e347
Author: 罗泽轩 <[email protected]>
AuthorDate: Mon Jun 20 14:24:17 2022 +0800
feat(deployment): support connecting to etcd via https (#7269)
---
.github/workflows/build.yml | 2 +-
.github/workflows/centos7-ci.yml | 2 +-
apisix/cli/file.lua | 8 ---
apisix/cli/ngx_tpl.lua | 2 +-
apisix/cli/ops.lua | 5 +-
apisix/cli/schema.lua | 5 +-
apisix/cli/snippet.lua | 42 ++++++++++-----
apisix/core/etcd.lua | 42 +++++++++++----
t/bin/gen_snippet.lua | 51 ++++++++++++++++++
t/cli/test_deployment_traditional.sh | 20 +++++++
t/deployment/conf_server.t | 100 +++++++++++++++++++++++++++++++++++
11 files changed, 243 insertions(+), 36 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index bd199672e..6834d8651 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -31,7 +31,7 @@ jobs:
- linux_openresty_1_17
test_dir:
- t/plugin
- - t/admin t/cli t/config-center-yaml t/control t/core t/debug
t/discovery t/error_page t/misc
+ - t/admin t/cli t/config-center-yaml t/control t/core t/debug
t/deployment t/discovery t/error_page t/misc
- t/node t/pubsub t/router t/script t/stream-node t/utils t/wasm
t/xds-library t/xrpc
runs-on: ${{ matrix.platform }}
diff --git a/.github/workflows/centos7-ci.yml b/.github/workflows/centos7-ci.yml
index 9b2f8fc81..589e5ed69 100644
--- a/.github/workflows/centos7-ci.yml
+++ b/.github/workflows/centos7-ci.yml
@@ -29,7 +29,7 @@ jobs:
matrix:
test_dir:
- t/plugin
- - t/admin t/cli t/config-center-yaml t/control t/core t/debug
t/discovery t/error_page t/misc
+ - t/admin t/cli t/config-center-yaml t/control t/core t/debug
t/deployment t/discovery t/error_page t/misc
- t/node t/pubsub t/router t/script t/stream-node t/utils t/wasm
t/xds-library
steps:
diff --git a/apisix/cli/file.lua b/apisix/cli/file.lua
index 5bd64a682..66600b54b 100644
--- a/apisix/cli/file.lua
+++ b/apisix/cli/file.lua
@@ -237,14 +237,6 @@ function _M.read_yaml_conf(apisix_home)
end
end
- if default_conf.deployment
- and default_conf.deployment.role == "traditional"
- and default_conf.deployment.etcd
- then
- default_conf.etcd = default_conf.deployment.etcd
- default_conf.etcd.unix_socket_proxy = "unix:./conf/config_listen.sock"
- end
-
if default_conf.apisix.config_center == "yaml" then
local apisix_conf_path = profile:yaml_path("apisix")
local apisix_conf_yaml, _ = util.read_file(apisix_conf_path)
diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua
index 161c530b8..f22280766 100644
--- a/apisix/cli/ngx_tpl.lua
+++ b/apisix/cli/ngx_tpl.lua
@@ -64,7 +64,7 @@ lua {
{% end %}
}
-{% if (enabled_stream_plugins["prometheus"] or conf_server) and not
enable_http then %}
+{% if enabled_stream_plugins["prometheus"] and not enable_http then %}
http {
{% if enabled_stream_plugins["prometheus"] then %}
init_worker_by_lua_block {
diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua
index 3e933ddd3..9a275648e 100644
--- a/apisix/cli/ops.lua
+++ b/apisix/cli/ops.lua
@@ -540,7 +540,10 @@ Please modify "admin_key" in conf/config.yaml .
proxy_mirror_timeouts = yaml_conf.plugin_attr["proxy-mirror"].timeout
end
- local conf_server = snippet.generate_conf_server(yaml_conf)
+ local conf_server, err = snippet.generate_conf_server(env, yaml_conf)
+ if err then
+ util.die(err, "\n")
+ end
-- Using template.render
local sys_conf = {
diff --git a/apisix/cli/schema.lua b/apisix/cli/schema.lua
index ab053a0a7..db4f47477 100644
--- a/apisix/cli/schema.lua
+++ b/apisix/cli/schema.lua
@@ -43,7 +43,7 @@ local etcd_schema = {
key = {
type = "string",
},
- }
+ },
},
prefix = {
type = "string",
@@ -54,7 +54,8 @@ local etcd_schema = {
items = {
type = "string",
pattern = [[^https?://]]
- }
+ },
+ minItems = 1,
}
},
required = {"prefix", "host"}
diff --git a/apisix/cli/snippet.lua b/apisix/cli/snippet.lua
index 014719511..191e3b0ed 100644
--- a/apisix/cli/snippet.lua
+++ b/apisix/cli/snippet.lua
@@ -22,19 +22,31 @@ local ipairs = ipairs
local _M = {}
-function _M.generate_conf_server(conf)
+function _M.generate_conf_server(env, conf)
if not (conf.deployment and conf.deployment.role == "traditional") then
- return nil
+ return nil, nil
end
-- we use proxy even the role is traditional so that we can test the proxy
in daily dev
- local servers = conf.deployment.etcd.host
+ local etcd = conf.deployment.etcd
+ local servers = etcd.host
+ local enable_https = false
+ local prefix = "https://"
+ if servers[1]:find(prefix, 1, true) then
+ enable_https = true
+ end
+ -- there is not a compatible way to verify upstream TLS like the one we do
in cosocket
+ -- so here we just ignore it as the verification is already done in the
init phase
for i, s in ipairs(servers) do
- local prefix = "http://"
- -- TODO: support https
- if s:find(prefix, 1, true) then
- servers[i] = s:sub(#prefix + 1)
+ if (s:find(prefix, 1, true) ~= nil) ~= enable_https then
+ return nil, "all nodes in the etcd cluster should enable/disable
TLS together"
+ end
+
+ local _, to = s:find("://", 1, true)
+ if not to then
+ return nil, "bad etcd endpoint format"
end
+ servers[i] = s:sub(to + 1)
end
local conf_render = template.compile([[
@@ -44,12 +56,16 @@ function _M.generate_conf_server(conf)
{% end %}
}
server {
- listen unix:./conf/config_listen.sock;
+ listen unix:{* home *}/conf/config_listen.sock;
access_log off;
location / {
- set $upstream_scheme 'http';
-
- proxy_pass $upstream_scheme://apisix_conf_backend;
+ {% if enable_https then %}
+ proxy_pass https://apisix_conf_backend;
+ proxy_ssl_server_name on;
+ proxy_ssl_protocols TLSv1.2 TLSv1.3;
+ {% else %}
+ proxy_pass http://apisix_conf_backend;
+ {% end %}
proxy_http_version 1.1;
proxy_set_header Connection "";
@@ -57,7 +73,9 @@ function _M.generate_conf_server(conf)
}
]])
return conf_render({
- servers = servers
+ servers = servers,
+ enable_https = enable_https,
+ home = env.apisix_home or ".",
})
end
diff --git a/apisix/core/etcd.lua b/apisix/core/etcd.lua
index 9d289bd5d..274b3a9d8 100644
--- a/apisix/core/etcd.lua
+++ b/apisix/core/etcd.lua
@@ -19,15 +19,19 @@
--
-- @module core.etcd
-local fetch_local_conf = require("apisix.core.config_local").local_conf
-local array_mt = require("apisix.core.json").array_mt
-local etcd = require("resty.etcd")
-local clone_tab = require("table.clone")
-local health_check = require("resty.etcd.health_check")
-local ipairs = ipairs
-local setmetatable = setmetatable
-local string = string
-local tonumber = tonumber
+local fetch_local_conf = require("apisix.core.config_local").local_conf
+local array_mt = require("apisix.core.json").array_mt
+local etcd = require("resty.etcd")
+local clone_tab = require("table.clone")
+local health_check = require("resty.etcd.health_check")
+local ipairs = ipairs
+local setmetatable = setmetatable
+local string = string
+local tonumber = tonumber
+local ngx_config_prefix = ngx.config.prefix()
+
+
+local is_http = ngx.config.subsystem == "http"
local _M = {}
@@ -38,7 +42,25 @@ local function new()
return nil, nil, err
end
- local etcd_conf = clone_tab(local_conf.etcd)
+ local etcd_conf
+
+ if local_conf.deployment
+ and local_conf.deployment.role == "traditional"
+ -- we proxy the etcd requests in traditional mode so we can test the
CP's behavior in
+ -- daily development. However, a stream proxy can't be the CP.
+ -- Hence, generate a HTTP conf server to proxy etcd requests in stream
proxy is
+ -- unnecessary and inefficient.
+ and is_http
+ then
+ local sock_prefix = ngx_config_prefix
+ etcd_conf = clone_tab(local_conf.deployment.etcd)
+ etcd_conf.unix_socket_proxy =
+ "unix:" .. sock_prefix .. "/conf/config_listen.sock"
+ etcd_conf.host = {"http://127.0.0.1:2379"}
+ else
+ etcd_conf = clone_tab(local_conf.etcd)
+ end
+
local prefix = etcd_conf.prefix
etcd_conf.http_host = etcd_conf.host
etcd_conf.host = nil
diff --git a/t/bin/gen_snippet.lua b/t/bin/gen_snippet.lua
new file mode 100755
index 000000000..085409b6b
--- /dev/null
+++ b/t/bin/gen_snippet.lua
@@ -0,0 +1,51 @@
+#!/usr/bin/env luajit
+--
+-- 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.
+--
+-- this script generates Nginx configuration in the test
+-- so we can test some features with test-nginx
+local pkg_cpath_org = package.cpath
+local pkg_path_org = package.path
+local pkg_cpath = "deps/lib64/lua/5.1/?.so;deps/lib/lua/5.1/?.so;"
+local pkg_path = "deps/share/lua/5.1/?.lua;"
+-- modify the load path to load our dependencies
+package.cpath = pkg_cpath .. pkg_cpath_org
+package.path = pkg_path .. pkg_path_org
+
+
+local file = require("apisix.cli.file")
+local schema = require("apisix.cli.schema")
+local snippet = require("apisix.cli.snippet")
+local yaml_conf, err = file.read_yaml_conf("t/servroot")
+if not yaml_conf then
+ error(err)
+end
+local ok, err = schema.validate(yaml_conf)
+if not ok then
+ error(err)
+end
+
+local res, err
+if arg[1] == "conf_server" then
+ res, err = snippet.generate_conf_server(
+ {apisix_home = "t/servroot/"},
+ yaml_conf)
+end
+
+if not res then
+ error(err or "none")
+end
+print(res)
diff --git a/t/cli/test_deployment_traditional.sh
b/t/cli/test_deployment_traditional.sh
index f6d7d62c9..895675118 100755
--- a/t/cli/test_deployment_traditional.sh
+++ b/t/cli/test_deployment_traditional.sh
@@ -111,3 +111,23 @@ if grep '\[error\]' logs/error.log; then
fi
echo "passed: could connect to etcd"
+
+echo '
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: etcd
+ etcd:
+ prefix: "/apisix"
+ host:
+ - http://127.0.0.1:2379
+ - https://127.0.0.1:2379
+' > conf/config.yaml
+
+out=$(make init 2>&1 || true)
+if ! echo "$out" | grep 'all nodes in the etcd cluster should enable/disable
TLS together'; then
+ echo "failed: should validate etcd host"
+ exit 1
+fi
+
+echo "passed: validate etcd host"
diff --git a/t/deployment/conf_server.t b/t/deployment/conf_server.t
new file mode 100644
index 000000000..84b045055
--- /dev/null
+++ b/t/deployment/conf_server.t
@@ -0,0 +1,100 @@
+#
+# 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;
+
+my $nginx_binary = $ENV{'TEST_NGINX_BINARY'} || 'nginx';
+my $version = eval { `$nginx_binary -V 2>&1` };
+
+if ($version =~ m/\/1.17.8/) {
+ plan(skip_all => "require OpenResty 1.19+");
+} else {
+ plan('no_plan');
+}
+
+add_block_preprocessor(sub {
+ my ($block) = @_;
+
+ if (!$block->request) {
+ $block->set_value("request", "GET /t");
+ }
+
+ if ((!defined $block->error_log) && (!defined $block->no_error_log)) {
+ $block->set_value("no_error_log", "[error]");
+ }
+
+});
+
+Test::Nginx::Socket::set_http_config_filter(sub {
+ my $config = shift;
+ my $snippet = `./t/bin/gen_snippet.lua conf_server`;
+ $config .= $snippet;
+ return $config;
+});
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: sync in https
+--- config
+ location /t {
+ content_by_lua_block {
+ local core = require("apisix.core")
+ local t = require("lib.test_admin").test
+
+ local consumers, _ = core.config.new("/consumers", {
+ automatic = true,
+ item_schema = core.schema.consumer,
+ })
+
+ ngx.sleep(0.6)
+ local idx = consumers.prev_index
+
+ local code, body = t('/apisix/admin/consumers',
+ ngx.HTTP_PUT,
+ [[{
+ "username": "jobs",
+ "plugins": {
+ "basic-auth": {
+ "username": "jobs",
+ "password": "678901"
+ }
+ }
+ }]])
+
+ ngx.sleep(2)
+ local new_idx = consumers.prev_index
+ if new_idx > idx then
+ ngx.say("prev_index updated")
+ else
+ ngx.say("prev_index not update")
+ end
+ }
+ }
+--- response_body
+prev_index updated
+--- extra_yaml_config
+deployment:
+ role: traditional
+ role_traditional:
+ config_provider: etcd
+ etcd:
+ prefix: "/apisix"
+ host:
+ - https://127.0.0.1:12379
+ tls:
+ verify: false