This is an automated email from the ASF dual-hosted git repository.
wenming 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 d8bd34414 feat: support Nacos ak/sk authentication (#10445)
d8bd34414 is described below
commit d8bd34414239ed36942c19f435ac10ad0d5e57c0
Author: yuweizzz <[email protected]>
AuthorDate: Mon Nov 13 10:19:07 2023 +0800
feat: support Nacos ak/sk authentication (#10445)
---
apisix/discovery/nacos/init.lua | 26 ++
apisix/discovery/nacos/schema.lua | 2 +
conf/config-default.yaml | 2 +
t/discovery/nacos3.t | 638 ++++++++++++++++++++++++++++++++++++++
4 files changed, 668 insertions(+)
diff --git a/apisix/discovery/nacos/init.lua b/apisix/discovery/nacos/init.lua
index 2e06f5553..b014d0fef 100644
--- a/apisix/discovery/nacos/init.lua
+++ b/apisix/discovery/nacos/init.lua
@@ -39,6 +39,8 @@ local auth_path = 'auth/login'
local instance_list_path = 'ns/instance/list?healthyOnly=true&serviceName='
local default_namespace_id = "public"
local default_group_name = "DEFAULT_GROUP"
+local access_key
+local secret_key
local events
local events_list
@@ -53,6 +55,7 @@ local function discovery_nacos_callback(data, event, source,
pid)
", application: ", core.json.encode(applications, true))
end
+
local function request(request_uri, path, body, method, basic_auth)
local url = request_uri .. path
log.info('request url:', url)
@@ -127,6 +130,7 @@ local function get_token_param(base_uri, username, password)
return '&accessToken=' .. data.accessToken
end
+
local function get_namespace_param(namespace_id)
local param = ''
if namespace_id then
@@ -136,6 +140,7 @@ local function get_namespace_param(namespace_id)
return param
end
+
local function get_group_name_param(group_name)
local param = ''
if group_name then
@@ -145,6 +150,22 @@ local function get_group_name_param(group_name)
return param
end
+
+local function get_signed_param(group_name, service_name)
+ local param = ''
+ if access_key ~= '' and secret_key ~= '' then
+ local str_to_sign = ngx.now() * 1000 .. '@@' .. group_name .. '@@' ..
service_name
+ local args = {
+ ak = access_key,
+ data = str_to_sign,
+ signature = ngx.encode_base64(ngx.hmac_sha1(secret_key,
str_to_sign))
+ }
+ param = '&' .. ngx.encode_args(args)
+ end
+ return param
+end
+
+
local function get_base_uri()
local host = local_conf.discovery.nacos.host
-- TODO Add health check to get healthy nodes.
@@ -257,6 +278,7 @@ local function is_grpc(scheme)
return false
end
+
local function fetch_full_registry(premature)
if premature then
return
@@ -286,8 +308,10 @@ local function fetch_full_registry(premature)
local scheme = service_info.scheme or ''
local namespace_param = get_namespace_param(service_info.namespace_id)
local group_name_param = get_group_name_param(service_info.group_name)
+ local signature_param = get_signed_param(service_info.group_name,
service_info.service_name)
local query_path = instance_list_path .. service_info.service_name
.. token_param .. namespace_param ..
group_name_param
+ .. signature_param
data, err = get_url(base_uri, query_path)
if err then
log.error('get_url:', query_path, ' err:', err)
@@ -385,6 +409,8 @@ function _M.init_worker()
log.info('default_weight:', default_weight)
local fetch_interval = local_conf.discovery.nacos.fetch_interval
log.info('fetch_interval:', fetch_interval)
+ access_key = local_conf.discovery.nacos.access_key
+ secret_key = local_conf.discovery.nacos.secret_key
ngx_timer_at(0, fetch_full_registry)
ngx_timer_every(fetch_interval, fetch_full_registry)
end
diff --git a/apisix/discovery/nacos/schema.lua
b/apisix/discovery/nacos/schema.lua
index 40c1ba77c..294048736 100644
--- a/apisix/discovery/nacos/schema.lua
+++ b/apisix/discovery/nacos/schema.lua
@@ -52,6 +52,8 @@ return {
read = 5000,
}
},
+ access_key = {type = 'string', default = ''},
+ secret_key = {type = 'string', default = ''},
},
required = {'host'}
}
diff --git a/conf/config-default.yaml b/conf/config-default.yaml
index b435533ca..4e257f4d4 100755
--- a/conf/config-default.yaml
+++ b/conf/config-default.yaml
@@ -308,6 +308,8 @@ nginx_config: # Config for render the
template to generate n
# connect: 2000 # Default 2000ms
# send: 2000 # Default 2000ms
# read: 5000 # Default 5000ms
+# access_key: "" # Nacos AccessKey ID in Alibaba Cloud, notice that
it's for Nacos instances on Microservices Engine (MSE)
+# secret_key: "" # Nacos AccessKey Secret in Alibaba Cloud, notice
that it's for Nacos instances on Microservices Engine (MSE)
# consul_kv: # Consul KV
# servers: # Consul KV address(es)
# - "http://127.0.0.1:8500"
diff --git a/t/discovery/nacos3.t b/t/discovery/nacos3.t
new file mode 100644
index 000000000..c71259386
--- /dev/null
+++ b/t/discovery/nacos3.t
@@ -0,0 +1,638 @@
+#
+# 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.
+#
+
+# we can't use mse nacos to test, access_key and secret_key won't affect the
open source nacos
+use t::APISIX 'no_plan';
+
+workers(4);
+
+add_block_preprocessor(sub {
+ my ($block) = @_;
+
+ if (!$block->request) {
+ $block->set_value("request", "GET /t");
+ }
+});
+
+our $yaml_config = <<_EOC_;
+apisix:
+ node_listen: 1984
+deployment:
+ role: data_plane
+ role_data_plane:
+ config_provider: yaml
+discovery:
+ nacos:
+ host:
+ - "http://127.0.0.1:8858"
+ prefix: "/nacos/v1/"
+ fetch_interval: 1
+ weight: 1
+ timeout:
+ connect: 2000
+ send: 2000
+ read: 5000
+ access_key: "my_access_key"
+ secret_key: "my_secret_key"
+
+_EOC_
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: error service_name
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS-DEMO
+ discovery_type: nacos
+ type: roundrobin
+
+#END
+--- request
+GET /hello
+--- error_code: 503
+--- error_log
+no valid upstream node
+
+
+
+=== TEST 2: error namespace_id
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS-DEMO
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ namespace_id: err_ns
+#END
+--- request
+GET /hello
+--- error_code: 503
+--- error_log
+no valid upstream node
+
+
+
+=== TEST 3: error group_name
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS-DEMO
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ group_name: err_group_name
+#END
+--- request
+GET /hello
+--- error_code: 503
+--- error_log
+no valid upstream node
+
+
+
+=== TEST 4: error namespace_id and error group_name
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS-DEMO
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ namespace_id: err_ns
+ group_name: err_group_name
+#END
+--- request
+GET /hello
+--- error_code: 503
+--- error_log
+no valid upstream node
+
+
+
+=== TEST 5: error group_name and correct namespace_id
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS-DEMO
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ namespace_id: test_ns
+ group_name: err_group_name
+#END
+--- request
+GET /hello
+--- error_code: 503
+--- error_log
+no valid upstream node
+
+
+
+=== TEST 6: error namespace_id and correct group_name
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS-DEMO
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ namespace_id: err_ns
+ group_name: test_group
+#END
+--- request
+GET /hello
+--- error_code: 503
+--- error_log
+no valid upstream node
+
+
+
+=== TEST 7: get APISIX-NACOS info from NACOS - configured in services
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ service_id: 1
+services:
+ -
+ id: 1
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+
+
+
+=== TEST 8: get APISIX-NACOS info from NACOS - configured in services with
group_name
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ service_id: 1
+services:
+ -
+ id: 1
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ group_name: test_group
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+
+
+
+=== TEST 9: get APISIX-NACOS info from NACOS - configured in services with
namespace_id
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ service_id: 1
+services:
+ -
+ id: 1
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ namespace_id: test_ns
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+
+
+
+=== TEST 10: get APISIX-NACOS info from NACOS - configured in services with
group_name and namespace_id
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ service_id: 1
+services:
+ -
+ id: 1
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ group_name: test_group
+ namespace_id: test_ns
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+
+
+
+=== TEST 11: get APISIX-NACOS info from NACOS - configured in upstreams
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+--- no_error_log
+[error, error]
+
+
+
+=== TEST 12: get APISIX-NACOS info from NACOS - configured in upstreams with
namespace_id
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ namespace_id: test_ns
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+
+
+
+=== TEST 13: get APISIX-NACOS info from NACOS - configured in upstreams with
group_name
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ group_name: test_group
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+
+
+
+=== TEST 14: get APISIX-NACOS info from NACOS - configured in upstreams with
namespace_id and group_name
+--- yaml_config eval: $::yaml_config
+--- apisix_yaml
+routes:
+ -
+ uri: /hello
+ upstream:
+ service_name: APISIX-NACOS
+ discovery_type: nacos
+ type: roundrobin
+ discovery_args:
+ namespace_id: test_ns
+ group_name: test_group
+#END
+--- pipelined_requests eval
+[
+ "GET /hello",
+ "GET /hello",
+]
+--- response_body_like eval
+[
+ qr/server [1-2]/,
+ qr/server [1-2]/,
+]
+
+
+
+=== TEST 15: get APISIX-NACOS info from NACOS - configured in upstreams + etcd
+--- extra_yaml_config
+discovery:
+ nacos:
+ host:
+ - "http://127.0.0.1:8858"
+ fetch_interval: 1
+ access_key: "my_access_key"
+ secret_key: "my_secret_key"
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/upstreams/1',
+ ngx.HTTP_PUT,
+ [[{
+ "service_name": "APISIX-NACOS",
+ "discovery_type": "nacos",
+ "type": "roundrobin"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream_id": 1
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 16: same namespace_id and service_name, different group_name
+--- extra_yaml_config
+discovery:
+ nacos:
+ host:
+ - "http://127.0.0.1:8858"
+ fetch_interval: 1
+ access_key: "my_access_key"
+ secret_key: "my_secret_key"
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+
+ -- use nacos-service5
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream": {
+ "service_name": "APISIX-NACOS",
+ "discovery_type": "nacos",
+ "type": "roundrobin",
+ "discovery_args": {
+ "namespace_id": "test_ns",
+ "group_name": "test_group"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+
+ -- use nacos-service6
+ local code, body = t('/apisix/admin/routes/2',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello1",
+ "upstream": {
+ "service_name": "APISIX-NACOS",
+ "discovery_type": "nacos",
+ "type": "roundrobin",
+ "discovery_args": {
+ "namespace_id": "test_ns",
+ "group_name": "test_group2"
+ }
+ },
+ "plugins": {
+ "proxy-rewrite": {
+ "uri": "/hello"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+
+ ngx.sleep(1.5)
+
+ local http = require "resty.http"
+ local httpc = http.new()
+ local uri1 = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
+ local res, err = httpc:request_uri(uri1, { method = "GET"})
+ if err then
+ ngx.log(ngx.ERR, err)
+ ngx.status = res.status
+ return
+ end
+ ngx.say(res.body)
+
+ local uri2 = "http://127.0.0.1:" .. ngx.var.server_port ..
"/hello1"
+ res, err = httpc:request_uri(uri2, { method = "GET"})
+ if err then
+ ngx.log(ngx.ERR, err)
+ ngx.status = res.status
+ return
+ end
+ ngx.say(res.body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+server 1
+server 3
+
+
+
+=== TEST 17: same group_name and service_name, different namespace_id
+--- extra_yaml_config
+discovery:
+ nacos:
+ host:
+ - "http://127.0.0.1:8858"
+ fetch_interval: 1
+ access_key: "my_access_key"
+ secret_key: "my_secret_key"
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+
+ -- use nacos-service5
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream": {
+ "service_name": "APISIX-NACOS",
+ "discovery_type": "nacos",
+ "type": "roundrobin",
+ "discovery_args": {
+ "namespace_id": "test_ns",
+ "group_name": "test_group"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+
+ -- use nacos-service7
+ local code, body = t('/apisix/admin/routes/2',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello1",
+ "upstream": {
+ "service_name": "APISIX-NACOS",
+ "discovery_type": "nacos",
+ "type": "roundrobin",
+ "discovery_args": {
+ "namespace_id": "test_ns2",
+ "group_name": "test_group"
+ }
+ },
+ "plugins": {
+ "proxy-rewrite": {
+ "uri": "/hello"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+
+ ngx.sleep(1.5)
+
+ local http = require "resty.http"
+ local httpc = http.new()
+ local uri1 = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
+ local res, err = httpc:request_uri(uri1, { method = "GET"})
+ if err then
+ ngx.log(ngx.ERR, err)
+ ngx.status = res.status
+ return
+ end
+ ngx.say(res.body)
+
+ local uri2 = "http://127.0.0.1:" .. ngx.var.server_port ..
"/hello1"
+ res, err = httpc:request_uri(uri2, { method = "GET"})
+ if err then
+ ngx.log(ngx.ERR, err)
+ ngx.status = res.status
+ return
+ end
+ ngx.say(res.body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+server 1
+server 4