diff --git a/API.md b/API.md
index 5123745bf..e6720bd71 100644
--- a/API.md
+++ b/API.md
@@ -4,7 +4,7 @@
Interface for Home Assistant to control things from supervisor.
-On error:
+On error / Code 400:
```json
{
@@ -13,7 +13,7 @@ On error:
}
```
-On success:
+On success / Code 200:
```json
{
@@ -22,6 +22,8 @@ On success:
}
```
+For access to API you need set the `X-HASSIO-KEY` they will be available for Add-ons/HomeAssistant with envoriment `HASSIO_TOKEN`.
+
### Hass.io
- GET `/supervisor/ping`
@@ -99,44 +101,7 @@ Output is the raw docker log.
}
```
-### Security
-
-- GET `/security/info`
-
-```json
-{
- "initialize": "bool",
- "totp": "bool"
-}
-```
-
-- POST `/security/options`
-
-```json
-{
- "password": "xy"
-}
-```
-
-- POST `/security/totp`
-
-```json
-{
- "password": "xy"
-}
-```
-
-Return QR-Code
-
-- POST `/security/session`
-```json
-{
- "password": "xy",
- "totp": "null|123456"
-}
-```
-
-### Backup/Snapshot
+### Snapshot
- GET `/snapshots`
diff --git a/hassio/api/__init__.py b/hassio/api/__init__.py
index 5601d469d..39b01cfc8 100644
--- a/hassio/api/__init__.py
+++ b/hassio/api/__init__.py
@@ -10,7 +10,6 @@ from .host import APIHost
from .network import APINetwork
from .proxy import APIProxy
from .supervisor import APISupervisor
-from .security import APISecurity
from .snapshots import APISnapshots
from ..coresys import CoreSysAttributes
@@ -38,7 +37,6 @@ class RestAPI(CoreSysAttributes):
self._register_panel()
self._register_addons()
self._register_snapshots()
- self._register_security()
self._register_network()
def _register_host(self):
@@ -138,16 +136,6 @@ class RestAPI(CoreSysAttributes):
self.webapp.router.add_post('/addons/{addon}/stdin', api_addons.stdin)
self.webapp.router.add_get('/addons/{addon}/stats', api_addons.stats)
- def _register_security(self):
- """Register security function."""
- api_security = APISecurity()
- api_security.coresys = self.coresys
-
- self.webapp.router.add_get('/security/info', api_security.info)
- self.webapp.router.add_post('/security/options', api_security.options)
- self.webapp.router.add_post('/security/totp', api_security.totp)
- self.webapp.router.add_post('/security/session', api_security.session)
-
def _register_snapshots(self):
"""Register snapshots function."""
api_snapshots = APISnapshots()
diff --git a/hassio/api/security.py b/hassio/api/security.py
deleted file mode 100644
index cbb56b0b0..000000000
--- a/hassio/api/security.py
+++ /dev/null
@@ -1,98 +0,0 @@
-"""Init file for HassIO security rest api."""
-from datetime import datetime, timedelta
-import io
-import logging
-import hashlib
-import os
-
-from aiohttp import web
-import voluptuous as vol
-import pyotp
-import pyqrcode
-
-from .utils import api_process, api_validate, hash_password
-from ..const import ATTR_INITIALIZE, ATTR_PASSWORD, ATTR_TOTP, ATTR_SESSION
-from ..coresys import CoreSysAttributes
-
-_LOGGER = logging.getLogger(__name__)
-
-SCHEMA_PASSWORD = vol.Schema({
- vol.Required(ATTR_PASSWORD): vol.Coerce(str),
-})
-
-SCHEMA_SESSION = SCHEMA_PASSWORD.extend({
- vol.Optional(ATTR_TOTP, default=None): vol.Coerce(str),
-})
-
-
-class APISecurity(CoreSysAttributes):
- """Handle rest api for security functions."""
-
- def _check_password(self, body):
- """Check if password is valid and security is initialize."""
- if not self._config.security_initialize:
- raise RuntimeError("First set a password")
-
- password = hash_password(body[ATTR_PASSWORD])
- if password != self._config.security_password:
- raise RuntimeError("Wrong password")
-
- @api_process
- async def info(self, request):
- """Return host information."""
- return {
- ATTR_INITIALIZE: self._config.security_initialize,
- ATTR_TOTP: self._config.security_totp is not None,
- }
-
- @api_process
- async def options(self, request):
- """Set options / password."""
- body = await api_validate(SCHEMA_PASSWORD, request)
-
- if self._config.security_initialize:
- raise RuntimeError("Password is already set!")
-
- self._config.security_password = hash_password(body[ATTR_PASSWORD])
- self._config.security_initialize = True
- return True
-
- @api_process
- async def totp(self, request):
- """Set and initialze TOTP."""
- body = await api_validate(SCHEMA_PASSWORD, request)
- self._check_password(body)
-
- # generate TOTP
- totp_init_key = pyotp.random_base32()
- totp = pyotp.TOTP(totp_init_key)
-
- # init qrcode
- buff = io.BytesIO()
-
- qrcode = pyqrcode.create(totp.provisioning_uri("Hass.IO"))
- qrcode.svg(buff)
-
- # finish
- self._config.security_totp = totp_init_key
- return web.Response(body=buff.getvalue(), content_type='image/svg+xml')
-
- @api_process
- async def session(self, request):
- """Set and initialze session."""
- body = await api_validate(SCHEMA_SESSION, request)
- self._check_password(body)
-
- # check TOTP
- if self._config.security_totp:
- totp = pyotp.TOTP(self._config.security_totp)
- if body[ATTR_TOTP] != totp.now():
- raise RuntimeError("Invalid TOTP token!")
-
- # create session
- valid_until = datetime.now() + timedelta(days=1)
- session = hashlib.sha256(os.urandom(54)).hexdigest()
-
- # store session
- self._config.add_security_session(session, valid_until)
- return {ATTR_SESSION: session}
diff --git a/hassio/config.py b/hassio/config.py
index 3df086e07..6e50f0bc2 100644
--- a/hassio/config.py
+++ b/hassio/config.py
@@ -5,8 +5,7 @@ import os
from pathlib import Path, PurePath
from .const import (
- FILE_HASSIO_CONFIG, HASSIO_DATA, ATTR_SECURITY, ATTR_SESSIONS,
- ATTR_PASSWORD, ATTR_TOTP, ATTR_TIMEZONE, ATTR_ADDONS_CUSTOM_LIST,
+ FILE_HASSIO_CONFIG, HASSIO_DATA, ATTR_TIMEZONE, ATTR_ADDONS_CUSTOM_LIST,
ATTR_AUDIO_INPUT, ATTR_AUDIO_OUTPUT, ATTR_LAST_BOOT, ATTR_WAIT_BOOT)
from .utils.dt import parse_datetime
from .utils.json import JsonConfig
@@ -181,59 +180,6 @@ class CoreConfig(JsonConfig):
self._data[ATTR_ADDONS_CUSTOM_LIST].remove(repo)
self.save()
- @property
- def security_initialize(self):
- """Return is security was initialize."""
- return self._data[ATTR_SECURITY]
-
- @security_initialize.setter
- def security_initialize(self, value):
- """Set is security initialize."""
- self._data[ATTR_SECURITY] = value
- self.save()
-
- @property
- def security_totp(self):
- """Return the TOTP key."""
- return self._data.get(ATTR_TOTP)
-
- @security_totp.setter
- def security_totp(self, value):
- """Set the TOTP key."""
- self._data[ATTR_TOTP] = value
- self.save()
-
- @property
- def security_password(self):
- """Return the password key."""
- return self._data.get(ATTR_PASSWORD)
-
- @security_password.setter
- def security_password(self, value):
- """Set the password key."""
- self._data[ATTR_PASSWORD] = value
- self.save()
-
- @property
- def security_sessions(self):
- """Return api sessions."""
- return {
- session: parse_datetime(until) for
- session, until in self._data[ATTR_SESSIONS].items()
- }
-
- def add_security_session(self, session, valid):
- """Set the a new session."""
- self._data[ATTR_SESSIONS].update(
- {session: valid.isoformat()}
- )
- self.save()
-
- def drop_security_session(self, session):
- """Delete the a session."""
- self._data[ATTR_SESSIONS].pop(session, None)
- self.save()
-
@property
def audio_output(self):
"""Return ALSA audio output card,dev."""
diff --git a/hassio/tasks.py b/hassio/tasks.py
index 2ca22ef86..277064781 100644
--- a/hassio/tasks.py
+++ b/hassio/tasks.py
@@ -1,6 +1,5 @@
"""Multible tasks."""
import asyncio
-from datetime import datetime
import logging
from .coresys import CoreSysAttributes
@@ -22,8 +21,6 @@ class Tasks(CoreSysAttributes):
RUN_WATCHDOG_HOMEASSISTANT_DOCKER = 15
RUN_WATCHDOG_HOMEASSISTANT_API = 300
- RUN_CLEANUP_API_SESSIONS = 900
-
def __init__(self, coresys):
"""Initialize Tasks."""
self.coresys = coresys
@@ -55,13 +52,6 @@ class Tasks(CoreSysAttributes):
_LOGGER.info("All core tasks are scheduled")
- async def _cleanup_sessions(self):
- """Cleanup old api sessions."""
- now = datetime.now()
- for session, until_valid in self._config.security_sessions.items():
- if now >= until_valid:
- self._config.drop_security_session(session)
-
async def _update_addons(self):
"""Check if a update is available of a addon and update it."""
tasks = []
diff --git a/hassio/validate.py b/hassio/validate.py
index 0c56d2405..71b843d81 100644
--- a/hassio/validate.py
+++ b/hassio/validate.py
@@ -5,11 +5,10 @@ import voluptuous as vol
import pytz
from .const import (
- ATTR_IMAGE, ATTR_LAST_VERSION, ATTR_SESSIONS, ATTR_PASSWORD, ATTR_TOTP,
- ATTR_SECURITY, ATTR_BETA_CHANNEL, ATTR_TIMEZONE, ATTR_ADDONS_CUSTOM_LIST,
- ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT, ATTR_HOMEASSISTANT, ATTR_HASSIO,
- ATTR_BOOT, ATTR_LAST_BOOT, ATTR_SSL, ATTR_PORT, ATTR_WATCHDOG,
- ATTR_WAIT_BOOT, ATTR_UUID)
+ ATTR_IMAGE, ATTR_LAST_VERSION, ATTR_BETA_CHANNEL, ATTR_TIMEZONE,
+ ATTR_ADDONS_CUSTOM_LIST, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT,
+ ATTR_PASSWORD, ATTR_HOMEASSISTANT, ATTR_HASSIO, ATTR_BOOT, ATTR_LAST_BOOT,
+ ATTR_SSL, ATTR_PORT, ATTR_WATCHDOG, ATTR_WAIT_BOOT, ATTR_UUID)
NETWORK_PORT = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535))
@@ -87,11 +86,6 @@ SCHEMA_HASSIO_CONFIG = vol.Schema({
vol.Optional(ATTR_ADDONS_CUSTOM_LIST, default=[
"https://github.com/hassio-addons/repository",
]): [vol.Url()],
- vol.Optional(ATTR_SECURITY, default=False): vol.Boolean(),
- vol.Optional(ATTR_TOTP): vol.Coerce(str),
- vol.Optional(ATTR_PASSWORD): vol.Coerce(str),
- vol.Optional(ATTR_SESSIONS, default={}):
- vol.Schema({vol.Coerce(str): vol.Coerce(str)}),
vol.Optional(ATTR_AUDIO_OUTPUT): ALSA_CHANNEL,
vol.Optional(ATTR_AUDIO_INPUT): ALSA_CHANNEL,
vol.Optional(ATTR_WAIT_BOOT, default=5): WAIT_BOOT,
diff --git a/misc/hassio.png b/misc/hassio.png
index 22c013125..3ccbf7ae9 100644
Binary files a/misc/hassio.png and b/misc/hassio.png differ
diff --git a/misc/hassio.xml b/misc/hassio.xml
index 42fa0b23c..685610ae1 100644
--- a/misc/hassio.xml
+++ b/misc/hassio.xml
@@ -1 +1 @@
-5Vptc6M2EP41/ng3gHj9mPiSy820c5n6Q3sfsVBsNTJyhYid/voKkABZkOBY+KYtmYnR6pVn99ld1l6A5e74laX77a80Q2ThOdlxAb4sPC8OY/G/Erw2At9xG8GG4awR9QQr/DeSQkdKS5yhQhvIKSUc73UhpHmOINdkKWP0oA97okTfdZ9ukCFYwZSY0t9xxrdS6oZJ1/GA8GYrt469sOlYp/B5w2iZy/0WHniqr6Z7l6q15IMW2zSjh54I3C3AklHKm7vdcYlIBa2CrZl3P9LbnpuhnE+Z4DUTXlJSInXikIipt09UrCAOyF8lKOFfJVUdn4paZTdigNjtKD5ERw206DtIYKrenLJdSrrJ4m5TfX5fqX3E2Zqtmg4JS7urd9hijlb7FFbtg7A2MWjLd0S03Oo0mJAlJZTVowXYKIRQyAvO6DPq9Tj1Jc+/kutLvF4Q4+g4CqHbKkbYO6I7xNmrGKImJKCZIm09SKRuD53l+Arobc9oQjkulca6aZfuFCZupM6G9QcM/X3LcaW31WvB0e5CNGGG1vF6CE0QggRkrb7sAhhNBNCzAKBvAPiFwmfELkUOokCQ/trI+SZy3hBywAJyoYHcw9JArXaFqJpRUe9MLscQDXN5HQd+4NjB0A8DHcPQxDBwTAgDCxAmBl4oE3FINinjW7qheUruOumtjmgPPXTE/I9K/DkKZPOH6srFwZq+QDV/yBX+RJy/ygiclpwKUbfxL5Tu5RrNUavzvQ20eBxaMihHRTJ4p2yDeM9uTHUwRFKOX/TVLwFX5RK20fXeQDcB3im+deMRMSweALGfBbp/JdCj0Xxi3UX48xIMN6wSjNMEYlXuEXvBhXAJagOm+h7Sovj2fTTBaMXr0aSjMwP3fbdluKflMgybVEN3aFmA4sy347ZAoLstMJB1uPGA33JtRE3Xm4Nbbo9Yyou13NJ4VbuxeUnkqveOHouiK7EIzOO6NHh1dE/iQtc89VyFwIPfVK9YQgCJYBqGSnyPidpzqm5QnpmLCWFvqcFMfrm0qlgvvlZQUm8cvaxJrPLpRjy6wLByU9dxRSmKn6CtLFR3Rd5A/t56HS1/9224ovDKXHE/O3qQ/+zG8aWBfiKtPmjxwLR4d0Sn1i3enyVUSJ30srCJCPYcTk5zpHmb8xQ2Vl+AJXtp+WpPYdeKPa5ZUrjJMpoXhhqLbbqvbveMQlQU73sn3ZVN9lX34qr9fZMTCt07XhiBxANhEHtx7PhgpqRqyJN5bmB6ssSCI1O1nDmJ0rVOHdWlqYAkU59uc7zoXEAAOfWR4vq9Q5WqneE0Wq3Q0FJO6hdSz1ynobKxTm0U7dNMs5PYJCjk1KxYKX6WO9IMALcVOzAUyKdrRB5pgTmmuRiyppzTnRhAqo7btoitVVbrMna3xg3Bm2oup+fRvCvEnpZu5QYWiHxS0wEDNR0wkJBYqciaNJ5AUifSWOq/x1LX5OgUOk5Ity8PgO97LQshEng/L0SqvXsMPBwOpvcmBO+LWg2SiZDQMrs4Tl6FQInuz3xnIKeP5iovgLcLo9K4P5DEn8mRmTLEXqzt3hyaQ3qj0faDNPFNmjTmaz+S+icmc+pN7YVAMP6tjfNQrkcjIUzZ5fQL62uAfkH1Z4d+CThJJ4boN1TdsxLBopnY17f7yGaWOT9lP8i+YAb2TVZjYJDkK+bbuekxFp2QmwUomocevnppvQo94v9LcEpCnaOR5dgU/idjk/m9+G9oX71qUYbReBXl30s+Vf6dgXyi2f0WqlFG93szcPcP
\ No newline at end of file
+5VrLcqM4FP0aLzsFiOcycefRVTPVqfFippdYKLYmMvII4cd8/QiQDEKQ4Bicnmp7Yevqybk691zJnoH55vDI4u36d5ogMnOs5DADX2eOY1vAER+F5VhZ3DCoDCuGE9moNizwv0j1lNYcJyjTGnJKCcdb3QhpmiLINVvMGN3rzV4o0WfdxitkGBYwJqb1T5zwtbTaflRXPCG8WsupQ8evKpYxfF0xmqdyvpkDXspXVb2J1VjyQbN1nNB9wwTuZ2DOKOXVt81hjkiBrYKt6vfQU3taN0MpH9JB+mkXkxypFftEdL17oWIEsUB+lKD4/+RUVXzJSpfdigZitoP4EBUl0KJuL4EpalPKNjGpO4tvq+Lz+0LNI9ZWTVVVSFhOszr7NeZosY1hUd6L7SYarfmGiJJdrAYTMqeEsrK1ABv5EAp7xhl9RY0aq3zJ9S/k+B14SdMOMY4ODZPE7xHRDeLsKJqo2ghUXeRe9yLp2329c1wF9LqxaXzZLpabdXUaunaY+CJ91u0/YPjvW4oLvy2OGUebC9GECVqGyy40gQ8ikJz8NS6AwUAAnREAdA0Av1L4itilyEHkCdJfGznXRM7pQg6MgJxvIPc0N1ArQyEqehTUO5PLIUTdXF6GnutZ42Do+p6OoW9i6FkmhN4IEEYGXigROiSLlPE1XdE0Jve19U5HtIEeOmD+V2G+CTxZ/KGqUrGwqs5TxR9yhL8R50epwHHOqTDVE/9G6VaO0Qt1RnMG5fKlyvOYrRDXtknxYG+6gyESc7zTBfgScFUuMTa6zhvoRiLxaeFbFp4Rw+IBELsS6O5ngR705hPLWuHPSzBsv0gw2gnEIt8itsOZCAlqAqbqnuIs+/a9N8E4mZe9SUe9Dez3w5YRnuZz369SDT2gJR4KE3ecsAU8PWyBjqzDDjvilj2GatrOFNyyG8RSUezELY1XZRgbSqJMMIPfFqcCYYBEbA4MlfkBE7WKQVyz1WmkQbbgs8gGpolwmhd0J7Tkoy62A9xAzIe6EKWJOZgwNobqTPjn80sc64Sfpl0qHjSSKzHKl1vx6ALDIppdJ2LFKHyBYyWresRyOtL8U3DS0nx3jIjlX5kr9o2l5wI3dhhemg8MpFWDLilNkcaVN9NmjRHAZITal9dnhDuJ4kifNZK5kRAe7tC+awqYs92Jzx922Kdpk2veTHzAgRoIvd4832d9InK52zrx/rjrrqE1pqduk4SmmeGvbB1vi69bRiHKsvd1RhelwarzIF6lcleHAMFSy/EDEDnA90InDC0XTJRFd2mSY3umJkUjSJK6vJsypNWltuRcmtTJsNck2Sgn2/FClez6THF50JQuV2ei9rlJjVDRUnZyGjfnZ45TUdkYp9wUp6cZtk9Ck6CQU/OKUvEz35CqAbgrqIChQD5eIvJMM8wxTUWTJeWcbkQDUlTcnX610K7Sy98t6jFuCV4VfTk9j+b1zXv7rl5OMAKRW5d4oOMSD3SklqNcwZs0HkBSK9BY6r7HUtvk6BA6XkXzztTxQYqofkH8KZIZtZgGA/f7vRm9CcHbrHSDZCIkNE8u1smrECjS45lrdZzOgqnuk8DbN+Fyc3/gOHYmRybK5RtaW58Bq0U6vWo7jCauSRO1WydXUre1ZdrRdDwJBP0/01lP+bJXCWHMLqefX7466OcV73HoF4FWOtFFv67r3FEULJiIfc19H4yZZU5P2WHs867BvsFu9AySPGK+npoefeqE7MRDwTT0cNWh9Sr0CH8VcYp8naPBZdrk/xraZP4R4g+0LY5alGHUf4vy/yWfusifgHyiWP/5rXJG/Q9DcP8f
\ No newline at end of file
diff --git a/misc/security.png b/misc/security.png
deleted file mode 100644
index 8343b0e84..000000000
Binary files a/misc/security.png and /dev/null differ
diff --git a/misc/security.xml b/misc/security.xml
deleted file mode 100644
index 162e082f7..000000000
--- a/misc/security.xml
+++ /dev/null
@@ -1 +0,0 @@
-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
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 7b17c82c1..ac212a027 100644
--- a/setup.py
+++ b/setup.py
@@ -46,8 +46,6 @@ setup(
'colorlog',
'voluptuous',
'gitpython',
- 'pyotp',
- 'pyqrcode',
'pytz',
'pyudev'
]