Always print invalid configuration data (#21972)
* Always print invalide configuration data * Print offending data as yaml * Revert "Print offending data as yaml" This reverts commit 01721a21a9ff918ed2c8595151ebfe55eb2f7d36. * Do not print sensitive data * Print MQTT topic * Add line break * Review comments * review comments
This commit is contained in:
parent
4c4f0e38d4
commit
8d775caaac
2 changed files with 59 additions and 21 deletions
|
@ -210,6 +210,12 @@ def clear_discovery_hash(hass, discovery_hash):
|
||||||
del hass.data[ALREADY_DISCOVERED][discovery_hash]
|
del hass.data[ALREADY_DISCOVERED][discovery_hash]
|
||||||
|
|
||||||
|
|
||||||
|
class MQTTConfig(dict):
|
||||||
|
"""Dummy class to allow adding attributes."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
||||||
config_entry=None) -> bool:
|
config_entry=None) -> bool:
|
||||||
"""Initialize of MQTT Discovery."""
|
"""Initialize of MQTT Discovery."""
|
||||||
|
@ -236,7 +242,7 @@ async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
||||||
object_id, payload)
|
object_id, payload)
|
||||||
return
|
return
|
||||||
|
|
||||||
payload = dict(payload)
|
payload = MQTTConfig(payload)
|
||||||
|
|
||||||
for key in list(payload.keys()):
|
for key in list(payload.keys()):
|
||||||
abbreviated_key = key
|
abbreviated_key = key
|
||||||
|
@ -264,6 +270,10 @@ async def async_start(hass: HomeAssistantType, discovery_topic, hass_config,
|
||||||
discovery_hash = (component, discovery_id)
|
discovery_hash = (component, discovery_id)
|
||||||
|
|
||||||
if payload:
|
if payload:
|
||||||
|
# Attach MQTT topic to the payload, used for debug prints
|
||||||
|
setattr(payload, '__configuration_source__',
|
||||||
|
"MQTT (topic: '{}')".format(topic))
|
||||||
|
|
||||||
if CONF_PLATFORM in payload and 'schema' not in payload:
|
if CONF_PLATFORM in payload and 'schema' not in payload:
|
||||||
platform = payload[CONF_PLATFORM]
|
platform = payload[CONF_PLATFORM]
|
||||||
if (component in DEPRECATED_PLATFORM_TO_SCHEMA and
|
if (component in DEPRECATED_PLATFORM_TO_SCHEMA and
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""Helpers for config validation using voluptuous."""
|
"""Helpers for config validation using voluptuous."""
|
||||||
import inspect
|
import inspect
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -15,11 +16,11 @@ from pkg_resources import parse_version
|
||||||
|
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
CONF_ABOVE, CONF_ALIAS, CONF_BELOW, CONF_CONDITION, CONF_ENTITY_ID,
|
||||||
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
|
CONF_ENTITY_NAMESPACE, CONF_NAME, CONF_PLATFORM, CONF_SCAN_INTERVAL,
|
||||||
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, CONF_TIMEOUT, SUN_EVENT_SUNSET,
|
CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC, CONF_VALUE_TEMPLATE,
|
||||||
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC,
|
CONF_TIMEOUT, ENTITY_MATCH_ALL, SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET,
|
||||||
ENTITY_MATCH_ALL, CONF_ENTITY_NAMESPACE, __version__)
|
TEMP_CELSIUS, TEMP_FAHRENHEIT, WEEKDAYS, __version__)
|
||||||
from homeassistant.core import valid_entity_id, split_entity_id
|
from homeassistant.core import valid_entity_id, split_entity_id
|
||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
from homeassistant.helpers import template as template_helper
|
from homeassistant.helpers import template as template_helper
|
||||||
|
@ -677,26 +678,53 @@ class HASchema(vol.Schema):
|
||||||
self.extra = vol.PREVENT_EXTRA
|
self.extra = vol.PREVENT_EXTRA
|
||||||
|
|
||||||
# This is a legacy config, print warning
|
# This is a legacy config, print warning
|
||||||
extra_key_errs = [err for err in orig_err.errors
|
extra_key_errs = [err.path[-1] for err in orig_err.errors
|
||||||
if err.error_message == 'extra keys not allowed']
|
if err.error_message == 'extra keys not allowed']
|
||||||
if extra_key_errs:
|
|
||||||
msg = "Your configuration contains extra keys " \
|
if not extra_key_errs:
|
||||||
"that the platform does not support.\n" \
|
|
||||||
"Please remove "
|
|
||||||
submsg = ', '.join('[{}]'.format(err.path[-1]) for err in
|
|
||||||
extra_key_errs)
|
|
||||||
submsg += '. '
|
|
||||||
if hasattr(data, '__config_file__'):
|
|
||||||
submsg += " (See {}, line {}). ".format(
|
|
||||||
data.__config_file__, data.__line__)
|
|
||||||
msg += submsg
|
|
||||||
logging.getLogger(__name__).warning(msg)
|
|
||||||
INVALID_EXTRA_KEYS_FOUND.append(submsg)
|
|
||||||
else:
|
|
||||||
# This should not happen (all errors should be extra key
|
# This should not happen (all errors should be extra key
|
||||||
# errors). Let's raise the original error anyway.
|
# errors). Let's raise the original error anyway.
|
||||||
raise orig_err
|
raise orig_err
|
||||||
|
|
||||||
|
WHITELIST = [
|
||||||
|
re.compile(CONF_NAME),
|
||||||
|
re.compile(CONF_PLATFORM),
|
||||||
|
re.compile('.*_topic'),
|
||||||
|
]
|
||||||
|
|
||||||
|
msg = "Your configuration contains extra keys " \
|
||||||
|
"that the platform does not support.\n" \
|
||||||
|
"Please remove "
|
||||||
|
submsg = ', '.join('[{}]'.format(err) for err in
|
||||||
|
extra_key_errs)
|
||||||
|
submsg += '. '
|
||||||
|
|
||||||
|
# Add file+line information, if available
|
||||||
|
if hasattr(data, '__config_file__'):
|
||||||
|
submsg += " (See {}, line {}). ".format(
|
||||||
|
data.__config_file__, data.__line__)
|
||||||
|
|
||||||
|
# Add configuration source information, if available
|
||||||
|
if hasattr(data, '__configuration_source__'):
|
||||||
|
submsg += "\nConfiguration source: {}. ".format(
|
||||||
|
data.__configuration_source__)
|
||||||
|
redacted_data = {}
|
||||||
|
|
||||||
|
# Print configuration causing the error, but filter any potentially
|
||||||
|
# sensitive data
|
||||||
|
for k, v in data.items():
|
||||||
|
if (any(regex.match(k) for regex in WHITELIST) or
|
||||||
|
k in extra_key_errs):
|
||||||
|
redacted_data[k] = v
|
||||||
|
else:
|
||||||
|
redacted_data[k] = '<redacted>'
|
||||||
|
submsg += "\nOffending data: {}".format(
|
||||||
|
json.dumps(redacted_data))
|
||||||
|
|
||||||
|
msg += submsg
|
||||||
|
logging.getLogger(__name__).warning(msg)
|
||||||
|
INVALID_EXTRA_KEYS_FOUND.append(submsg)
|
||||||
|
|
||||||
# Return legacy validated config
|
# Return legacy validated config
|
||||||
return validated
|
return validated
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue