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 d6b04871e feat: add vault common components (#8412)
d6b04871e is described below

commit d6b04871ea6b165693a04c7260097115d4ceb5b8
Author: soulbird <[email protected]>
AuthorDate: Mon Nov 28 20:35:56 2022 +0800

    feat: add vault common components (#8412)
    
    Co-authored-by: soulbird <[email protected]>
---
 .github/workflows/build.yml      |   3 +-
 .github/workflows/centos7-ci.yml |   3 +-
 Makefile                         |   3 +
 apisix/kms/vault.lua             |  91 ++++++++++++++++++++++
 ci/init-common-test-service.sh   |  21 ++++++
 ci/init-plugin-test-service.sh   |   3 -
 ci/pod/docker-compose.common.yml |  15 ++++
 ci/pod/docker-compose.plugin.yml |  17 -----
 t/kms/vault.t                    | 158 +++++++++++++++++++++++++++++++++++++++
 9 files changed, 292 insertions(+), 22 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9031b2dad..0626767ad 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -32,7 +32,7 @@ jobs:
         test_dir:
           - t/plugin/[a-k]*
           - t/plugin/[l-z]*
-          - t/admin t/cli t/config-center-yaml t/control t/core t/debug 
t/deployment 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/kms 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 }}
@@ -86,6 +86,7 @@ jobs:
       - name: Linux launch common services
         run: |
           make ci-env-up project_compose_ci=ci/pod/docker-compose.common.yml
+          sudo ./ci/init-common-test-service.sh
 
       - name: Create tarball
         if: ${{ startsWith(github.ref, 'refs/heads/release/') }}
diff --git a/.github/workflows/centos7-ci.yml b/.github/workflows/centos7-ci.yml
index ba76759bf..d5b8facc4 100644
--- a/.github/workflows/centos7-ci.yml
+++ b/.github/workflows/centos7-ci.yml
@@ -30,7 +30,7 @@ jobs:
         test_dir:
           - t/plugin/[a-k]*
           - t/plugin/[l-z]*
-          - t/admin t/cli t/config-center-yaml t/control t/core t/debug 
t/deployment 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/kms t/misc
           - t/node t/pubsub t/router t/script t/stream-node t/utils t/wasm 
t/xds-library
 
     steps:
@@ -72,6 +72,7 @@ jobs:
     - name: Linux launch common services
       run: |
         make ci-env-up project_compose_ci=ci/pod/docker-compose.common.yml
+        sudo ./ci/init-common-test-service.sh
 
     - name: Build rpm package
       if: ${{ startsWith(github.ref, 'refs/heads/release/') }}
diff --git a/Makefile b/Makefile
index 49468dc57..f8668c8d4 100644
--- a/Makefile
+++ b/Makefile
@@ -345,6 +345,9 @@ install: runtime
        $(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/pubsub
        $(ENV_INSTALL) apisix/pubsub/*.lua $(ENV_INST_LUADIR)/apisix/pubsub/
 
+       $(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/kms
+       $(ENV_INSTALL) apisix/kms/*.lua $(ENV_INST_LUADIR)/apisix/kms/
+
        $(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/plugins/zipkin
        $(ENV_INSTALL) apisix/plugins/zipkin/*.lua 
$(ENV_INST_LUADIR)/apisix/plugins/zipkin/
 
diff --git a/apisix/kms/vault.lua b/apisix/kms/vault.lua
new file mode 100644
index 000000000..1343002fc
--- /dev/null
+++ b/apisix/kms/vault.lua
@@ -0,0 +1,91 @@
+--
+-- 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.
+--
+
+--- Vault Tools.
+--  Vault is an identity-based secrets and encryption management system.
+
+local core = require("apisix.core")
+local http = require("resty.http")
+
+local norm_path = require("pl.path").normpath
+
+local sub        = core.string.sub
+local rfind_char = core.string.rfind_char
+
+local _M = {}
+
+
+local function make_request_to_vault(conf, method, key, data)
+    local httpc = http.new()
+    -- config timeout or default to 5000 ms
+    httpc:set_timeout((conf.timeout or 5)*1000)
+
+    local req_addr = conf.uri .. norm_path("/v1/"
+                .. conf.prefix .. "/" .. key)
+
+    local res, err = httpc:request_uri(req_addr, {
+        method = method,
+        headers = {
+            ["X-Vault-Token"] = conf.token
+        },
+        body = core.json.encode(data or {}, true)
+    })
+
+    if not res then
+        return nil, err
+    end
+
+    return res.body
+end
+
+-- key is the vault kv engine path
+local function get(conf, key)
+    core.log.info("fetching data from vault for key: ", key)
+
+    local idx = rfind_char(key, '/')
+    if not idx then
+        return nil, "error key format, key: " .. key
+    end
+
+    local main_key = sub(key, 1, idx - 1)
+    if main_key == "" then
+        return nil, "can't find main key, key: " .. key
+    end
+    local sub_key = sub(key, idx + 1)
+    if sub_key == "" then
+        return nil, "can't find sub key, key: " .. key
+    end
+
+    core.log.info("main: ", main_key, " sub: ", sub_key)
+
+    local res, err = make_request_to_vault(conf, "GET", main_key)
+    if not res then
+        return nil, "failed to retrtive data from vault kv engine: " .. err
+    end
+
+    local ret = core.json.decode(res)
+    if not ret or not ret.data then
+        return nil, "failed to decode result, res: " .. res
+    end
+
+    return ret.data[sub_key]
+end
+
+_M.get = get
+
+
+return _M
diff --git a/ci/init-common-test-service.sh b/ci/init-common-test-service.sh
new file mode 100755
index 000000000..7a54cd49a
--- /dev/null
+++ b/ci/init-common-test-service.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+# prepare vault kv engine
+sleep 3s
+docker exec -i vault sh -c "VAULT_TOKEN='root' 
VAULT_ADDR='http://0.0.0.0:8200' vault secrets enable -path=kv -version=1 kv"
diff --git a/ci/init-plugin-test-service.sh b/ci/init-plugin-test-service.sh
index 1f973ce36..fd090441e 100755
--- a/ci/init-plugin-test-service.sh
+++ b/ci/init-plugin-test-service.sh
@@ -39,9 +39,6 @@ docker exec -i rmqnamesrv 
/home/rocketmq/rocketmq-4.6.0/bin/mqadmin updateTopic
 docker exec -i rmqnamesrv /home/rocketmq/rocketmq-4.6.0/bin/mqadmin 
updateTopic -n rocketmq_namesrv:9876 -t test3 -c DefaultCluster
 docker exec -i rmqnamesrv /home/rocketmq/rocketmq-4.6.0/bin/mqadmin 
updateTopic -n rocketmq_namesrv:9876 -t test4 -c DefaultCluster
 
-# prepare vault kv engine
-docker exec -i vault sh -c "VAULT_TOKEN='root' 
VAULT_ADDR='http://0.0.0.0:8200' vault secrets enable -path=kv -version=1 kv"
-
 # wait for keycloak ready
 bash -c 'while true; do curl -s localhost:8080 &>/dev/null; ret=$?; [[ $ret 
-eq 0 ]] && break; sleep 3; done'
 docker cp ci/kcadm_configure_cas.sh apisix_keycloak_new:/tmp/
diff --git a/ci/pod/docker-compose.common.yml b/ci/pod/docker-compose.common.yml
index 9e0394a48..222dc1e1e 100644
--- a/ci/pod/docker-compose.common.yml
+++ b/ci/pod/docker-compose.common.yml
@@ -87,3 +87,18 @@ services:
       - "5004:6382"
       - "5005:6383"
       - "5006:6384"
+
+
+  ## HashiCorp Vault
+  vault:
+    image: vault:1.9.0
+    container_name: vault
+    restart: unless-stopped
+    ports:
+      - "8200:8200"
+    cap_add:
+      - IPC_LOCK
+    environment:
+      VAULT_DEV_ROOT_TOKEN_ID: root
+      VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200
+    command: [ "vault", "server", "-dev" ]
diff --git a/ci/pod/docker-compose.plugin.yml b/ci/pod/docker-compose.plugin.yml
index 6715c7a33..4b8c2a4c1 100644
--- a/ci/pod/docker-compose.plugin.yml
+++ b/ci/pod/docker-compose.plugin.yml
@@ -130,22 +130,6 @@ services:
     networks:
       skywalk_net:
 
-  ## HashiCorp Vault
-  vault:
-    image: vault:1.9.0
-    container_name: vault
-    restart: unless-stopped
-    ports:
-      - "8200:8200"
-    cap_add:
-      - IPC_LOCK
-    environment:
-      VAULT_DEV_ROOT_TOKEN_ID: root
-      VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200
-    command: [ "vault", "server", "-dev" ]
-    networks:
-      vault_net:
-
 
   ## OpenLDAP
   openldap:
@@ -284,5 +268,4 @@ networks:
   kafka_net:
   skywalk_net:
   rocketmq_net:
-  vault_net:
   opa_net:
diff --git a/t/kms/vault.t b/t/kms/vault.t
new file mode 100644
index 000000000..5e0cdb54a
--- /dev/null
+++ b/t/kms/vault.t
@@ -0,0 +1,158 @@
+#
+# 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);
+no_long_string();
+no_root_location();
+log_level("info");
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: check key: error format
+--- config
+    location /t {
+        content_by_lua_block {
+            local vault = require("apisix.kms.vault")
+            local conf = {
+                prefix = "/kv/prefix",
+                token = "root",
+                uri = "http://127.0.0.1:2800";
+            }
+            local data, err = vault.get(conf, "apisix")
+            if err then
+                return ngx.say(err)
+            end
+
+            ngx.say("done")
+        }
+    }
+--- request
+GET /t
+--- response_body
+error key format, key: apisix
+
+
+
+=== TEST 2: check key: no main key
+--- config
+    location /t {
+        content_by_lua_block {
+            local vault = require("apisix.kms.vault")
+            local conf = {
+                prefix = "/kv/prefix",
+                token = "root",
+                uri = "http://127.0.0.1:2800";
+            }
+            local data, err = vault.get(conf, "/apisix")
+            if err then
+                return ngx.say(err)
+            end
+
+            ngx.say("done")
+        }
+    }
+--- request
+GET /t
+--- response_body
+can't find main key, key: /apisix
+
+
+
+=== TEST 3: check key: no sub key
+--- config
+    location /t {
+        content_by_lua_block {
+            local vault = require("apisix.kms.vault")
+            local conf = {
+                prefix = "/kv/prefix",
+                token = "root",
+                uri = "http://127.0.0.1:2800";
+            }
+            local data, err = vault.get(conf, "apisix/")
+            if err then
+                return ngx.say(err)
+            end
+
+            ngx.say("done")
+        }
+    }
+--- request
+GET /t
+--- response_body
+can't find sub key, key: apisix/
+
+
+
+=== TEST 4: error vault uri
+--- config
+    location /t {
+        content_by_lua_block {
+            local vault = require("apisix.kms.vault")
+            local conf = {
+                prefix = "/kv/prefix",
+                token = "root",
+                uri = "http://127.0.0.2:2800";
+            }
+            local data, err = vault.get(conf, "/apisix/sub")
+            if err then
+                return ngx.say(err)
+            end
+
+            ngx.say("done")
+        }
+    }
+--- request
+GET /t
+--- response_body
+failed to retrtive data from vault kv engine: connection refused
+--- timeout: 6
+
+
+
+=== TEST 5: store secret into vault
+--- exec
+VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put 
kv/apisix/apisix-key/jack key=value
+--- response_body
+Success! Data written to: kv/apisix/apisix-key/jack
+
+
+
+=== TEST 6: get value from vault
+--- config
+    location /t {
+        content_by_lua_block {
+            local vault = require("apisix.kms.vault")
+            local conf = {
+                prefix = "kv/apisix",
+                token = "root",
+                uri = "http://127.0.0.1:8200";
+            }
+            local value, err = vault.get(conf, "/apisix-key/jack/key")
+            if err then
+                return ngx.say(err)
+            end
+
+            ngx.say("value")
+        }
+    }
+--- request
+GET /t
+--- response_body
+value

Reply via email to