-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
SNI-based cert selection during TLS handshake #22036
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/wait
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/wait
@ggreenway Do we need to add release notes for this? |
I've been busy and haven't had time to review this yet; thanks for your patience. |
It's ok. :) Thanks for your response. |
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
/retest |
Retrying Azure Pipelines: |
@ggreenway would you be able to take a look today? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/wait
There was a problem hiding this 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
Retrying Azure Pipelines: |
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]>
c019fef
to
e62edc4
Compare
/retest |
Retrying Azure Pipelines: |
Done |
There was a problem hiding this 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())); |
There was a problem hiding this comment.
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()
There was a problem hiding this comment.
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
envoy/source/extensions/transport_sockets/tls/context_impl.cc
Lines 198 to 204 in 8433082
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.
envoy/source/extensions/transport_sockets/tls/context_impl.cc
Lines 215 to 216 in 8433082
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?
Revert 22036. Signed-off-by: Kevin Baichoo <[email protected]>
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]>
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]>
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]