Bug: negotiatedProtocolMustBeAcceptedProtocolTest tests fail with "TLSv1.1 failed to negotiate" on JDK17
Status: Resolved
Priority: Normal
Resolution: Fixed
Created: 20/May/23 00:16
Resolved: 14/Jun/23 18:23

Note: This depends on having a fix for CASSANDRA-18180, otherwise most/all tests in {{NativeTransportEncryptionOptionsTest}} and {{InternodeEncryptionOptionsTest}} are failing due to that issue.

Using the patch for CASSANDRA-18180, the {{negotiatedProtocolMustBeAcceptedProtocolTest}} test in both {{NativeTransportEncryptionOptionsTest}} and {{InternodeEncryptionOptionsTest}} fails with "TLSv1.1 failed to negotiate" on JDK17.

From what I can see, the {{negotiatedProtocolMustBeAcceptedProtocolTest}} is failing because in JDK11 and JDK17 the "TLSv1.1" protocol is disabled.

Since TLSv1.1 is disabled in JDK11 and 17, one possibility is to change the test to use TLSv1.2 instead of TLSv1.1. That should work directly with JDK11 and 17, since TLSv1.2 is one of the defaults, and it won't be an issue for JDK8 as that will be dropped.

Also, I think the point of the {{negotiatedProtocolMustBeAcceptedProtocolTest}} is to test that the {{accepted_protocols}} option is working correctly rather than the choice of _which_ protocol is used. Meaning, I don’t think the intent was to test TLSv1.1 specifically, rather that the mechanism of accepted protocols works and choosing TLSv1.1 was at the time convenient - but I could be wrong.

It also seems to me like bit of a coincidence that these tests are currently working on JDK11, at least on CI. Indeed, running locally with JDK11, these fail for me:

{noformat}
$ pwd
/Users/dan.jatnieks/apache/cassandra-4.0

$ java -version
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)

$ ant test-jvm-dtest-some -Dtest.name=org.apache.cassandra.distributed.test.NativeTransportEncryptionOptionsTest -Duse.jdk11=true

...

[junit-timeout] Testcase: negotiatedProtocolMustBeAcceptedProtocolTest(org.apache.cassandra.distributed.test.NativeTransportEncryptionOptionsTest):	FAILED
[junit-timeout] Should be possible to establish a TLSv1.1 connection expected:<NEGOTIATED> but was:<FAILED_TO_NEGOTIATE>
[junit-timeout] junit.framework.AssertionFailedError: Should be possible to establish a TLSv1.1 connection expected:<NEGOTIATED> but was:<FAILED_TO_NEGOTIATE>
[junit-timeout] 	at org.apache.cassandra.distributed.test.NativeTransportEncryptionOptionsTest.negotiatedProtocolMustBeAcceptedProtocolTest(NativeTransportEncryptionOptionsTest.java:160)
[junit-timeout] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[junit-timeout] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[junit-timeout] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
{noformat}

I believe these work on CI because of CASSANDRA-16848 - in that ticket, after 2021-Apr JDK8 dropped TLSv1.1 which led to a fix in [cassandra-build|https://github.com/apache/cassandra-builds/commit/d1a3a0c59b3c5c17697d6a6656cd5d4f3a1cdbe9] docker code to make sure TLSv1.1 is accepted. 

I say coincidence because this change also makes it work for JDK11 and JDK17, and I've been able to verify that making a change locally to the JDK {{java.security}} file. I’m not sure that at the time of CASSANDRA-16848 it was intended for any JDK versions.

The point of mentioning this is that if {{negotiatedProtocolMustBeAcceptedProtocolTest}} is changed to use TLSv1.2, and support for JDK8 is dropped, then the changes made in CASSANDRA-16848 could also be reverted.