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