Revert "Block peer certs on supervisor" (#67104)

This commit is contained in:
Franck Nijhof 2022-02-23 12:32:07 +01:00 committed by GitHub
parent 8dbb184ed5
commit 3afadf8adb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 31 additions and 121 deletions

View File

@ -23,7 +23,7 @@ from .const import (
SIGNAL_BOOTSTRAP_INTEGRATONS, SIGNAL_BOOTSTRAP_INTEGRATONS,
) )
from .exceptions import HomeAssistantError from .exceptions import HomeAssistantError
from .helpers import area_registry, device_registry, entity_registry, supervisor from .helpers import area_registry, device_registry, entity_registry
from .helpers.dispatcher import async_dispatcher_send from .helpers.dispatcher import async_dispatcher_send
from .helpers.typing import ConfigType from .helpers.typing import ConfigType
from .setup import ( from .setup import (
@ -398,7 +398,7 @@ def _get_domains(hass: core.HomeAssistant, config: dict[str, Any]) -> set[str]:
domains.update(hass.config_entries.async_domains()) domains.update(hass.config_entries.async_domains())
# Make sure the Hass.io component is loaded # Make sure the Hass.io component is loaded
if supervisor.has_supervisor(): if "HASSIO" in os.environ:
domains.add("hassio") domains.add("hassio")
return domains return domains

View File

@ -104,7 +104,7 @@ class Analytics:
@property @property
def supervisor(self) -> bool: def supervisor(self) -> bool:
"""Return bool if a supervisor is present.""" """Return bool if a supervisor is present."""
return hassio.is_hassio() return hassio.is_hassio(self.hass)
async def load(self) -> None: async def load(self) -> None:
"""Load preferences.""" """Load preferences."""

View File

@ -41,8 +41,6 @@ from homeassistant.helpers.device_registry import (
async_get_registry, async_get_registry,
) )
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.frame import report
from homeassistant.helpers.supervisor import has_supervisor
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
@ -396,21 +394,12 @@ def get_core_info(hass):
@callback @callback
@bind_hass @bind_hass
def is_hassio( def is_hassio(hass: HomeAssistant) -> bool:
hass: HomeAssistant | None = None, # pylint: disable=unused-argument
) -> bool:
"""Return true if Hass.io is loaded. """Return true if Hass.io is loaded.
Async friendly. Async friendly.
""" """
if hass is not None: return DOMAIN in hass.config.components
report(
"hass param deprecated for is_hassio",
exclude_integrations={DOMAIN},
error_if_core=False,
)
return has_supervisor()
@callback @callback
@ -423,8 +412,11 @@ def get_supervisor_ip() -> str:
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901
"""Set up the Hass.io component.""" """Set up the Hass.io component."""
if not has_supervisor(): # Check local setup
_LOGGER.error("Supervisor not available") for env in ("HASSIO", "HASSIO_TOKEN"):
if os.environ.get(env):
continue
_LOGGER.error("Missing %s environment variable", env)
if config_entries := hass.config_entries.async_entries(DOMAIN): if config_entries := hass.config_entries.async_entries(DOMAIN):
hass.async_create_task( hass.async_create_task(
hass.config_entries.async_remove(config_entries[0].entry_id) hass.config_entries.async_remove(config_entries[0].entry_id)

View File

@ -23,7 +23,8 @@ from homeassistant.components.network import async_get_source_ip
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, SERVER_PORT from homeassistant.const import EVENT_HOMEASSISTANT_STOP, SERVER_PORT
from homeassistant.core import Event, HomeAssistant from homeassistant.core import Event, HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv, storage, supervisor from homeassistant.helpers import storage
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.network import NoURLAvailableError, get_url from homeassistant.helpers.network import NoURLAvailableError, get_url
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
@ -166,12 +167,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
login_threshold = conf[CONF_LOGIN_ATTEMPTS_THRESHOLD] login_threshold = conf[CONF_LOGIN_ATTEMPTS_THRESHOLD]
ssl_profile = conf[CONF_SSL_PROFILE] ssl_profile = conf[CONF_SSL_PROFILE]
if ssl_peer_certificate is not None and supervisor.has_supervisor():
_LOGGER.warning(
"Peer certificates are not supported when running the supervisor"
)
ssl_peer_certificate = None
server = HomeAssistantHTTP( server = HomeAssistantHTTP(
hass, hass,
server_host=server_host, server_host=server_host,

View File

@ -195,7 +195,7 @@ class CoreConfigOnboardingView(_BaseOnboardingView):
from homeassistant.components import hassio from homeassistant.components import hassio
if ( if (
hassio.is_hassio() hassio.is_hassio(hass)
and "raspberrypi" in hassio.get_core_info(hass)["machine"] and "raspberrypi" in hassio.get_core_info(hass)["machine"]
): ):
onboard_integrations.append("rpi_power") onboard_integrations.append("rpi_power")

View File

@ -45,7 +45,7 @@ class DomainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
# Set a unique_id to make sure discovery flow is aborted on progress. # Set a unique_id to make sure discovery flow is aborted on progress.
await self.async_set_unique_id(DOMAIN, raise_on_progress=False) await self.async_set_unique_id(DOMAIN, raise_on_progress=False)
if not hassio.is_hassio(): if not hassio.is_hassio(self.hass):
return self._async_use_mqtt_integration() return self._async_use_mqtt_integration()
return await self.async_step_on_supervisor() return await self.async_step_on_supervisor()

View File

@ -74,7 +74,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
_LOGGER.debug("Fetched version %s: %s", newest, release_notes) _LOGGER.debug("Fetched version %s: %s", newest, release_notes)
# Load data from Supervisor # Load data from Supervisor
if hassio.is_hassio(): if hassio.is_hassio(hass):
core_info = hassio.get_core_info(hass) core_info = hassio.get_core_info(hass)
newest = core_info["version_latest"] newest = core_info["version_latest"]

View File

@ -332,14 +332,14 @@ class ConfigFlow(BaseZwaveJSFlow, config_entries.ConfigFlow, domain=DOMAIN):
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> FlowResult: ) -> FlowResult:
"""Handle the initial step.""" """Handle the initial step."""
if is_hassio(): if is_hassio(self.hass):
return await self.async_step_on_supervisor() return await self.async_step_on_supervisor()
return await self.async_step_manual() return await self.async_step_manual()
async def async_step_usb(self, discovery_info: usb.UsbServiceInfo) -> FlowResult: async def async_step_usb(self, discovery_info: usb.UsbServiceInfo) -> FlowResult:
"""Handle USB Discovery.""" """Handle USB Discovery."""
if not is_hassio(): if not is_hassio(self.hass):
return self.async_abort(reason="discovery_requires_supervisor") return self.async_abort(reason="discovery_requires_supervisor")
if self._async_current_entries(): if self._async_current_entries():
return self.async_abort(reason="already_configured") return self.async_abort(reason="already_configured")
@ -641,7 +641,7 @@ class OptionsFlowHandler(BaseZwaveJSFlow, config_entries.OptionsFlow):
self, user_input: dict[str, Any] | None = None self, user_input: dict[str, Any] | None = None
) -> FlowResult: ) -> FlowResult:
"""Manage the options.""" """Manage the options."""
if is_hassio(): if is_hassio(self.hass):
return await self.async_step_on_supervisor() return await self.async_step_on_supervisor()
return await self.async_step_manual() return await self.async_step_manual()

View File

@ -1,11 +0,0 @@
"""Supervisor helper."""
import os
from homeassistant.core import callback
@callback
def has_supervisor() -> bool:
"""Return true if supervisor is available."""
return "SUPERVISOR" in os.environ

View File

@ -21,8 +21,6 @@ def hassio_env():
), patch.dict(os.environ, {"HASSIO_TOKEN": HASSIO_TOKEN}), patch( ), patch.dict(os.environ, {"HASSIO_TOKEN": HASSIO_TOKEN}), patch(
"homeassistant.components.hassio.HassIO.get_info", "homeassistant.components.hassio.HassIO.get_info",
Mock(side_effect=HassioAPIError()), Mock(side_effect=HassioAPIError()),
), patch.dict(
os.environ, {"SUPERVISOR": "127.0.0.1"}
): ):
yield yield

View File

@ -11,11 +11,7 @@ from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
MOCK_ENVIRON = { MOCK_ENVIRON = {"HASSIO": "127.0.0.1", "HASSIO_TOKEN": "abcdefgh"}
"HASSIO": "127.0.0.1",
"HASSIO_TOKEN": "abcdefgh",
"SUPERVISOR": "127.0.0.1",
}
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)

View File

@ -16,11 +16,7 @@ from homeassistant.util import dt as dt_util
from tests.common import MockConfigEntry, async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
MOCK_ENVIRON = { MOCK_ENVIRON = {"HASSIO": "127.0.0.1", "HASSIO_TOKEN": "abcdefgh"}
"HASSIO": "127.0.0.1",
"HASSIO_TOKEN": "abcdefgh",
"SUPERVISOR": "127.0.0.1",
}
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -155,6 +151,7 @@ async def test_setup_api_ping(hass, aioclient_mock):
assert aioclient_mock.call_count == 10 assert aioclient_mock.call_count == 10
assert hass.components.hassio.get_core_info()["version_latest"] == "1.0.0" assert hass.components.hassio.get_core_info()["version_latest"] == "1.0.0"
assert hass.components.hassio.is_hassio()
async def test_setup_api_panel(hass, aioclient_mock): async def test_setup_api_panel(hass, aioclient_mock):
@ -337,6 +334,7 @@ async def test_warn_when_cannot_connect(hass, caplog):
result = await async_setup_component(hass, "hassio", {}) result = await async_setup_component(hass, "hassio", {})
assert result assert result
assert hass.components.hassio.is_hassio()
assert "Not connected with the supervisor / system too busy!" in caplog.text assert "Not connected with the supervisor / system too busy!" in caplog.text

View File

@ -11,11 +11,7 @@ from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
MOCK_ENVIRON = { MOCK_ENVIRON = {"HASSIO": "127.0.0.1", "HASSIO_TOKEN": "abcdefgh"}
"HASSIO": "127.0.0.1",
"HASSIO_TOKEN": "abcdefgh",
"SUPERVISOR": "127.0.0.1",
}
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)

View File

@ -36,9 +36,7 @@ def hassio_env_fixture():
with patch.dict(os.environ, {"HASSIO": "127.0.0.1"}), patch( with patch.dict(os.environ, {"HASSIO": "127.0.0.1"}), patch(
"homeassistant.components.hassio.HassIO.is_connected", "homeassistant.components.hassio.HassIO.is_connected",
return_value={"result": "ok", "data": {}}, return_value={"result": "ok", "data": {}},
), patch.dict(os.environ, {"HASSIO_TOKEN": "123456"}), patch.dict( ), patch.dict(os.environ, {"HASSIO_TOKEN": "123456"}):
os.environ, {"SUPERVISOR": "127.0.0.1"}
):
yield yield

View File

@ -261,42 +261,6 @@ async def test_peer_cert(hass, tmpdir):
assert len(mock_load_verify_locations.mock_calls) == 1 assert len(mock_load_verify_locations.mock_calls) == 1
async def test_peer_cert_ignored_with_supervisor(hass, tmpdir):
"""Test peer certiicate requirement ignored in supervised deployments."""
cert_path, key_path, peer_cert_path = await hass.async_add_executor_job(
_setup_empty_ssl_pem_files, tmpdir
)
with patch("ssl.SSLContext.load_cert_chain"), patch(
"homeassistant.components.http.supervisor.has_supervisor", return_value=True
), patch(
"ssl.SSLContext.load_verify_locations"
) as mock_load_verify_locations, patch(
"homeassistant.util.ssl.server_context_modern",
side_effect=server_context_modern,
) as mock_context:
assert (
await async_setup_component(
hass,
"http",
{
"http": {
"ssl_peer_certificate": peer_cert_path,
"ssl_profile": "modern",
"ssl_certificate": cert_path,
"ssl_key": key_path,
}
},
)
is True
)
await hass.async_start()
await hass.async_block_till_done()
assert len(mock_context.mock_calls) == 1
mock_load_verify_locations.assert_not_called()
async def test_emergency_ssl_certificate_when_invalid(hass, tmpdir, caplog): async def test_emergency_ssl_certificate_when_invalid(hass, tmpdir, caplog):
"""Test http can startup with an emergency self signed cert when the current one is broken.""" """Test http can startup with an emergency self signed cert when the current one is broken."""

View File

@ -86,8 +86,6 @@ async def mock_supervisor_fixture(hass, aioclient_mock):
return_value={"panels": {}}, return_value={"panels": {}},
), patch.dict( ), patch.dict(
os.environ, {"HASSIO_TOKEN": "123456"} os.environ, {"HASSIO_TOKEN": "123456"}
), patch.dict(
os.environ, {"SUPERVISOR": "127.0.0.1"}
): ):
yield yield

View File

@ -7,6 +7,8 @@ from homeassistant.components import updater
from homeassistant.helpers.update_coordinator import UpdateFailed from homeassistant.helpers.update_coordinator import UpdateFailed
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import mock_component
NEW_VERSION = "10000.0" NEW_VERSION = "10000.0"
MOCK_VERSION = "10.0" MOCK_VERSION = "10.0"
MOCK_DEV_VERSION = "10.0.dev0" MOCK_DEV_VERSION = "10.0.dev0"
@ -111,7 +113,7 @@ async def test_new_version_shows_entity_after_hour_hassio(
hass, mock_get_newest_version hass, mock_get_newest_version
): ):
"""Test if binary sensor gets updated if new version is available / Hass.io.""" """Test if binary sensor gets updated if new version is available / Hass.io."""
with patch("homeassistant.components.updater.hassio.is_hassio", return_value=True): mock_component(hass, "hassio")
hass.data["hassio_core_info"] = {"version_latest": "999.0"} hass.data["hassio_core_info"] = {"version_latest": "999.0"}
assert await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}}) assert await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}})

View File

@ -1,16 +0,0 @@
"""Test the Hassio helper."""
from unittest.mock import patch
from homeassistant.helpers.supervisor import has_supervisor
async def test_has_supervisor_yes():
"""Test has_supervisor when supervisor available."""
with patch("homeassistant.helpers.supervisor.os.environ", {"SUPERVISOR": True}):
assert has_supervisor()
async def test_has_supervisor_no():
"""Test has_supervisor when supervisor not available."""
with patch("homeassistant.helpers.supervisor.os.environ"):
assert not has_supervisor()

View File

@ -86,7 +86,7 @@ async def test_load_hassio(hass):
with patch.dict(os.environ, {}, clear=True): with patch.dict(os.environ, {}, clear=True):
assert bootstrap._get_domains(hass, {}) == set() assert bootstrap._get_domains(hass, {}) == set()
with patch.dict(os.environ, {"SUPERVISOR": "1"}): with patch.dict(os.environ, {"HASSIO": "1"}):
assert bootstrap._get_domains(hass, {}) == {"hassio"} assert bootstrap._get_domains(hass, {}) == {"hassio"}