mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-08 17:56:33 +00:00
New generation of security and access (#652)
* New generation of security and access * Update const.py * Update validate.py * Update addon.py * Update validate.py * Fix name * Allow access * Fix * add logs * change message * add rating * fix lint * fix lint * fix * Fix
This commit is contained in:
parent
85fbde8e36
commit
ecd12732ee
4
API.md
4
API.md
@ -478,6 +478,9 @@ Get all available addons.
|
|||||||
"changelog": "bool",
|
"changelog": "bool",
|
||||||
"hassio_api": "bool",
|
"hassio_api": "bool",
|
||||||
"homeassistant_api": "bool",
|
"homeassistant_api": "bool",
|
||||||
|
"full_access": "bool",
|
||||||
|
"protected": "bool",
|
||||||
|
"rating": "1-5",
|
||||||
"stdin": "bool",
|
"stdin": "bool",
|
||||||
"webui": "null|http(s)://[HOST]:port/xy/zx",
|
"webui": "null|http(s)://[HOST]:port/xy/zx",
|
||||||
"gpio": "bool",
|
"gpio": "bool",
|
||||||
@ -507,6 +510,7 @@ Get all available addons.
|
|||||||
"CONTAINER": "port|[ip, port]"
|
"CONTAINER": "port|[ip, port]"
|
||||||
},
|
},
|
||||||
"options": {},
|
"options": {},
|
||||||
|
"protected": "bool",
|
||||||
"audio_output": "null|0,0",
|
"audio_output": "null|0,0",
|
||||||
"audio_input": "null|0,0"
|
"audio_input": "null|0,0"
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,9 @@ from ..const import (
|
|||||||
ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT,
|
ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT,
|
||||||
ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC,
|
ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC,
|
||||||
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES,
|
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES,
|
||||||
ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, SECURITY_PROFILE,
|
ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, ATTR_FULL_ACCESS,
|
||||||
SECURITY_DISABLE, SECURITY_DEFAULT)
|
ATTR_PROTECTED,
|
||||||
|
SECURITY_PROFILE, SECURITY_DISABLE, SECURITY_DEFAULT)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..docker.addon import DockerAddon
|
from ..docker.addon import DockerAddon
|
||||||
from ..utils.json import write_json_file, read_json_file
|
from ..utils.json import write_json_file, read_json_file
|
||||||
@ -201,6 +202,18 @@ class Addon(CoreSysAttributes):
|
|||||||
return self._data.cache[self._id][ATTR_VERSION]
|
return self._data.cache[self._id][ATTR_VERSION]
|
||||||
return self.version_installed
|
return self.version_installed
|
||||||
|
|
||||||
|
@property
|
||||||
|
def protected(self):
|
||||||
|
"""Return if addon is in protected mode."""
|
||||||
|
if self.is_installed:
|
||||||
|
return self._data.user[self._id][ATTR_PROTECTED]
|
||||||
|
return True
|
||||||
|
|
||||||
|
@protected.setter
|
||||||
|
def protected(self, value):
|
||||||
|
"""Set addon in protected mode."""
|
||||||
|
self._data.user[self._id][ATTR_PROTECTED] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def startup(self):
|
def startup(self):
|
||||||
"""Return startup type of addon."""
|
"""Return startup type of addon."""
|
||||||
@ -336,7 +349,7 @@ class Addon(CoreSysAttributes):
|
|||||||
return self._mesh.get(ATTR_LEGACY)
|
return self._mesh.get(ATTR_LEGACY)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def with_docker_api(self):
|
def access_docker_api(self):
|
||||||
"""Return if the add-on need read-only docker API access."""
|
"""Return if the add-on need read-only docker API access."""
|
||||||
return self._mesh.get(ATTR_DOCKER_API)
|
return self._mesh.get(ATTR_DOCKER_API)
|
||||||
|
|
||||||
@ -360,6 +373,11 @@ class Addon(CoreSysAttributes):
|
|||||||
"""Return True if the add-on access to gpio interface."""
|
"""Return True if the add-on access to gpio interface."""
|
||||||
return self._mesh[ATTR_GPIO]
|
return self._mesh[ATTR_GPIO]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def with_full_access(self):
|
||||||
|
"""Return True if the add-on want full access to hardware."""
|
||||||
|
return self._mesh[ATTR_FULL_ACCESS]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def with_devicetree(self):
|
def with_devicetree(self):
|
||||||
"""Return True if the add-on read access to devicetree."""
|
"""Return True if the add-on read access to devicetree."""
|
||||||
|
@ -4,11 +4,49 @@ import hashlib
|
|||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from ..const import (
|
||||||
|
SECURITY_DISABLE, SECURITY_PROFILE, PRIVILEGED_NET_ADMIN,
|
||||||
|
PRIVILEGED_SYS_ADMIN, PRIVILEGED_SYS_RAWIO)
|
||||||
|
|
||||||
RE_SHA1 = re.compile(r"[a-f0-9]{8}")
|
RE_SHA1 = re.compile(r"[a-f0-9]{8}")
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def rating_security(addon):
|
||||||
|
"""Return 1-5 for security rating.
|
||||||
|
|
||||||
|
1 = not secure
|
||||||
|
5 = high secure
|
||||||
|
"""
|
||||||
|
rating = 4
|
||||||
|
|
||||||
|
# AppArmor
|
||||||
|
if addon.apparmor == SECURITY_DISABLE:
|
||||||
|
rating += -1
|
||||||
|
elif addon.apparmor == SECURITY_PROFILE:
|
||||||
|
rating += 1
|
||||||
|
|
||||||
|
# API Access
|
||||||
|
if addon.access_hassio_api or addon.access_homeassistant_api:
|
||||||
|
rating += -1
|
||||||
|
|
||||||
|
# Privileged options
|
||||||
|
if addon.privileged in (PRIVILEGED_NET_ADMIN, PRIVILEGED_SYS_ADMIN,
|
||||||
|
PRIVILEGED_SYS_RAWIO):
|
||||||
|
rating += -1
|
||||||
|
|
||||||
|
# Full Access
|
||||||
|
if addon.with_full_access:
|
||||||
|
rating += -2
|
||||||
|
|
||||||
|
# Docker Access
|
||||||
|
if addon.access_docker_api:
|
||||||
|
rating = 1
|
||||||
|
|
||||||
|
return max(min(5, rating), 1)
|
||||||
|
|
||||||
|
|
||||||
def get_hash_from_repository(name):
|
def get_hash_from_repository(name):
|
||||||
"""Generate a hash from repository."""
|
"""Generate a hash from repository."""
|
||||||
key = name.lower().encode()
|
key = name.lower().encode()
|
||||||
|
@ -18,7 +18,11 @@ from ..const import (
|
|||||||
ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH,
|
ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH,
|
||||||
ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY,
|
ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY,
|
||||||
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_SERVICES, ATTR_DISCOVERY,
|
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_SERVICES, ATTR_DISCOVERY,
|
||||||
ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API)
|
ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, ATTR_PROTECTED,
|
||||||
|
ATTR_FULL_ACCESS,
|
||||||
|
PRIVILEGED_NET_ADMIN, PRIVILEGED_SYS_ADMIN, PRIVILEGED_SYS_RAWIO,
|
||||||
|
PRIVILEGED_IPC_LOCK, PRIVILEGED_SYS_TIME, PRIVILEGED_SYS_NICE,
|
||||||
|
PRIVILEGED_SYS_RESOURCE)
|
||||||
from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_DEVICE
|
from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_DEVICE
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -58,13 +62,13 @@ STARTUP_ALL = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
PRIVILEGED_ALL = [
|
PRIVILEGED_ALL = [
|
||||||
"NET_ADMIN",
|
PRIVILEGED_NET_ADMIN,
|
||||||
"SYS_ADMIN",
|
PRIVILEGED_SYS_ADMIN,
|
||||||
"SYS_RAWIO",
|
PRIVILEGED_SYS_RAWIO,
|
||||||
"IPC_LOCK",
|
PRIVILEGED_IPC_LOCK,
|
||||||
"SYS_TIME",
|
PRIVILEGED_SYS_TIME,
|
||||||
"SYS_NICE",
|
PRIVILEGED_SYS_NICE,
|
||||||
"SYS_RESOURCE"
|
PRIVILEGED_SYS_RESOURCE,
|
||||||
]
|
]
|
||||||
|
|
||||||
BASE_IMAGE = {
|
BASE_IMAGE = {
|
||||||
@ -110,6 +114,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({
|
|||||||
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
|
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
|
||||||
vol.Optional(ATTR_PRIVILEGED): [vol.In(PRIVILEGED_ALL)],
|
vol.Optional(ATTR_PRIVILEGED): [vol.In(PRIVILEGED_ALL)],
|
||||||
vol.Optional(ATTR_APPARMOR, default=True): vol.Boolean(),
|
vol.Optional(ATTR_APPARMOR, default=True): vol.Boolean(),
|
||||||
|
vol.Optional(ATTR_FULL_ACCESS, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(),
|
vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_GPIO, default=False): vol.Boolean(),
|
vol.Optional(ATTR_GPIO, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_DEVICETREE, default=False): vol.Boolean(),
|
vol.Optional(ATTR_DEVICETREE, default=False): vol.Boolean(),
|
||||||
@ -170,6 +175,7 @@ SCHEMA_ADDON_USER = vol.Schema({
|
|||||||
vol.Optional(ATTR_NETWORK): DOCKER_PORTS,
|
vol.Optional(ATTR_NETWORK): DOCKER_PORTS,
|
||||||
vol.Optional(ATTR_AUDIO_OUTPUT): ALSA_DEVICE,
|
vol.Optional(ATTR_AUDIO_OUTPUT): ALSA_DEVICE,
|
||||||
vol.Optional(ATTR_AUDIO_INPUT): ALSA_DEVICE,
|
vol.Optional(ATTR_AUDIO_INPUT): ALSA_DEVICE,
|
||||||
|
vol.Optional(ATTR_PROTECTED, default=True): vol.Boolean(),
|
||||||
}, extra=vol.REMOVE_EXTRA)
|
}, extra=vol.REMOVE_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import voluptuous as vol
|
|||||||
from voluptuous.humanize import humanize_error
|
from voluptuous.humanize import humanize_error
|
||||||
|
|
||||||
from .utils import api_process, api_process_raw, api_validate
|
from .utils import api_process, api_process_raw, api_validate
|
||||||
|
from ..addons.utils import rating_security
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_STATE, ATTR_BOOT, ATTR_OPTIONS,
|
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_STATE, ATTR_BOOT, ATTR_OPTIONS,
|
||||||
ATTR_URL, ATTR_DESCRIPTON, ATTR_DETACHED, ATTR_NAME, ATTR_REPOSITORY,
|
ATTR_URL, ATTR_DESCRIPTON, ATTR_DETACHED, ATTR_NAME, ATTR_REPOSITORY,
|
||||||
@ -18,9 +19,11 @@ from ..const import (
|
|||||||
ATTR_CPU_PERCENT, ATTR_MEMORY_LIMIT, ATTR_MEMORY_USAGE, ATTR_NETWORK_TX,
|
ATTR_CPU_PERCENT, ATTR_MEMORY_LIMIT, ATTR_MEMORY_USAGE, ATTR_NETWORK_TX,
|
||||||
ATTR_NETWORK_RX, ATTR_BLK_READ, ATTR_BLK_WRITE, ATTR_ICON, ATTR_SERVICES,
|
ATTR_NETWORK_RX, ATTR_BLK_READ, ATTR_BLK_WRITE, ATTR_ICON, ATTR_SERVICES,
|
||||||
ATTR_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API,
|
ATTR_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API,
|
||||||
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT)
|
ATTR_FULL_ACCESS, ATTR_PROTECTED, ATTR_RATING,
|
||||||
|
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT, REQUEST_FROM)
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..validate import DOCKER_PORTS, ALSA_DEVICE
|
from ..validate import DOCKER_PORTS, ALSA_DEVICE
|
||||||
|
from ..exceptions import APINotSupportedError
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -35,6 +38,7 @@ SCHEMA_OPTIONS = vol.Schema({
|
|||||||
vol.Optional(ATTR_AUTO_UPDATE): vol.Boolean(),
|
vol.Optional(ATTR_AUTO_UPDATE): vol.Boolean(),
|
||||||
vol.Optional(ATTR_AUDIO_OUTPUT): ALSA_DEVICE,
|
vol.Optional(ATTR_AUDIO_OUTPUT): ALSA_DEVICE,
|
||||||
vol.Optional(ATTR_AUDIO_INPUT): ALSA_DEVICE,
|
vol.Optional(ATTR_AUDIO_INPUT): ALSA_DEVICE,
|
||||||
|
vol.Optional(ATTR_PROTECTED): vol.Boolean(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -116,6 +120,8 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_REPOSITORY: addon.repository,
|
ATTR_REPOSITORY: addon.repository,
|
||||||
ATTR_LAST_VERSION: addon.last_version,
|
ATTR_LAST_VERSION: addon.last_version,
|
||||||
ATTR_STATE: await addon.state(),
|
ATTR_STATE: await addon.state(),
|
||||||
|
ATTR_PROTECTED: addon.protected,
|
||||||
|
ATTR_RATING: rating_security(addon),
|
||||||
ATTR_BOOT: addon.boot,
|
ATTR_BOOT: addon.boot,
|
||||||
ATTR_OPTIONS: addon.options,
|
ATTR_OPTIONS: addon.options,
|
||||||
ATTR_URL: addon.url,
|
ATTR_URL: addon.url,
|
||||||
@ -126,6 +132,7 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_HOST_IPC: addon.host_ipc,
|
ATTR_HOST_IPC: addon.host_ipc,
|
||||||
ATTR_HOST_DBUS: addon.host_dbus,
|
ATTR_HOST_DBUS: addon.host_dbus,
|
||||||
ATTR_PRIVILEGED: addon.privileged,
|
ATTR_PRIVILEGED: addon.privileged,
|
||||||
|
ATTR_FULL_ACCESS: addon.with_full_access,
|
||||||
ATTR_APPARMOR: addon.apparmor,
|
ATTR_APPARMOR: addon.apparmor,
|
||||||
ATTR_DEVICES: self._pretty_devices(addon),
|
ATTR_DEVICES: self._pretty_devices(addon),
|
||||||
ATTR_ICON: addon.with_icon,
|
ATTR_ICON: addon.with_icon,
|
||||||
@ -137,7 +144,7 @@ class APIAddons(CoreSysAttributes):
|
|||||||
ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api,
|
ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api,
|
||||||
ATTR_GPIO: addon.with_gpio,
|
ATTR_GPIO: addon.with_gpio,
|
||||||
ATTR_DEVICETREE: addon.with_devicetree,
|
ATTR_DEVICETREE: addon.with_devicetree,
|
||||||
ATTR_DOCKER_API: addon.with_docker_api,
|
ATTR_DOCKER_API: addon.access_docker_api,
|
||||||
ATTR_AUDIO: addon.with_audio,
|
ATTR_AUDIO: addon.with_audio,
|
||||||
ATTR_AUDIO_INPUT: addon.audio_input,
|
ATTR_AUDIO_INPUT: addon.audio_input,
|
||||||
ATTR_AUDIO_OUTPUT: addon.audio_output,
|
ATTR_AUDIO_OUTPUT: addon.audio_output,
|
||||||
@ -150,6 +157,11 @@ class APIAddons(CoreSysAttributes):
|
|||||||
"""Store user options for addon."""
|
"""Store user options for addon."""
|
||||||
addon = self._extract_addon(request)
|
addon = self._extract_addon(request)
|
||||||
|
|
||||||
|
# Have Access
|
||||||
|
if addon.slug == request[REQUEST_FROM]:
|
||||||
|
_LOGGER.error("Add-on can't self modify his options!")
|
||||||
|
raise APINotSupportedError()
|
||||||
|
|
||||||
addon_schema = SCHEMA_OPTIONS.extend({
|
addon_schema = SCHEMA_OPTIONS.extend({
|
||||||
vol.Optional(ATTR_OPTIONS): vol.Any(None, addon.schema),
|
vol.Optional(ATTR_OPTIONS): vol.Any(None, addon.schema),
|
||||||
})
|
})
|
||||||
@ -168,6 +180,9 @@ class APIAddons(CoreSysAttributes):
|
|||||||
addon.audio_input = body[ATTR_AUDIO_INPUT]
|
addon.audio_input = body[ATTR_AUDIO_INPUT]
|
||||||
if ATTR_AUDIO_OUTPUT in body:
|
if ATTR_AUDIO_OUTPUT in body:
|
||||||
addon.audio_output = body[ATTR_AUDIO_OUTPUT]
|
addon.audio_output = body[ATTR_AUDIO_OUTPUT]
|
||||||
|
if ATTR_PROTECTED in body:
|
||||||
|
_LOGGER.warning("Protected flag changing for %s!", addon.slug)
|
||||||
|
addon.protected = body[ATTR_PROTECTED]
|
||||||
|
|
||||||
addon.save_data()
|
addon.save_data()
|
||||||
return True
|
return True
|
||||||
|
@ -30,10 +30,10 @@ def api_process(method):
|
|||||||
"""Return api information."""
|
"""Return api information."""
|
||||||
try:
|
try:
|
||||||
answer = await method(api, *args, **kwargs)
|
answer = await method(api, *args, **kwargs)
|
||||||
except RuntimeError as err:
|
|
||||||
return api_return_error(message=str(err))
|
|
||||||
except HassioError:
|
except HassioError:
|
||||||
return api_return_error()
|
return api_return_error()
|
||||||
|
except RuntimeError as err:
|
||||||
|
return api_return_error(message=str(err))
|
||||||
|
|
||||||
if isinstance(answer, dict):
|
if isinstance(answer, dict):
|
||||||
return api_return_ok(data=answer)
|
return api_return_ok(data=answer)
|
||||||
|
@ -179,6 +179,9 @@ ATTR_VERSION_CLI = 'version_cli'
|
|||||||
ATTR_VERSION_CLI_LATEST = 'version_cli_latest'
|
ATTR_VERSION_CLI_LATEST = 'version_cli_latest'
|
||||||
ATTR_REFRESH_TOKEN = 'refresh_token'
|
ATTR_REFRESH_TOKEN = 'refresh_token'
|
||||||
ATTR_DOCKER_API = 'docker_api'
|
ATTR_DOCKER_API = 'docker_api'
|
||||||
|
ATTR_FULL_ACCESS = 'full_access'
|
||||||
|
ATTR_PROTECTED = 'protected'
|
||||||
|
ATTR_RATING = 'rating'
|
||||||
|
|
||||||
SERVICE_MQTT = 'mqtt'
|
SERVICE_MQTT = 'mqtt'
|
||||||
|
|
||||||
@ -227,6 +230,14 @@ SECURITY_PROFILE = 'profile'
|
|||||||
SECURITY_DEFAULT = 'default'
|
SECURITY_DEFAULT = 'default'
|
||||||
SECURITY_DISABLE = 'disable'
|
SECURITY_DISABLE = 'disable'
|
||||||
|
|
||||||
|
PRIVILEGED_NET_ADMIN = 'NET_ADMIN'
|
||||||
|
PRIVILEGED_SYS_ADMIN = 'SYS_ADMIN'
|
||||||
|
PRIVILEGED_SYS_RAWIO = 'SYS_RAWIO'
|
||||||
|
PRIVILEGED_IPC_LOCK = 'IPC_LOCK'
|
||||||
|
PRIVILEGED_SYS_TIME = 'SYS_TIME'
|
||||||
|
PRIVILEGED_SYS_NICE = 'SYS_NICE'
|
||||||
|
PRIVILEGED_SYS_RESOURCE = 'SYS_RESOURCE'
|
||||||
|
|
||||||
FEATURES_SHUTDOWN = 'shutdown'
|
FEATURES_SHUTDOWN = 'shutdown'
|
||||||
FEATURES_REBOOT = 'reboot'
|
FEATURES_REBOOT = 'reboot'
|
||||||
FEATURES_HASSOS = 'hassos'
|
FEATURES_HASSOS = 'hassos'
|
||||||
|
@ -67,6 +67,11 @@ class DockerAddon(DockerInterface):
|
|||||||
return 'host'
|
return 'host'
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def full_access(self):
|
||||||
|
"""Return True if full access is enabled."""
|
||||||
|
return not self.addon.protected and self.addon.with_full_access
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hostname(self):
|
def hostname(self):
|
||||||
"""Return slug/id of addon."""
|
"""Return slug/id of addon."""
|
||||||
@ -223,7 +228,7 @@ class DockerAddon(DockerInterface):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Docker API support
|
# Docker API support
|
||||||
if self.addon.with_docker_api:
|
if not self.addon.protected and self.addon.access_docker_api:
|
||||||
volumes.update({
|
volumes.update({
|
||||||
"/var/run/docker.sock": {
|
"/var/run/docker.sock": {
|
||||||
'bind': "/var/run/docker.sock", 'mode': 'ro'
|
'bind': "/var/run/docker.sock", 'mode': 'ro'
|
||||||
@ -254,6 +259,11 @@ class DockerAddon(DockerInterface):
|
|||||||
if self._is_running():
|
if self._is_running():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# Security check
|
||||||
|
if not self.addon.protected:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"%s run with disabled proteced mode!", self.addon.name)
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
self._stop()
|
self._stop()
|
||||||
|
|
||||||
@ -263,6 +273,7 @@ class DockerAddon(DockerInterface):
|
|||||||
hostname=self.hostname,
|
hostname=self.hostname,
|
||||||
detach=True,
|
detach=True,
|
||||||
init=True,
|
init=True,
|
||||||
|
privileged=self.full_access,
|
||||||
ipc_mode=self.ipc,
|
ipc_mode=self.ipc,
|
||||||
stdin_open=self.addon.with_stdin,
|
stdin_open=self.addon.with_stdin,
|
||||||
network_mode=self.network_mode,
|
network_mode=self.network_mode,
|
||||||
|
@ -76,6 +76,19 @@ class HostServiceError(HostError):
|
|||||||
|
|
||||||
class HostAppArmorError(HostError):
|
class HostAppArmorError(HostError):
|
||||||
"""Host apparmor functions fails."""
|
"""Host apparmor functions fails."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# API
|
||||||
|
|
||||||
|
class APIError(HassioError):
|
||||||
|
"""API errors."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class APINotSupportedError(HassioNotSupportedError):
|
||||||
|
"""API not supported error."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# utils/gdbus
|
# utils/gdbus
|
||||||
|
Loading…
x
Reference in New Issue
Block a user