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

SNI-based cert selection during TLS handshake #22036

Merged
merged 1 commit into from
Nov 30, 2022

Conversation

LuyaoZhong
Copy link
Contributor

@LuyaoZhong LuyaoZhong commented Jul 6, 2022

Envoy supports selecting certs by selecting filter chain based on SNI.
But it is possible that we access different services via one filter
chain, which requires SNI-based cert selection in one single filter
chain during handshake.

Risk Level: Medium
Testing: unit tests
Docs Changes: ssl
Release Notes: yes
Fixes #21739

Signed-off-by: Luyao Zhong [email protected]

@LuyaoZhong LuyaoZhong marked this pull request as draft July 7, 2022 10:12
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.

/wait

docs/root/intro/arch_overview/security/ssl.rst Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/context_impl.cc Outdated Show resolved Hide resolved
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.

/wait

source/extensions/transport_sockets/tls/context_impl.cc Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/context_impl.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/context_impl.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/utility.cc Outdated Show resolved Hide resolved
@LuyaoZhong LuyaoZhong requested a review from ggreenway July 19, 2022 05:43
@LuyaoZhong LuyaoZhong marked this pull request as ready for review July 21, 2022 01:55
@LuyaoZhong LuyaoZhong changed the title [WIP] SNI-based cert selection during TLS handshake SNI-based cert selection during TLS handshake Jul 21, 2022
@LuyaoZhong
Copy link
Contributor Author

@ggreenway Do we need to add release notes for this?

@ggreenway
Copy link
Contributor

I've been busy and haven't had time to review this yet; thanks for your patience.

@LuyaoZhong
Copy link
Contributor Author

I've been busy and haven't had time to review this yet; thanks for your patience.

It's ok. :) Thanks for your response.

@repokitteh-read-only
Copy link

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to (api/envoy/|docs/root/api-docs/).
envoyproxy/api-shepherds assignee is @lizan
CC @envoyproxy/api-watchers: FYI only for changes made to (api/envoy/|docs/root/api-docs/).

🐱

Caused by: #22036 was synchronize by LuyaoZhong.

see: more, trace.

@LuyaoZhong
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #22036 (comment) was created by @LuyaoZhong.

see: more, trace.

@alyssawilk
Copy link
Contributor

@ggreenway would you be able to take a look today?

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.

/wait

source/extensions/transport_sockets/tls/context_impl.cc Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/context_impl.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/context_impl.h Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/context_impl.cc Outdated Show resolved Hide resolved
source/extensions/transport_sockets/tls/context_impl.cc Outdated Show resolved Hide resolved
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.

Please add more test coverage:

  • Multiple certs with multiple SANs; matching works correctly
  • CN is not used if SANs are present
  • Wildcard in SANs is matched properly
  • Wildcard does not match if an exact match is present
  • Wildcard only matches 1 level, eg *.example.com does not match a.b.example.com
  • Config fails to load with conflicting SANs in certs, both exact and wildcard
  • Any other new behavior you've added in this PR that isn't tested.

/wait

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #22036 (comment) was created by @LuyaoZhong.

see: more, trace.

@mattklein123
Copy link
Member

Please fix DCO (you may need to squash the entire thing and force push). Then we can do a final pass. Thanks.

/wait

Envoy supports selecting certs by selecting filter chain based on SNI.
BUt it is possible that we access different services via one filter
chain, which requires SNI-based cert selection in one single filter
chain during handshake.

Signed-off-by: Luyao Zhong <[email protected]>
@LuyaoZhong
Copy link
Contributor Author

/retest

@repokitteh-read-only
Copy link

Retrying Azure Pipelines:
Retried failed jobs in: envoy-presubmit

🐱

Caused by: a #22036 (comment) was created by @LuyaoZhong.

see: more, trace.

@LuyaoZhong
Copy link
Contributor Author

Please fix DCO (you may need to squash the entire thing and force push). Then we can do a final pass. Thanks.

/wait

Done

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.

This looks good. Thanks for all the work on this!

if (config.tlsCertificates().empty() && !config.capabilities().provides_certificates) {
throw EnvoyException("Server TlsCertificates must have a certificate specified");
}

for (auto& ctx : tls_contexts_) {
bssl::UniquePtr<EVP_PKEY> public_key(X509_get_pubkey(ctx.cert_chain_.get()));
Copy link
Contributor

Choose a reason for hiding this comment

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

This crashes for cases when cert_chain is nullptr. It is missing nullptr check present in ContextImpl::getCertChainInformation()

Copy link
Contributor Author

@LuyaoZhong LuyaoZhong Dec 11, 2022

Choose a reason for hiding this comment

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

It already gets checked in loading phase. If the cert_chain is nullptr, envoy will log and raise exception, you could check following code path

if (!tls_certificate.pkcs12().empty()) {
ctx.loadPkcs12(tls_certificate.pkcs12(), tls_certificate.pkcs12Path(),
tls_certificate.password());
} else {
ctx.loadCertificateChain(tls_certificate.certificateChain(),
tls_certificate.certificateChainPath());
}

So I don't think this will cause crash, and we can see similar code in constructor of its parent class, it checks nothing since it gets checked earlier.

bssl::UniquePtr<EVP_PKEY> public_key(X509_get_pubkey(ctx.cert_chain_.get()));
const int pkey_id = EVP_PKEY_id(public_key.get());

I saw this change was reverted by #24475 , but no enough context for me, could you elaborate the example config that it will crash?

cc @ggreenway @KBaichoo

KBaichoo added a commit that referenced this pull request Dec 10, 2022
Revert 22036.

Signed-off-by: Kevin Baichoo <[email protected]>
LuyaoZhong pushed a commit to LuyaoZhong/envoy that referenced this pull request Dec 11, 2022
Envoy supports selecting certs by selecting filter chain based on SNI.
But it is possible that we access different services via one filter
chain, which requires SNI-based cert selection in one single filter
chain during handshake.

This change is merged by envoyproxy#22036 and reverted by envoyproxy#24475.

Signed-off-by: Luyao Zhong <[email protected]>
ggreenway pushed a commit that referenced this pull request Dec 14, 2022
Envoy supports selecting certs by selecting filter chain based on SNI.
But it is possible that we access different services via one filter
chain, which requires SNI-based cert selection in one single filter
chain during handshake.

This change is merged by #22036 and reverted by #24475.

Signed-off-by: Luyao Zhong <[email protected]>
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.

SNI-based cert selection in TLS transport socket