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

Reply via email to