From 0468d78918c268d82f7c975f4326f4a0e79f3c10 Mon Sep 17 00:00:00 2001 From: Zeping Bai Date: Thu, 23 May 2024 16:37:31 +0800 Subject: [PATCH] feat: support hcv namespace (#11277) --- apisix/secret/vault.lua | 16 ++++++-- docs/en/latest/admin-api.md | 1 + docs/en/latest/terminology/secret.md | 12 ++++-- docs/zh/latest/admin-api.md | 5 ++- docs/zh/latest/terminology/secret.md | 6 +++ t/secret/vault.t | 57 ++++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 8 deletions(-) diff --git a/apisix/secret/vault.lua b/apisix/secret/vault.lua index f5dcb7a24628..40b5d404bdf4 100644 --- a/apisix/secret/vault.lua +++ b/apisix/secret/vault.lua @@ -37,6 +37,9 @@ local schema = { token = { type = "string", }, + namespace = { + type = "string", + }, }, required = {"uri", "prefix", "token"}, } @@ -58,11 +61,18 @@ local function make_request_to_vault(conf, method, key, data) token = conf.token end + local headers = { + ["X-Vault-Token"] = token + } + if conf.namespace then + -- The namespace rule is referenced in + -- https://developer.hashicorp.com/vault/docs/enterprise/namespaces#vault-api-and-namespaces + headers["X-Vault-Namespace"] = conf.namespace + end + local res, err = httpc:request_uri(req_addr, { method = method, - headers = { - ["X-Vault-Token"] = token - }, + headers = headers, body = core.json.encode(data or {}, true) }) diff --git a/docs/en/latest/admin-api.md b/docs/en/latest/admin-api.md index 158c8154335f..e2807622ea2e 100644 --- a/docs/en/latest/admin-api.md +++ b/docs/en/latest/admin-api.md @@ -1466,6 +1466,7 @@ When `{secretmanager}` is `vault`: | uri | True | URI | URI of the vault server. | | | prefix | True | string | key prefix | token | True | string | vault token. | | +| namespace | False | string | Vault namespace, no default value | `admin` | Example Configuration: diff --git a/docs/en/latest/terminology/secret.md b/docs/en/latest/terminology/secret.md index c38ffb68ca1b..bc233f3d9ce1 100644 --- a/docs/en/latest/terminology/secret.md +++ b/docs/en/latest/terminology/secret.md @@ -123,9 +123,9 @@ curl http://127.0.0.1:9180/apisix/admin/consumers \ Through the above steps, the `key` configuration in the `key-auth` plugin can be saved in the environment variable instead of being displayed in plain text when configuring the plugin. -## Use Vault to manage secrets +## Use HashiCorp Vault to manage secrets -Using Vault to manage secrets means that you can store secrets information in the Vault service and refer to it through variables in a specific format when configuring plugins. APISIX currently supports [Vault KV engine version V1](https://developer.hashicorp.com/vault/docs/secrets/kv/kv-v1). +Using HashiCorp Vault to manage secrets means that you can store secrets information in the Vault service and refer to it through variables in a specific format when configuring plugins. APISIX currently supports [Vault KV engine version V1](https://developer.hashicorp.com/vault/docs/secrets/kv/kv-v1). ### Usage @@ -133,7 +133,7 @@ Using Vault to manage secrets means that you can store secrets information in th $secret://$manager/$id/$secret_name/$key ``` -- manager: secrets management service, could be the Vault, AWS, etc. +- manager: secrets management service, could be the HashiCorp Vault, AWS, etc. - id: APISIX Secrets resource ID, which needs to be consistent with the one specified when adding the APISIX Secrets resource - secret_name: the secret name in the secrets management service - key: the key corresponding to the secret in the secrets management service @@ -168,6 +168,12 @@ secrets: uri: 127.0.0.1:8200 ``` +:::tip + +It now supports the use of the [`namespace` field](../admin-api.md#request-body-parameters-11) to set the multi-tenant namespace concepts supported by [HashiCorp Vault Enterprise](https://developer.hashicorp.com/vault/docs/enterprise/namespaces#vault-api-and-namespaces) and HCP Vault. + +::: + Step 3: Reference the APISIX Secrets resource in the `key-auth` plugin and fill in the key information: ```shell diff --git a/docs/zh/latest/admin-api.md b/docs/zh/latest/admin-api.md index 1d2e17c3a73e..461771a95d72 100644 --- a/docs/zh/latest/admin-api.md +++ b/docs/zh/latest/admin-api.md @@ -358,7 +358,7 @@ Route 对象 JSON 配置示例: "desc": "hello world", "remote_addrs": ["127.0.0.1"], # 一组客户端请求 IP 地址 "vars": [["http_user", "==", "ios"]], # 由一个或多个 [var, operator, val] 元素组成的列表 - "upstream_id": "1", # upstream 对象在 etcd 中的 id ,建议使用此值 + "upstream_id": "1", # upstream 对象在 etcd 中的 id,建议使用此值 "upstream": {}, # upstream 信息对象,建议尽量不要使用 "timeout": { # 为 route 设置 upstream 的连接、发送消息、接收消息的超时时间。 "connect": 3, @@ -652,7 +652,7 @@ Service 对象 JSON 配置示例: { "id": "1", # id "plugins": {}, # 指定 service 绑定的插件 - "upstream_id": "1", # upstream 对象在 etcd 中的 id ,建议使用此值 + "upstream_id": "1", # upstream 对象在 etcd 中的 id,建议使用此值 "upstream": {}, # upstream 信息对象,不建议使用 "name": "test svc", # service 名称 "desc": "hello world", # service 描述 @@ -1476,6 +1476,7 @@ Secret 资源请求地址:/apisix/admin/secrets/{secretmanager}/{id} | uri | 是 | URI | Vault 服务器的 URI | | | prefix | 是 | 字符串 | 密钥前缀 | token | 是 | 字符串 | Vault 令牌 | | +| namespace | 否 | 字符串 | Vault 命名空间,该字段无默认值 | `admin` | 配置示例: diff --git a/docs/zh/latest/terminology/secret.md b/docs/zh/latest/terminology/secret.md index c59f0d4ceca4..100a44475eb3 100644 --- a/docs/zh/latest/terminology/secret.md +++ b/docs/zh/latest/terminology/secret.md @@ -169,6 +169,12 @@ secrets: uri: 127.0.0.1:8200 ``` +:::tip + +它现在支持使用 [`namespace` 字段](../admin-api.md#secret-config-body-requset-parameters] 设置 [HashiCorp Vault Enterprise](https://developer.hashicorp.com/vault/docs/enterprise/namespaces#vault-api-and-namespaces) 和 HCP Vault 所支持的多租户命名空间概念。 + +::: + 第三步:在 `key-auth` 插件中引用 APISIX Secret 资源,填充秘钥信息: ```shell diff --git a/t/secret/vault.t b/t/secret/vault.t index b3db13179447..607604f7acc6 100644 --- a/t/secret/vault.t +++ b/t/secret/vault.t @@ -236,3 +236,60 @@ failed to decode result, res: \{\"errors\":\[\"permission denied\"\]}\n GET /t --- response_body_like failed to decode result, res: \{\"errors\":\[\"permission denied\"\]}\n + + + +=== TEST 10: setup route +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "plugins": { + "serverless-pre-function": { + "phase": "access", + "functions": [ + "return function(conf, ctx) ngx.log(ngx.ERR, 'HCV_NAMESAPCE:'..(ctx.var.http_x_vault_namespace or '_')); require('apisix.core').response.exit(200); end" + ] + } + }, + "uri": "/*" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 11: hit route (test namespace header) +--- config + location /t { + content_by_lua_block { + local vault = require("apisix.secret.vault") + local conf = { + prefix = "kv/apisix", + token = "test", + uri = "http://localhost:1984/mock", + namespace = "apisix", + } + local value, err = vault.get(conf, "/apisix-key/jack/key") + if err then + return ngx.say(err) + end + } + } +--- request +GET /t +--- error_log +HCV_NAMESAPCE:apisix