mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-27 02:56:31 +00:00
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:
parent
3a834d1a73
commit
25d324c73a
@ -89,6 +89,11 @@ class RestAPI(CoreSysAttributes):
|
|||||||
|
|
||||||
self.webapp.add_routes(
|
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.get("/hassos/info", api_hassos.info),
|
||||||
web.post("/hassos/update", api_hassos.update),
|
web.post("/hassos/update", api_hassos.update),
|
||||||
web.post("/hassos/update/cli", api_hassos.update_cli),
|
web.post("/hassos/update/cli", api_hassos.update_cli),
|
||||||
@ -150,6 +155,17 @@ class RestAPI(CoreSysAttributes):
|
|||||||
|
|
||||||
self.webapp.add_routes(
|
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/info", api_hass.info),
|
||||||
web.get("/homeassistant/logs", api_hass.logs),
|
web.get("/homeassistant/logs", api_hass.logs),
|
||||||
web.get("/homeassistant/stats", api_hass.stats),
|
web.get("/homeassistant/stats", api_hass.stats),
|
||||||
@ -170,6 +186,13 @@ class RestAPI(CoreSysAttributes):
|
|||||||
|
|
||||||
self.webapp.add_routes(
|
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/api/websocket", api_proxy.websocket),
|
||||||
web.get("/homeassistant/websocket", api_proxy.websocket),
|
web.get("/homeassistant/websocket", api_proxy.websocket),
|
||||||
web.get("/homeassistant/api/stream", api_proxy.stream),
|
web.get("/homeassistant/api/stream", api_proxy.stream),
|
||||||
|
@ -23,6 +23,7 @@ from ..const import (
|
|||||||
ATTR_ENABLE,
|
ATTR_ENABLE,
|
||||||
COOKIE_INGRESS,
|
COOKIE_INGRESS,
|
||||||
HEADER_TOKEN,
|
HEADER_TOKEN,
|
||||||
|
HEADER_TOKEN_OLD,
|
||||||
REQUEST_FROM,
|
REQUEST_FROM,
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
@ -212,6 +213,7 @@ def _init_header(
|
|||||||
hdrs.SEC_WEBSOCKET_VERSION,
|
hdrs.SEC_WEBSOCKET_VERSION,
|
||||||
hdrs.SEC_WEBSOCKET_KEY,
|
hdrs.SEC_WEBSOCKET_KEY,
|
||||||
istr(HEADER_TOKEN),
|
istr(HEADER_TOKEN),
|
||||||
|
istr(HEADER_TOKEN_OLD),
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
headers[name] = value
|
headers[name] = value
|
||||||
|
@ -9,7 +9,6 @@ from aiohttp.web_exceptions import HTTPBadGateway, HTTPUnauthorized
|
|||||||
from aiohttp.client_exceptions import ClientConnectorError
|
from aiohttp.client_exceptions import ClientConnectorError
|
||||||
from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION
|
from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION
|
||||||
|
|
||||||
from ..const import HEADER_HA_ACCESS
|
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import HomeAssistantAuthError, HomeAssistantAPIError, APIError
|
from ..exceptions import HomeAssistantAuthError, HomeAssistantAPIError, APIError
|
||||||
|
|
||||||
@ -17,6 +16,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
FORWARD_HEADERS = ("X-Speech-Content",)
|
FORWARD_HEADERS = ("X-Speech-Content",)
|
||||||
|
HEADER_HA_ACCESS = "X-Ha-Access"
|
||||||
|
|
||||||
|
|
||||||
class APIProxy(CoreSysAttributes):
|
class APIProxy(CoreSysAttributes):
|
||||||
|
@ -3,16 +3,16 @@ import logging
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from aiohttp.web import middleware
|
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 (
|
from ..const import (
|
||||||
HEADER_TOKEN,
|
|
||||||
REQUEST_FROM,
|
REQUEST_FROM,
|
||||||
ROLE_ADMIN,
|
ROLE_ADMIN,
|
||||||
|
ROLE_BACKUP,
|
||||||
ROLE_DEFAULT,
|
ROLE_DEFAULT,
|
||||||
ROLE_HOMEASSISTANT,
|
ROLE_HOMEASSISTANT,
|
||||||
ROLE_MANAGER,
|
ROLE_MANAGER,
|
||||||
ROLE_BACKUP,
|
|
||||||
)
|
)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
|||||||
BLACKLIST = re.compile(
|
BLACKLIST = re.compile(
|
||||||
r"^(?:"
|
r"^(?:"
|
||||||
r"|/homeassistant/api/hassio/.*"
|
r"|/homeassistant/api/hassio/.*"
|
||||||
|
r"|/core/api/hassio/.*"
|
||||||
r")$"
|
r")$"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,6 +33,8 @@ NO_SECURITY_CHECK = re.compile(
|
|||||||
r"^(?:"
|
r"^(?:"
|
||||||
r"|/homeassistant/api/.*"
|
r"|/homeassistant/api/.*"
|
||||||
r"|/homeassistant/websocket"
|
r"|/homeassistant/websocket"
|
||||||
|
r"|/core/api/.*"
|
||||||
|
r"|/core/websocket"
|
||||||
r"|/supervisor/ping"
|
r"|/supervisor/ping"
|
||||||
r")$"
|
r")$"
|
||||||
)
|
)
|
||||||
@ -59,6 +62,7 @@ ADDONS_ROLE_ACCESS = {
|
|||||||
),
|
),
|
||||||
ROLE_HOMEASSISTANT: re.compile(
|
ROLE_HOMEASSISTANT: re.compile(
|
||||||
r"^(?:"
|
r"^(?:"
|
||||||
|
r"|/core/.+"
|
||||||
r"|/homeassistant/.+"
|
r"|/homeassistant/.+"
|
||||||
r")$"
|
r")$"
|
||||||
),
|
),
|
||||||
@ -70,9 +74,11 @@ ADDONS_ROLE_ACCESS = {
|
|||||||
ROLE_MANAGER: re.compile(
|
ROLE_MANAGER: re.compile(
|
||||||
r"^(?:"
|
r"^(?:"
|
||||||
r"|/dns/.*"
|
r"|/dns/.*"
|
||||||
|
r"|/core/.+"
|
||||||
r"|/homeassistant/.+"
|
r"|/homeassistant/.+"
|
||||||
r"|/host/.+"
|
r"|/host/.+"
|
||||||
r"|/hardware/.+"
|
r"|/hardware/.+"
|
||||||
|
r"|/os/.+"
|
||||||
r"|/hassos/.+"
|
r"|/hassos/.+"
|
||||||
r"|/supervisor/.+"
|
r"|/supervisor/.+"
|
||||||
r"|/addons(?:/[^/]+/(?!security).+|/reload)?"
|
r"|/addons(?:/[^/]+/(?!security).+|/reload)?"
|
||||||
@ -98,7 +104,7 @@ class SecurityMiddleware(CoreSysAttributes):
|
|||||||
async def token_validation(self, request, handler):
|
async def token_validation(self, request, handler):
|
||||||
"""Check security access of this layer."""
|
"""Check security access of this layer."""
|
||||||
request_from = None
|
request_from = None
|
||||||
hassio_token = request.headers.get(HEADER_TOKEN)
|
supervisor_token = excract_supervisor_token(request)
|
||||||
|
|
||||||
# Blacklist
|
# Blacklist
|
||||||
if BLACKLIST.match(request.path):
|
if BLACKLIST.match(request.path):
|
||||||
@ -111,24 +117,24 @@ class SecurityMiddleware(CoreSysAttributes):
|
|||||||
return await handler(request)
|
return await handler(request)
|
||||||
|
|
||||||
# Not token
|
# Not token
|
||||||
if not hassio_token:
|
if not supervisor_token:
|
||||||
_LOGGER.warning("No API token provided for %s", request.path)
|
_LOGGER.warning("No API token provided for %s", request.path)
|
||||||
raise HTTPUnauthorized()
|
raise HTTPUnauthorized()
|
||||||
|
|
||||||
# Home-Assistant
|
# 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)
|
_LOGGER.debug("%s access from Home Assistant", request.path)
|
||||||
request_from = self.sys_homeassistant
|
request_from = self.sys_homeassistant
|
||||||
|
|
||||||
# Host
|
# Host
|
||||||
if hassio_token == self.sys_machine_id:
|
if supervisor_token == self.sys_machine_id:
|
||||||
_LOGGER.debug("%s access from Host", request.path)
|
_LOGGER.debug("%s access from Host", request.path)
|
||||||
request_from = self.sys_host
|
request_from = self.sys_host
|
||||||
|
|
||||||
# Add-on
|
# Add-on
|
||||||
addon = None
|
addon = None
|
||||||
if hassio_token and not request_from:
|
if supervisor_token and not request_from:
|
||||||
addon = self.sys_addons.from_token(hassio_token)
|
addon = self.sys_addons.from_token(supervisor_token)
|
||||||
|
|
||||||
# Check Add-on API access
|
# Check Add-on API access
|
||||||
if addon and ADDONS_API_BYPASS.match(request.path):
|
if addon and ADDONS_API_BYPASS.match(request.path):
|
||||||
|
@ -4,11 +4,14 @@ import logging
|
|||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
from aiohttp.hdrs import AUTHORIZATION
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from voluptuous.humanize import humanize_error
|
from voluptuous.humanize import humanize_error
|
||||||
|
|
||||||
from ..const import (
|
from ..const import (
|
||||||
CONTENT_TYPE_BINARY,
|
CONTENT_TYPE_BINARY,
|
||||||
|
HEADER_TOKEN,
|
||||||
|
HEADER_TOKEN_OLD,
|
||||||
JSON_DATA,
|
JSON_DATA,
|
||||||
JSON_MESSAGE,
|
JSON_MESSAGE,
|
||||||
JSON_RESULT,
|
JSON_RESULT,
|
||||||
@ -20,6 +23,22 @@ from ..exceptions import APIError, APIForbidden, HassioError
|
|||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_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]:
|
def json_loads(data: Any) -> Dict[str, Any]:
|
||||||
"""Extract json from string with support for '' and None."""
|
"""Extract json from string with support for '' and None."""
|
||||||
if not data:
|
if not data:
|
||||||
|
@ -58,11 +58,13 @@ CONTENT_TYPE_JSON = "application/json"
|
|||||||
CONTENT_TYPE_TEXT = "text/plain"
|
CONTENT_TYPE_TEXT = "text/plain"
|
||||||
CONTENT_TYPE_TAR = "application/tar"
|
CONTENT_TYPE_TAR = "application/tar"
|
||||||
CONTENT_TYPE_URL = "application/x-www-form-urlencoded"
|
CONTENT_TYPE_URL = "application/x-www-form-urlencoded"
|
||||||
HEADER_HA_ACCESS = "X-Ha-Access"
|
|
||||||
HEADER_TOKEN = "X-Hassio-Key"
|
|
||||||
COOKIE_INGRESS = "ingress_session"
|
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"
|
ENV_TIME = "TZ"
|
||||||
|
|
||||||
REQUEST_FROM = "HASSIO_FROM"
|
REQUEST_FROM = "HASSIO_FROM"
|
||||||
|
@ -6,7 +6,7 @@ from ipaddress import IPv4Address, ip_address
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
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 docker
|
||||||
import requests
|
import requests
|
||||||
@ -15,6 +15,7 @@ from ..addons.build import AddonBuild
|
|||||||
from ..const import (
|
from ..const import (
|
||||||
ENV_TIME,
|
ENV_TIME,
|
||||||
ENV_TOKEN,
|
ENV_TOKEN,
|
||||||
|
ENV_TOKEN_OLD,
|
||||||
MAP_ADDONS,
|
MAP_ADDONS,
|
||||||
MAP_BACKUP,
|
MAP_BACKUP,
|
||||||
MAP_CONFIG,
|
MAP_CONFIG,
|
||||||
@ -118,6 +119,7 @@ class DockerAddon(DockerInterface):
|
|||||||
**addon_env,
|
**addon_env,
|
||||||
ENV_TIME: self.sys_timezone,
|
ENV_TIME: self.sys_timezone,
|
||||||
ENV_TOKEN: self.addon.hassio_token,
|
ENV_TOKEN: self.addon.hassio_token,
|
||||||
|
ENV_TOKEN_OLD: self.addon.hassio_token,
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -189,7 +191,10 @@ class DockerAddon(DockerInterface):
|
|||||||
@property
|
@property
|
||||||
def network_mapping(self) -> Dict[str, str]:
|
def network_mapping(self) -> Dict[str, str]:
|
||||||
"""Return hosts mapping."""
|
"""Return hosts mapping."""
|
||||||
return {"hassio": self.sys_docker.network.supervisor}
|
return {
|
||||||
|
"supervisor": self.sys_docker.network.supervisor,
|
||||||
|
"hassio": self.sys_docker.network.supervisor,
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def network_mode(self) -> Optional[str]:
|
def network_mode(self) -> Optional[str]:
|
||||||
|
@ -6,7 +6,7 @@ from typing import Awaitable, Optional
|
|||||||
|
|
||||||
import docker
|
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 ..exceptions import DockerAPIError
|
||||||
from .interface import CommandReturn, DockerInterface
|
from .interface import CommandReturn, DockerInterface
|
||||||
|
|
||||||
@ -69,8 +69,10 @@ class DockerHomeAssistant(DockerInterface):
|
|||||||
network_mode="host",
|
network_mode="host",
|
||||||
environment={
|
environment={
|
||||||
"HASSIO": self.sys_docker.network.supervisor,
|
"HASSIO": self.sys_docker.network.supervisor,
|
||||||
|
"SUPERVISOR": self.sys_docker.network.supervisor,
|
||||||
ENV_TIME: self.sys_timezone,
|
ENV_TIME: self.sys_timezone,
|
||||||
ENV_TOKEN: self.sys_homeassistant.hassio_token,
|
ENV_TOKEN: self.sys_homeassistant.hassio_token,
|
||||||
|
ENV_TOKEN_OLD: self.sys_homeassistant.hassio_token,
|
||||||
},
|
},
|
||||||
volumes={
|
volumes={
|
||||||
str(self.sys_config.path_extern_homeassistant): {
|
str(self.sys_config.path_extern_homeassistant): {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user