Observer access handling (#2043)

* Change access handling

* add security check
This commit is contained in:
Pascal Vizeli 2020-09-11 23:01:01 +02:00 committed by GitHub
parent da83edf231
commit 409b53109b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 27 additions and 22 deletions

View File

@ -39,6 +39,13 @@ NO_SECURITY_CHECK = re.compile(
r")$"
)
# Observer allow API calls
OBSERVER_CHECK = re.compile(
r"^(?:"
r"|/[^/]+/info"
r")$"
)
# Can called by every add-on
ADDONS_API_BYPASS = re.compile(
r"^(?:"
@ -95,7 +102,7 @@ ADDONS_ROLE_ACCESS = {
),
}
# fmt: off
# fmt: on
class SecurityMiddleware(CoreSysAttributes):
@ -136,6 +143,14 @@ class SecurityMiddleware(CoreSysAttributes):
_LOGGER.debug("%s access from Host", request.path)
request_from = self.sys_host
# Observer
if supervisor_token == self.sys_plugins.observer.supervisor_token:
if not OBSERVER_CHECK.match(request.url):
_LOGGER.warning("%s invalid Observer access", request.path)
raise HTTPForbidden()
_LOGGER.debug("%s access from Observer", request.path)
request_from = self.sys_plugins.observer
# Add-on
addon = None
if supervisor_token and not request_from:

View File

@ -70,8 +70,7 @@ HEADER_TOKEN_OLD = "X-Hassio-Key"
ENV_TIME = "TZ"
ENV_TOKEN = "SUPERVISOR_TOKEN"
ENV_TOKEN_OLD = "HASSIO_TOKEN"
ENV_OBSERVER = "OBSERVER_TOKEN"
ENV_TOKEN_HASSIO = "HASSIO_TOKEN"
ENV_HOMEASSISTANT_REPOSITORY = "HOMEASSISTANT_REPOSITORY"
ENV_SUPERVISOR_DEV = "SUPERVISOR_DEV"

View File

@ -15,7 +15,7 @@ from ..addons.build import AddonBuild
from ..const import (
ENV_TIME,
ENV_TOKEN,
ENV_TOKEN_OLD,
ENV_TOKEN_HASSIO,
MAP_ADDONS,
MAP_BACKUP,
MAP_CONFIG,
@ -119,7 +119,7 @@ class DockerAddon(DockerInterface):
**addon_env,
ENV_TIME: self.sys_config.timezone,
ENV_TOKEN: self.addon.supervisor_token,
ENV_TOKEN_OLD: self.addon.supervisor_token,
ENV_TOKEN_HASSIO: self.addon.supervisor_token,
}
@property

View File

@ -1,7 +1,7 @@
"""HA Cli docker object."""
import logging
from ..const import ENV_OBSERVER, ENV_TIME, ENV_TOKEN
from ..const import ENV_TIME, ENV_TOKEN
from ..coresys import CoreSysAttributes
from .interface import DockerInterface
@ -52,7 +52,6 @@ class DockerCli(DockerInterface, CoreSysAttributes):
environment={
ENV_TIME: self.sys_config.timezone,
ENV_TOKEN: self.sys_plugins.cli.supervisor_token,
ENV_OBSERVER: self.sys_plugins.observer.access_token,
},
)

View File

@ -6,14 +6,7 @@ from typing import Awaitable, Dict, Optional
import docker
import requests
from ..const import (
ENV_OBSERVER,
ENV_TIME,
ENV_TOKEN,
ENV_TOKEN_OLD,
LABEL_MACHINE,
MACHINE_ID,
)
from ..const import ENV_TIME, ENV_TOKEN, ENV_TOKEN_HASSIO, LABEL_MACHINE, MACHINE_ID
from ..exceptions import DockerAPIError
from .interface import CommandReturn, DockerInterface
@ -131,8 +124,7 @@ class DockerHomeAssistant(DockerInterface):
"SUPERVISOR": self.sys_docker.network.supervisor,
ENV_TIME: self.sys_config.timezone,
ENV_TOKEN: self.sys_homeassistant.supervisor_token,
ENV_TOKEN_OLD: self.sys_homeassistant.supervisor_token,
ENV_OBSERVER: self.sys_plugins.observer.access_token,
ENV_TOKEN_HASSIO: self.sys_homeassistant.supervisor_token,
},
)

View File

@ -1,7 +1,7 @@
"""Observer docker object."""
import logging
from ..const import ENV_OBSERVER, ENV_TIME
from ..const import ENV_TIME, ENV_TOKEN
from ..coresys import CoreSysAttributes
from .interface import DockerInterface
@ -47,7 +47,7 @@ class DockerObserver(DockerInterface, CoreSysAttributes):
extra_hosts={"supervisor": self.sys_docker.network.supervisor},
environment={
ENV_TIME: self.sys_config.timezone,
ENV_OBSERVER: self.sys_plugins.observer.access_token,
ENV_TOKEN: self.sys_plugins.observer.supervisor_token,
},
volumes={"/run/docker.sock": {"bind": "/run/docker.sock", "mode": "ro"}},
ports={"80/tcp": 4357},

View File

@ -21,7 +21,7 @@ class PluginManager(CoreSysAttributes):
required_cli: LegacyVersion = pkg_parse("26")
required_dns: LegacyVersion = pkg_parse("9")
required_audio: LegacyVersion = pkg_parse("17")
required_observer: LegacyVersion = pkg_parse("1")
required_observer: LegacyVersion = pkg_parse("2")
required_multicast: LegacyVersion = pkg_parse("3")
def __init__(self, coresys: CoreSys):

View File

@ -62,7 +62,7 @@ class Observer(CoreSysAttributes, JsonConfig):
return self.version != self.latest_version
@property
def access_token(self) -> str:
def supervisor_token(self) -> str:
"""Return an access token for the Observer API."""
return self._data.get(ATTR_ACCESS_TOKEN)
@ -149,7 +149,7 @@ class Observer(CoreSysAttributes, JsonConfig):
async def start(self) -> None:
"""Run observer."""
# Create new API token
if not self.access_token:
if not self.supervisor_token:
self._data[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
self.save_data()