Skip to content

Mutual TLS support - #6076

Merged
gianm merged 11 commits into
apache:masterfrom
jon-wei:mutual_tls
Sep 19, 2018
Merged

gianm merged 11 commits into
apache:masterfrom
jon-wei:mutual_tls

Conversation

@jon-wei

@jon-wei jon-wei commented Jul 31, 2018 •

Copy link
Copy Markdown
Contributor

This PR adds support for mutual TLS (https://en.wikipedia.org/wiki/Mutual_authentication).

This adds a new "requireClientAuth" property and truststore properties on the server-side TLS config.

If "requireClientAuth" is true, Druid will require clients to identify themselves by providing a TLS certificate.

The server-side truststore needs to be configured with the certificates needed to validate the client certificates.

On the client side for internal communications (simple-client-sslcontext extension), new keystore properties are added, specifying the client certificate that a Druid service will use when communicating with other Druid services.

@gianm gianm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This functionality should have a test of some sort: client cert validation is an important thing and we want to make sure it keeps working even if the code is refactored later in some way.

@jon-wei

jon-wei commented Aug 1, 2018

Copy link
Copy Markdown
Contributor Author

@gianm hm, I don't think we have any tests for TLS in general, I'll add some integration tests

@gianm

gianm commented Aug 2, 2018

Copy link
Copy Markdown
Contributor

@jon-wei, thanks, I think it is really valuable especially as we add more features to the feature.

(I heard you like features so we put features in your features?)

@nishantmonu51 nishantmonu51 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@gianm

gianm commented Aug 9, 2018

Copy link
Copy Markdown
Contributor

@jon-wei Are you done working on this patch? I wasn't sure since the last few commits are named "WIP"

@jon-wei

jon-wei commented Aug 9, 2018

Copy link
Copy Markdown
Contributor Author

Not yet, I made the integration tests use mutual TLS, but there's a test for coordinator -> overlord proxying that's failing, haven't fixed that yet

@jon-wei jon-wei changed the title Mutual TLS support [WIP] Mutual TLS support Aug 9, 2018
@jon-wei jon-wei added the WIP label Aug 9, 2018
@gianm

gianm commented Aug 9, 2018

Copy link
Copy Markdown
Contributor

Got it, thanks.

@fjy fjy added this to the 0.13.0 milestone Aug 13, 2018
@jon-wei
jon-wei force-pushed the mutual_tls branch 3 times, most recently from 29d43b4 to b159728 Compare August 14, 2018 01:11
@jon-wei jon-wei changed the title [WIP] Mutual TLS support [WIP] Aug 14, 2018
@jon-wei jon-wei changed the title [WIP] Mutual TLS support Aug 14, 2018
@jon-wei jon-wei removed the WIP label Aug 14, 2018
@jon-wei

jon-wei commented Aug 14, 2018 •

Copy link
Copy Markdown
Contributor Author

I updated the patch with the following:

  • Added mutual TLS to the integration tests. All druid services will have both plaintext and TLS port enabled with client cert checking enabled. A new test that accesses TLS and non-TLS endpoints on each service has been added.
  • Adjusted the timers in the integration tests: I shortened the retry periods and increased the number of retries
  • Fixed some timing issues in certain integration tests (like feeding events to a worker task before it's ready)
  • Fixes coordinator -> overlord proxy requests when TLS is enabled (the OverlordProxyServlet was not using a http client with the proper SSLContext)

@fjy

fjy commented Aug 14, 2018

Copy link
Copy Markdown
Contributor

👍

@gianm gianm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jon-wei. Please also include a couple of other features in the tests (I didn't see these, but if I missed them let me know).

  • Different private keys and certs for the client and server. (Can be the same root CA, and same CN/altNames, but generate two different keys, and two different keyStores.)
  • A negative test (getting the connection rejected in two cases: client cert missing; and client cert present, but CN/altName don't match the client hostname).

These are intended to verify that the certificate validation is being done properly by the https server.

Comment thread docs/content/operations/tls-support.md Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't be used for anything other than verifying client certificates?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the truststore on the server configuration side is only used to check the client certificates

Comment thread docs/content/operations/tls-support.md Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about requireClientCertificate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to requireClientCertificate

@jon-wei

jon-wei commented Aug 21, 2018 •

Copy link
Copy Markdown
Contributor Author

Different private keys and certs for the client and server. (Can be the same root CA, and same CN/altNames, but generate two different keys, and two different keyStores.)

The services and clients have different keys/certs, I'll update the patch to rename the client files so that this is more apparent

@gianm

gianm commented Aug 26, 2018

Copy link
Copy Markdown
Contributor

@jon-wei is this still a WIP or is it ready for re-review?

@jon-wei
jon-wei force-pushed the mutual_tls branch 3 times, most recently from cc3ae32 to d1f9820 Compare August 30, 2018 23:13
@jon-wei

jon-wei commented Sep 4, 2018

Copy link
Copy Markdown
Contributor Author

@gianm Still WIP, adjusting the networking in the integration tests for hostname verification, also looking into cert revocation handling

@jon-wei jon-wei closed this Sep 10, 2018
@jon-wei jon-wei reopened this Sep 10, 2018
sslContextFactory.setNeedClientAuth(tlsServerConfig.isRequireClientCertificate());
if (tlsServerConfig.isRequireClientCertificate()) {
if (tlsServerConfig.getCrlPath() != null) {
sslContextFactory.setValidatePeerCerts(true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a pretty crazy API on Jetty's part: it looks like that the only thing setValidatePeerCerts does is turn on CRL checking. Is that right? If so, the method is definitely not named intuitively. Could you add a comment about this?

I'm asking because at first glance, it looks like a bug, even if it's not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment here

if (tlsServerConfig.getTrustStorePath() != null) {
sslContextFactory.setTrustStorePath(tlsServerConfig.getTrustStorePath());
sslContextFactory.setTrustStoreType(
tlsServerConfig.getTrustStoreType() == null ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: formatting is a little strange here, and in similar statements below.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reformatted these areas

@@ -39,28 +44,77 @@ public static SSLContext createSSLContext(
String trustStoreType,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the trust store parameters should be marked @Nullable.

@jon-wei jon-wei Sep 19, 2018 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marked the nullable params @Nullable

PasswordProvider trustStorePasswordProvider
PasswordProvider trustStorePasswordProvider,
String keyStoreType,
String keyStorePath,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the key store parameters should be marked @Nullable too. Maybe some other parameters as well?

@jon-wei jon-wei Sep 19, 2018 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marked the nullable params @Nullable

@Path("/status")
public class StatusResource
{
private static Logger log = new Logger(StatusResource.class);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

String keyStoreAlgorithm,
String certAlias,
PasswordProvider keyStorePasswordProvider,
PasswordProvider keyManagerFactoryPasswordProvider

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method's arg list is getting super long. It would be nicer, although not required, to use a builder instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a builder and replaced constructor calls with builder use

Comment thread docs/content/operations/tls-support.md Outdated
|`druid.server.https.trustStorePath`|The file path or URL of the trust store containing certificates used to validate client certificates. Not needed if `requireClientCertificate` is false.|none|yes, only if `requireClientCertificate` is true|
|`druid.server.https.trustStoreAlgorithm`|Algorithm to be used by TrustManager to validate client certificate chains. Not needed if `requireClientCertificate` is false.|`javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm()`|no|
|`druid.server.https.trustStorePassword`|The [Password Provider](../../operations/password-provider.html) or String password for the Trust Store. Not needed if `requireClientCertificate` is false.|none|no|
|`druid.server.https.validateHostnames`|If set to true, perform hostname validation on client certificates. Not used if `requireClientCertificate` is false.|false|no|

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "hostname validation" mean in this context? If it means checking CN/altNames, then it should be true by default, since otherwise it's a trap waiting to be sprung on people.

(Once you turn on druid.server.https.requireClientCertificate, we should be secure as possible by default, and you should have to explicitly set options to be less secure.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed default to true and added more details to the documentation

@jon-wei

jon-wei commented Sep 19, 2018

Copy link
Copy Markdown
Contributor Author

Addressed comments, also adjusted pom.xml to exclude the TLS certs/keys generated by the integration tests from Rat license chcking

@gianm gianm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jon-wei!

@gianm
gianm merged commit 8972244 into apache:master Sep 19, 2018
jon-wei added a commit to implydata/druid-public that referenced this pull request Sep 20, 2018
* Mutual TLS support

* Kafka test fixes

* TeamCity fix

* Split integration tests

* Use localhost DOCKER_IP

* Increase server thread count

* Increase SSL handshake timeouts

* Add broken pipe retries, use injected client config params

* PR comments, Rat license check exclusion
riovic918data pushed a commit to riovic918data/druid that referenced this pull request Jun 12, 2026
* Mutual TLS support

* Kafka test fixes

* TeamCity fix

* Split integration tests

* Use localhost DOCKER_IP

* Increase server thread count

* Increase SSL handshake timeouts

* Add broken pipe retries, use injected client config params

* PR comments, Rat license check exclusion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants