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

Client certificate validation (mTLS) design proposal #1233

Merged
merged 12 commits into from
Jan 26, 2020

Conversation

uablrek
Copy link
Contributor

@uablrek uablrek commented Jul 8, 2019

Implementation proposal for #1090

See also PR #1226

Copy link
Contributor

@davecheney davecheney left a comment

Choose a reason for hiding this comment

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

Thank you for breaking this out. My overall feedback is this proposal is missing the mark. What I believe you want is to be able to use XFCC to secure, or authenticate (its' not clear to me), communication between a remote user and a backend in a k8s cluster.

If this is the problem statement I suggest starting from that as a proposal.


At a high level I propose the following:

1. A new record "clientValidation" is added in spec.virtualhost.tls
Copy link
Contributor

Choose a reason for hiding this comment

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

You lost me here. The previous section talked about XFCC being between the end user and and backend application server. Now this is talking about a change to the tls settings for the whole virtual host. Is this a problem with the problem statement? Is this a security issue? If so what is the threat model? Is this an authentication issue? It's not clear to me at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you may be right. I will remove the XFCC header from the proposal since it may be confusing. It can be handled separately later on in another issue.

Copy link
Member

Choose a reason for hiding this comment

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

Hey @uablrek, just taking a look here as well.

I'm curious about @davecheney's comment earlier about if this is a vhost setting or a per route setting. Could I have each route in my cluster use a different cert based upon the upstream it's calling?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@stevesloka I asked the very same question in the Envoy slack 😄 The ansver is; No client certificate validation is per vhost, not for routes. The reason is that the route is in the data, but the client validation is performed before data is decrypted.

Copy link
Contributor Author

@uablrek uablrek Jul 20, 2019

Choose a reason for hiding this comment

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

For the XFCC header on the other hand it seems possible to forward different certificate details to different routes. But as @davecheney commented it is much better to add XFCC support as a different item, so I do not mention it in the design document any more.

Copy link
Member

Choose a reason for hiding this comment

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

Ok so to clarify, is this looking to mTLS a public client calling into Envoy with a backend service? Or to secure communication from Envoy to a backend service inside the cluster?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not about cluster internal Envoy-backend communication. It is mTLS used to validate an external client accessing the service through contour/envoy from outside the cluster.

3. For phase 1 the configuration of what to forward in the XFCC header is
hard-coded to SANITIZE_SET and certificate hash.

The design of phase 2, the XFCC configuration, is dependent on the
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to see an issue for something like XFCC should be supported by Contour. If that's the actual goal of this proposal then lets agree on that first before getting side tracked into implementation issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please see the comment above

@uablrek uablrek force-pushed the mtls-design branch 2 times, most recently from 06c1456 to 748fb19 Compare July 9, 2019 05:53
@uablrek
Copy link
Contributor Author

uablrek commented Jul 9, 2019

To clearify; the XFCC header is not necessary for mTLS. It is a way of informing the backend that client validation has been conducted by the proxy with a certain certificate.

So, XFCC is informational data to the backend, it has nothing to do with security.

@uablrek
Copy link
Contributor Author

uablrek commented Jul 11, 2019

More about XFCC; Different client certificates may be used, e.g an "admin" certificate or "user", having different rights. Then it is not sufficient for the server that the client is validated as any client, the server must know which client that is validated. Then the XFCC is used to forward the necessary client certificate details.

Not all applications needs client certificate details, only those who uses different types of client certificates, and the way of forwarding client certificate details is not standard and varies between proxies which of course makes it hard for applications

@uablrek
Copy link
Contributor Author

uablrek commented Jul 11, 2019

@davecheney Can you please re-check the document?

@davecheney
Copy link
Contributor

davecheney commented Jul 12, 2019 via email

Copy link
Member

@stevesloka stevesloka left a comment

Choose a reason for hiding this comment

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

It would be great if you could add a top-level summary of the feature. Just a quick explanation of what you're looking to accomplish and some use-cases.

I'm also curious about the placement of the new ClientValidation struct (See comment).

## Goals

- Allow client certificate validation (mTLS) on contour (performed by Envoy)
- Allow various ways for client certificate validation; Spki, Hash and CA
Copy link
Member

Choose a reason for hiding this comment

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

Can only one type be specified? Envoy allows multiple, but I'm not sure of the use-cases that would drive picking multiple.

When both: verify_certificate_hash and verify_certificate_spki are specified, a hash matching value from either of the lists will result in the certificate being accepted.

Copy link
Contributor Author

@uablrek uablrek Jul 20, 2019

Choose a reason for hiding this comment

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

Me neither to be honest. I rely on that Envoy knows what they are doing and try to allow all Envoy configurations for mTLS also in contour. That is also a reason for the non-goal;

Repeat configuration details described in Envoy documentation (make references)

I will pass the question on to a security expert, but they tend to be busy...

Copy link
Member

Choose a reason for hiding this comment

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

I think using multiple types makes most sense in combination of a trusted_ca and verify_subject_alt_name. In this case the administrator wants to uniquely authenticate a particular client(s) before allowing them to establish TLS connection. For example a client with identity "CN=Joe" issued by certain trusted CA (or a sub-CAs of the trusted CA). This is by far the most common use case for client certificates in general. However, like discussed in PR comments, in some cases the specific client identity might not matter and one would then specify trusted_ca alone.

Combination of verify_certificate_spki and verify_certificate_hash does not make sense to me, since it is likely that administrator picks just one way to pin a specific certificate: either administrator wants to identify client(s) by hash of public key or hash of the complete certificate file, not both at the same time. Since this is an act of whitelisting a specific client certificate, it would be bit redundant or at least confusing, to use trusted_ca in combination with either of these two methods. When a client identified by a specific cert is explicitly marked as allowed to establish a TLS connection, validating that it is also issued by a trusted CA should not generally matter (though I have not tested if this combination is supported by Envoy). Obviously Envoy will still require the client to demonstrate proof-of-possession of the private key associated to the client certificate, in addition to validating the hash of the public part.

In theory one could imagine a use case where some clients are allowed to establish a connection because they are issued by trusted_ca and others because they are specifically pinned/whitelisted by their verify_certificate_spki and verify_certificate_hash fingerprint but I don't think this is very common scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tsaarni I have ignored verify_subject_alt_name since I did not understand it's use. From your comment I see it's important. Can the configuration look something like this?;

      clientValidation:
        secretName: clientsecret
        subjectAltNames:
          - Joe

The list of subjectAltNames would be passed to Envoy in the verify_subject_alt_name field.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Correction to my comment: My example "CN=Joe" (X509 Common Name field) was for subjectName and subjectAltName would rather be something like email "joe@example.com", instead of just "joe". Obvious from documentation, Envoy only supports validation of subjectAltName field.

One complication is that X509 subjectAltName is not just free text: there is type involved (see list here and definition of GeneralName in RFC5280. However Envoy documentation does not seem to specify what format it supports?

I have small doubt that maybe it just supports URIs since this feature might be added to Envoy due to Istio, which uses subjectAltName in the SPIFFE certs and it leaves subjectName empty. I might try to find this from envoy code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok thanks for the update. I will change from "Joe" to an URI, "service.example.com".

Copy link
Member

Choose a reason for hiding this comment

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

Just out of curiosity I checked what types of subjectAltName's Envoy supports as values of verify_subject_alt_name. The code is here. The value can be DNS name, URI or IPv4/6 address.

@uablrek
Copy link
Contributor Author

uablrek commented Jul 20, 2019

@stevesloka

I have improved the "Background" chapter. Please notify me if you think it should be more.

We want to use contour but a stopping issue is lack of support for mTLS. A proposal is to use istio as it also uses Envoy and have mTLS support, but I would not like to go that way. I do not know the use cases in our product that require mTLS, just that they do.

@uablrek
Copy link
Contributor Author

uablrek commented Jul 23, 2019

@davecheney @stevesloka Can you please take another look at this after the updates?

If the proposal is acceptable I can continue with the implementation.

more widespread for business-to-business (B2B) applications (which
may use gRPC and REST APIs).

I can't give a real-life example but it is easy to imagine cases where
Copy link
Member

Choose a reason for hiding this comment

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

Here are some common example scenarios for protecting REST APIs:

  • Elasticsearch did not support authentication, until very recently. The common pattern was to put reverse proxy in front of Elasticsearch to handle TLS and authentication
  • Prometheus does not support either TLS or authentication. Common patter is to put reverse proxy in front.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

more widespread for business-to-business (B2B) applications (which
may use gRPC and REST APIs).

I can't give a real-life example but it is easy to imagine cases where
Copy link
Member

Choose a reason for hiding this comment

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

I'd like to challenge this statement: "I can't give a real-life example but it is easy to imagine cases".

You're looking to add this feature, so there's a need to have this, right? We should be adding real-life use-cases to back up the proposal, without those, then I question why we are adding this feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have updated the examples with the ones in the comment above #1233 (comment)


### CAs in Secrets

Same as for [TLS backend verification](tls-backend-verification.md).
Copy link
Member

Choose a reason for hiding this comment

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

What is the same? How communication is secured? How secrets are named?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They are named, used and created in the same way.

I removed the reference and copied the chapter from tls-backend-verification.md instead to make it clear.

Copy link
Contributor Author

@uablrek uablrek Jul 23, 2019

Choose a reason for hiding this comment

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

Communication is secured with TLS (encryption), same as always. mTLS is just a way to limit the access to the server to validated clients. You may see it as an "add-on" to normal TLS, not a replacement.

@uablrek
Copy link
Contributor Author

uablrek commented Jul 31, 2019

@stevesloka @davecheney Can you please have another look at this?

I have added use-cases as requested.

Please note that mTLS is not something I have invented myself and try to impose on contour. mTLS is a well established standard for client authentication over TLS, and it has support in envoy. I just would like to make it available for contour users since we need client authentication for some REST interfaces.

@uablrek
Copy link
Contributor Author

uablrek commented Aug 14, 2019

Here is another use-case, client validation using mTLS for helm-charts with an example fow to configure the nginx ingress controller for mTLS; https://hub.helm.sh/charts/drgrove/mtls

@tsaarni
Copy link
Member

tsaarni commented Nov 13, 2019

I would like to continue with this PR (which we agreed with @uablrek). The design doc now only contains proposal for validating external client certificate with trusted CA certificate, all other proposals were removed.

I'd be grateful for any feedback!

Copy link
Member

@youngnick youngnick 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 this document is ready now. It's well scoped, has a clear plan, and is implementable pretty much straight away.

I'd like to see the commits squashed before merging though.

@youngnick
Copy link
Member

Oops, I also missed that CI hasn't passed, looks like there's a misspelling in the document. @tsaarni, could you run make check in your local repo and fix any errors? Once the CI is green and @davecheney has given the 👍 , then I'll squash and merge for you.

Copy link
Contributor

@davecheney davecheney left a comment

Choose a reason for hiding this comment

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

Thank you for working on this. I think this is very close. In addition to some formatting nits, I would like to see any reference to mTLS removed -- that word is cursed, different people use it to mean different things so avoiding it completely will make the document more precise.

Other than that this looks pretty straight forward.

@@ -0,0 +1,125 @@
# External client certificate validation (mutual TLS authentication)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/(mutual TLS authentication)//

Copy link
Member

Choose a reason for hiding this comment

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

I have now removed references to mutual TLS authentication and mTLS.


Status: Draft

This document outlines how to add support for authentication of external
Copy link
Contributor

Choose a reason for hiding this comment

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

Do not wrap lines. One line per sentence please. This makes it easier to comment a specific line, and reduces the diff size for comments.

Copy link
Member

Choose a reason for hiding this comment

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

I have now reformatted the document accordingly.


## Background

In TLS (and HTTPS) often only the client authenticates the server. TLS
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove all the words about mutual TLS authentication, as I understand it this proposal is only about client side certificate authentication. If you want to add mutual TLS as a non goal, please do so in the previous section.

Copy link
Member

Choose a reason for hiding this comment

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

I have now removed references to mutual TLS authentication and mTLS.

* A new record `clientValidation` is added in `spec.virtualhost.tls`
in the `HTTPProxy`.

* The `clientValidation` contains parameter `caSecret` which is a reference
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the justification for a new key, do you think we'll have to add additional keys under clientValidation in the future?

Copy link
Member

Choose a reason for hiding this comment

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

I wish that in future we could add verification of subject alternative name of the client (option 2. in the list above).

Copy link
Contributor

Choose a reason for hiding this comment

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

We should use UpstreamValidation (with a new name) to describe both upstream and downstream TLS validation policy.

```

TLS certificate delegation is not in scope for CA certificates.

Copy link
Contributor

Choose a reason for hiding this comment

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

remove newline

Copy link
Member

Choose a reason for hiding this comment

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

Done!

APIs. The application acting as TLS client authenticates itself towards the
TLS server by using x509 certificate and by providing proof of posession of
the corresponding private key.

Copy link
Contributor

Choose a reason for hiding this comment

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

remove newline

Copy link
Member

Choose a reason for hiding this comment

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

Done!

Client certificate validation is enabled in Envoy by setting
`auth.DownstreamTlsContext.RequireClientCertificate` value to `true` and by
adding trusted CA certificates to `auth.CommonTlsContext.ValidationContextType`.

Copy link
Contributor

Choose a reason for hiding this comment

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

remove newline

Copy link
Member

Choose a reason for hiding this comment

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

Done!

To use annotation in the `Ingress` object was considered to
clumsy. Annotation must on `Ingress` level and refer to an individual
virtual host.

Copy link
Contributor

Choose a reason for hiding this comment

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

remove newline

Copy link
Member

Choose a reason for hiding this comment

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

Done!

Lars Ekman added 5 commits November 28, 2019 10:22
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>

Describe the 2-phase implementation and XFCC details.
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Lars Ekman and others added 7 commits November 28, 2019 10:22
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
(rather than a reference)

Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Signed-off-by: Lars Ekman <lars.g.ekman@est.tech>
Signed-off-by: Tero Saarni <tero.saarni@est.tech>
* corrected misspellings
* removed references to mutual TLS authentication and mTLS
* corrected formatting

Signed-off-by: Tero Saarni <tero.saarni@est.tech>
@tsaarni
Copy link
Member

tsaarni commented Nov 28, 2019

Thanks @davecheney and @youngnick for the review! I have now corrected the document accordingly. If there is further comments, I'll gladly do updates!

@tsaarni
Copy link
Member

tsaarni commented Jan 22, 2020

I wonder what your thinking is about this feature currently: Would it be something that could be accepted? Is there some changes or investigations that I could do?

@jpeach
Copy link
Contributor

jpeach commented Jan 23, 2020 via email

Copy link
Contributor

@jpeach jpeach left a comment

Choose a reason for hiding this comment

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

LGTM, with the proviso that in the final implementation, the upstream and downstream validation fields should use the same struct (i.e. the one currently named "UpstreamValidation").

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.

6 participants