Let Home Assistant trust a personal certificate authority

Hello everyone!

I’m using a personal certificate authority which I add to the trusted CAs of any of my devices so that they can identify other devices that I usually don’t permit to have internet access, which is partially why I’m not using a service like Let’s Encrypt for that matter.
I also have such a “locally” signed certificate in my HomeMatic CCU and I would like to enable the verify_ssl option in the homematic integration.
Sadly, I didn’t manage to locate where Home Assistant stores its trusted CAs or how the verification takes place and didn’t find a corresponding article in the Docs or the forum.

Can someone show me how I could let Home Assistant trust my certificate authority for ssl verification or point me to a resource from which I could continue my search?

1 Like

I couldn’t quite solve the problem yet, but I kind of forgot that HassOS is build upon alpine when asking the question.
I ssh’d into my Home Assistant setup, added my ca to /usr/local/share/ca-certificates/ and ran update-ca-certificates afterwards. I also verified that my certificate was correctly appended to /etc/ssl/certs/ca-certificates.crt .
Sadly to no avail it seems, as all HomeMatic devices remain unavailable when using the verify_ssl option.
Does Home Assistant maybe use a different certificate store?

Same situation here. Was there any resolution? The device tracker integration I am using doesn’t seem to allow for turning off SSL certificate validation, so I think I’m truly stuck. (Aruba Clearpass)

No progress yet sadly.

Let me know if you find something, I’ll update this thread too if I get to a solution!

1 Like

Okay, I made some progress. This post got me over the hump, though I don’t understand how to make the change permanent:

The short version is that Home Assistant uses a Python package called Certifi to manage trusted certificate authorities. The trust store is stored separately from the Linux platform trust store. This explains why updating the Linux trust store has no effect. The private CA can be either appended to the Certifi trust store (it’s text only), or you can run the script in the above post. Then restart the HASS services. The problem is that the file is not persistent across boots.

The Certifi trust store is located here: /usr/local/lib/python3.7/site-packages/certifi/cacert.pem

I am no expert on HASS or containers, so I don’t follow how to make this script run on boot so that the change is effectively permanent. That’s the last piece of the puzzle. Right now, I have to log in to the container and run the script manually. Maybe you can advise?

Finally, there needs to be some mechanism for updating or adding to the trust store on Home Assistant without all the above gymnastics. I’ll be digging in to how to make a suggestion for a feature enhancement on this topic.

Ken.

3 Likes

Great lead!
Back then I never searched for the acronyms, didn’t find some relevant topics in another case because of that too…

You’re running hass.io, right?

I’m running HASS on a VM on VMWare ESXi where I simply imported the VMDK file. I don’t think that’s hass.io, but again, I’m a bit of a newb here…

Damn, it didn’t post my reply from about half a week ago, but at least it saved a lot of what I had written:

A short, hopefully helpful rundown of the naming because I was quite confusedtoo when I started a few months ago (take all with a grain of salt though, the understanding is built from the context of many topics I read here):
Hass is just short for HomeAssistant; hass.io is the old term for running hass in Docker, today you’d just call it HomeAssistant or HomeAssistant Supervised if you want to emphasize the dockerization; HassOS is a kind of minimal Linux distro with everything necessary to run Hass by itself.
When you mentioned containers before I thought you were running Hass supervised, but if I got you correctly you’re running HassOS like me.

I used the script from the topic you linked and appended my CA to certifi’s store, but I still can’t connect to the CCU while using the verify_ssl option. A reboot resets the store like you said; calling homematic.reconnect after appending didn’t help either. The verify_ssl option works for you after appending to certifi’s store?

To run the script automatically I would normally use systemd, but I think Alpine uses OpenRC. However, /etc/local.d doesn’t exist and I also can’t run rc-update - so right now I’m not sure how HassOS handles initialization.
A cron service isn’t active either, so I’m running out of options a bit.

I think I found a way to add self-signed certs. Here’s the code I used, the trick was to append a .PEM version of the cert to the certifi CA.

# prep certs, this cannot be done in the Dockerfile because
# we also need to copy them to a mounted volume
cp /usr/local/share/ca-certificates/cert.crt /config/ssl/cert.crt
cp /usr/local/share/ca-certificates/cert.key /config/ssl/cert.key

update-ca-certificates

# create base64 PEM file from cert
openssl x509 -in /config/ssl/cert.crt -out /config/ssl/cert.pem

# add the pem to the certifi Python package certificate authority file
# the Python requests library does not use the system default CA, but uses the CA from the certifi package
# adding the PEM lets HA not spam warnings about insecure connections in the logs
cat /usr/local/lib/python3.8/site-packages/certifi/cacert.pem /config/ssl/cert.pem > /usr/local/lib/python3.8/site-packages/certifi/cacert-updated.pem
mv /usr/local/lib/python3.8/site-packages/certifi/cacert-updated.pem /usr/local/lib/python3.8/site-packages/certifi/cacert.pem
1 Like

Thank you for the suggestion, but krich11 and I are both on HassOS, not Supervised.
For us, the certifi certificate store resets on every reboot and so far I haven’t found out how HassOS handles initialization so that I could run a script on every boot (You can find what I’ve tried in that matter in my last comment before this one).
We also were already appending in pem format to our certifi store, whereby krich11 seems to have got it running, with the problem that a reboot resets the store, and I have properly appended my certificate but wasn’t able to connect to HomeMatic with the verify_ssl option nonetheless.

I verified the success of my appendix with the following script,

import certifi
import requests

try:
        print('Checking connection to RaspberryMatic...')
        requests.get('URL_TO_CCU')
        print('SSL is fine.')
except requests.exceptions.SSLError as err:
        print('SSL Error.')

which printed SSL error before my appendix and SSL is fine afterwards as expected.

1 Like

Was there any further progress being made? I am facing the same issue and created my own Root CA which of course hass.io does not accept. Because of that I can no longer connect to my QNAP NAS, QVR Pro and the Unifi components for presence detection. All use the certificates created with that Root CA which I would need to add to HA.

Does anyone know if a feature request or something exists to maybe create an “official” way to add it permanently to HA?

Thanks!

1 Like

Sadly not, I’m still facing the same issue.
I’m not aware of a feature request and hadn’t thought of one before because I expected some mildly-hacky way to accomplish this, even though certifi states that adding certificates is not supported.

I’m not sure how likely it will be for the request to go through, since it seems to me that the certificate store would need to be changed and that very few people are using their own CAs like us, but I can create a request over the next few days!

I think in this case the official way is the best way to do it. I personally created certificates covering the internal domains within my LAN and the externally reachable ones. So while the external part is no biggie with given plugins like Let’s Encrypt, etc. the challenge is always the internal domains. Since I did not want to use things strictly over the internet when I’m at home, I did not want to go all external.
So perhaps with a feature request we can at least get more information on how it can be done manually if there won’t be any “officially” implemented solution.
Maybe you can post the link to the request here as well for upvoting. :wink:

1 Like

Just posted the feature request!

Let me know if I should edit something in that would be better to have on top than in a separate comment!

Ok, I think I’ve got a workaround for homeassistant OS, but this is more like a workaround than a perm solution given you will lose this every time you install a core upgrade.

  1. Get that USB drive ready with the authorized_keys file described here: https://developers.home-assistant.io/docs/operating-system/debugging/
  2. Login to the :22222 ssh, and type “login” to get the shell
  3. Warg into the home assistant container: docker exec -it homeassistant /bin/bash
  4. Add your certificates to /etc/ssl/certs/ and ultimately to /etc/ssl/certs/ca-certificates.crt

Adding certs follows the same process you get automated by update-ca-certificates many linux distros:

  • Copy the cert into the /etc/ssl/certs directory
  • Get a hash with openssl x509 -hash -noout -in yourcert.pem
  • Symlink the certificate to $hash.0 (for example: fe8a2cd8.0 -> SZAFIR_ROOT_CA2.pem)
  • Add the cert to the end of /etc/ssl/certs/ca-certificates.crt (it is likely that this alone is enough, the rest is future-proofing / past-proofing)
  • Test success with curl https://yoursite.lan

The process of adding this can be automated rather easily, however my homeassisntant based cert-injector automation needs to wait :smiley:

Hope that helps,
mb

3 Likes

Wow, that looks promising, thanks a lot! I’ll definitely give it a try as soon as I find the time!

Presumably it’s even more helpful to kurisutian, since he can’t simply turn off verify_ssl like I can as it seems :sweat_smile:
And luckily, a MITM attack via my RaspberryMatic in my home network is rather unlikely - at least I hope that it is… :smiley:

Cool!

For the automation piece what I have in mind is:

  • sensor to check if https site loads with curl -skIX
  • sensor to check of https site loads with curl -sIX

Should only the last one fail, we need to inject the certs with a shell_command.

And this ideally fixes sensors as well upon the next check. Exceptions would be integrations that kick when initialized and put on an error path when they fail. Worst case: needs a restart.

Yeah, needs some time but nothing significant I imagine.

1 Like

Hi!, i need help on how to copy the CA file into step 4 ? I’m completely loss on where I’m when seeing the homeassistant /bin/bash. I also can not paste/edit via terminal text editor like nano or vim in there. I’m sorry for my silly question. Thanks anyway.

Edit:
Problem solved, how to resolve:

  1. In the /etc/ssl/certs directory: Get .pem certificate file from web using wget. ($ wget https://ca.example.com/ca.cert.pem)
  2. Get hash, and create symbolic link ($ ln -sf pathtoca.cert.pem pathtosymlinkwithhash)
  3. Create backup of ca-certificates.crt: $ cp ca-certificates.crt ca-certificates.crt.backup
  4. Join the certificate: $ cat ca-certificates.crt.backup ca.cert.pem > ca-certificates.crt

Done

2 Likes

Manual updates for this are tedious if you try to stay up-to-date with HA Core. I have a thread with a feature request here.

Discuss and more importantly, vote!

I’ve got some nastyhack proto code here that automates this process.
With the included binary sensor used, it constantly checks for losing trust, and re-injects as appropriate; this basically “smooths” you through core updates.

The important bit is that you’ll need to run this inside Core (homeassistant docker container).

While I’m sure there must be easier ways around this, I’ve chosen to live with this until a proper solution emerges.
Let me know if this works for you.

mb

1 Like