Mobile App: Require encryption for registrations that support it (#21852)

## Description:

**Related issue (if applicable):** fixes #21758

## Checklist:
  - [x] The code change is tested and works locally.
  - [x] Local tests pass with `tox`. **Your PR cannot be merged unless tests pass**
  - [x] There is no commented out code in this PR.
This commit is contained in:
Robbie Trencheny 2019-03-13 15:22:43 -07:00 committed by Paulus Schoutsen
parent 9e6a7a6357
commit b336322e9e
3 changed files with 32 additions and 9 deletions

View File

@ -41,6 +41,7 @@ ATTR_WEBHOOK_ENCRYPTED = 'encrypted'
ATTR_WEBHOOK_ENCRYPTED_DATA = 'encrypted_data'
ATTR_WEBHOOK_TYPE = 'type'
ERR_ENCRYPTION_REQUIRED = 'encryption_required'
ERR_INVALID_COMPONENT = 'invalid_component'
ERR_RENDER_FAILURE = 'render_failure'
ERR_SAVE_FAILURE = 'save_failure'

View File

@ -20,15 +20,16 @@ from homeassistant.helpers.discovery import load_platform
from homeassistant.helpers.storage import Store
from homeassistant.helpers.typing import HomeAssistantType
from .const import (ATTR_APP_COMPONENT, DATA_DELETED_IDS,
ATTR_DEVICE_NAME, ATTR_EVENT_DATA, ATTR_EVENT_TYPE,
DATA_REGISTRATIONS, ATTR_TEMPLATE, ATTR_TEMPLATE_VARIABLES,
ATTR_WEBHOOK_DATA, ATTR_WEBHOOK_ENCRYPTED,
ATTR_WEBHOOK_ENCRYPTED_DATA, ATTR_WEBHOOK_TYPE,
CONF_SECRET, DOMAIN, ERR_RENDER_FAILURE,
WEBHOOK_PAYLOAD_SCHEMA, WEBHOOK_SCHEMAS,
WEBHOOK_TYPE_CALL_SERVICE, WEBHOOK_TYPE_FIRE_EVENT,
WEBHOOK_TYPE_RENDER_TEMPLATE, WEBHOOK_TYPE_UPDATE_LOCATION,
from .const import (ATTR_APP_COMPONENT, ATTR_DEVICE_NAME, ATTR_EVENT_DATA,
ATTR_EVENT_TYPE, ATTR_SUPPORTS_ENCRYPTION, ATTR_TEMPLATE,
ATTR_TEMPLATE_VARIABLES, ATTR_WEBHOOK_DATA,
ATTR_WEBHOOK_ENCRYPTED, ATTR_WEBHOOK_ENCRYPTED_DATA,
ATTR_WEBHOOK_TYPE, CONF_SECRET, DATA_DELETED_IDS,
DATA_REGISTRATIONS, DOMAIN, ERR_ENCRYPTION_REQUIRED,
ERR_RENDER_FAILURE, WEBHOOK_PAYLOAD_SCHEMA,
WEBHOOK_SCHEMAS, WEBHOOK_TYPE_CALL_SERVICE,
WEBHOOK_TYPE_FIRE_EVENT, WEBHOOK_TYPE_RENDER_TEMPLATE,
WEBHOOK_TYPE_UPDATE_LOCATION,
WEBHOOK_TYPE_UPDATE_REGISTRATION)
from .helpers import (_decrypt_payload, empty_okay_response, error_response,
@ -78,6 +79,12 @@ async def handle_webhook(store: Store, hass: HomeAssistantType,
_LOGGER.warning('Received invalid JSON from mobile_app')
return empty_okay_response(status=HTTP_BAD_REQUEST)
if (ATTR_WEBHOOK_ENCRYPTED not in req_data and
registration[ATTR_SUPPORTS_ENCRYPTION]):
_LOGGER.warning("Refusing to accept unencrypted webhook from %s",
registration[ATTR_DEVICE_NAME])
return error_response(ERR_ENCRYPTION_REQUIRED, "Encryption required")
try:
req_data = WEBHOOK_PAYLOAD_SCHEMA(req_data)
except vol.Invalid as ex:

View File

@ -149,3 +149,18 @@ async def test_webhook_handle_decryption(webhook_client): # noqa: F811
decrypted_data = decrypted_data.decode("utf-8")
assert json.loads(decrypted_data) == {'rendered': 'Hello world'}
async def test_webhook_requires_encryption(webhook_client): # noqa: F811
"""Test that encrypted registrations only accept encrypted data."""
resp = await webhook_client.post(
'/api/webhook/mobile_app_test',
json=RENDER_TEMPLATE
)
assert resp.status == 400
webhook_json = await resp.json()
assert 'error' in webhook_json
assert webhook_json['success'] is False
assert webhook_json['error']['code'] == 'encryption_required'