From aa6cb97335610502f4d0a48a29c957eb03702371 Mon Sep 17 00:00:00 2001 From: Walker Zhao Date: Wed, 22 Apr 2026 18:03:43 +0800 Subject: [PATCH] add ssl_trusted_store option to connect for custom CA store Passes the value to `tcpsock:settrustedstore` when available, errors out otherwise, and folds it into the default pool name so connections with different trusted stores are not reused. Signed-off-by: Walker Zhao --- README.md | 1 + lib/resty/http_connect.lua | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/README.md b/README.md index 59c02f5a..cd5ce4fe 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,7 @@ The options table has the following fields: * `ssl_send_status_req`: option as per [OpenResty docs](https://github.com/openresty/lua-nginx-module#tcpsocksslhandshake) * `ssl_client_cert`: will be passed to `tcpsock:setclientcert`. Requires `ngx_lua_http_module` >= v0.10.23. * `ssl_client_priv_key`: as above. +* `ssl_trusted_store`: a custom trusted CA store (cdata `X509_STORE*`) to verify the server certificate against, passed to `tcpsock:settrustedstore`. Requires a cosocket build with `settrustedstore` support. ## set\_timeout diff --git a/lib/resty/http_connect.lua b/lib/resty/http_connect.lua index 83b6d2f4..068cdc3f 100644 --- a/lib/resty/http_connect.lua +++ b/lib/resty/http_connect.lua @@ -53,6 +53,11 @@ client:connect { ssl_client_cert = nil, ssl_client_priv_key = nil, + -- Custom trusted CA store (cdata `X509_STORE*`), passed to + -- `tcpsock:settrustedstore`. Requires a cosocket build with + -- `settrustedstore` support. + ssl_trusted_store = nil, + proxy_opts, -- proxy opts, defaults to global proxy options } ]] @@ -81,6 +86,7 @@ local function connect(self, options) -- ssl settings local ssl, ssl_reused_session, ssl_server_name local ssl_verify, ssl_send_status_req, ssl_client_cert, ssl_client_priv_key + local ssl_trusted_store if request_scheme == "https" then ssl = true ssl_reused_session = options.ssl_reused_session @@ -92,6 +98,7 @@ local function connect(self, options) end ssl_client_cert = options.ssl_client_cert ssl_client_priv_key = options.ssl_client_priv_key + ssl_trusted_store = options.ssl_trusted_store end -- proxy related settings @@ -244,6 +251,7 @@ local function connect(self, options) .. ":" .. (proxy_uri or "") .. ":" .. (request_scheme == "https" and proxy_authorization or "") .. ":" .. (cert_hash or "") + .. ":" .. tostring(ssl_trusted_store or "") -- in the above we only add the 'proxy_authorization' as part of the poolname -- when the request is https. Because in that case the CONNECT request (which -- carries the authorization header) is part of the connect procedure, whereas @@ -320,6 +328,19 @@ local function connect(self, options) end end + -- Custom trusted CA store support + if ssl_trusted_store then + if type(sock.settrustedstore) ~= "function" then + return nil, "cannot use ssl_trusted_store without settrustedstore support" + + else + ok, err = sock:settrustedstore(ssl_trusted_store) + if not ok then + return nil, "could not set trusted store: " .. err + end + end + end + ssl_session, err = sock:sslhandshake(ssl_reused_session, ssl_server_name, ssl_verify, ssl_send_status_req) if not ssl_session then self:close()