diff --git a/apisix/ssl/router/radixtree_sni.lua b/apisix/ssl/router/radixtree_sni.lua index 95e39c0ec4cd..5d6e9642ad0c 100644 --- a/apisix/ssl/router/radixtree_sni.lua +++ b/apisix/ssl/router/radixtree_sni.lua @@ -174,12 +174,13 @@ function _M.match_and_set(api_ctx, match_only, alt_sni) local sni_rev = sni:reverse() local ok = radixtree_router:dispatch(sni_rev, nil, api_ctx) if not ok then + -- callers that pass alt_sni decide whether a miss is a failure: the Host + -- re-check in verify_https_client expects misses, and ssl_client_hello_phase + -- logs and marks its own span when the handshake SNI has no certificate if not alt_sni then - -- it is expected that alternative SNI doesn't have a SSL certificate associated - -- with it sometimes core.log.error("failed to find any SSL certificate by SNI: ", sni) + span:set_status(tracer.status.ERROR, "failed match SNI") end - span:set_status(tracer.status.ERROR, "failed match SNI") span:finish(api_ctx.ngx_ctx) return false end diff --git a/t/lib/test_otel.lua b/t/lib/test_otel.lua index fb897cc84896..5e8f77812a2f 100644 --- a/t/lib/test_otel.lua +++ b/t/lib/test_otel.lua @@ -82,6 +82,16 @@ local function verify(spans_by_id, expected, actual, path, errors) path, expected.kind, tostring(actual.kind))) end + if expected.status_code then + -- OTLP JSON omits the status code when it is UNSET (0) + local code = actual.status and actual.status.code or 0 + if code ~= expected.status_code then + table.insert(errors, string.format( + "%s: expected status_code=%d, got=%s", + path, expected.status_code, tostring(code))) + end + end + if expected.attributes then local attr_map = get_attr_map(actual) for key, val in pairs(expected.attributes) do diff --git a/t/plugin/opentelemetry6.t b/t/plugin/opentelemetry6.t index db3590673779..ffd91908904d 100644 --- a/t/plugin/opentelemetry6.t +++ b/t/plugin/opentelemetry6.t @@ -304,3 +304,69 @@ opentracing end } } + + + +=== TEST 10: clear file +--- exec +echo '' > ci/pod/otelcol-contrib/data-otlp.json +--- response_body eval +qr// + + + +=== TEST 11: request whose Host has no SSL object, over a connection whose SNI does +--- init_by_lua_block + require "resty.core" + apisix = require("apisix") + core = require("apisix.core") + apisix.http_init() + + local utils = require("apisix.core.utils") + utils.dns_parse = function (domain) + if domain == "test1.com" then + return {address = "127.0.0.2"} + end + error("unknown domain: " .. domain) + end +--- exec +curl -sk --resolve "test.com:1994:127.0.0.1" -H "Host: localhost" https://test.com:1994/opentracing +--- wait: 5 +--- response_body +opentracing + + + +=== TEST 12: the Host re-check in the access phase does not mark sni_radixtree_match as an error +--- config + location /t { + content_by_lua_block { + local otel = require("lib.test_otel") + + local ok, err = otel.verify_tree( + "ci/pod/otelcol-contrib/data-otlp.json", + { + name = "GET /opentracing", + kind = 2, + attributes = { + ["http.status_code"] = "200", + }, + children = { + { + name = "apisix.phase.access", + kind = 2, + children = { + { name = "sni_radixtree_match", kind = 1, status_code = 0 }, + } + }, + } + } + ) + + if not ok then + ngx.say("FAIL:\n" .. err) + else + ngx.say("passed") + end + } + }