From 14e213b58e332da5b760b246e2b70e301d190e3f Mon Sep 17 00:00:00 2001 From: Jochen Arnold Date: Mon, 2 Mar 2026 16:16:25 +0000 Subject: [PATCH] Support secrets for client ca --- apisix/schema_def.lua | 7 +- apisix/ssl.lua | 8 +- apisix/ssl/router/radixtree_sni.lua | 6 +- docs/en/latest/terminology/secret.md | 4 +- t/node/ssl.t | 113 ++++++++++++++++++++++++++- 5 files changed, 128 insertions(+), 10 deletions(-) diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua index c66f4bc2f03f..e5448ac70df9 100644 --- a/apisix/schema_def.lua +++ b/apisix/schema_def.lua @@ -838,7 +838,12 @@ _M.ssl = { client = { type = "object", properties = { - ca = certificate_scheme, + ca = { + oneOf = { + certificate_scheme, + secret_uri_schema + } + }, depth = { type = "integer", minimum = 0, diff --git a/apisix/ssl.lua b/apisix/ssl.lua index 2bd757077ebc..f0e9b235b5f0 100644 --- a/apisix/ssl.lua +++ b/apisix/ssl.lua @@ -300,9 +300,11 @@ function _M.check_ssl_conf(in_dp, conf) return nil, "client tls verify unsupported" end - local ok, err = validate(conf.client.ca, nil) - if not ok then - return nil, "failed to validate client_cert: " .. err + if not secret.check_secret_uri(conf.client.ca) then + local ok, err = validate(conf.client.ca, nil) + if not ok then + return nil, "failed to validate client_cert: " .. err + end end end diff --git a/apisix/ssl/router/radixtree_sni.lua b/apisix/ssl/router/radixtree_sni.lua index 15ea67225fc4..fbce200bba87 100644 --- a/apisix/ssl/router/radixtree_sni.lua +++ b/apisix/ssl/router/radixtree_sni.lua @@ -253,9 +253,9 @@ function _M.set(matched_ssl, sni) return false, err end - if matched_ssl.value.client then - local ca_cert = matched_ssl.value.client.ca - local depth = matched_ssl.value.client.depth + if new_ssl_value.client then + local ca_cert = new_ssl_value.client.ca + local depth = new_ssl_value.client.depth if apisix_ssl.support_client_verification() then local parsed_cert, err = apisix_ssl.fetch_cert(sni, ca_cert) if not parsed_cert then diff --git a/docs/en/latest/terminology/secret.md b/docs/en/latest/terminology/secret.md index 94c1b8843b0a..76185e7f2326 100644 --- a/docs/en/latest/terminology/secret.md +++ b/docs/en/latest/terminology/secret.md @@ -23,10 +23,10 @@ title: Secret ## Description -Secrets refer to any sensitive information required during the running process of APISIX, which may be part of the core configuration (such as the etcd's password) or some sensitive information in the plugin. Common types of Secrets in APISIX include: +Secrets refer to any sensitive information required during the running process of APISIX, which may be part of the core configuration (such as the etcd's password), cryptographic material or some sensitive information in the plugin. Common types of Secrets in APISIX include: - username, the password for some components (etcd, Redis, Kafka, etc.) -- the private key of the certificate +- the public certificate, private key and ca certificates - API key - Sensitive plugin configuration fields, typically used for authentication, hashing, signing, or encryption diff --git a/t/node/ssl.t b/t/node/ssl.t index 33347366e975..fe7537812d52 100644 --- a/t/node/ssl.t +++ b/t/node/ssl.t @@ -30,6 +30,7 @@ BEGIN { set_env_from_file('TEST_KEY', 't/certs/apisix.key'); set_env_from_file('TEST2_CERT', 't/certs/test2.crt'); set_env_from_file('TEST2_KEY', 't/certs/test2.key'); + set_env_from_file('TEST_CA_CERT', 't/certs/mtls_ca.crt'); } use t::APISIX 'no_plan'; @@ -67,7 +68,8 @@ VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/ssl \ test.com.crt=@t/certs/apisix.crt \ test.com.key=@t/certs/apisix.key \ test.com.2.crt=@t/certs/test2.crt \ - test.com.2.key=@t/certs/test2.key + test.com.2.key=@t/certs/test2.key \ + test.com.3.client-ca.crt=@t/certs/mtls_ca.crt --- response_body Success! Data written to: kv/apisix/ssl @@ -241,3 +243,112 @@ fetching data from env uri fetching data from env uri fetching data from env uri fetching data from env uri + + +=== TEST 8: set ssl with cert, key and client ca in vault +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + local t = require("lib.test_admin") + + local data = { + snis = {"test.com"}, + key = "$secret://vault/test/ssl/test.com.key", + cert = "$secret://vault/test/ssl/test.com.crt", + client = { + ca = "$secret://vault/test/ssl/test.com.3.client-ca.key" + }, + } + + local code, body = t.test('/apisix/admin/ssls/1', + ngx.HTTP_PUT, + core.json.encode(data), + [[{ + "value": { + "snis": ["test.com"], + "key": "$secret://vault/test/ssl/test.com.key", + "cert": "$secret://vault/test/ssl/test.com.crt", + "client": { + "ca": "$secret://vault/test/ssl/test.com.3.client-ca.crt" + } + }, + "key": "/apisix/ssls/1" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + +=== TEST 9: access to https with test.com +--- exec +curl -s -k --cacert ./t/certs/mtls_ca.crt --key ./t/certs/mtls_client.key --cert ./t/certs/mtls_client.crt https://test.com:1994/hello +--- response_body +hello world +--- error_log +fetching data from env uri +fetching data from env uri +fetching data from env uri +fetching data from env uri + + +=== TEST 10: set ssl with cert, key and client ca in env +--- config + location /t { + content_by_lua_block { + local core = require("apisix.core") + local t = require("lib.test_admin") + + local data = { + snis = {"test.com"}, + key = "$env://TEST_KEY", + cert = "$env://TEST_CERT", + client = { + ca = "$env://TEST_CA_CERT" + }, + } + + local code, body = t.test('/apisix/admin/ssls/1', + ngx.HTTP_PUT, + core.json.encode(data), + [[{ + "value": { + "snis": ["test.com"], + "key": "$env://TEST_KEY", + "cert": "$env://TEST_CERT", + "client": { + "ca": "$env://TEST_CA_CERT" + }, + }, + "key": "/apisix/ssls/1" + }]] + ) + + ngx.status = code + ngx.say(body) + } + } +--- request +GET /t +--- response_body +passed + + + +=== TEST 11: access to https with test.com +--- exec +curl -s -k --cacert ./t/certs/mtls_ca.crt --key ./t/certs/mtls_client.key --cert ./t/certs/mtls_client.crt https://test.com:1994/hello +--- response_body +hello world +--- error_log +fetching data from env uri +fetching data from env uri +fetching data from env uri +fetching data from env uri \ No newline at end of file