mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 17:27:52 +00:00
Raise issue if SSL is set but no external URL configured (#121768)
* Raise issue if SSL is set but no external URL configured * Add cloud * Add cloud * Fix strings * Attempt * Fix * Fix * Move strings * Fixes * fix * Fix * Fix * Fix * Break tests * Fix tests
This commit is contained in:
parent
c289248ac5
commit
2fa7113787
@ -30,10 +30,14 @@ import voluptuous as vol
|
||||
from yarl import URL
|
||||
|
||||
from homeassistant.components.network import async_get_source_ip
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, SERVER_PORT
|
||||
from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
SERVER_PORT,
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import frame, storage
|
||||
from homeassistant.helpers import frame, issue_registry as ir, storage
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.http import (
|
||||
KEY_ALLOW_CONFIGURED_CORS,
|
||||
@ -264,6 +268,32 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
local_ip, host, server_port, ssl_certificate is not None
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_check_ssl_issue(_: Event) -> None:
|
||||
if (
|
||||
ssl_certificate is not None
|
||||
and (hass.config.external_url or hass.config.internal_url) is None
|
||||
):
|
||||
# pylint: disable-next=import-outside-toplevel
|
||||
from homeassistant.components.cloud import (
|
||||
CloudNotAvailable,
|
||||
async_remote_ui_url,
|
||||
)
|
||||
|
||||
try:
|
||||
async_remote_ui_url(hass)
|
||||
except CloudNotAvailable:
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"ssl_configured_without_configured_urls",
|
||||
is_fixable=False,
|
||||
severity=ir.IssueSeverity.ERROR,
|
||||
translation_key="ssl_configured_without_configured_urls",
|
||||
)
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, _async_check_ssl_issue)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
8
homeassistant/components/http/strings.json
Normal file
8
homeassistant/components/http/strings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"issues": {
|
||||
"ssl_configured_without_configured_urls": {
|
||||
"title": "SSL is configured without an external URL or internal URL",
|
||||
"description": "Home Assistant detected that SSL has been set up on your instance, however, no custom external internet URL has been set.\n\nThis may result in unexpected behavior. Text-to-speech may fail, and integrations may not be able to connect back to your instance correctly.\n\nTo address this issue, go to Settings > System > Network; under the \"Home Assistant URL\" section, configure your new \"Internet\" and \"Local network\" addresses that match your new SSL configuration."
|
||||
}
|
||||
}
|
||||
}
|
@ -12,8 +12,10 @@ from unittest.mock import Mock, patch
|
||||
import pytest
|
||||
|
||||
from homeassistant.auth.providers.homeassistant import HassAuthProvider
|
||||
from homeassistant.components import http
|
||||
from homeassistant.components import cloud, http
|
||||
from homeassistant.components.cloud import CloudNotAvailable
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.helpers.http import KEY_HASS
|
||||
from homeassistant.helpers.network import NoURLAvailableError
|
||||
from homeassistant.setup import async_setup_component
|
||||
@ -545,3 +547,150 @@ async def test_register_static_paths(
|
||||
"event loop, instead call "
|
||||
"`await hass.http.async_register_static_paths"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
async def test_ssl_issue_if_no_urls_configured(
|
||||
hass: HomeAssistant,
|
||||
tmp_path: Path,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test raising SSL issue if no external or internal URL is configured."""
|
||||
|
||||
assert hass.config.external_url is None
|
||||
assert hass.config.internal_url is None
|
||||
|
||||
cert_path, key_path, _ = await hass.async_add_executor_job(
|
||||
_setup_empty_ssl_pem_files, tmp_path
|
||||
)
|
||||
|
||||
with (
|
||||
patch("ssl.SSLContext.load_cert_chain"),
|
||||
patch(
|
||||
"homeassistant.util.ssl.server_context_modern",
|
||||
side_effect=server_context_modern,
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
"http",
|
||||
{"http": {"ssl_certificate": cert_path, "ssl_key": key_path}},
|
||||
)
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert ("http", "ssl_configured_without_configured_urls") in issue_registry.issues
|
||||
|
||||
|
||||
async def test_ssl_issue_if_using_cloud(
|
||||
hass: HomeAssistant,
|
||||
tmp_path: Path,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test raising no SSL issue if not right configured but using cloud."""
|
||||
assert hass.config.external_url is None
|
||||
assert hass.config.internal_url is None
|
||||
|
||||
cert_path, key_path, _ = await hass.async_add_executor_job(
|
||||
_setup_empty_ssl_pem_files, tmp_path
|
||||
)
|
||||
|
||||
with (
|
||||
patch("ssl.SSLContext.load_cert_chain"),
|
||||
patch.object(cloud, "async_remote_ui_url", return_value="https://example.com"),
|
||||
patch(
|
||||
"homeassistant.util.ssl.server_context_modern",
|
||||
side_effect=server_context_modern,
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
"http",
|
||||
{"http": {"ssl_certificate": cert_path, "ssl_key": key_path}},
|
||||
)
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"http",
|
||||
"ssl_configured_without_configured_urls",
|
||||
) not in issue_registry.issues
|
||||
|
||||
|
||||
async def test_ssl_issue_if_not_connected_to_cloud(
|
||||
hass: HomeAssistant,
|
||||
tmp_path: Path,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test raising no SSL issue if not right configured and not connected to cloud."""
|
||||
assert hass.config.external_url is None
|
||||
assert hass.config.internal_url is None
|
||||
|
||||
cert_path, key_path, _ = await hass.async_add_executor_job(
|
||||
_setup_empty_ssl_pem_files, tmp_path
|
||||
)
|
||||
|
||||
with (
|
||||
patch("ssl.SSLContext.load_cert_chain"),
|
||||
patch(
|
||||
"homeassistant.util.ssl.server_context_modern",
|
||||
side_effect=server_context_modern,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.cloud.async_remote_ui_url",
|
||||
side_effect=CloudNotAvailable,
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
"http",
|
||||
{"http": {"ssl_certificate": cert_path, "ssl_key": key_path}},
|
||||
)
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert ("http", "ssl_configured_without_configured_urls") in issue_registry.issues
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("external_url", "internal_url"),
|
||||
[
|
||||
("https://example.com", "https://example.local"),
|
||||
(None, "http://example.local"),
|
||||
("https://example.com", None),
|
||||
],
|
||||
)
|
||||
async def test_ssl_issue_urls_configured(
|
||||
hass: HomeAssistant,
|
||||
tmp_path: Path,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
external_url: str | None,
|
||||
internal_url: str | None,
|
||||
) -> None:
|
||||
"""Test raising SSL issue if no external or internal URL is configured."""
|
||||
|
||||
cert_path, key_path, _ = await hass.async_add_executor_job(
|
||||
_setup_empty_ssl_pem_files, tmp_path
|
||||
)
|
||||
|
||||
hass.config.external_url = external_url
|
||||
hass.config.internal_url = internal_url
|
||||
|
||||
with (
|
||||
patch("ssl.SSLContext.load_cert_chain"),
|
||||
patch(
|
||||
"homeassistant.util.ssl.server_context_modern",
|
||||
side_effect=server_context_modern,
|
||||
),
|
||||
):
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
"http",
|
||||
{"http": {"ssl_certificate": cert_path, "ssl_key": key_path}},
|
||||
)
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
"http",
|
||||
"ssl_configured_without_configured_urls",
|
||||
) not in issue_registry.issues
|
||||
|
@ -1181,6 +1181,10 @@ async def test_subscribe_unsubscribe_logbook_stream(
|
||||
await async_wait_recording_done(hass)
|
||||
websocket_client = await hass_ws_client()
|
||||
init_listeners = hass.bus.async_listeners()
|
||||
init_listeners = {
|
||||
**init_listeners,
|
||||
EVENT_HOMEASSISTANT_START: init_listeners[EVENT_HOMEASSISTANT_START] - 1,
|
||||
}
|
||||
await websocket_client.send_json(
|
||||
{"id": 7, "type": "logbook/event_stream", "start_time": now.isoformat()}
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user