Remove path whitelisting for hassio (#7399)

* Remove path whitelisting for hassio

* Update frontend

* Lint
pull/7312/merge
Paulus Schoutsen 2017-05-02 00:27:50 -07:00 committed by GitHub
parent 8ea6c7319a
commit f17c1090e1
14 changed files with 19 additions and 302 deletions

View File

@ -3,20 +3,20 @@
FINGERPRINTS = {
"compatibility.js": "83d9c77748dafa9db49ae77d7f3d8fb0",
"core.js": "5d08475f03adb5969bd31855d5ca0cfd",
"frontend.html": "1533f44c55927e814294de757cd7eada",
"frontend.html": "094c2015c8291c767b8933428d92076f",
"mdi.html": "1cc8593d3684f7f6f3b3854403216f77",
"micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a",
"panels/ha-panel-config.html": "39f00f769faa63ee61f1fe6fc85d67f7",
"panels/ha-panel-config.html": "59d9eb28758b497a4d9b2428f978b9b1",
"panels/ha-panel-dev-event.html": "2db9c218065ef0f61d8d08db8093cad2",
"panels/ha-panel-dev-info.html": "61610e015a411cfc84edd2c4d489e71d",
"panels/ha-panel-dev-service.html": "415552027cb083badeff5f16080410ed",
"panels/ha-panel-dev-state.html": "d70314913b8923d750932367b1099750",
"panels/ha-panel-dev-template.html": "567fbf86735e1b891e40c2f4060fec9b",
"panels/ha-panel-hassio.html": "1d954cfe5f47c4be3cf4f6f5db9a83b2",
"panels/ha-panel-hassio.html": "0aa1523357326cb40e2242dce9b2c0d6",
"panels/ha-panel-history.html": "89062c48c76206cad1cec14ddbb1cbb1",
"panels/ha-panel-iframe.html": "d920f0aa3c903680f2f8795e2255daab",
"panels/ha-panel-logbook.html": "6dd6a16f52117318b202e60f98400163",
"panels/ha-panel-map.html": "31c592c239636f91e07c7ac232a5ebc4",
"panels/ha-panel-zwave.html": "a81f82b48439da80286798558f414a2e",
"panels/ha-panel-zwave.html": "84fb45638d2a69bac343246a687f647c",
"websocket_test.html": "575de64b431fe11c3785bf96d7813450"
}

File diff suppressed because one or more lines are too long

@ -1 +1 @@
Subproject commit 863ccb548616236faafa3b3393a1f51429bb8afd
Subproject commit 110f152e2371319ff4cf0b6fcc18b10e943cf08d

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,8 +11,7 @@ import re
import aiohttp
from aiohttp import web
from aiohttp.web_exceptions import (
HTTPBadGateway, HTTPNotFound, HTTPMethodNotAllowed)
from aiohttp.web_exceptions import HTTPBadGateway
from aiohttp.hdrs import CONTENT_TYPE
import async_timeout
@ -28,23 +27,6 @@ DEPENDENCIES = ['http']
TIMEOUT = 10
HASSIO_REST_COMMANDS = {
'host/shutdown': ['POST'],
'host/reboot': ['POST'],
'host/update': ['POST'],
'host/info': ['GET'],
'supervisor/info': ['GET'],
'supervisor/update': ['POST'],
'supervisor/options': ['POST'],
'supervisor/reload': ['POST'],
'supervisor/logs': ['GET'],
'homeassistant/info': ['GET'],
'homeassistant/update': ['POST'],
'homeassistant/logs': ['GET'],
'network/info': ['GET'],
'network/options': ['POST'],
}
ADDON_REST_COMMANDS = {
'install': ['POST'],
'uninstall': ['POST'],
@ -166,21 +148,6 @@ class HassIOView(HomeAssistantView):
@asyncio.coroutine
def _handle(self, request, path):
"""Route data to hassio."""
if path.startswith('addons/'):
parts = path.split('/')
if len(parts) != 3:
raise HTTPNotFound()
allowed_methods = ADDON_REST_COMMANDS.get(parts[-1])
else:
allowed_methods = HASSIO_REST_COMMANDS.get(path)
if allowed_methods is None:
raise HTTPNotFound()
if request.method not in allowed_methods:
raise HTTPMethodNotAllowed(request.method, allowed_methods)
client = yield from self.hassio.command_proxy(path, request)
data = yield from client.read()

View File

@ -48,32 +48,13 @@ def test_fail_setup_cannot_connect(hass):
@asyncio.coroutine
def test_invalid_path(hassio_client):
"""Test requesting invalid path."""
with patch.dict(ho.HASSIO_REST_COMMANDS, {}, clear=True):
resp = yield from hassio_client.post('/api/hassio/beer')
assert resp.status == 404
@asyncio.coroutine
def test_invalid_method(hassio_client):
"""Test requesting path with invalid method."""
with patch.dict(ho.HASSIO_REST_COMMANDS, {'beer': ['POST']}):
resp = yield from hassio_client.get('/api/hassio/beer')
assert resp.status == 405
@asyncio.coroutine
def test_forward_normal_path(hassio_client):
def test_forward_request(hassio_client):
"""Test fetching normal path."""
response = MagicMock()
response.read.return_value = mock_coro('data')
with patch.dict(ho.HASSIO_REST_COMMANDS, {'beer': ['POST']}), \
patch('homeassistant.components.hassio.HassIO.command_proxy',
Mock(return_value=mock_coro(response))), \
with patch('homeassistant.components.hassio.HassIO.command_proxy',
Mock(return_value=mock_coro(response))), \
patch('homeassistant.components.hassio._create_response') as mresp:
mresp.return_value = 'response'
resp = yield from hassio_client.post('/api/hassio/beer')
@ -89,14 +70,13 @@ def test_forward_normal_path(hassio_client):
@asyncio.coroutine
def test_forward_normal_log_path(hassio_client):
def test_forward_log_request(hassio_client):
"""Test fetching normal log path."""
response = MagicMock()
response.read.return_value = mock_coro('data')
with patch.dict(ho.HASSIO_REST_COMMANDS, {'beer/logs': ['GET']}), \
patch('homeassistant.components.hassio.HassIO.command_proxy',
Mock(return_value=mock_coro(response))), \
with patch('homeassistant.components.hassio.HassIO.command_proxy',
Mock(return_value=mock_coro(response))), \
patch('homeassistant.components.hassio.'
'_create_response_log') as mresp:
mresp.return_value = 'response'
@ -112,69 +92,6 @@ def test_forward_normal_log_path(hassio_client):
assert mresp.mock_calls[0][1] == (response, 'data')
@asyncio.coroutine
def test_forward_addon_path(hassio_client):
"""Test fetching addon path."""
response = MagicMock()
response.read.return_value = mock_coro('data')
with patch.dict(ho.ADDON_REST_COMMANDS, {'install': ['POST']}), \
patch('homeassistant.components.hassio.'
'HassIO.command_proxy') as proxy_command, \
patch('homeassistant.components.hassio._create_response') as mresp:
proxy_command.return_value = mock_coro(response)
mresp.return_value = 'response'
resp = yield from hassio_client.post('/api/hassio/addons/beer/install')
# Check we got right response
assert resp.status == 200
body = yield from resp.text()
assert body == 'response'
assert proxy_command.mock_calls[0][1][0] == 'addons/beer/install'
# Check we forwarded command
assert len(mresp.mock_calls) == 1
assert mresp.mock_calls[0][1] == (response, 'data')
@asyncio.coroutine
def test_forward_addon_log_path(hassio_client):
"""Test fetching addon log path."""
response = MagicMock()
response.read.return_value = mock_coro('data')
with patch.dict(ho.ADDON_REST_COMMANDS, {'logs': ['GET']}), \
patch('homeassistant.components.hassio.'
'HassIO.command_proxy') as proxy_command, \
patch('homeassistant.components.hassio.'
'_create_response_log') as mresp:
proxy_command.return_value = mock_coro(response)
mresp.return_value = 'response'
resp = yield from hassio_client.get('/api/hassio/addons/beer/logs')
# Check we got right response
assert resp.status == 200
body = yield from resp.text()
assert body == 'response'
assert proxy_command.mock_calls[0][1][0] == 'addons/beer/logs'
# Check we forwarded command
assert len(mresp.mock_calls) == 1
assert mresp.mock_calls[0][1] == (response, 'data')
@asyncio.coroutine
def test_bad_request_when_wrong_addon_url(hassio_client):
"""Test we cannot mess with addon url."""
resp = yield from hassio_client.get('/api/hassio/addons/../../info')
assert resp.status == 404
resp = yield from hassio_client.get('/api/hassio/addons/info')
assert resp.status == 404
@asyncio.coroutine
def test_bad_gateway_when_cannot_find_supervisor(hassio_client):
"""Test we get a bad gateway error if we can't find supervisor."""