feat(tls): support custom CA via OS trust store + SSL_CERT_FILE#56
Merged
Conversation
Users running their own CA (step-ca, smallstep, homelab OpenSSL) need hass-mcp to trust the certificate without disabling verification. Existing approaches in the ecosystem either silently downgrade to verify=False or duplicate work httpx already does. This PR layers two mechanisms so the right thing happens regardless of how the user deploys hass-mcp: 1. OS native trust store via truststore (the same library pip uses by default since 24.2). Bridges to macOS Keychain, Windows Cert Store, and Linux ca-certificates. Users who installed their CA at the OS level get it for free with zero config. 2. Explicit SSL_CERT_FILE override. The canonical OpenSSL env var, honored by every TLS-aware tool. This is the primary Docker mechanism — bind-mount the CA file, set the env var, done. Also serves as the override path on any platform. Explicitly declined: - REQUESTS_CA_BUNDLE — that's a requests-specific alias, not a standard - verify=False — silent downgrade is worse than a hard failure; HA_URL=http://... is the documented path for unencrypted LAN Adds `truststore>=0.10` (~30 KB, no runtime deps; Python 3.13 satisfies the 3.10+ floor). Tests cover both code paths: - Default returns truststore.SSLContext - SSL_CERT_FILE takes precedence and yields a stdlib ssl.SSLContext README documents the canonical Docker pattern (bind-mount + env var). Supersedes #15. Co-Authored-By: rmoriz <rmoriz@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Users running their own PKI (step-ca, smallstep, homelab OpenSSL) need hass-mcp to verify their HA's certificate without disabling TLS. Supersedes #15 with a portable, defaults-safe mechanism that works across local installs, Docker containers, and standalone deployments.
Two layered mechanisms
OS native trust store via
truststore— the same library pip has used by default since 24.2 (mid-2024). Bridges to macOS Keychain, Windows Cert Store, and Linux ca-certificates. Users who installed their CA at the OS level get it for free with no config.SSL_CERT_FILEexplicit override — the canonical OpenSSL env var, honored by every TLS-aware tool. Primary mechanism for Docker (bind-mount + env var). Also the override path on any platform.Deployment coverage
SSL_CERT_FILE— explicit override pathSSL_CERT_FILEalready setDocumented in README with the canonical Docker example.
Explicitly declined
REQUESTS_CA_BUNDLE—requests-specific alias, not a standard. We're not arequestscodebase; don't propagate it.verify=False— silent downgrade is worse than a hard failure. Users who genuinely want unencrypted local LAN can useHA_URL=http://...which is already documented.Why this is better than #15
#15 reads
REQUESTS_CA_BUNDLE/SSL_CERT_FILEand passes toverify=. Two problems:SSL_CERT_FILEis already honored by httpx natively whentrust_env=True(default). The env-var read is partially redundant.update-ca-certificatesif hass-mcp runs in a Docker container without that file mounted in.This PR fixes both: truststore handles every OS-native store,
SSL_CERT_FILEhandles every explicit-path scenario.Dependency
Adds
truststore>=0.10. ~30 KB, no transitive runtime deps. Used by pip, uv, and recommended in the httpx SSL docs for OS-store integration. Python 3.13 (our minimum) satisfies its 3.10+ floor.Tests
Two new tests in
tests/test_hass.py::TestSSLContext:test_default_uses_truststore_os_native_store— confirms truststore is selected when no env vartest_ssl_cert_file_takes_precedence— generates a self-signed PEM, pointsSSL_CERT_FILEat it, confirms a stdlibssl.SSLContextis built from the file (not truststore)Credit
@rmoriz flagged the right problem in #15. The cleaner mechanism preserves the spirit (don't weaken TLS) with a more portable implementation. Their PR can be closed as superseded;
Co-Authored-Byon the merge commit.