Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tls] Add an extension point for TLS handshaker behavior. #12658

Merged
merged 35 commits into from
Sep 11, 2020

Conversation

ambuc
Copy link
Contributor

@ambuc ambuc commented Aug 14, 2020

Commit Message: Add an extension point to allow overriding TLS handshaker behavior.

Additional Description: This PR necessitated decoupling SslHandshakerImpl from ContextConfig a bit. We now pass an int representing the index of the extended_info struct rather than the ContextConfig.

This PR moves SslHandshakerImpl to its own build target, moves SslHandshaker construction into the ContextConfig, and adds a HandshakerFactoryContext and HandshakerFactory for modifying the ContextConfig's behavior when constructing a Handshaker. This PR also adds a control (requireCertificates) to turn off the release asserts that a context must have certificates.

This PR builds off work in #12571 and refines work done (and abandoned) in #12075. For more discussion please see the comments section of #12075.

Risk Level: Low. This PR does not modify existing handshaking behavior, it just adds an extension point for modifying it.
Testing: A representative alternative implementation was added under :handshaker_test.
Docs Changes: N/a
Release Notes: N/a

@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to api/envoy/.
CC @envoyproxy/api-watchers: FYI only for changes made to api/envoy/.

🐱

Caused by: #12658 was opened by ambuc.

see: more, trace.

Copy link
Member

@lizan lizan left a comment

Choose a reason for hiding this comment

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

Other than style nits LGTM

@ambuc ambuc requested a review from lizan August 20, 2020 21:22
Copy link
Contributor

@PiotrSikora PiotrSikora left a comment

Choose a reason for hiding this comment

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

I think a lot more configuration settings should be guarded, since depending on what's handled by the custom handshaker, a lot of features in the context is going to be a dead code:

  1. Does the custom handshaker provide certificates and/or private key operations?
  2. Does the custom handshaker handle session resumption (Session IDs, Session Tickets, PSK)? Notably, in TLS 1.3, NewSessionTicket message is sent after the handshake is completed.
  3. Does the custom handshaker handle ALPN negotiation?
  4. Does the custom handshaker verify client certificates?
  5. Is the custom handshaker FIPS compliant? Should we reject configuration if non-compliant handshaker is provided in --define=boringssl=fips builds?

@ambuc
Copy link
Contributor Author

ambuc commented Aug 21, 2020

I think a lot more configuration settings should be guarded, since depending on what's handled by the custom handshaker, a lot of features in the context is going to be a dead code:

  1. Does the custom handshaker provide certificates and/or private key operations?
  2. Does the custom handshaker handle session resumption (Session IDs, Session Tickets, PSK)? Notably, in TLS 1.3, NewSessionTicket message is sent after the handshake is completed.
  3. Does the custom handshaker handle ALPN negotiation?
  4. Does the custom handshaker verify client certificates?
  5. Is the custom handshaker FIPS compliant? Should we reject configuration if non-compliant handshaker is provided in --define=boringssl=fips builds?

This makes sense to me. I've introduced a struct enumerating these requirements (HandshakerRequirements) and propagated it down to ContextConfigImpl. I've gated several SSL_CTX_foo calls behind these bools, and the bools are configurable from the extended factory impl. I think this provides the appropriate controls for an implementation of this handshaker to switch off SSL calls when required.

@ambuc ambuc requested a review from PiotrSikora August 21, 2020 20:26
@ambuc
Copy link
Contributor Author

ambuc commented Sep 8, 2020

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines, to retry CircleCI checks, use /retest-circle.
Cannot retry non-completed check: envoy-presubmit (Linux-x64 compile_time_options), please wait.

🐱

Caused by: a #12658 (comment) was created by @ambuc.

see: more, trace.

@ambuc
Copy link
Contributor Author

ambuc commented Sep 8, 2020

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines, to retry CircleCI checks, use /retest-circle.
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #12658 (comment) was created by @ambuc.

see: more, trace.

@antoniovicente
Copy link
Contributor

@PiotrSikora PTAL. Any other comments?

@ambuc
Copy link
Contributor Author

ambuc commented Sep 9, 2020

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines, to retry CircleCI checks, use /retest-circle.
Check envoy-presubmit didn't fail.

🐱

Caused by: a #12658 (comment) was created by @ambuc.

see: more, trace.

Copy link
Contributor

@PiotrSikora PiotrSikora left a comment

Choose a reason for hiding this comment

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

You need to go through all code of TLS extension and add capability guards where appropriate, e.g. the certificate loading block is not guarded by capabilities right now, etc.

Also, it would be helpful if you were consistent and always added them either as the first or as the last condition, right now it's mixed.

@ambuc
Copy link
Contributor Author

ambuc commented Sep 10, 2020

You need to go through all code of TLS extension and add capability guards where appropriate, e.g. the certificate loading block is not guarded by capabilities right now, etc.

Also, it would be helpful if you were consistent and always added them either as the first or as the last condition, right now it's mixed.

The capability guards are now either outside, or the last argument to a conditional. I added some capability guards around the cert loading mechanisms as well. Thanks for catching this :)

@ambuc ambuc requested a review from PiotrSikora September 10, 2020 15:32
@ambuc
Copy link
Contributor Author

ambuc commented Sep 10, 2020

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines, to retry CircleCI checks, use /retest-circle.
Cannot retry non-completed check: envoy-presubmit (Linux multi-arch docker), please wait.

🐱

Caused by: a #12658 (comment) was created by @ambuc.

see: more, trace.

@ambuc
Copy link
Contributor Author

ambuc commented Sep 10, 2020

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines, to retry CircleCI checks, use /retest-circle.
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #12658 (comment) was created by @ambuc.

see: more, trace.

@lizan lizan merged commit 7d6e7a4 into envoyproxy:master Sep 11, 2020
@mattklein123
Copy link
Member

@ambuc post merge drive by: can you please add a release note and some documentation for this feature? For docs I'm thinking here? https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/security/ssl

In particular it would be good to briefly discuss how this feature is different from the existing private key methods support. Thank you!

info_ = std::make_shared<SslHandshakerImpl>(std::move(ssl), ctx_, this);

ctx_(std::dynamic_pointer_cast<ContextImpl>(ctx)),
info_(std::dynamic_pointer_cast<SslHandshakerImpl>(
Copy link
Member

Choose a reason for hiding this comment

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

I'm probably missing something, but how is this dynamic_cast safe if someone is using a custom implementation? Don't you need a virtual method to get the info off of the handshake interface since you don't know the inheritance structure of the implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My custom implementation in the test is fortunate enough to extend SslHandshakerImpl. My thought was that anyone who wanted to write their own custom implementation of Ssl::Handshaker would also want to extend the existing SslHandshakerImpl to avoid reimplementing all the fiddly methods in ConnectionInfo. But you're right, this isn't safe for anyone who writes their own impl which doesn't extend SslHandshakerImpl.

I think the right thing to do here is (a) add the relevant methods to Ssl::Handshaker (the interface) so that it's OK for (b) info_ to be an Ssl::Handshaker*. I'll fix this forward in a new PR.

Copy link
Member

Choose a reason for hiding this comment

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

Cool thanks. Feel free to combine with the docs PR. Up to you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressing this in #13081. Docs PR to follow.

@ambuc
Copy link
Contributor Author

ambuc commented Sep 14, 2020

@ambuc post merge drive by: can you please add a release note and some documentation for this feature? For docs I'm thinking here? https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/security/ssl

In particular it would be good to briefly discuss how this feature is different from the existing private key methods support. Thank you!

Addressing this in #13083.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants