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 a custom listener handshaker for TLS. #12075

Closed
wants to merge 42 commits into from

Conversation

ambuc
Copy link
Contributor

@ambuc ambuc commented Jul 14, 2020

Signed-off-by: James Buckland jbuckland@google.com

Commit Message: [tls] Add a custom listener handshaker for TLS.
Additional Description: This CL introduces a mechanism for modifying the behavior a TLS socket uses to handshake. It moves the existing implementation into a default HandshakerImpl and introduces an extension for injecting custom handshaker behavior.
Risk Level: Low, the default handshaking behavior in unmodified Envoy is unchanged.
Testing: All existing unit/integration tests use the default handshaking behavior (as before). The existing handshaker implementation also gains unit tests.
Docs Changes: None -- I think the API comments will generate documentation.
Release Notes: n/a

Signed-off-by: James Buckland <jbuckland@google.com>
@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: #12075 was opened by ambuc.

see: more, trace.

Signed-off-by: James Buckland <jbuckland@google.com>
@lizan lizan self-assigned this Jul 14, 2020
@rojkov
Copy link
Member

rojkov commented Jul 15, 2020

What's the use case for a custom handshaker?

@ambuc
Copy link
Contributor Author

ambuc commented Jul 15, 2020

@rojkov We want to be able to modify TLS termination to perform crypto operations outside of the Envoy binary.

@rojkov
Copy link
Member

rojkov commented Jul 15, 2020

We want to be able to modify TLS termination to perform crypto operations outside of the Envoy binary.

Probably a custom PrivateKeyMethodProvider could be suitable for your needs.

@ambuc
Copy link
Contributor Author

ambuc commented Jul 15, 2020

I got the impression PrivateKeyMethodProvider lets you inject behavior before a handshake. My motivation for this change is to override behavior within a handshake.

…shaking

Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
@htuch
Copy link
Member

htuch commented Jul 15, 2020

@ggreenway @PiotrSikora @lizan could you folks take a look at this? Thanks.

source/extensions/transport_sockets/tls/handshaker_impl.cc Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/ssl_socket.cc Outdated Show resolved Hide resolved
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
@PiotrSikora
Copy link
Contributor

Probably a custom PrivateKeyMethodProvider could be suitable for your needs.

For some use cases, yes. But custom handshaker allows you to offload more than just private key operations.

@ambuc ambuc marked this pull request as ready for review July 17, 2020 19:24
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
@lizan lizan added the waiting label Jul 18, 2020
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
…ck_format

Signed-off-by: James Buckland <jbuckland@google.com>
Copy link
Contributor

@ggreenway ggreenway 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 the overall design is fine.

I'd like to see a reference implementation of calling another handshaker out of process, or at least in another thread in a test. This can't be adequately tested without it I don't think. Also, I think should be clear how to implement this interface, ie an implementation needs to get some data from the SSL, send it to the thing that does the privatekey operations, do those operations, send the result back, and apply the result to the SSL. The private-key operation server-like thing doesn't need to be production-grade, but the envoy implementation of a handshaker probably should be.

include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/handshaker_impl.cc Outdated Show resolved Hide resolved
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/handshaker_impl.h Outdated Show resolved Hide resolved
test/extensions/transport_sockets/tls/handshaker_test.cc Outdated Show resolved Hide resolved
@ggreenway
Copy link
Contributor

One option for a Handshaker implementation would be to write an integration with https://github.com/cloudflare/gokeyless. Although I don't know if the license actually allows that (it's not a standard open-source license).

Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
Copy link
Contributor

@ggreenway ggreenway left a comment

Choose a reason for hiding this comment

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

The overall pattern looks good.

Copy link
Contributor

@ggreenway ggreenway left a comment

Choose a reason for hiding this comment

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

If you put names like this (bssl, rbio, etc) in backticks in the comment the spellchecker won't check them, and then they don't need to be in the dictionary.

@ggreenway ggreenway self-assigned this Jul 28, 2020
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/ssl_socket.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/ssl_socket.h Outdated Show resolved Hide resolved
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
… to a non-dangling SSL*.

Signed-off-by: James Buckland <jbuckland@google.com>
Signed-off-by: James Buckland <jbuckland@google.com>
@ambuc ambuc requested review from lizan and ggreenway July 29, 2020 17:11
Signed-off-by: James Buckland <jbuckland@google.com>
@ambuc ambuc requested a review from lizan July 29, 2020 20:49
include/envoy/ssl/handshaker.h Outdated Show resolved Hide resolved
handshaker_callbacks_ = &handshaker_callbacks;
}

SSL* ssl() override { return ssl_.get(); }
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we're missing an important restriction on the use of this method: access to the SSL* object before handshake is complete should be forbidden.

I think this restriction clashes with use of this method in SslSocketInfo's constructor and possibly in a few other places.

}

Network::PostIoAction doHandshake(Ssl::SocketState& state) override {
ASSERT(state != Ssl::SocketState::HandshakeComplete && state != Ssl::SocketState::ShutdownSent);
Copy link
Contributor

Choose a reason for hiding this comment

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

This for test doHandshake implementation looks too real. it seems like a copy of HandshakeImpl::doHandshake.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It basically is. I specifically wanted to demonstrate special-case error handling under switch(SSL_get_error(...)). Should I add more comments to call out that only the SSL_ERROR_WANT_X509_LOOKUP block is different?

virtual SSL* ssl() PURE;
};

using HandshakerSharedPtr = std::shared_ptr<Handshaker>;
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like we should statically know the lifetime of this, and should be able to use a unique_ptr + references.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What's the alternative here? @lizan pointed out (#12075 (comment)) that the SslSocketInfo struct expects to have access to the SSL object after the connection has been destroyed, for logging purposes. What do you think of explicitly std::move()ing the SSL object from the handshaker to the SslSocketInfo just before ~SslSocket(), perhaps during SslSocket::shutdown()? @antoniovicente

Copy link
Member

Choose a reason for hiding this comment

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

It might make sense for Handshaker to implement Ssl::ConnectionInfo, as the socket info class is basically represent the result of handshake.

Copy link
Contributor

@antoniovicente antoniovicente Aug 3, 2020

Choose a reason for hiding this comment

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

Handshaker providing Ssl::ConnectionInfo makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

PTAL @ #12571, I am attempting to move the handshaker behavior into SslSocketInfo before adding an extension point.

@ggreenway
Copy link
Contributor

/wait

@ambuc
Copy link
Contributor Author

ambuc commented Aug 10, 2020

Closing this PR. Will continue work in #12571 and a follow-up PR. PTAL at #12571 instead.

@ambuc ambuc closed this Aug 10, 2020
lizan pushed a commit that referenced this pull request Sep 11, 2020
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

Signed-off-by: James Buckland <jbuckland@google.com>
mattklein123 pushed a commit to envoyproxy/data-plane-api that referenced this pull request Sep 11, 2020
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 envoyproxy/envoy#12571 and refines work done (and abandoned) in envoyproxy/envoy#12075. For more discussion please see the comments section of envoyproxy/envoy#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

Signed-off-by: James Buckland <jbuckland@google.com>

Mirrored from https://github.com/envoyproxy/envoy @ 7d6e7a4e559bdf0346687f7f404412e2412ea6fb
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.

8 participants