teslamotors / fleet-telemetry

Apache License 2.0
668 stars 79 forks source link

How to generate and use the mTLS keys and cert? #99

Closed jbanyer closed 6 months ago

jbanyer commented 9 months ago

Can anyone clarify how to generate the keys and certificate required to use fleet telemetry mTLS?

I can't find instructions on generating the keys in this repo.

The vehicle-command repo has instructions for generating a key for TLS for the http proxy, which are:

openssl req -x509 -nodes -newkey ec \
    -pkeyopt ec_paramgen_curve:secp521r1 \
    -pkeyopt ec_param_enc:named_curve  \
    -subj '/CN=localhost' \
    -keyout key.pem -out cert.pem -sha256 -days 3650 \
    -addext "extendedKeyUsage = serverAuth" \
    -addext "keyUsage = digitalSignature, keyCertSign, keyAgreement"

Will that work? Just need to set an appropriate value for subj?

What is the relationship between these fleet-telemetry mTLS keys and the public key registered against our domain for API access? Does the CN value in these keys need to exactly match the domain that was registered? Is the API private/public key pair somehow used in the creation of the mTLS keys?

jbanyer commented 9 months ago

Also, what is the purpose of the Certificate Signing Request (CSR) that we send to fleetapisupport@tesla.com per these instructions?

Does that cause something to change on the Tesla backend or vehicles?

Does Tesla reply with a certificate, signed by them? If so, how do we make use of this certificate?

Bre77 commented 9 months ago

There are two different things your talking about here:

The first thing you were talking about is for the vehicle-command HTTPS server, not fleet-telemetry or mTLS. You can completely disregard that when talking about Fleet Telemetry, its literally just a webserver key and cert and has zero relationship to the mTLS.

To generate your mTLS private key which is used for both vehicle-command signing and fleet-telemetry mTLS, see https://developer.tesla.com/docs/fleet-api#fleet-telemetry

openssl req -out partner_domain.com.csr -key private_key.pem -subj /CN=partner_domain.com/ -new

Then you use that key to create a CSR, email that to tesla, and they then return you a certificate to use with fleet-telemetry.

I have been waiting 3 weeks to get a reply with my certificate though.

So at the end of the day you need: Vehicle Command Proxy web certificate pair - Just a regular HTTPS cert and key from letsencrypt or digicert or openssh. Vehicle Command signing key and Fleet Telemetry mTLS key pair - use to authenticate with vehicles

jbanyer commented 9 months ago

To generate your mTLS private key which is used for both vehicle-command signing and fleet-telemetry mTLS, see https://developer.tesla.com/docs/fleet-api#fleet-telemetry

openssl req -out partner_domain.com.csr -key private_key.pem -subj /CN=partner_domain.com/ -new

As I understand, that command generates a CSR using an existing private key (which must be the private key used for command signing, as per the instructions). It does not generate a private key.

I ran that command, passing my existing command-signing private key eg -key ../my-keys/com.tesla.3p.key.pem and it created the .csr file, which I've emailed to Tesla.

Bre77 commented 9 months ago

Yeah correct, I didnt read it close enough before copy pasting. Now you wait for Tesla.

When you get the certificate back, you can start a Fleet Telemetry server by setting the key and certificate in the tls section of the Fleet Telemetry server config.

jbanyer commented 9 months ago

I notice outstanding PR #88, which adds a bit more info regarding the keys:

You may generate a self-signed certificate using the OpenSSL command below, though we recommend using best practices for generating a server certificate from a trusted certificate authority (have your domain/CNAME ready) openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem

But it doesn't mention the CSR we send to Tesla. Perhaps the self-signed approach is an alternative to the CSR, for non-production use?

It may largely be my ignorance, but I'm having trouble grasping the overall picture of how it all fits together, which key is used where etc. I'd be happy to submit PRs to improve the READMEs but I currently don't understand enough :(

Bre77 commented 9 months ago

You cannot self-sign the fleet-telemetry certificate, I tried, the /api/1/vehicles/fleet_telemetry_config API endpoint will reject it. The server will start, but you wont be able to configure a vehicle to use it.

I'll try break all the crypto down for you:

  1. ECDSA Private Key
  2. ECDSA Public Key hosted at /.well-known/appspecific/com.tesla.3p.public-key.pem, created using (1)
  3. CSR created from (1)
  4. Certificate signed by Tesla, created from (3)

Fleet Telemetry uses (1) and (4) in the TLS config. Vehicle Command Proxy uses (1) only in -key-file parameter.

Then, completely seperate:

PrriyaR commented 8 months ago

How do you send the CSR to Tesla? I tried to send through register endpoint but I am getting Internal server Error. Do we email CSR to Tesla? If yes what is the email address?

{ "response": null, "error": "An unexpected error occurred - 0630a97bd01d81c0798bc7bac2d9eea3", "error_description": "" }

Bre77 commented 8 months ago

If yes what is the email address?

fleetapisupport@tesla.com

The process is all in the documentation.

StephenPorter commented 8 months ago

We sent a revised CSR that passes the check_csr.sh script to fleetapisupport@tesla.com about 3 weeks ago (2/10), but haven't heard anything back. I also submitted the same CSR to the register endpoint as there was some indication that was an alternative route to register.

I am still getting an error that I don't have a CSR every time I call the fleet_telemetry_config endpoint for our vehicles, so I interpret that to mean we haven't been issued a certificate yet.

Does anyone know if there is a way to get an update on the progress of approval? It would just be helpful to know if we are held up because of use-case, an incorrect request, or just process delay.

jbanyer commented 8 months ago

In the helpful guide written by @patrickdemers6, it suggests using certbot and LetsEncrypt (or equivalent) to generate a Certificate and CA Bundle for use with TLS.

Bre77 commented 8 months ago
  • does this mean the TLS certificate must be signed by a public CA, and not with our own private key?

No, mine is signed by my own CA based on the private key used to create the CSR.

  • if so, what is the purpose of sending a CSR to Tesla? What does Tesla do with it?

I think it's because you could certify the vehicle cert using your private key, but this also confused me because I though running your own CA was required.

In fact, all three of my Fleet Telemetry servers have their own private key and cert, but all signed by a CA that uses my private key, which is the CA that gets sent to vehicles.

idonkeyliu commented 7 months ago

When I access this interface,https://fleet-api.prd.cn.vn.cloud.tesla.cn/api/1/vehicles/fleet_telemetry_config. The interface returns...

{"response":null,"error":"upstream internal error","error_description":""}. What could be the reasons for this return

Furthermore,What should be filled in for this parameter(config.ca) in this interface?

agbpatro commented 7 months ago

When I access this interface,https://fleet-api.prd.cn.vn.cloud.tesla.cn/api/1/vehicles/fleet_telemetry_config. The interface returns...

{"response":null,"error":"upstream internal error","error_description":""}. What could be the reasons for this return

Furthermore,What should be filled in for this parameter(config.ca) in this interface?

fleet_telemetry isn't supported in China yet

idonkeyliu commented 7 months ago

When I access this interface,https://fleet-api.prd.cn.vn.cloud.tesla.cn/api/1/vehicles/fleet_telemetry_config. The interface returns... {"response":null,"error":"upstream internal error","error_description":""}. What could be the reasons for this return Furthermore,What should be filled in for this parameter(config.ca) in this interface?

fleet_telemetry isn't supported in China yet

Are you sure? Previously, when I submitted this interface, it showed success. it returns {"response":{"updated_vehicles":1}}

The error occurred now because I am changing the domain name and re-submitting.

jbanyer commented 6 months ago

Docs have been updated to make all this stuff clearer.