First clean renaming for smooth migration (#1476)

* First clean renaming for smooth migration

* Update security

* fix lint

* Update hassio/const.py

Co-Authored-By: Franck Nijhof <git@frenck.dev>

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
Pascal Vizeli 2020-02-05 10:57:57 +01:00 committed by GitHub
parent 3a834d1a73
commit 25d324c73a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 16 deletions

View File

@ -89,6 +89,11 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/os/info", api_hassos.info),
web.post("/os/update", api_hassos.update),
web.post("/os/update/cli", api_hassos.update_cli),
web.post("/os/config/sync", api_hassos.config_sync),
# Remove with old Hass.io fallback
web.get("/hassos/info", api_hassos.info),
web.post("/hassos/update", api_hassos.update),
web.post("/hassos/update/cli", api_hassos.update_cli),
@ -150,6 +155,17 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/core/info", api_hass.info),
web.get("/core/logs", api_hass.logs),
web.get("/core/stats", api_hass.stats),
web.post("/core/options", api_hass.options),
web.post("/core/update", api_hass.update),
web.post("/core/restart", api_hass.restart),
web.post("/core/stop", api_hass.stop),
web.post("/core/start", api_hass.start),
web.post("/core/check", api_hass.check),
web.post("/core/rebuild", api_hass.rebuild),
# Remove with old Hass.io fallback
web.get("/homeassistant/info", api_hass.info),
web.get("/homeassistant/logs", api_hass.logs),
web.get("/homeassistant/stats", api_hass.stats),
@ -170,6 +186,13 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/core/api/websocket", api_proxy.websocket),
web.get("/core/websocket", api_proxy.websocket),
web.get("/core/api/stream", api_proxy.stream),
web.post("/core/api/{path:.+}", api_proxy.api),
web.get("/core/api/{path:.+}", api_proxy.api),
web.get("/core/api/", api_proxy.api),
# Remove with old Hass.io fallback
web.get("/homeassistant/api/websocket", api_proxy.websocket),
web.get("/homeassistant/websocket", api_proxy.websocket),
web.get("/homeassistant/api/stream", api_proxy.stream),

View File

@ -23,6 +23,7 @@ from ..const import (
ATTR_ENABLE,
COOKIE_INGRESS,
HEADER_TOKEN,
HEADER_TOKEN_OLD,
REQUEST_FROM,
)
from ..coresys import CoreSysAttributes
@ -212,6 +213,7 @@ def _init_header(
hdrs.SEC_WEBSOCKET_VERSION,
hdrs.SEC_WEBSOCKET_KEY,
istr(HEADER_TOKEN),
istr(HEADER_TOKEN_OLD),
):
continue
headers[name] = value

View File

@ -9,7 +9,6 @@ from aiohttp.web_exceptions import HTTPBadGateway, HTTPUnauthorized
from aiohttp.client_exceptions import ClientConnectorError
from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION
from ..const import HEADER_HA_ACCESS
from ..coresys import CoreSysAttributes
from ..exceptions import HomeAssistantAuthError, HomeAssistantAPIError, APIError
@ -17,6 +16,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
FORWARD_HEADERS = ("X-Speech-Content",)
HEADER_HA_ACCESS = "X-Ha-Access"
class APIProxy(CoreSysAttributes):

View File

@ -3,16 +3,16 @@ import logging
import re
from aiohttp.web import middleware
from aiohttp.web_exceptions import HTTPUnauthorized, HTTPForbidden
from aiohttp.web_exceptions import HTTPForbidden, HTTPUnauthorized
from .utils import excract_supervisor_token
from ..const import (
HEADER_TOKEN,
REQUEST_FROM,
ROLE_ADMIN,
ROLE_BACKUP,
ROLE_DEFAULT,
ROLE_HOMEASSISTANT,
ROLE_MANAGER,
ROLE_BACKUP,
)
from ..coresys import CoreSysAttributes
@ -24,6 +24,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
BLACKLIST = re.compile(
r"^(?:"
r"|/homeassistant/api/hassio/.*"
r"|/core/api/hassio/.*"
r")$"
)
@ -32,6 +33,8 @@ NO_SECURITY_CHECK = re.compile(
r"^(?:"
r"|/homeassistant/api/.*"
r"|/homeassistant/websocket"
r"|/core/api/.*"
r"|/core/websocket"
r"|/supervisor/ping"
r")$"
)
@ -59,6 +62,7 @@ ADDONS_ROLE_ACCESS = {
),
ROLE_HOMEASSISTANT: re.compile(
r"^(?:"
r"|/core/.+"
r"|/homeassistant/.+"
r")$"
),
@ -70,9 +74,11 @@ ADDONS_ROLE_ACCESS = {
ROLE_MANAGER: re.compile(
r"^(?:"
r"|/dns/.*"
r"|/core/.+"
r"|/homeassistant/.+"
r"|/host/.+"
r"|/hardware/.+"
r"|/os/.+"
r"|/hassos/.+"
r"|/supervisor/.+"
r"|/addons(?:/[^/]+/(?!security).+|/reload)?"
@ -98,7 +104,7 @@ class SecurityMiddleware(CoreSysAttributes):
async def token_validation(self, request, handler):
"""Check security access of this layer."""
request_from = None
hassio_token = request.headers.get(HEADER_TOKEN)
supervisor_token = excract_supervisor_token(request)
# Blacklist
if BLACKLIST.match(request.path):
@ -111,24 +117,24 @@ class SecurityMiddleware(CoreSysAttributes):
return await handler(request)
# Not token
if not hassio_token:
if not supervisor_token:
_LOGGER.warning("No API token provided for %s", request.path)
raise HTTPUnauthorized()
# Home-Assistant
if hassio_token == self.sys_homeassistant.hassio_token:
if supervisor_token == self.sys_homeassistant.hassio_token:
_LOGGER.debug("%s access from Home Assistant", request.path)
request_from = self.sys_homeassistant
# Host
if hassio_token == self.sys_machine_id:
if supervisor_token == self.sys_machine_id:
_LOGGER.debug("%s access from Host", request.path)
request_from = self.sys_host
# Add-on
addon = None
if hassio_token and not request_from:
addon = self.sys_addons.from_token(hassio_token)
if supervisor_token and not request_from:
addon = self.sys_addons.from_token(supervisor_token)
# Check Add-on API access
if addon and ADDONS_API_BYPASS.match(request.path):

View File

@ -4,11 +4,14 @@ import logging
from typing import Any, Dict, List, Optional
from aiohttp import web
from aiohttp.hdrs import AUTHORIZATION
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..const import (
CONTENT_TYPE_BINARY,
HEADER_TOKEN,
HEADER_TOKEN_OLD,
JSON_DATA,
JSON_MESSAGE,
JSON_RESULT,
@ -20,6 +23,22 @@ from ..exceptions import APIError, APIForbidden, HassioError
_LOGGER: logging.Logger = logging.getLogger(__name__)
def excract_supervisor_token(request: web.Request) -> Optional[str]:
"""Extract Supervisor token from request."""
supervisor_token = request.headers.get(AUTHORIZATION)
if supervisor_token:
return supervisor_token.split(" ")[-1]
# Header token handling
supervisor_token = request.headers.get(HEADER_TOKEN)
# Remove with old Hass.io fallback
if not supervisor_token:
supervisor_token = request.headers.get(HEADER_TOKEN_OLD)
return supervisor_token
def json_loads(data: Any) -> Dict[str, Any]:
"""Extract json from string with support for '' and None."""
if not data:

View File

@ -58,11 +58,13 @@ CONTENT_TYPE_JSON = "application/json"
CONTENT_TYPE_TEXT = "text/plain"
CONTENT_TYPE_TAR = "application/tar"
CONTENT_TYPE_URL = "application/x-www-form-urlencoded"
HEADER_HA_ACCESS = "X-Ha-Access"
HEADER_TOKEN = "X-Hassio-Key"
COOKIE_INGRESS = "ingress_session"
ENV_TOKEN = "HASSIO_TOKEN"
HEADER_TOKEN = "X-Supervisor-Token"
HEADER_TOKEN_OLD = "X-Hassio-Key"
ENV_TOKEN_OLD = "HASSIO_TOKEN"
ENV_TOKEN = "SUPERVISOR_TOKEN"
ENV_TIME = "TZ"
REQUEST_FROM = "HASSIO_FROM"

View File

@ -6,7 +6,7 @@ from ipaddress import IPv4Address, ip_address
import logging
import os
from pathlib import Path
from typing import TYPE_CHECKING, Dict, List, Optional, Union, Awaitable
from typing import TYPE_CHECKING, Awaitable, Dict, List, Optional, Union
import docker
import requests
@ -15,6 +15,7 @@ from ..addons.build import AddonBuild
from ..const import (
ENV_TIME,
ENV_TOKEN,
ENV_TOKEN_OLD,
MAP_ADDONS,
MAP_BACKUP,
MAP_CONFIG,
@ -118,6 +119,7 @@ class DockerAddon(DockerInterface):
**addon_env,
ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.addon.hassio_token,
ENV_TOKEN_OLD: self.addon.hassio_token,
}
@property
@ -189,7 +191,10 @@ class DockerAddon(DockerInterface):
@property
def network_mapping(self) -> Dict[str, str]:
"""Return hosts mapping."""
return {"hassio": self.sys_docker.network.supervisor}
return {
"supervisor": self.sys_docker.network.supervisor,
"hassio": self.sys_docker.network.supervisor,
}
@property
def network_mode(self) -> Optional[str]:

View File

@ -6,7 +6,7 @@ from typing import Awaitable, Optional
import docker
from ..const import ENV_TIME, ENV_TOKEN, LABEL_MACHINE
from ..const import ENV_TIME, ENV_TOKEN, ENV_TOKEN_OLD, LABEL_MACHINE
from ..exceptions import DockerAPIError
from .interface import CommandReturn, DockerInterface
@ -69,8 +69,10 @@ class DockerHomeAssistant(DockerInterface):
network_mode="host",
environment={
"HASSIO": self.sys_docker.network.supervisor,
"SUPERVISOR": self.sys_docker.network.supervisor,
ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.sys_homeassistant.hassio_token,
ENV_TOKEN_OLD: self.sys_homeassistant.hassio_token,
},
volumes={
str(self.sys_config.path_extern_homeassistant): {