Crazy-xyr commented on issue #12641:
URL: https://github.com/apache/apisix/issues/12641#issuecomment-3345601817

   @Baoyuantop I found through the current `lua-resty-healthcheck-api7 = 3.2.0` 
test that healthcheck is unable to send the client certificate. Check the 
source code, is found 
ngx.socket.tcp():[setclientcert](https://github.com/openresty/lua-nginx-module?tab=readme-ov-file#tcpsocksetclientcert)
  that sets the client certificate, but does not send it during the 
sock:handshake().
   
   Does `apisix` have any additional patch or modifications to 
`ngx.socket.tcp()` ? The same TEST1 `content_by_lua_block` works in the 
openresty environment
   
   healthcheck.lua [source 
code](https://github.com/api7/lua-resty-healthcheck/blob/09a672e0784c75231ceca51e0a4cb39313c020f5/lib/resty/healthcheck.lua#L1036-L1158)
   <details>
   <summary> Reproduce in the test unit </summary>
   
   ```t
   
   BEGIN {
       if ($ENV{TEST_EVENTS_MODULE} ne "lua-resty-events") {
           $SkipReason = "Only for lua-resty-events events module";
       }
   }
   
   use t::APISIX 'no_plan';
   
   repeat_each(1);
   log_level('info');
   no_root_location();
   no_shuffle();
   worker_connections(256);
   
   
   add_block_preprocessor(sub {
       my ($block) = @_;
   
       if (!$block->http_config) {
           my $http_config = <<'_EOC_';
   lua_shared_dict test_shm 8m;
   
   server {
       listen 8765 ssl;
       ssl_certificate ../../certs/mtls_server.crt;
       ssl_certificate_key ../../certs/mtls_server.key;
       ssl_client_certificate ../../certs/mtls_ca.crt;
       ssl_verify_client on;
   
       location /healthz {
           return 200 'ok';
       }
   }
   
   _EOC_
           $block->set_value("http_config", $http_config);
       }
   
       if (!$block->request) {
           $block->set_value("request", "GET /t");
       }
   
   });
   
   run_tests();
   
   __DATA__
   
   === TEST 1: mtls check via healthcheck
   --- config
       location /t {
           content_by_lua_block {
               local events = require("apisix.events")
   
               -- ngx.say(events:get_healthcheck_events_module())
   
               local f = assert(io.open('/workspace/t/certs/mtls_client.crt'))
               local cert_data = f:read('*a')
               f:close()
               f = assert(io.open('/workspace/t/certs/mtls_client.key'))
               local key_data = f:read('*a')
               f:close()
   
               local healthcheck = require("resty.healthcheck")
               local checker = healthcheck.new({
                   name = "testing",
                   shm_name = "test_shm",
                   events_module = events:get_healthcheck_events_module(),
                   ssl_cert = cert,
                   ssl_key = key,
                   checks = {
                   active = {
                           type = "https",
                           https_verify_certificate = false,
                           http_path = "/healthz",
                           healthy  = {
                               interval = 1,
                               successes = 3
                           },
                           unhealthy  = {
                               interval = 1,
                               http_failures = 3,
                           }
                       },
                   }
               })
   
               local ok, err = checker:add_target("127.0.0.1", 8765, 
"127.0.0.1", false)
               ngx.sleep(3) -- wait for check
               ngx.status = 200
               ngx.say("passed")
           }
           
       }
   --- request
   GET /t
   --- response_body
   passed
   --- error_log
   client sent no required SSL certificate
   
   
   
   === TEST 2: mtls check via socket
   --- config
       location /t {
           content_by_lua_block {
               local f = assert(io.open('/workspace/t/certs/mtls_client.crt'))
               local cert_data = f:read('*a')
               f:close()
               f = assert(io.open('/workspace/t/certs/mtls_client.key'))
               local key_data = f:read('*a')
               f:close()
   
   
               local ssl = require('ngx.ssl')
               local cert = assert(ssl.parse_pem_cert(cert_data))
               local key = assert(ssl.parse_pem_priv_key(key_data))
               ngx.log(ngx.ERR, "cert: ", type(cert)," key: ",type(key))
   
   
               local sock = ngx.socket.tcp()
               sock:settimeout(6000) 
   
               local ok, err = sock:connect("127.0.0.1", 8765)
               if not ok then
                   ngx.say("err: ", err)
                   return
               end
   
               ok, err = sock:setclientcert(cert, key)
               if not ok then
                   ngx.say("err: ", err)
                   sock:close()
                   ngx.status = 500
                   return
               end
   
               session, err = sock:sslhandshake(nil,"127.0.0.1")
               if not session then
                   ngx.say("err: ", err)
                   sock:close()
                   ngx.status = 500
                   return
               end
   
               local req = "GET /healthz HTTP/1.1\r\nConnection: close\r\nHost: 
127.0.0.1\r\n\r\n"
               ok, err = sock:send(req)
               if not ok then
                   ngx.say("err: ", err)
                   sock:close()
                   ngx.status = 500
                   return
               end
   
               local response, err = sock:receive()
               if not response then
                   ngx.say("err: ", err)
                   sock:close()
                   ngx.status = 500
                   return
               end
   
               local re_find = ngx.re.find
               local from, to = re_find(response,
                             [[^HTTP/\d+\.\d+\s+(\d+)]],
                             "joi", nil, 1)
               local status
   
               if from then
                   status = tonumber(response:sub(from, to))
               else
                   status = 500
               end
   
               ngx.status = status
               ngx.say(response)
           }
           
       }
   --- request
   GET /t
   --- error_code: 400
   --- response_body
   HTTP/1.1 400 Bad Request
   --- error_log
   cert: cdata key: cdata
   client sent no required SSL certificate
   ```
   </details>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to