Merge pull request #653 from home-assistant/dev

Release 126
This commit is contained in:
Pascal Vizeli 2018-08-16 23:38:24 +02:00 committed by GitHub
commit 9f25606986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 182 additions and 40 deletions

4
API.md
View File

@ -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"
} }

View File

@ -1,15 +1,17 @@
ARG BUILD_FROM ARG BUILD_FROM
FROM $BUILD_FROM FROM $BUILD_FROM
# Setup base # Install base
COPY requirements.txt /usr/src/
RUN apk add --no-cache \ RUN apk add --no-cache \
git \ git \
socat \ socat \
glib \ glib \
libstdc++ \ libstdc++ \
eudev-libs \ eudev-libs
&& apk add --no-cache --virtual .build-dependencies \
# Install requirements
COPY requirements.txt /usr/src/
RUN apk add --no-cache --virtual .build-dependencies \
make \ make \
g++ \ g++ \
&& pip3 install --no-cache-dir -r /usr/src/requirements.txt \ && pip3 install --no-cache-dir -r /usr/src/requirements.txt \

View File

@ -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."""

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -66,10 +66,11 @@ def initialize_system_data(coresys):
config = coresys.config config = coresys.config
# homeassistant config folder # homeassistant config folder
if not config.path_config.is_dir(): if not config.path_homeassistant.is_dir():
_LOGGER.info( _LOGGER.info(
"Create Home-Assistant config folder %s", config.path_config) "Create Home-Assistant config folder %s",
config.path_config.mkdir() config.path_homeassistant)
config.path_homeassistant.mkdir()
# hassio ssl folder # hassio ssl folder
if not config.path_ssl.is_dir(): if not config.path_ssl.is_dir():

View File

@ -2,8 +2,11 @@
from datetime import datetime from datetime import datetime
import logging import logging
import os import os
import re
from pathlib import Path, PurePath from pathlib import Path, PurePath
import pytz
from .const import ( from .const import (
FILE_HASSIO_CONFIG, HASSIO_DATA, ATTR_TIMEZONE, ATTR_ADDONS_CUSTOM_LIST, FILE_HASSIO_CONFIG, HASSIO_DATA, ATTR_TIMEZONE, ATTR_ADDONS_CUSTOM_LIST,
ATTR_LAST_BOOT, ATTR_WAIT_BOOT) ATTR_LAST_BOOT, ATTR_WAIT_BOOT)
@ -29,6 +32,8 @@ APPARMOR_DATA = PurePath("apparmor")
DEFAULT_BOOT_TIME = datetime.utcfromtimestamp(0).isoformat() DEFAULT_BOOT_TIME = datetime.utcfromtimestamp(0).isoformat()
RE_TIMEZONE = re.compile(r"time_zone: (?P<timezone>[\w/\-+]+)")
class CoreConfig(JsonConfig): class CoreConfig(JsonConfig):
"""Hold all core config data.""" """Hold all core config data."""
@ -40,7 +45,21 @@ class CoreConfig(JsonConfig):
@property @property
def timezone(self): def timezone(self):
"""Return system timezone.""" """Return system timezone."""
return self._data[ATTR_TIMEZONE] config_file = Path(self.path_homeassistant, 'configuration.yaml')
try:
assert config_file.exists()
configuration = config_file.read_text()
data = RE_TIMEZONE.search(configuration)
assert data
timezone = data.group('timezone')
pytz.timezone(timezone)
except (pytz.exceptions.UnknownTimeZoneError, OSError, AssertionError):
_LOGGER.debug("Can't parse HomeAssistant timezone")
return self._data[ATTR_TIMEZONE]
return timezone
@timezone.setter @timezone.setter
def timezone(self, value): def timezone(self, value):
@ -83,12 +102,12 @@ class CoreConfig(JsonConfig):
return PurePath(os.environ['SUPERVISOR_SHARE']) return PurePath(os.environ['SUPERVISOR_SHARE'])
@property @property
def path_extern_config(self): def path_extern_homeassistant(self):
"""Return config path extern for docker.""" """Return config path extern for docker."""
return str(PurePath(self.path_extern_hassio, HOMEASSISTANT_CONFIG)) return str(PurePath(self.path_extern_hassio, HOMEASSISTANT_CONFIG))
@property @property
def path_config(self): def path_homeassistant(self):
"""Return config path inside supervisor.""" """Return config path inside supervisor."""
return Path(HASSIO_DATA, HOMEASSISTANT_CONFIG) return Path(HASSIO_DATA, HOMEASSISTANT_CONFIG)

View File

@ -2,7 +2,7 @@
from pathlib import Path from pathlib import Path
from ipaddress import ip_network from ipaddress import ip_network
HASSIO_VERSION = '125' HASSIO_VERSION = '126'
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons" URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
URL_HASSIO_VERSION = \ URL_HASSIO_VERSION = \
@ -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'

View File

@ -66,6 +66,11 @@ class CoreSys:
"""Return True if we run dev modus.""" """Return True if we run dev modus."""
return self._updater.channel == CHANNEL_DEV return self._updater.channel == CHANNEL_DEV
@property
def timezone(self):
"""Return timezone."""
return self._config.timezone
@property @property
def loop(self): def loop(self):
"""Return loop object.""" """Return loop object."""

View File

@ -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."""
@ -86,7 +91,7 @@ class DockerAddon(DockerInterface):
return { return {
**addon_env, **addon_env,
ENV_TIME: self.sys_config.timezone, ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.addon.uuid, ENV_TOKEN: self.addon.uuid,
} }
@ -173,7 +178,7 @@ class DockerAddon(DockerInterface):
# setup config mappings # setup config mappings
if MAP_CONFIG in addon_mapping: if MAP_CONFIG in addon_mapping:
volumes.update({ volumes.update({
str(self.sys_config.path_extern_config): { str(self.sys_config.path_extern_homeassistant): {
'bind': "/config", 'mode': addon_mapping[MAP_CONFIG] 'bind': "/config", 'mode': addon_mapping[MAP_CONFIG]
}}) }})
@ -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,

View File

@ -61,11 +61,11 @@ class DockerHomeAssistant(DockerInterface):
network_mode='host', network_mode='host',
environment={ environment={
'HASSIO': self.sys_docker.network.supervisor, 'HASSIO': self.sys_docker.network.supervisor,
ENV_TIME: self.sys_config.timezone, ENV_TIME: self.sys_timezone,
ENV_TOKEN: self.sys_homeassistant.uuid, ENV_TOKEN: self.sys_homeassistant.uuid,
}, },
volumes={ volumes={
str(self.sys_config.path_extern_config): str(self.sys_config.path_extern_homeassistant):
{'bind': '/config', 'mode': 'rw'}, {'bind': '/config', 'mode': 'rw'},
str(self.sys_config.path_extern_ssl): str(self.sys_config.path_extern_ssl):
{'bind': '/ssl', 'mode': 'ro'}, {'bind': '/ssl', 'mode': 'ro'},
@ -95,10 +95,10 @@ class DockerHomeAssistant(DockerInterface):
stdout=True, stdout=True,
stderr=True, stderr=True,
environment={ environment={
ENV_TIME: self.sys_config.timezone, ENV_TIME: self.sys_timezone,
}, },
volumes={ volumes={
str(self.sys_config.path_extern_config): str(self.sys_config.path_extern_homeassistant):
{'bind': '/config', 'mode': 'rw'}, {'bind': '/config', 'mode': 'rw'},
str(self.sys_config.path_extern_ssl): str(self.sys_config.path_extern_ssl):
{'bind': '/ssl', 'mode': 'ro'}, {'bind': '/ssl', 'mode': 'ro'},

View File

@ -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

View File

@ -9,7 +9,6 @@ UTC = pytz.utc
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
FREEGEOIP_URL = "https://freegeoip.net/json/"
# Copyright (c) Django Software Foundation and individual contributors. # Copyright (c) Django Software Foundation and individual contributors.
# All rights reserved. # All rights reserved.

View File

@ -1,7 +1,7 @@
attr==0.3.1 attr==0.3.1
async_timeout==3.0.0 async_timeout==3.0.0
aiohttp==3.3.2 aiohttp==3.3.2
docker==3.4.1 docker==3.5.0
colorlog==3.1.2 colorlog==3.1.2
voluptuous==0.11.5 voluptuous==0.11.5
gitpython==2.1.10 gitpython==2.1.10
@ -9,5 +9,5 @@ pytz==2018.4
pyudev==0.21.0 pyudev==0.21.0
pycryptodome==3.6.4 pycryptodome==3.6.4
cpe==1.2.1 cpe==1.2.1
uvloop==0.11.1 uvloop==0.11.2
cchardet==2.1.1 cchardet==2.1.1