diff --git a/src/ngx_http_apisix_module.c b/src/ngx_http_apisix_module.c index 3c17fb5..98778d9 100644 --- a/src/ngx_http_apisix_module.c +++ b/src/ngx_http_apisix_module.c @@ -323,7 +323,6 @@ ngx_http_apisix_set_upstream_ssl(ngx_http_request_t *r, ngx_connection_t *c) if (ctx->upstream_cert != NULL) { cert = ctx->upstream_cert; pkey = ctx->upstream_pkey; - store = ctx->upstream_trusted_store; if (sk_X509_num(cert) < 1) { ngx_ssl_error(NGX_LOG_ERR, c->log, 0, @@ -364,16 +363,20 @@ ngx_http_apisix_set_upstream_ssl(ngx_http_request_t *r, ngx_connection_t *c) "SSL_use_PrivateKey() failed"); goto failed; } + } - if (store != NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, - "overriding upstream SSL trusted store"); - - if (SSL_set1_verify_cert_store(sc, store) == 0) { - ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, - "SSL_set1_verify_cert_store() failed"); - goto failed; - } + /* the trusted store is independent of the client certificate: verifying the + * upstream against a caller-supplied CA must work without mTLS too */ + store = ctx->upstream_trusted_store; + + if (store != NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "overriding upstream SSL trusted store"); + + if (SSL_set1_verify_cert_store(sc, store) == 0) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, + "SSL_set1_verify_cert_store() failed"); + goto failed; } } diff --git a/t/upstream_mtls2.t b/t/upstream_mtls2.t index ac13796..4a2a67e 100644 --- a/t/upstream_mtls2.t +++ b/t/upstream_mtls2.t @@ -129,3 +129,90 @@ unable to verify the first certificate --- response_body ok + + + +=== TEST 3: without a trusted store, the upstream is verified against proxy_ssl_trusted_certificate +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name admin.apisix.dev; + ssl_certificate ../../certs/mtls_server.crt; + ssl_certificate_key ../../certs/mtls_server.key; + + server_tokens off; + + location /foo { + return 200 'ok\n'; + } + } +--- config + location /t { + proxy_ssl_trusted_certificate ../../certs/mtls_client.crt; + proxy_ssl_verify on; + proxy_ssl_name admin.apisix.dev; + proxy_pass https://unix:$TEST_NGINX_HTML_DIR/nginx.sock:/foo; + } +--- error_code: 502 +--- error_log +unable to verify the first certificate + + + +=== TEST 4: set only the trusted store, without a client certificate +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name admin.apisix.dev; + ssl_certificate ../../certs/mtls_server.crt; + ssl_certificate_key ../../certs/mtls_server.key; + + server_tokens off; + + location /foo { + return 200 'ok\n'; + } + } +--- config + location /t { + access_by_lua_block { + local upstream = require("resty.apisix.upstream") + local openssl_x509_store = require "resty.openssl.x509.store" + local openssl_x509 = require "resty.openssl.x509" + + local f = assert(io.open("t/certs/mtls_ca.crt")) + local ca_data = f:read("*a") + f:close() + + local trust_store, err = openssl_x509_store.new() + if not trust_store then + ngx.log(ngx.ERR, "failed to create trust store: ", err) + ngx.exit(500) + end + + local x509, err = openssl_x509.new(ca_data, "PEM") + if not x509 then + ngx.log(ngx.ERR, "failed to parse ca cert: ", err) + ngx.exit(500) + end + + local ok, err = trust_store:add(x509) + if not ok then + ngx.log(ngx.ERR, "failed to add ca cert to trust store: ", err) + ngx.exit(500) + end + + local ok, err = upstream.set_ssl_trusted_store(trust_store) + if not ok then + ngx.log(ngx.ERR, "set_ssl_trusted_store failed: ", err) + ngx.exit(500) + end + } + + proxy_ssl_trusted_certificate ../../certs/mtls_client.crt; + proxy_ssl_verify on; + proxy_ssl_name admin.apisix.dev; + proxy_pass https://unix:$TEST_NGINX_HTML_DIR/nginx.sock:/foo; + } +--- response_body +ok