Building secure access to Teslamate using Azure

Building secure access to Teslamate using Azure

Today I’m writing about something fairly esoteric – an open-source project called Teslamate and how to set it up so that I can access it securely. Even if you don’t have plans to deploy Teslamate, I feel it’s still useful to highlight how flexible Azure is in securing services like this.

What is Teslamate, and why should I care?

Teslamate is a software piece allowing you to track, monitor, and analyze data about your car – specifically, a Tesla-branded car. It’s a project by Adrian Kumpf. I’ve written about the Tesla API previously, where I used a bit of C# to ping my car and extract useful data about it. With Teslamate, someone actually went far and above and built a real tool for all this.

Once it’s running, you can view all sorts of data from the pre-made dashboards. This is the overview dashboard:

Drive Stats reveal insights about the usual destinations, and extrapolated values:

(I’ve blurred the actual specific addresses, as quite many of those are actual homes of people I know)

Trip statistics is mostly the same data, with a nice map:

There are about 15 different dashboards. I’m most interested in seeing how much charging is done, how much it costs (you can input the specific cost for each charge if you’d like), and overall how the car is doing.

You can get the sources from this GitHub repo.

Requirements for Teslamate

Teslamate requires a Postgres database, visualization with Grafana, and a local MQTT broker. The idea is that you’ll deploy these in Docker containers. They’ll also need to be running continuously to keep pulling data from your car. Otherwise, it wouldn’t be too useful in the long run.

Running Teslamate

I pondered for a bit where to host Teslamate. All the data it gathers is mostly useful to me, yet there is enough data collected over time that makes it valuable. How much am I paying for charging in the long term? How many kilometers do I anticipate driving in the next year? And of course, logs of all places I’ve visited with the car.

By default, Teslamate runs over HTTP – thus, all traffic is unsecured. To secure it takes a bit of bravery: setting up a reverse proxy, creating a custom configuration and an existing SSL certificate (from Let’s Encrypt). I didn’t want to start tinkering with Apache .htpasswd files either.

I opted to run Teslamate by using my NAS as the Docker host: it’s a Synology DS1821+, with 32 GB of RAM. It runs Docker containers natively, and has a nice GUI for basic settings.

Setting up Teslamate on Synology was a breeze – and it just works:

Securing Teslamate

Now that Teslamate works and is accessible via HTTP in my local network, it’s time to secure it. As I opted to run the solution in my local network, it would be great to access the Teslamate statistics and analytics remotely. The options I have at my disposal are:

  1. A VPN connection – a user opens a dedicated client connection to access the app
  2. Exposing the app directly from my Synology NAS
  3. Using Azure AD Application Proxy

For a VPN connection, the problem is that it’s quite tiresome to configure and manage on certain devices, such as mobile devices. Exposing the app directly was something I tried – but sadly, it will only limit access based on an IP range, which I feel is not too modern. Users have dynamic IPs, so essentially, you’d open up the whole world anyway.

Azure AD Application Proxy is a feature of Azure AD, requiring a Premium license for the users. In essence, it allows you to publish an endpoint securely and enforcing Azure-related security aspects – such as two-factor authentication – while accessing the service.

Azure AD Application Proxy requires a connector, which is a piece of software you drop in your local network. I dropped the connector to a VM I have running for random scripts and tasks like this. It builds a tunnel between the Teslamate Docker container and Azure AD, exposing a neat HTTPS:// endpoint.

This is the logical architecture:

And configuring this via Azure AD in Azure Portal, you only need to point to the internal URL of the container:

Note, that I’ve enabled Azure AD for pre-authentication. This ensures that anyone accessing my Teslamate instance will have to authenticate through Azure AD first. And the user account that will be used, has Microsoft’s Multi-Factor Authentication (MFA) enforced. Each user can then securely access Teslamate with:

  1. HTTPS enabled and enforced
  2. Azure AD authentication required
  3. MFA enforced

And nothing has to be published directly from my internal network to the public Internet.

But does it work? Yes!