-
Notifications
You must be signed in to change notification settings - Fork 91
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
Add ability to disable mTLS #279
base: main
Are you sure you want to change the base?
Conversation
@patrickdemers6 Hi could you help review again? |
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 looking better, thanks!
I will try using this once back from holiday travels. Have you been able to test this with a real vehicle?
An integration test for this would be nice to have but at first glance, it doesn't look like the easiest thing to add.
config/config.go
Outdated
@@ -47,6 +47,11 @@ type Config struct { | |||
// TLS contains certificates & CA info for the webserver | |||
TLS *TLS `json:"tls,omitempty"` | |||
|
|||
// DisableTLS indicates whether to disable mutual TLS (mTLS) for incoming connections. | |||
// This should only be set to true if there is a reverse proxy that is already handling | |||
// mTLS on behalf of this service. TLS will be ignored. |
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.
Include a comment about how client cert needs to be included in headers.
README.md
Outdated
@@ -284,3 +284,4 @@ Moreover, the following application-specific considerations apply: | |||
the frequency they need. | |||
* Providers agree to take full responsibility for privacy risks, as soon as data | |||
leave the devices (for more info read our privacy policies). | |||
* If you're running your Fleet Telemetry instance behind a trusted proxy which handles mTLS, set ```"disable_tls"``` to ```true``` in the config. |
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.
Include a comment about how client cert needs to be included in headers.
if len(allCerts) == 0 { | ||
return nil, errors.New("missing_certificate_error") | ||
} | ||
return allCerts[0], nil |
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.
Is index 0 correct? The TLS method grabs the last cert, not the first. If first is correct, let's exit early in for loop.
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.
server/streaming/server_test.go
Outdated
"crypto/x509/pkix" | ||
"encoding/base64" | ||
"encoding/pem" | ||
"github.com/teslamotors/fleet-telemetry/metrics/adapter/noop" |
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.
nit: grouping of imports
I haven't test with real vehicle setup.
I'll try to add another integration test. |
There's only a unit test currently. Integration tests are defined in |
I try to add integration test, but still struggle with it. My idea is to add nginx that expose another port that terminate mTLS and forward in header on docker compose. Add a similar test as existing one, but call on that another port. |
Hey folks! Thanks for PR! I'm planing to use telemetry behind cloudflare tunnel and it's now not possible because of mTLS. |
I'm not so sure this is possible. I would be happy if you prove me wrong. mTLS is not something you should/can just ignore, this PR just tries to handle it differently. Instead of terminating the mTLS connection directly in the telemetry-server, where the full client cert is validated, it expects some proxy to terminate it and forward the full client cert via the "Client-Cert-Chain" header, so it again can be validated. cloudflare is technically such a proxy. But as far as I am aware, it can not insert the full client cert into a header. This is the list of fields you could add into headers: https://developers.cloudflare.com/ruleset-engine/rules-language/fields/dynamic-fields/#cftls_client_authcert_revoked If you just use the issuer and client subject DN without any verification, this information could easily be spoofed. There is a "cf.tls_client_auth.cert_verified" field that would work for Cloudflare-issued client certificates, but in order to validate the certificate the vehicle sends against the Tesla Vehicle CA, you need to provide Teslas CA cert to cloudflare, which is only possible for enterprise acccounts: https://developers.cloudflare.com/ssl/client-certificates/byo-ca/#availability |
@@ -235,6 +244,35 @@ func extractIdentityFromConnection(r *http.Request) (*telemetry.RequestIdentity, | |||
} | |||
|
|||
func extractCertFromHeaders(r *http.Request) (*x509.Certificate, error) { | |||
raw := r.Header.Get("Client-Cert-Chain") // Client-Cert and Client-Cert-Chain HTTP Header Field https://datatracker.ietf.org/doc/rfc9440/ |
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.
Thank you for your contribution, I am interested as well so please let me know if I can help in any way (like checking the behavior in my environment etc.)!
Just a thought: it could be useful to be able to specify which header contains the client cert chain, for example to use it behind an AWS ALB in mutual TLS passthrough mode (in which case the header is X-Amzn-Mtls-Clientcert
).
Implementation image:
# config/config.go
type Config struct {
...
ClientCertChainHeader string `json:"client_cert_chain_header,omitempty"`
...
}
# server/streaming/server.go
func extractCertFromHeaders(r *http.Request, config *config.Config) (*x509.Certificate, error) {
header := "Client-Cert-Chain" // Client-Cert and Client-Cert-Chain HTTP Header Field
if config.ClientCertChainHeader != "" {
header = config.ClientCertChainHeader
}
raw := r.Header.Get(header)
...
}
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.
Nice idea. @patrickdemers6 as maintainer, what do you think?
Should we adhere to rfc9440 or allow custom header to pass 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'm a fan of ensuring we support the most popular proxies, load balancers, etc. If rfc9440 isn't widely adopted, we should try to create a flexible configuration that can evolve to differing header names and formats.
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.
@quentinplessis I read https://docs.aws.amazon.com/elasticloadbalancing/latest/application/mutual-authentication.html#mtls-http-headers document. Simply adding customer header client_cert_chain_header won't work because it doesn't is base64 format same as RFC9440 does. I checked another LB from GCP it follows https://cloud.google.com/load-balancing/docs/https/custom-headers-global#variables RFC9440.
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've got an idea. Instead of a custom ClientCertChainHeader
, make a enum config
# config/config.go
type Config struct {
...
TLSHeaderConfig HeaderExtractConfig `json:"client_cert_header_config,omitempty"` // naming this is hard. Open for suggestion
...
}
type HeaderExtractConfig string
const (
RFC9440 HeaderExtractConfig = "rfc9440"
AWSApplicationLoadBalancer HeaderExtractConfig = "aws_application_load_balancer"
)
The valid value are rfc9440
, aws_application_load_balancer
. If another wants to add custom implementation then they can made PR.
Just pushed an image to docker hub and will try testing shortly.
|
Description
Add option to disable mTLS
Fixes (issue)
Type of change
Please select all options that apply to this change:
Checklist:
Confirm you have completed the following steps: