-
Notifications
You must be signed in to change notification settings - Fork 682
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
allow configuration of upstream TLS connection settings #5828
Conversation
@sunjayBhatia , it is still pretty rough, but I've attempted to wire everything up for this new configuartion. One question though: how do I enforce defaults for min and max TLS version in CRD and the ConfigMap? I would like the Contour default for max version to be different than Envoy's default. EDIT: I ended up just sticking the default max in the code where the creation of UpstreamTLSContext happens |
069fd5f
to
1fc65cd
Compare
/test test-linux |
9b98cd9
to
dbd25ad
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #5828 +/- ##
=======================================
Coverage 78.69% 78.70%
=======================================
Files 138 138
Lines 19687 19717 +30
=======================================
+ Hits 15493 15518 +25
- Misses 3890 3895 +5
Partials 304 304
|
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.
Added some comments inline, but looks good to me in general!
I think it would be good to have some reasoning here about the corner cases that have led Envoy not to enable TLSv1.3 for upstream, and why it is OK for Contour to do so - something that answers to #5666 (review)
One more thought: It would be nice to have e2e test for the protocol version. The echoserver
used for e2e suite returns a JSON response that includes the negotiated TLS version (see here). We could check that TLSv1.3 gets returned. Check test/e2e/httpproxy/backend_tls_test.go
on similar assertion checks done for the response. In responseTLSDetails
the client certificate was parsed from response document and compared to what we had configured.
efaffd3
to
741590d
Compare
The Contour project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to the #contour channel in the Kubernetes Slack |
21e08ee
to
803416a
Compare
@sunjayBhatia @tsaarni looks like the tests are passing now, thanks for your feedback so far. I tried linking the upstream tls config into extension services and dnsservices as well, but I'm not so sure I got it correct. I'd appreciate if you all took a closer look in that area next time you look through this 🙇 |
internal/dag/httpproxy_processor.go
Outdated
@@ -1026,6 +1030,7 @@ func (p *HTTPProxyProcessor) computeRoutes( | |||
SlowStartConfig: slowStart, | |||
MaxRequestsPerConnection: p.MaxRequestsPerConnection, | |||
PerConnectionBufferLimitBytes: p.PerConnectionBufferLimitBytes, | |||
UpstreamTLS: determineUpstreamTLS(p.UpstreamTLS), |
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.
Just an observation about small inconsistency:
It seems we have previously in some cases avoided setting TLS parameters if TLS is not used by upstream in the first place: Cluster.UpstreamValidation
is set to nil
. We also have set TLS parameters unconditionally: Cluster.SNI
will be set even if TLS is not used. Now Cluster.UpstreamTLS
will also be set even if cluster.Protocol
is not implying TLS.
Just setting the values unconditionally can be seen as simplification of the logic here. In reality the TLS parameters are ignored later in internal/envoy/v3/cluster.go
when constructing envoy.Cluster
when Cluster.protocol
does not indicate TLS. So at the end, it does not matter if Cluster
is filled in with TLS settings, even when TLS is not used.
pkg/config/parameters.go
Outdated
@@ -429,6 +429,9 @@ type ClusterParameters struct { | |||
// | |||
// +optional | |||
PerConnectionBufferLimitBytes *uint32 `yaml:"per-connection-buffer-limit-bytes,omitempty"` | |||
|
|||
// UpstreamTLS contains the TLS policy parameters for upstream connections | |||
UpstreamTLS TLSParameters `yaml:"upstream-tls,omitempty"` |
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.
Should we avoid reusing the TLSParameters
struct here since it contains some parameters that can be meaningful only for downstream or upstream TSL?
For example field TLSParameters.FallbackCertificate
is used as server certificate, which appears as configuration file field tls.fallback-certificate
. When reusing the struct for upstream, it could be also defined as cluster.upstream-tls.fallback-certificate
according purely to syntax, but if defined there, it would be ignored.
Similarly, config file field tls.envoy-client-certificate
is used as optional client cert in upstream TLS. Reusing the struct would mean field cluster.upstream-tls.envoy-client-certificate
is syntactically correct, but actually it will not get used.
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.
hmmm I see. I went with TLSParameters originally because it had what I needed and I didn't want to create a similar-but-not-quite-the-same struct.
What would you say to creating a new struct that just contains {MinimumProtocolVersion,MaximumProtocolVersion,CipherSuites}
, and then making that struct a part of TLSParameters?
Then cluster.upstream-tls
would only contain options that can actually be used.
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.
👍 that sounds good to me
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.
Okay, I ended up creating a new smaller struct called ProtocolParameters. I can always change it if you think a different name is better
// UpstreamTLS contains the TLS policy parameters for upstream connections | ||
// | ||
// +optional | ||
UpstreamTLS *EnvoyTLS `json:"upstream-tls,omitempty"` |
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.
Question: What do people prefer: nesting TLS config in ContourConfiguration.spec.envoy.cluster.upstream-tls
(like suggested here) or bumping it one level ContourConfiguration.spec.envoy.upstream-tls
?
Maybe bit unfortunate but there is existing upstream TLS parameter directly under ContourConfiguration.spec.envoy
, which is clientCertificate
. It's bit unfortunate that the upstream TLS settings will be split in two places, but hopefully not too far from each other.
The corresponding downstream TLS setting is ContourConfiguration.spec.envoy.listener.tls
. I guess perfect symmetry across TLS settings is not achievable anymore, not even in CRD config which was the fresh start :)
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.
Given dowstream TLS settings are nested under envoy.listener
, I think putting upstream settings under envoy.cluster
is logical.
Re: clientCertificate -- the CRD is still v1alpha1
, so we could make a breaking change if we wanted to reorganize. Seems like moving clientCertificate
into UpstreamTLS might make sense?
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.
I could move clientCertificate into UpstreamTLS. OR would you prefer that be in a separate MR?
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.
Let's hold off for now to see what others think about that change, we can do it in a separate PR if we decide to proceed.
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.
+1 for keeping it under cluster
// UpstreamTLS contains the TLS policy parameters for upstream connections | ||
// | ||
// +optional | ||
UpstreamTLS *EnvoyTLS `json:"upstream-tls,omitempty"` |
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.
Given dowstream TLS settings are nested under envoy.listener
, I think putting upstream settings under envoy.cluster
is logical.
Re: clientCertificate -- the CRD is still v1alpha1
, so we could make a breaking change if we wanted to reorganize. Seems like moving clientCertificate
into UpstreamTLS might make sense?
Signed-off-by: Clay Kauzlaric <[email protected]>
6b15f75
to
f09bcc9
Compare
* change json key style * re-run make generate Co-authored-by: Steve Kriss <[email protected]> Signed-off-by: Clay Kauzlaric <[email protected]>
Signed-off-by: Clay Kauzlaric <[email protected]>
a1cf66a
to
2177ee7
Compare
test/e2e/httpproxy/httpproxy_test.go
Outdated
Namespace: namespace, | ||
} | ||
}) | ||
Context("with backend tls version configured via Contour ConfigMap", func() { |
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.
I think we can combine these two contexts (configmap and contourconfig-specific wrappers) and just set the same options in the BeforeEach just as we do here:
contour/test/e2e/httpproxy/httpproxy_test.go
Lines 115 to 118 in 4d48db7
BeforeEach(func() { | |
contourConfig.EnableExternalNameService = true | |
contourConfiguration.Spec.EnableExternalNameService = ref.To(true) | |
}) |
we have different test runs for using each type of config so we should only need one instance of the test
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.
okay I combined them into 1 before each. Does it look how you're imagining now?
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.
Functionality looks good and change overall looks good modulo whatever existing nits there are and questions about API types
Once those are resolved I'm good to go with this change 👍🏽
pkg/config/parameters.go
Outdated
@@ -429,6 +429,9 @@ type ClusterParameters struct { | |||
// | |||
// +optional | |||
PerConnectionBufferLimitBytes *uint32 `yaml:"per-connection-buffer-limit-bytes,omitempty"` | |||
|
|||
// UpstreamTLS contains the TLS policy parameters for upstream connections | |||
UpstreamTLS TLSParameters `yaml:"upstream-tls,omitempty"` |
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.
👍 that sounds good to me
Signed-off-by: Clay Kauzlaric <[email protected]>
* because the two structs are identical, we can cast between them apparently Signed-off-by: Clay Kauzlaric <[email protected]>
Signed-off-by: Clay Kauzlaric <[email protected]>
Signed-off-by: Clay Kauzlaric <[email protected]>
Signed-off-by: Clay Kauzlaric <[email protected]>
I'll take another pass today but I think this is looking pretty good |
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.
Sorry, a couple last things, but I think that's it from me.
Signed-off-by: Clay Kauzlaric <[email protected]>
Signed-off-by: Clay Kauzlaric <[email protected]>
Signed-off-by: Clay Kauzlaric <[email protected]>
89ee43e
to
7d64501
Compare
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 LGTM, will leave for another maintainer to take another pass, thanks @KauzClay!
Signed-off-by: Clay Kauzlaric <[email protected]>
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.
Looks good to me too! Just one more small request. If I'm not mistaken, I think we can avoid the typecasts to dag.UpstreamTLS
* gets rid of need to typecast Signed-off-by: Clay Kauzlaric <[email protected]>
Looks like we're good to merge here, thanks @KauzClay! Will merge later today. |
Just as you can configure TLS settings for downstream connections, like setting min/max TLS versions and cipher suites, you should be able to do that for upstream connections too.
For upstream connections, I would like the default Max TLS version to be 1.3, instead of the current Envoy default of 1.2
release-note/minor
Fixes #5501
Fixes #3574