This is an automated email from the ASF dual-hosted git repository.
wenming 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 aaad8ba42 feat: add support for "system" ssl_trusted_certificate
(#11809)
aaad8ba42 is described below
commit aaad8ba4276452a608649511a1d210eb2e4fddb8
Author: Ashish Tiwari <[email protected]>
AuthorDate: Mon Dec 9 15:05:51 2024 +0530
feat: add support for "system" ssl_trusted_certificate (#11809)
---
apisix/cli/ops.lua | 36 +++++++++++++++++++++------
apisix/cli/schema.lua | 3 +++
apisix/cli/util.lua | 53 +++++++++++++++++++++++++++++++++++++++
conf/config.yaml.example | 5 ++--
t/cli/test_stream_config.sh | 3 ++-
t/cli/test_upstream_mtls.sh | 60 +++++++++++++++++++++++++++++++++++++++++++++
t/core/config_etcd.t | 2 +-
7 files changed, 150 insertions(+), 12 deletions(-)
diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua
index 16547fce3..c10bcfaa7 100644
--- a/apisix/cli/ops.lua
+++ b/apisix/cli/ops.lua
@@ -49,6 +49,9 @@ local str_find = string.find
local str_byte = string.byte
local str_sub = string.sub
local str_format = string.format
+local string = string
+local table = table
+
local _M = {}
@@ -502,17 +505,34 @@ Please modify "admin_key" in conf/config.yaml .
if yaml_conf.apisix.ssl.ssl_trusted_certificate ~= nil then
- local cert_path = yaml_conf.apisix.ssl.ssl_trusted_certificate
- -- During validation, the path is relative to PWD
- -- When Nginx starts, the path is relative to conf
- -- Therefore we need to check the absolute version instead
- cert_path = pl_path.abspath(cert_path)
+ local cert_paths = {}
+ local ssl_certificates = yaml_conf.apisix.ssl.ssl_trusted_certificate
+ for cert_path in string.gmatch(ssl_certificates, '([^,]+)') do
+ cert_path = util.trim(cert_path)
+ if cert_path == "system" then
+ local trusted_certs_path, err =
util.get_system_trusted_certs_filepath()
+ if not trusted_certs_path then
+ util.die(err)
+ end
+ table.insert(cert_paths, trusted_certs_path)
+ else
+ -- During validation, the path is relative to PWD
+ -- When Nginx starts, the path is relative to conf
+ -- Therefore we need to check the absolute version instead
+ cert_path = pl_path.abspath(cert_path)
+ if not pl_path.exists(cert_path) then
+ util.die("certificate path", cert_path, "doesn't exist\n")
+ end
- if not pl_path.exists(cert_path) then
- util.die("certificate path", cert_path, "doesn't exist\n")
+ table.insert(cert_paths, cert_path)
+ end
end
- yaml_conf.apisix.ssl.ssl_trusted_certificate = cert_path
+ local combined_cert_filepath =
yaml_conf.apisix.ssl.ssl_trusted_combined_path
+ or
"/usr/local/apisix/conf/ssl_trusted_combined.pem"
+ util.gen_trusted_certs_combined_file(combined_cert_filepath,
cert_paths)
+
+ yaml_conf.apisix.ssl.ssl_trusted_certificate = combined_cert_filepath
end
-- enable ssl with place holder crt&key
diff --git a/apisix/cli/schema.lua b/apisix/cli/schema.lua
index e6720f88f..1def95484 100644
--- a/apisix/cli/schema.lua
+++ b/apisix/cli/schema.lua
@@ -209,6 +209,9 @@ local config_schema = {
ssl_trusted_certificate = {
type = "string",
},
+ ssl_trusted_combined_path = {
+ type = "string",
+ },
listen = {
type = "array",
items = {
diff --git a/apisix/cli/util.lua b/apisix/cli/util.lua
index bcd56a241..d69468efb 100644
--- a/apisix/cli/util.lua
+++ b/apisix/cli/util.lua
@@ -24,6 +24,9 @@ local exit = os.exit
local stderr = io.stderr
local str_format = string.format
local tonumber = tonumber
+local io = io
+local ipairs = ipairs
+local assert = assert
local _M = {}
@@ -133,4 +136,54 @@ function _M.file_exists(file_path)
return f ~= nil and close(f)
end
+do
+ local trusted_certs_paths = {
+ "/etc/ssl/certs/ca-certificates.crt", --
Debian/Ubuntu/Gentoo
+ "/etc/pki/tls/certs/ca-bundle.crt", -- Fedora/RHEL 6
+ "/etc/ssl/ca-bundle.pem", -- OpenSUSE
+ "/etc/pki/tls/cacert.pem", -- OpenELEC
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", -- CentOS/RHEL 7
+ "/etc/ssl/cert.pem", -- OpenBSD, Alpine
+ }
+
+ -- Check if a file exists using Lua's built-in `io.open`
+ local function file_exists(path)
+ local file = io.open(path, "r")
+ if file then
+ file:close()
+ return true
+ else
+ return false
+ end
+ end
+
+ function _M.get_system_trusted_certs_filepath()
+ for _, path in ipairs(trusted_certs_paths) do
+ if file_exists(path) then
+ return path
+ end
+ end
+
+ return nil,
+ "Could not find trusted certs file in " ..
+ "any of the `system`-predefined locations. " ..
+ "Please install a certs file there or set " ..
+ "`lua_ssl_trusted_certificate` to a " ..
+ "specific file path instead of `system`"
+ end
+end
+
+
+function _M.gen_trusted_certs_combined_file(combined_filepath, paths)
+ local combined_file = assert(io.open(combined_filepath, "w"))
+ for _, path in ipairs(paths) do
+ local cert_file = assert(io.open(path, "r"))
+ combined_file:write(cert_file:read("*a"))
+ combined_file:write("\n")
+ cert_file:close()
+ end
+ combined_file:close()
+end
+
+
return _M
diff --git a/conf/config.yaml.example b/conf/config.yaml.example
index eea2335bc..d6846642f 100644
--- a/conf/config.yaml.example
+++ b/conf/config.yaml.example
@@ -99,8 +99,9 @@ apisix:
# - ip: 127.0.0.3 # If not set, default to
`0.0.0.0`.
# port: 9445
# enable_http3: true
- # ssl_trusted_certificate: /path/to/ca-cert # Set the path to CA
certificates used to verify client
- # certificates in the PEM
format.
+ ssl_trusted_combined_path: /usr/local/apisix/conf/ssl_trusted_combined.pem
# All the trusted certificates will be combined into a single file
+ #ssl_trusted_certificate: system # Specifies comma separated
list of trusted CA. Value can be either "system"(for using system available ca
certs) or
+ # a file path with trusted CA
certificates in the PEM format
ssl_protocols: TLSv1.2 TLSv1.3 # TLS versions supported.
ssl_ciphers:
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl_session_tickets: false # If true, session tickets are used for
SSL/TLS connections.
diff --git a/t/cli/test_stream_config.sh b/t/cli/test_stream_config.sh
index baab138a0..2843b5c5d 100755
--- a/t/cli/test_stream_config.sh
+++ b/t/cli/test_stream_config.sh
@@ -78,6 +78,7 @@ echo "
apisix:
ssl:
ssl_trusted_certificate: t/certs/mtls_ca.crt
+ ssl_trusted_combined_path: t/certs/mtls_ca_combined.crt
proxy_mode: http&stream
stream_proxy:
tcp:
@@ -86,7 +87,7 @@ apisix:
make init
-if ! grep "t/certs/mtls_ca.crt;" conf/nginx.conf > /dev/null; then
+if ! grep "t/certs/mtls_ca_combined.crt;" conf/nginx.conf > /dev/null; then
echo "failed: failed to set trust certificate"
exit 1
fi
diff --git a/t/cli/test_upstream_mtls.sh b/t/cli/test_upstream_mtls.sh
index 0318a4539..b2b366aa0 100755
--- a/t/cli/test_upstream_mtls.sh
+++ b/t/cli/test_upstream_mtls.sh
@@ -149,3 +149,63 @@ if ! grep -E 'self-signed certificate' logs/error.log; then
fi
echo "passed: when proxy_ssl_verify is enabled and ssl_trusted_certificate is
wrong ca cert, got 502"
+
+
+# test combined proxy_ssl_trusted_certificate success
+echo '
+apisix:
+ ssl:
+ ssl_trusted_certificate: system, t/certs/apisix.crt
+nginx_config:
+ http_configuration_snippet: |
+ server {
+ listen 1983 ssl;
+ server_name test.com;
+ ssl_certificate ../t/certs/apisix.crt;
+ ssl_certificate_key ../t/certs/apisix.key;
+ location /hello {
+ return 200 "hello world";
+ }
+ }
+ http_server_configuration_snippet: |
+ proxy_ssl_verify on;
+' > conf/config.yaml
+
+rm logs/error.log || true
+make init
+make run
+sleep 0.1
+
+curl -k -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY:
edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
+{
+ "uri": "/hello",
+ "upstream": {
+ "pass_host": "rewrite",
+ "nodes": {
+ "127.0.0.1:1983": 1
+ },
+ "scheme": "https",
+ "hash_on": "vars",
+ "upstream_host": "test.com",
+ "type": "roundrobin",
+ "tls": {
+ "client_cert": "-----BEGIN
CERTIFICATE-----\nMIIEojCCAwqgAwIBAgIJAK253pMhgCkxMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV\nBAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxDzANBgNVBAcMBlpodUhhaTEPMA0G\nA1UECgwGaXJlc3R5MREwDwYDVQQDDAh0ZXN0LmNvbTAgFw0xOTA2MjQyMjE4MDVa\nGA8yMTE5MDUzMTIyMTgwNVowVjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5n\nRG9uZzEPMA0GA1UEBwwGWmh1SGFpMQ8wDQYDVQQKDAZpcmVzdHkxETAPBgNVBAMM\nCHRlc3QuY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyCM0rqJe\ncvgnCfOw4fATotPwk5Ba0gC2YvIrO+gSbQkyxXF
[...]
+ "client_key":
"HrMHUvE9Esvn7GnZ+vAynaIg/8wlB3r0zm0htmnwofYLp1VhtLeU1EmMJkPLUkcn2+v6Uav9bOQMkPdSpUMcEpRplLSXs+miu+B07CCUnsMrXkfQawRMIoePJZSLH5+PfDAlWIK2Q+ruYnjtnpNziiAtXf/HRRwHHMelnfedXqD8kn3Toe46ZYyBir99o/r/do5ludez5oY7qhOgNSWKCfnZE8Ip82g7t7n7jsAf5tTdRulUGBQ4ITV2zM3cxpD0PWnWMbOfygZIDxR8QU9wj8ihuFL1s1NM8PplcKbUxC4QlrSN+ZNkr6mxy+akPmXlABwcFIiSK7c/xvU1NjoILnhPpL6aRpbhmQX/a1XUCl+2INlQ5QbXbTN+JmDBhrU9NiYecRJMfmA1N/lhwgt01tUnxMoAhfpUVgEbZNalCJt+wn8TC+Xp3DZ0bCpXrfzqsprGKan9qC3mCN03j
[...]
+ }
+ }
+}'
+
+sleep 1
+
+code=$(curl -v -k -i -m 20 -o /dev/null -s -w %{http_code}
http://127.0.0.1:9080/hello)
+
+if [ ! $code -eq 200 ]; then
+ echo "failed: connection to upstream with mTLS failed"
+ exit 1
+fi
+
+sleep 0.1
+
+make stop
+
+echo "passed: connection to upstream with mTLS success"
diff --git a/t/core/config_etcd.t b/t/core/config_etcd.t
index 7f31fc859..75b0e9bb6 100644
--- a/t/core/config_etcd.t
+++ b/t/core/config_etcd.t
@@ -60,7 +60,7 @@ qr/(connection refused){1,}/
apisix:
node_listen: 1984
ssl:
- ssl_trusted_certificate: t/servroot/conf/cert/etcd.pem
+ ssl_trusted_combined_path: t/servroot/conf/cert/etcd.pem
deployment:
role: traditional
role_traditional: