Re: TLS protocol configuration for secure internode messaging needs improvement before the final 4.0 release

2020-10-01 Thread Dinesh Joshi
+1 on it. It looks like a reasonable change.

Dinesh

> On Oct 1, 2020, at 4:31 PM, Jon Meredith  wrote:
> 
> I didn't receive any feedback on the previous email I sent about this
> on September 23rd. A couple of people pointed out the email got
> flagged as suspicious so I've updated the an older JIRA that captures
> the same problem instead.
> 
> https://issues.apache.org/jira/browse/CASSANDRA-13325
> 
> Please take a look if you have experience or interested in restricting
> TLS protocol versions and logging of configured/active
> protocols/ciphers.
> 
> -
> To unsubscribe, e-mail: dev-unsubscr...@cassandra.apache.org
> For additional commands, e-mail: dev-h...@cassandra.apache.org
> 


-
To unsubscribe, e-mail: dev-unsubscr...@cassandra.apache.org
For additional commands, e-mail: dev-h...@cassandra.apache.org



TLS protocol configuration for secure internode messaging needs improvement before the final 4.0 release

2020-10-01 Thread Jon Meredith
I didn't receive any feedback on the previous email I sent about this
on September 23rd. A couple of people pointed out the email got
flagged as suspicious so I've updated the an older JIRA that captures
the same problem instead.

https://issues.apache.org/jira/browse/CASSANDRA-13325

Please take a look if you have experience or interested in restricting
TLS protocol versions and logging of configured/active
protocols/ciphers.

-
To unsubscribe, e-mail: dev-unsubscr...@cassandra.apache.org
For additional commands, e-mail: dev-h...@cassandra.apache.org



TLS protocol configuration for secure internode messaging needs improvement before the final 4.0 release.

2020-09-23 Thread Jon Meredith
tl;dr Setting encryption_options.protocol does not control which TLS
protocols are accepted, only restricting cipher_suites by protocol
does and I think we should fix encryption_options.protocol to actually
restrict, and have a proposal to do so at the end of the email.


I've been investigating restricting the TLS protocols to prevent use
of TLSv1 & TLSv1.1 for secure internode messaging and streaming
connections and think the current implementation needs improvement
before the final 4.0 release.

The Apache Cassandra documentation page on security
https://cassandra.apache.org/doc/latest/operating/security.html
mentions

"...  the JVM defaults for supported protocols and cipher suites are
used when encryption is enabled. These can be overidden using the
settings in cassandra.yaml, but this is not recommended unless there
are policies in place which dictate certain settings or a need to
disable vulnerable ciphers or protocols in cases where the JVM cannot
be updated."

The implication to me there is that the preferred mechanism is to
configure the JSSE subsystem. Trawling through documentation, the
operator can disable older TLS protocol at the JVM level by creating
new security properties file

$ cat conf/cassandra-security.properties
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, anon, NULL, TLSv1, TLSv1.1

And appending to the current security properties using

  -Djava.security.properties=conf/cassandra-security.properties.

This works fine pre-4.0, however the introduction of Netty tcnative
which uses OpenSSL under the hood, does not use the
java.security.properties to restrict anything. Neither does it
implement the calls for supporting the OpenSSL configuration file. It
only seems possible to restrict the protocol & ciphers through the
Netty SSLContext API. It is possible to disable OpenSSL by setting the
Java system property cassandra.disable_tcactive_openssl=true, but it
seems undesirable to lose the performance benefit there.

Looking in cassandra.yaml, under 'More advanced defaults' there is a
‘protocol' setting, which an operator might expect restricts which TLS
protocols are accepted.

# More advanced defaults:
# protocol: TLS

However, setting that to TLSv1.2 had no effect on the protocols the
server accepted. Running "openssl s_client -tlsv1 -connect
127.0.0.1:7000" will connect without issue and negotiate a TLSv1.0
session.

I found two previous tickets that addressed TLS protocols, first
explicitly hard-coding the accepted TLS protocols to disable SSLv3
(due to POODLE) in CASSANDRA-8265 /
b93f48a5db321bf7c9fb55a800ed6ab2d6f6b102, and then rely back on Java8
defaults in CASSANDRA-10508 / e4a0a4bf65a87c3aabae4ee0cc35009879e2d455
once they were fixed.

CASSANDRA-10508 mentions the ‘protocol' field as a mechanism for
specifying the protocol, however according to Java docs, that only
verifies the protocol is to the SSL engine supported, and does not
restrict negotiation to using it, as the openssl s_client test
demonstrates.

>From a quick search of the internet, a couple of blog posts recommend
setting the cipher suite to only TLSv1.2 valid ciphers and I can
confirm that does work, leading to this being logged (at ERROR).

ERROR [Messaging-EventLoop-3-2] 2020-09-19T16:17:48,023 : - Failed to
properly handshake with peer /127.0.0.1:33826. Closing the channel.
io.netty.handler.codec.DecoderException:
javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1.1
is not enabled or supported in server context
Caused by: javax.net.ssl.SSLHandshakeException: Client requested
protocol TLSv1.1 is not enabled or supported in server context

While it does work to restrict the protocol, if we start logging the
accepted protocols the log will show that the server will negotiate
TLS1/TLS1.1 which may get flagged by anybody validating the operators
secure connection configuration.

I also discovered that if SSL is misconfigured (ciphers, keystone,
truststore etc), the node will start up happily but be unable to
accept or make any secure internode connections.

The current state of the code and documentation is unsatisfactory to
me.  We should at least improve the documentation to give clear
guidance to operators on how they can secure their systems under
4.0/tcnative, however I think we should go further and make the
encryption_option.protocol field behave as intended.

Here's my proposal:

1) Interpret the current protocol string as a comma separated list of
protocols that are accepted. Replace the default
EncryptionOptions.protocol of "TLS" with null.
2) If protocol is non-null, call SslContextBuilder.protocols() with
the configured protocols in
org.apache.cassandra.security.SSLFactory#createNettySslContext
3) Special case the protocol configuration "TLS" to mean {"TLSv1",
"TLSv1.1", "TLSv1.2”} for users that have uncommented the default
value. Passing “TLS” is invalid in the protocols() call.
4) Hard-code