This is an automated email from the ASF dual-hosted git repository. baoyuan 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 54418e19c feat: allow to use environment variables for openid-connect plugin (#11451) 54418e19c is described below commit 54418e19c2ef51dadf7da52f765c51eb049a9074 Author: darkSheep <49020899+darksheep...@users.noreply.github.com> AuthorDate: Mon Aug 25 11:25:56 2025 +0800 feat: allow to use environment variables for openid-connect plugin (#11451) --- apisix/plugins/openid-connect.lua | 4 +- docs/en/latest/plugins/openid-connect.md | 8 ++ docs/zh/latest/plugins/openid-connect.md | 9 ++ t/plugin/openid-connect.t | 1 - t/plugin/openid-connect9.t | 192 +++++++++++++++++++++++++++++++ 5 files changed, 212 insertions(+), 2 deletions(-) diff --git a/apisix/plugins/openid-connect.lua b/apisix/plugins/openid-connect.lua index 759e0c608..a273cca30 100644 --- a/apisix/plugins/openid-connect.lua +++ b/apisix/plugins/openid-connect.lua @@ -19,6 +19,7 @@ local core = require("apisix.core") local ngx_re = require("ngx.re") local openidc = require("resty.openidc") local random = require("resty.random") +local fetch_secrets = require("apisix.secret").fetch_secrets local jsonschema = require('jsonschema') local string = string local ngx = ngx @@ -554,7 +555,8 @@ local function validate_claims_in_oidcauth_response(resp, conf) end function _M.rewrite(plugin_conf, ctx) - local conf = core.table.clone(plugin_conf) + local conf_clone = core.table.clone(plugin_conf) + local conf = fetch_secrets(conf_clone, true, plugin_conf, "") -- Previously, we multiply conf.timeout before storing it in etcd. -- If the timeout is too large, we should not multiply it again. diff --git a/docs/en/latest/plugins/openid-connect.md b/docs/en/latest/plugins/openid-connect.md index 86c3395f0..caac61466 100644 --- a/docs/en/latest/plugins/openid-connect.md +++ b/docs/en/latest/plugins/openid-connect.md @@ -103,6 +103,14 @@ The `openid-connect` Plugin supports the integration with [OpenID Connect (OIDC) | claim_schema | object | False | | | JSON schema of OIDC response claim. Example: `{"type":"object","properties":{"access_token":{"type":"string"}},"required":["access_token"]}` - validates that the response contains a required string field `access_token`. | NOTE: `encrypt_fields = {"client_secret"}` is also defined in the schema, which means that the field will be stored encrypted in etcd. See [encrypted storage fields](../plugin-develop.md#encrypted-storage-fields). +In addition, you can use Environment Variables or APISIX secret to store and reference plugin attributes. APISIX currently supports storing secrets in two ways - [Environment Variables and HashiCorp Vault](../terminology/secret.md). + +For example, use below command to set environment variable +`export keycloak_secret=abc` + +and use it in plugin conf like below + +`"client_secret": "$ENV://keycloak_secret"` ## Examples diff --git a/docs/zh/latest/plugins/openid-connect.md b/docs/zh/latest/plugins/openid-connect.md index b9470200a..c8c50ad89 100644 --- a/docs/zh/latest/plugins/openid-connect.md +++ b/docs/zh/latest/plugins/openid-connect.md @@ -104,6 +104,15 @@ description: openid-connect 插件支持与 OpenID Connect (OIDC) 身份提供 注意:schema 中还定义了 `encrypt_fields = {"client_secret"}`,这意味着该字段将会被加密存储在 etcd 中。具体参考 [加密存储字段](../plugin-develop.md#加密存储字段)。 +此外:你可以使用环境变量或者 APISIX secret 来存放和引用插件配置,APISIX 当前支持通过两种方式配置 secrets - [Environment Variables and HashiCorp Vault](../terminology/secret.md)。 + +例如:你可以使用以下方式来设置环境变量 +`export keycloak_secret=abc` + +并且像下面这样在插件里使用 + +`"client_secret": "$ENV://keycloak_secret"` + ## 示例 以下示例演示了如何针对不同场景配置 `openid-connect` 插件。 diff --git a/t/plugin/openid-connect.t b/t/plugin/openid-connect.t index 54fdc8097..5a7042a62 100644 --- a/t/plugin/openid-connect.t +++ b/t/plugin/openid-connect.t @@ -33,7 +33,6 @@ add_block_preprocessor(sub { $block->set_value("request", "GET /t"); } }); - run_tests(); __DATA__ diff --git a/t/plugin/openid-connect9.t b/t/plugin/openid-connect9.t new file mode 100644 index 000000000..f6d6f5c7b --- /dev/null +++ b/t/plugin/openid-connect9.t @@ -0,0 +1,192 @@ +# +# 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'; + +log_level('debug'); +repeat_each(1); +no_long_string(); +no_root_location(); +no_shuffle(); + +add_block_preprocessor(sub { + my ($block) = @_; + + if ((!defined $block->error_log) && (!defined $block->no_error_log)) { + $block->set_value("no_error_log", "[error]"); + } + + if (!defined $block->request) { + $block->set_value("request", "GET /t"); + } +}); + +BEGIN { + $ENV{CLIENT_SECRET_ENV} = "60Op4HFM0I8ajz0WdiStAbziZ-VFQttXuxixHHs2R7r7-CW8GR79l-mmLqMhc-Sa"; + $ENV{VAULT_TOKEN} = "root"; +} + +run_tests(); + +__DATA__ + +=== TEST 1: configure oidc plugin with small public key using environment variable + --- 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": { + "openid-connect": { + "client_id": "kbyuFDidLLm280LIwVFiazOqjO3ty8KH", + "client_secret": "$ENV://CLIENT_SECRET_ENV", + "discovery": "https://samples.auth0.com/.well-known/openid-configuration", + "redirect_uri": "https://iresty.com", + "ssl_verify": false, + "timeout": 10, + "bearer_only": true, + "scope": "apisix", + "public_key": "-----BEGIN PUBLIC KEY-----\n]] .. + [[MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANW16kX5SMrMa2t7F2R1w6Bk/qpjS4QQ\n]] .. + [[hnrbED3Dpsl9JXAx90MYsIWp51hBxJSE/EPVK8WF/sjHK1xQbEuDfEECAwEAAQ==\n]] .. + [[-----END PUBLIC KEY-----", + "token_signing_alg_values_expected": "RS256" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) + } +} +--- response_body +passed + + + +=== TEST 2: store secret into vault +--- exec +VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/foo client_secret=60Op4HFM0I8ajz0WdiStAbziZ-VFQttXuxixHHs2R7r7-CW8GR79l-mmLqMhc-Sa +--- response_body +Success! Data written to: kv/apisix/foo + + + +=== TEST 3: configure oidc plugin with small public key using vault +--- 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": { + "openid-connect": { + "client_id": "kbyuFDidLLm280LIwVFiazOqjO3ty8KH", + "client_secret": "$secret://vault/test1/foo/client_secret", + "discovery": "https://samples.auth0.com/.well-known/openid-configuration", + "redirect_uri": "https://iresty.com", + "ssl_verify": false, + "timeout": 10, + "bearer_only": true, + "scope": "apisix", + "public_key": "-----BEGIN PUBLIC KEY-----\n]] .. + [[MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANW16kX5SMrMa2t7F2R1w6Bk/qpjS4QQ\n]] .. + [[hnrbED3Dpsl9JXAx90MYsIWp51hBxJSE/EPVK8WF/sjHK1xQbEuDfEECAwEAAQ==\n]] .. + [[-----END PUBLIC KEY-----", + "token_signing_alg_values_expected": "RS256" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + + if code >= 300 then + ngx.status = code + end + ngx.say(body) +} +} +--- response_body +passed + + + +=== TEST 4: configure oidc plugin with small public key using vault and request with token should success +--- config + location /hello { + content_by_lua_block { + ngx.say("success") + } + } + + 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": { + "openid-connect": { + "client_id": "kbyuFDidLLm280LIwVFiazOqjO3ty8KH", + "client_secret": "$secret://vault/test1/foo/client_secret", + "discovery": "https://samples.auth0.com/.well-known/openid-configuration", + "redirect_uri": "https://iresty.com", + "ssl_verify": false, + "timeout": 10, + "bearer_only": true, + "scope": "apisix", + "public_key": "-----BEGIN PUBLIC KEY-----\n]] .. + [[MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANW16kX5SMrMa2t7F2R1w6Bk/qpjS4QQ\n]] .. + [[hnrbED3Dpsl9JXAx90MYsIWp51hBxJSE/EPVK8WF/sjHK1xQbEuDfEECAwEAAQ==\n]] .. + [[-----END PUBLIC KEY-----", + "token_signing_alg_values_expected": "RS256" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + ngx.status = code + ngx.say(body) + } + } +--- request +GET /hello HTTP/1.1 +Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3NhbXBsZXMuYXV0aDAuY29tLyIsInN1YiI6InRlc3Qtc3ViamVjdCIsImF1ZCI6ImtieXVG RGlkTExtMjgwTEl3VkZpYXpPcWpPM3R5OEtIIiwic2NvcGUiOiJhcGlzaXgiLCJpYXQiOjEwMDAwMDAwLCJleHAiOjI1MDAwMDAwMDB9.bfcZsd4ABgo0GoLT8EwfnKgf AWbnJZbZ3kOtqyeSkXYqGlSmgMNW3q5Kx1SGjMNhEKVG_KrFfsPrQmcTljSPZA +--- response_body +success