Accept login from approved ips without password (#3427)

pull/3440/head
Daniel Høyer Iversen 2016-09-18 19:20:19 +02:00 committed by Paulus Schoutsen
parent 2c43d6718b
commit 11c07440fe
3 changed files with 32 additions and 4 deletions

View File

@ -74,7 +74,8 @@ def setup(hass, yaml_config):
api_password=None,
ssl_certificate=None,
ssl_key=None,
cors_origins=[]
cors_origins=[],
approved_ips=[]
)
server.register_view(DescriptionXmlView(hass, config))

View File

@ -28,6 +28,7 @@ DOMAIN = 'http'
REQUIREMENTS = ('cherrypy==8.1.0', 'static3==0.7.0', 'Werkzeug==0.11.11')
CONF_API_PASSWORD = 'api_password'
CONF_APPROVED_IPS = 'approved_ips'
CONF_SERVER_HOST = 'server_host'
CONF_SERVER_PORT = 'server_port'
CONF_DEVELOPMENT = 'development'
@ -71,7 +72,8 @@ CONFIG_SCHEMA = vol.Schema({
vol.Optional(CONF_DEVELOPMENT): cv.string,
vol.Optional(CONF_SSL_CERTIFICATE): cv.isfile,
vol.Optional(CONF_SSL_KEY): cv.isfile,
vol.Optional(CONF_CORS_ORIGINS): cv.ensure_list
vol.Optional(CONF_CORS_ORIGINS): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_APPROVED_IPS): vol.All(cv.ensure_list, [cv.string])
}),
}, extra=vol.ALLOW_EXTRA)
@ -108,6 +110,7 @@ def setup(hass, config):
ssl_certificate = conf.get(CONF_SSL_CERTIFICATE)
ssl_key = conf.get(CONF_SSL_KEY)
cors_origins = conf.get(CONF_CORS_ORIGINS, [])
approved_ips = conf.get(CONF_APPROVED_IPS, [])
server = HomeAssistantWSGI(
hass,
@ -117,7 +120,8 @@ def setup(hass, config):
api_password=api_password,
ssl_certificate=ssl_certificate,
ssl_key=ssl_key,
cors_origins=cors_origins
cors_origins=cors_origins,
approved_ips=approved_ips
)
def start_wsgi_server(event):
@ -249,7 +253,8 @@ class HomeAssistantWSGI(object):
# pylint: disable=too-many-arguments
def __init__(self, hass, development, api_password, ssl_certificate,
ssl_key, server_host, server_port, cors_origins):
ssl_key, server_host, server_port, cors_origins,
approved_ips):
"""Initilalize the WSGI Home Assistant server."""
from werkzeug.wrappers import Response
@ -268,6 +273,7 @@ class HomeAssistantWSGI(object):
self.server_host = server_host
self.server_port = server_port
self.cors_origins = cors_origins
self.approved_ips = approved_ips
self.event_forwarder = None
self.server = None
@ -468,6 +474,9 @@ class HomeAssistantView(object):
if self.hass.wsgi.api_password is None:
authenticated = True
elif request.remote_addr in self.hass.wsgi.approved_ips:
authenticated = True
elif hmac.compare_digest(request.headers.get(HTTP_HEADER_HA_AUTH, ''),
self.hass.wsgi.api_password):
# A valid auth header has been set

View File

@ -72,6 +72,15 @@ class TestHttp:
assert req.status_code == 401
def test_access_denied_with_ip_no_in_approved_ips(self, caplog):
"""Test access deniend with ip not in approved ip."""
hass.wsgi.approved_ips = ['134.4.56.1']
req = requests.get(_url(const.URL_API),
params={'api_password': ''})
assert req.status_code == 401
def test_access_with_password_in_header(self, caplog):
"""Test access with password in URL."""
# Hide logging from requests package that we use to test logging
@ -112,6 +121,15 @@ class TestHttp:
# assert const.URL_API in logs
assert API_PASSWORD not in logs
def test_access_with_ip_in_approved_ips(self, caplog):
"""Test access with approved ip."""
hass.wsgi.approved_ips = ['127.0.0.1', '134.4.56.1']
req = requests.get(_url(const.URL_API),
params={'api_password': ''})
assert req.status_code == 200
def test_cors_allowed_with_password_in_url(self):
"""Test cross origin resource sharing with password in url."""
req = requests.get(_url(const.URL_API),