diff --git a/homeassistant/components/camera/generic.py b/homeassistant/components/camera/generic.py index 911c14e7232..d1b5c7214fc 100644 --- a/homeassistant/components/camera/generic.py +++ b/homeassistant/components/camera/generic.py @@ -15,7 +15,7 @@ import voluptuous as vol from homeassistant.const import ( CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_AUTHENTICATION, - HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION) + HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION, CONF_VERIFY_SSL) from homeassistant.exceptions import TemplateError from homeassistant.components.camera import ( PLATFORM_SCHEMA, DEFAULT_CONTENT_TYPE, Camera) @@ -42,6 +42,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_CONTENT_TYPE, default=DEFAULT_CONTENT_TYPE): cv.string, vol.Optional(CONF_FRAMERATE, default=2): cv.positive_int, + vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, }) @@ -65,6 +66,7 @@ class GenericCamera(Camera): self._limit_refetch = device_info[CONF_LIMIT_REFETCH_TO_URL_CHANGE] self._frame_interval = 1 / device_info[CONF_FRAMERATE] self.content_type = device_info[CONF_CONTENT_TYPE] + self.verify_ssl = device_info[CONF_VERIFY_SSL] username = device_info.get(CONF_USERNAME) password = device_info.get(CONF_PASSWORD) @@ -108,7 +110,8 @@ class GenericCamera(Camera): def fetch(): """Read image from a URL.""" try: - response = requests.get(url, timeout=10, auth=self._auth) + response = requests.get(url, timeout=10, auth=self._auth, + verify=self.verify_ssl) return response.content except requests.exceptions.RequestException as error: _LOGGER.error("Error getting camera image: %s", error) @@ -119,7 +122,8 @@ class GenericCamera(Camera): # async else: try: - websession = async_get_clientsession(self.hass) + websession = async_get_clientsession( + self.hass, verify_ssl=self.verify_ssl) with async_timeout.timeout(10, loop=self.hass.loop): response = yield from websession.get( url, auth=self._auth) diff --git a/tests/components/camera/test_generic.py b/tests/components/camera/test_generic.py index 01edca1e996..b981fced320 100644 --- a/tests/components/camera/test_generic.py +++ b/tests/components/camera/test_generic.py @@ -1,5 +1,6 @@ """The tests for generic camera component.""" import asyncio + from unittest import mock from homeassistant.setup import async_setup_component @@ -32,6 +33,50 @@ def test_fetching_url(aioclient_mock, hass, aiohttp_client): assert aioclient_mock.call_count == 2 +@asyncio.coroutine +def test_fetching_without_verify_ssl(aioclient_mock, hass, aiohttp_client): + """Test that it fetches the given url when ssl verify is off.""" + aioclient_mock.get('https://example.com', text='hello world') + + yield from async_setup_component(hass, 'camera', { + 'camera': { + 'name': 'config_test', + 'platform': 'generic', + 'still_image_url': 'https://example.com', + 'username': 'user', + 'password': 'pass', + 'verify_ssl': 'false', + }}) + + client = yield from aiohttp_client(hass.http.app) + + resp = yield from client.get('/api/camera_proxy/camera.config_test') + + assert resp.status == 200 + + +@asyncio.coroutine +def test_fetching_url_with_verify_ssl(aioclient_mock, hass, aiohttp_client): + """Test that it fetches the given url when ssl verify is explicitly on.""" + aioclient_mock.get('https://example.com', text='hello world') + + yield from async_setup_component(hass, 'camera', { + 'camera': { + 'name': 'config_test', + 'platform': 'generic', + 'still_image_url': 'https://example.com', + 'username': 'user', + 'password': 'pass', + 'verify_ssl': 'true', + }}) + + client = yield from aiohttp_client(hass.http.app) + + resp = yield from client.get('/api/camera_proxy/camera.config_test') + + assert resp.status == 200 + + @asyncio.coroutine def test_limit_refetch(aioclient_mock, hass, aiohttp_client): """Test that it fetches the given url."""