[
https://issues.apache.org/jira/browse/THRIFT-6275?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Sylwester Lachiewicz updated THRIFT-6275:
-----------------------------------------
Description:
Every {{py-go_*-ip-ssl}} row of the cross-test matrix, 18 in all, has been
listed in
[test/known_failures_Linux.json|https://github.com/apache/thrift/blob/master/test/known_failures_Linux.json]
since THRIFT-847 in 2015. Re-running them on a fork branch with the entries
removed shows two defects on the Go client side: one that causes the failures,
and one that a fix for the first exposes on Go 1.27.
h2. 1. The Go cross-test client presents no client certificate
The TLS configuration in
[test/go/src/common/client.go|https://github.com/apache/thrift/blob/master/test/go/src/common/client.go#L46]
sets only {{InsecureSkipVerify}}. The Python test server requires a client
certificate
([test/py/TestServer.py:390|https://github.com/apache/thrift/blob/master/test/py/TestServer.py#L390],
{{cert_reqs=CERT_REQUIRED}}), so every socket transport over SSL fails at the
handshake:
{noformat}
Unexpected error in TestVoid() call: remote error: tls: certificate required
{noformat}
The http-ip-ssl rows pass only because the Python HTTP server does not ask for
one, and rb-go passes because the Ruby server uses {{VERIFY_PEER}} without
failing on an absent certificate. Every other cross-test client that presents a
certificate sends {{client_v3.crt}}.
h2. 2. Go 1.27 and later cannot load client_v3.crt
{{test/keys/client_v3.crt}} lists the alternative names 127.0.0.1, ::1,
::ffff:127.0.0.1 and localhost. Since go1.27.0 Go's x509 parser rejects any
certificate carrying an IPv4-mapped IPv6 address as a SAN, and the TLS client
will not send a certificate it cannot parse:
{noformat}
x509: SAN iPAddress contains IPv4-mapped IPv6 address
{noformat}
Reproduced with Go 1.27.1; Go 1.24.3 and 1.26.2 load the certificate. The
cross-test image builds with Go 1.24.3, so this does not cause the known
failures, but the lib-go job runs on 1.26 and 1.27 and test/go loads the
certificate once the client presents it. THRIFT-3660 added that entry in 2016
so the Python server's peer-address check would match a dual-stack peer. Since
THRIFT-6201 the Python matcher reduces {{::ffff:127.0.0.1}} to {{127.0.0.1}}
before comparing, so the entry is redundant.
A related documentation defect: the recipe in
[test/keys/README.md|https://github.com/apache/thrift/blob/master/test/keys/README.md]
says to sign {{client_v3.crt}} with {{CA.pem}} and {{server.key}}, but the
certificate shipped since the 2022 regeneration is self-signed with
{{client_v3.key}}. A certificate made from the recipe is rejected by the Python
server with {{unable to get local issuer certificate}}.
h2. Proposed fix
* Give the Go test client a {{--certPath}} flag like the server's and load
{{client_v3.crt}} and {{client_v3.key}} into its TLS configuration when
{{--ssl}} is set; pass the flag in {{test/tests.json}}.
* Regenerate {{client_v3.crt}} self-signed with the same key, the same
distinguished name and extensions, and the alternative names 127.0.0.1, ::1 and
localhost. Regenerate {{lib/java/src/crossTest/resources/.clientkeystore}} from
it, as the README describes.
* Correct the README recipe to produce what is shipped.
* Remove the 18 {{py-go_*-ip-ssl}} entries from the known failures.
With those changes, all twelve py-go SSL combinations (binary, compact, json
and header over buffered, framed and zlib) pass locally against a Python server
built from master. The cross-test run behind this analysis is recorded on
THRIFT-5809; THRIFT-4502 tracks the known-failures cleanup in general.
_This issue was created with AI assistance._
was:
Every {{py-go_*-ip-ssl}} row of the cross-test matrix, 18 in all, has been
listed in
[test/known_failures_Linux.json|https://github.com/apache/thrift/blob/master/test/known_failures_Linux.json]
since THRIFT-847 in 2015. Re-running them on a fork branch with the entries
removed shows two defects on the Go client side that stack, so fixing either
alone changes nothing.
h2. 1. The Go cross-test client presents no client certificate
The TLS configuration in
[test/go/src/common/client.go|https://github.com/apache/thrift/blob/master/test/go/src/common/client.go#L46]
sets only {{InsecureSkipVerify}}. The Python test server requires a client
certificate
([test/py/TestServer.py:390|https://github.com/apache/thrift/blob/master/test/py/TestServer.py#L390],
{{cert_reqs=CERT_REQUIRED}}), so every socket transport over SSL fails at the
handshake:
{noformat}
Unexpected error in TestVoid() call: remote error: tls: certificate required
{noformat}
The http-ip-ssl rows pass only because the Python HTTP server does not ask for
one, and rb-go passes because the Ruby server uses {{VERIFY_PEER}} without
failing on an absent certificate. Every other cross-test client that presents a
certificate sends {{client_v3.crt}}.
h2. 2. Go cannot load client_v3.crt
{{test/keys/client_v3.crt}} lists the alternative names 127.0.0.1, ::1,
::ffff:127.0.0.1 and localhost. Go's x509 parser rejects any certificate
carrying an IPv4-mapped IPv6 address as a SAN, and the TLS client will not send
a certificate it cannot parse:
{noformat}
x509: SAN iPAddress contains IPv4-mapped IPv6 address
{noformat}
Reproduced with Go 1.27.1; CI runs 1.26 and 1.27. THRIFT-3660 added that entry
in 2016 so the Python server's peer-address check would match a dual-stack
peer. Since THRIFT-6201 the Python matcher reduces {{::ffff:127.0.0.1}} to
{{127.0.0.1}} before comparing, so the entry is redundant.
A related documentation defect: the recipe in
[test/keys/README.md|https://github.com/apache/thrift/blob/master/test/keys/README.md]
says to sign {{client_v3.crt}} with {{CA.pem}} and {{server.key}}, but the
certificate shipped since the 2022 regeneration is self-signed with
{{client_v3.key}}. A certificate made from the recipe is rejected by the Python
server with {{unable to get local issuer certificate}}.
h2. Proposed fix
* Give the Go test client a {{--certPath}} flag like the server's and load
{{client_v3.crt}} and {{client_v3.key}} into its TLS configuration when
{{--ssl}} is set; pass the flag in {{test/tests.json}}.
* Regenerate {{client_v3.crt}} self-signed with the same key, the same
distinguished name and extensions, and the alternative names 127.0.0.1, ::1 and
localhost. Regenerate {{lib/java/src/crossTest/resources/.clientkeystore}} from
it, as the README describes.
* Correct the README recipe to produce what is shipped.
* Remove the 18 {{py-go_*-ip-ssl}} entries from the known failures.
With those changes, all twelve py-go SSL combinations (binary, compact, json
and header over buffered, framed and zlib) pass locally against a Python server
built from master. The cross-test run behind this analysis is recorded on
THRIFT-5809; THRIFT-4502 tracks the known-failures cleanup in general.
_This issue was created with AI assistance._
Summary: Go cross-test client presents no client certificate, and Go
1.27 cannot load client_v3.crt (was: Go cross-test client presents no client
certificate, and Go cannot load client_v3.crt)
> Go cross-test client presents no client certificate, and Go 1.27 cannot load
> client_v3.crt
> ------------------------------------------------------------------------------------------
>
> Key: THRIFT-6275
> URL: https://issues.apache.org/jira/browse/THRIFT-6275
> Project: Thrift
> Issue Type: Bug
> Components: Go - Library, Test Suite
> Reporter: Sylwester Lachiewicz
> Priority: Major
> Time Spent: 10m
> Remaining Estimate: 0h
>
> Every {{py-go_*-ip-ssl}} row of the cross-test matrix, 18 in all, has been
> listed in
> [test/known_failures_Linux.json|https://github.com/apache/thrift/blob/master/test/known_failures_Linux.json]
> since THRIFT-847 in 2015. Re-running them on a fork branch with the entries
> removed shows two defects on the Go client side: one that causes the
> failures, and one that a fix for the first exposes on Go 1.27.
> h2. 1. The Go cross-test client presents no client certificate
> The TLS configuration in
> [test/go/src/common/client.go|https://github.com/apache/thrift/blob/master/test/go/src/common/client.go#L46]
> sets only {{InsecureSkipVerify}}. The Python test server requires a client
> certificate
> ([test/py/TestServer.py:390|https://github.com/apache/thrift/blob/master/test/py/TestServer.py#L390],
> {{cert_reqs=CERT_REQUIRED}}), so every socket transport over SSL fails at
> the handshake:
> {noformat}
> Unexpected error in TestVoid() call: remote error: tls: certificate required
> {noformat}
> The http-ip-ssl rows pass only because the Python HTTP server does not ask
> for one, and rb-go passes because the Ruby server uses {{VERIFY_PEER}}
> without failing on an absent certificate. Every other cross-test client that
> presents a certificate sends {{client_v3.crt}}.
> h2. 2. Go 1.27 and later cannot load client_v3.crt
> {{test/keys/client_v3.crt}} lists the alternative names 127.0.0.1, ::1,
> ::ffff:127.0.0.1 and localhost. Since go1.27.0 Go's x509 parser rejects any
> certificate carrying an IPv4-mapped IPv6 address as a SAN, and the TLS client
> will not send a certificate it cannot parse:
> {noformat}
> x509: SAN iPAddress contains IPv4-mapped IPv6 address
> {noformat}
> Reproduced with Go 1.27.1; Go 1.24.3 and 1.26.2 load the certificate. The
> cross-test image builds with Go 1.24.3, so this does not cause the known
> failures, but the lib-go job runs on 1.26 and 1.27 and test/go loads the
> certificate once the client presents it. THRIFT-3660 added that entry in 2016
> so the Python server's peer-address check would match a dual-stack peer.
> Since THRIFT-6201 the Python matcher reduces {{::ffff:127.0.0.1}} to
> {{127.0.0.1}} before comparing, so the entry is redundant.
> A related documentation defect: the recipe in
> [test/keys/README.md|https://github.com/apache/thrift/blob/master/test/keys/README.md]
> says to sign {{client_v3.crt}} with {{CA.pem}} and {{server.key}}, but the
> certificate shipped since the 2022 regeneration is self-signed with
> {{client_v3.key}}. A certificate made from the recipe is rejected by the
> Python server with {{unable to get local issuer certificate}}.
> h2. Proposed fix
> * Give the Go test client a {{--certPath}} flag like the server's and load
> {{client_v3.crt}} and {{client_v3.key}} into its TLS configuration when
> {{--ssl}} is set; pass the flag in {{test/tests.json}}.
> * Regenerate {{client_v3.crt}} self-signed with the same key, the same
> distinguished name and extensions, and the alternative names 127.0.0.1, ::1
> and localhost. Regenerate
> {{lib/java/src/crossTest/resources/.clientkeystore}} from it, as the README
> describes.
> * Correct the README recipe to produce what is shipped.
> * Remove the 18 {{py-go_*-ip-ssl}} entries from the known failures.
> With those changes, all twelve py-go SSL combinations (binary, compact, json
> and header over buffered, framed and zlib) pass locally against a Python
> server built from master. The cross-test run behind this analysis is recorded
> on THRIFT-5809; THRIFT-4502 tracks the known-failures cleanup in general.
> _This issue was created with AI assistance._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)