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
Per Route TLS Configuration #35
Conversation
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: danehans The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Fixes Issue #52 |
// | ||
// Support: Core (Kubernetes Secrets) | ||
// Support: Implementation-specific (Other resource types) | ||
Certificates []core.TypedLocalObjectReference `json:"certificates,omitempty"` | ||
Certificate core.TypedLocalObjectReference `json:"certificate,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.
We should specify if this is required or optional.
I think this should be required.
This is essentially the fallback certificate for any request and has the lowest preference.
There is another issue though. It should be possible to specify SNI <-> secret mapping at this level as well to specify different certificates for different domains.
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 this should be required.
@hbagdi TLS is optional for a listener. For example, a listener is configured to listen on port 80 for HTTP. Maybe GatewaySpec
should have a Certificates
or DefaultCertificates
field for a gateway to use as "fall back" certs?
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.
My bad for not explaining properly.
What I mean is that if it is a TLS listener, then we should encourage user to provide a default certificate, which takes the lowest priority. As you said, it's the "fall back" cert.
Having more than one default certificate means that you need to have some sort of SNI
mapping to those certs. Both cases make sense to me.
// Support: Implementation-specific (For other resource types) | ||
// | ||
// +optional | ||
Certificate core.TypedLocalObjectReference `json:"certificate,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.
Same comment as: #35 (comment)
an HTTPRoute could have multiple SNIs.
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.
There's also other cases for allowing multiple server certificates (e.g. serving different type types).
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.
serving different type types
Not sure I understand. Can you elaborate?
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.
A single application, served over HTTPs that has a collection of server certificates with different key types. The client will negotiate the matching certificate.
For example, envoy TLS context lets you add ECDSA and RSA certificates, at least in theory, the docs are contradictory :)
type TLSConfig struct { | ||
// Termination defines how to terminate TLS connections. | ||
// | ||
// If unspecified, TLS termination type "Edge" will 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.
A significant number of users don't understand the details of TLS and higher-level protocols like HTTP and hence they associate TLS with a specific route, which is incorrect, since TLS session is established first and then the route is selected based on metadata of the higher-level protocol.
And then, there is the case were two different HTTPRoute (or other types of Route) have the same SNI but different cert. Sometimes we see that there are two secrets (no cross-namespace referencing of secret) but the content it same, other times, they will have different content as well. We usually honor the oldest Ingress resource in that case usually.
Here, we should be explicit about the behavior. I'm not sure what the solution should be but it should be hard to break production setups easily.
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.
A significant number of users don't understand the details of TLS and higher-level protocols like HTTP and hence they associate TLS with a specific route, which is incorrect, since TLS session is established first and then the route is selected based on metadata of the higher-level protocol.
TLS cannot decide whether it is transport or application layer and has some unfortunate metadata redundancy with respect to HTTP. Does the API need to reflect that?
And then, there is the case were two different HTTPRoute (or other types of Route) have the same SNI but different cert. Sometimes we see that there are two secrets (no cross-namespace referencing of secret) but the content it same, other times, they will have different content as well. We usually honor the oldest Ingress resource in that case usually.
You could have two certificates with overlapping CNs or SANs in a Gateway
object's spec.listeners.tls.certificates
specification. I am not confident the API can be designed in such a way that it cannot be easily and accidentally used to express certificates that conflict with each other; it will be necessary to detect and report conflicts at run time.
Here, we should be explicit about the behavior. I'm not sure what the solution should be but it should be hard to break production setups easily.
Report conflicts in a status condition?
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.
A significant number of users don't understand the details of TLS and higher-level protocols like HTTP and hence they associate TLS with a specific route, which is incorrect, since TLS session is established first and then the route is selected based on metadata of the higher-level protocol.
IMHO, the default common case should be to require the SNI and HTTP names to match (see #72).
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.
TLS cannot decide whether it is transport or application layer and has some unfortunate metadata redundancy with respect to HTTP. Does the API need to reflect that?
No. I'm advocating to have TLS not be associated with our HTTP metadata based resources like HTTPRoute
. That removes the possibility of expressing a certificate associated with a specific route (and that is not possible to enforce because of how TLS and HTTP work).
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.
@hbagdi A couple of times I started writing a response here, but I'm not sure I understand your position well enough :)
WDYT about filing a separate issue to capture a user story for the case you are advocating?
// TLSTerminationReencrypt terminates the TLS connection at the gateway. | ||
// The gateway creates an encrypted connection to the destination service | ||
// using the provided certificate from DestinationCACertificate. | ||
TLSTerminationReencrypt TLSTerminationType = "Reencrypt" |
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 was confused when I saw this option.
- If we are doing passthrough, it should not be an HTTPRoute, I'd rather see that in TCPRoute or a TLSRoute, since we can't even know the protocol or muck around in it as it's an encrypted stream.
- Upstream connection details should not be part of the route level details but
HTTPRouteAction
maybe. Each service or action can potentially tweak this part a little differently.
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.
Right. I think that it is useful to think about this hop-by-hop. What does the hop from client to gateway look like? What does the hop from gateway to the next endpoint look like? I this model the name "reencrypt" doesn't really apply because we are focused only on hops.
/cc @smarterclayton |
// TLS is the TLS configuration of an HTTPRouteHost. | ||
// | ||
// If unspecified, the TLS configuration of the binding gateway | ||
// will 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.
The gateway gets a server TLS config, but here we need a client TLS config because this is the TLS policy describing how to connect to a backend service, right? If so, how can we re-use the gateway policy?
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.
Kubernetes is adding support for describing app-protocol on the core.Service
.
I would like to see if that suffices to describe the basic use case.
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.
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.
we need a client TLS config because this is the TLS policy describing how to connect to a backend service, right?
That should be part of a HTTPRouteAction since you can have different TLS configs for different services.
@bowei The AppProtocol solves the problem of which protocol to use, but an operator can still want to specify protocol level configuration settings, such as CAs to use, client cert to use (if need be).
Having said that, my interpretation is that this field represents downstream TLS configs(TLS settings between client and proxy) and not upstream TLS config (between proxy and service).
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.
OK, I got mixed up here. I was thinking this was the TLS context for the upstream hop. but it's the server context for termination the client TLS session.
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.
One important thing to keep in mind is that while all the bells and whistles are really cool to have, for the initial version, we don't/can't/don't have to do it all.
Remember, there is a core
that needs to be as universal as Ingress, extended
that we can reasonably live with.
Things beyond that we should really try to aim towards understanding how they would be expressed as custom
.
As things progress, it's easier to add than to remove.
// ca-bundle.crt: | | ||
// -----BEGIN CERTIFICATE----- | ||
// Destination Service CA Certificate Bundle. | ||
// -----END CERTIFICATE----- |
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 filed #74 to discuss certificates more generally.
|
||
// DestinationCACertificate is a reference to a CA certificate used | ||
// for establishing a TLS connection with the final destination when | ||
// using TLS termination type "Reencrypt". |
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 is a CA bundle? Then we can call this CACertificates
and I'd suggest the comment read something more like:
CACertificates is a reference to the bundle of trusted CA certificates used to validate the server certificate when establishing a TLS connection ...
// Support: Implementation-specific (For other resource types) | ||
// | ||
// +optional | ||
Certificate core.TypedLocalObjectReference `json:"certificate,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.
There's also other cases for allowing multiple server certificates (e.g. serving different type types).
Termination TLSTerminationType `json:"termination,omitempty"` | ||
|
||
// Certificate is a reference to a Kubernetes object containing | ||
// the identity certificate, key and CA certificate used to terminate |
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 this needs to be specced in detail for implementations to be interoperable. I raised most of the issues that occurred to me in #74 . We should also consider whether to allow separation of the key from all the certificate material.
type TLSConfig struct { | ||
// Termination defines how to terminate TLS connections. | ||
// | ||
// If unspecified, TLS termination type "Edge" will 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.
A significant number of users don't understand the details of TLS and higher-level protocols like HTTP and hence they associate TLS with a specific route, which is incorrect, since TLS session is established first and then the route is selected based on metadata of the higher-level protocol.
IMHO, the default common case should be to require the SNI and HTTP names to match (see #72).
/hold in favor of #71. |
@jpeach ptal at #35 (comment) and the associated PR. |
@danehans: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Closing in favor of #71. |
Currently,
Gateway
provides the ability to specify one or more certificates to use with a TLS listener. This requires application developers to coordinate with cluster operators when creating a TLSHTTPRoute
. This PR introduces the following changes:Gateway
specified certificate to be used for a TLSHTTPRoute
when the route does not specify a certificate.HTTPRoute
that includes the ability to specify how TLS connections should be terminated and the TLS assets (i.e. certificate) used for TLS connections./cc @bowei