Blow up startup if init auth providers or modules failed (#16240)
* Blow up startup if init auth providers or modules failed * Delete core.entity_registry
This commit is contained in:
parent
9a786e449b
commit
257b8b9b80
8 changed files with 194 additions and 72 deletions
|
@ -24,7 +24,11 @@ async def auth_manager_from_config(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
provider_configs: List[Dict[str, Any]],
|
provider_configs: List[Dict[str, Any]],
|
||||||
module_configs: List[Dict[str, Any]]) -> 'AuthManager':
|
module_configs: List[Dict[str, Any]]) -> 'AuthManager':
|
||||||
"""Initialize an auth manager from config."""
|
"""Initialize an auth manager from config.
|
||||||
|
|
||||||
|
CORE_CONFIG_SCHEMA will make sure do duplicated auth providers or
|
||||||
|
mfa modules exist in configs.
|
||||||
|
"""
|
||||||
store = auth_store.AuthStore(hass)
|
store = auth_store.AuthStore(hass)
|
||||||
if provider_configs:
|
if provider_configs:
|
||||||
providers = await asyncio.gather(
|
providers = await asyncio.gather(
|
||||||
|
@ -35,17 +39,7 @@ async def auth_manager_from_config(
|
||||||
# So returned auth providers are in same order as config
|
# So returned auth providers are in same order as config
|
||||||
provider_hash = OrderedDict() # type: _ProviderDict
|
provider_hash = OrderedDict() # type: _ProviderDict
|
||||||
for provider in providers:
|
for provider in providers:
|
||||||
if provider is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
key = (provider.type, provider.id)
|
key = (provider.type, provider.id)
|
||||||
|
|
||||||
if key in provider_hash:
|
|
||||||
_LOGGER.error(
|
|
||||||
'Found duplicate provider: %s. Please add unique IDs if you '
|
|
||||||
'want to have the same provider twice.', key)
|
|
||||||
continue
|
|
||||||
|
|
||||||
provider_hash[key] = provider
|
provider_hash[key] = provider
|
||||||
|
|
||||||
if module_configs:
|
if module_configs:
|
||||||
|
@ -57,15 +51,6 @@ async def auth_manager_from_config(
|
||||||
# So returned auth modules are in same order as config
|
# So returned auth modules are in same order as config
|
||||||
module_hash = OrderedDict() # type: _MfaModuleDict
|
module_hash = OrderedDict() # type: _MfaModuleDict
|
||||||
for module in modules:
|
for module in modules:
|
||||||
if module is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if module.id in module_hash:
|
|
||||||
_LOGGER.error(
|
|
||||||
'Found duplicate multi-factor module: %s. Please add unique '
|
|
||||||
'IDs if you want to have the same module twice.', module.id)
|
|
||||||
continue
|
|
||||||
|
|
||||||
module_hash[module.id] = module
|
module_hash[module.id] = module
|
||||||
|
|
||||||
manager = AuthManager(hass, store, provider_hash, module_hash)
|
manager = AuthManager(hass, store, provider_hash, module_hash)
|
||||||
|
|
|
@ -11,6 +11,7 @@ from voluptuous.humanize import humanize_error
|
||||||
from homeassistant import requirements, data_entry_flow
|
from homeassistant import requirements, data_entry_flow
|
||||||
from homeassistant.const import CONF_ID, CONF_NAME, CONF_TYPE
|
from homeassistant.const import CONF_ID, CONF_NAME, CONF_TYPE
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.util.decorator import Registry
|
from homeassistant.util.decorator import Registry
|
||||||
|
|
||||||
MULTI_FACTOR_AUTH_MODULES = Registry()
|
MULTI_FACTOR_AUTH_MODULES = Registry()
|
||||||
|
@ -127,26 +128,23 @@ class SetupFlow(data_entry_flow.FlowHandler):
|
||||||
|
|
||||||
async def auth_mfa_module_from_config(
|
async def auth_mfa_module_from_config(
|
||||||
hass: HomeAssistant, config: Dict[str, Any]) \
|
hass: HomeAssistant, config: Dict[str, Any]) \
|
||||||
-> Optional[MultiFactorAuthModule]:
|
-> MultiFactorAuthModule:
|
||||||
"""Initialize an auth module from a config."""
|
"""Initialize an auth module from a config."""
|
||||||
module_name = config[CONF_TYPE]
|
module_name = config[CONF_TYPE]
|
||||||
module = await _load_mfa_module(hass, module_name)
|
module = await _load_mfa_module(hass, module_name)
|
||||||
|
|
||||||
if module is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = module.CONFIG_SCHEMA(config) # type: ignore
|
config = module.CONFIG_SCHEMA(config) # type: ignore
|
||||||
except vol.Invalid as err:
|
except vol.Invalid as err:
|
||||||
_LOGGER.error('Invalid configuration for multi-factor module %s: %s',
|
_LOGGER.error('Invalid configuration for multi-factor module %s: %s',
|
||||||
module_name, humanize_error(config, err))
|
module_name, humanize_error(config, err))
|
||||||
return None
|
raise
|
||||||
|
|
||||||
return MULTI_FACTOR_AUTH_MODULES[module_name](hass, config) # type: ignore
|
return MULTI_FACTOR_AUTH_MODULES[module_name](hass, config) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
async def _load_mfa_module(hass: HomeAssistant, module_name: str) \
|
async def _load_mfa_module(hass: HomeAssistant, module_name: str) \
|
||||||
-> Optional[types.ModuleType]:
|
-> types.ModuleType:
|
||||||
"""Load an mfa auth module."""
|
"""Load an mfa auth module."""
|
||||||
module_path = 'homeassistant.auth.mfa_modules.{}'.format(module_name)
|
module_path = 'homeassistant.auth.mfa_modules.{}'.format(module_name)
|
||||||
|
|
||||||
|
@ -154,7 +152,8 @@ async def _load_mfa_module(hass: HomeAssistant, module_name: str) \
|
||||||
module = importlib.import_module(module_path)
|
module = importlib.import_module(module_path)
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
_LOGGER.error('Unable to load mfa module %s: %s', module_name, err)
|
_LOGGER.error('Unable to load mfa module %s: %s', module_name, err)
|
||||||
return None
|
raise HomeAssistantError('Unable to load mfa module {}: {}'.format(
|
||||||
|
module_name, err))
|
||||||
|
|
||||||
if hass.config.skip_pip or not hasattr(module, 'REQUIREMENTS'):
|
if hass.config.skip_pip or not hasattr(module, 'REQUIREMENTS'):
|
||||||
return module
|
return module
|
||||||
|
@ -170,7 +169,9 @@ async def _load_mfa_module(hass: HomeAssistant, module_name: str) \
|
||||||
hass, module_path, module.REQUIREMENTS) # type: ignore
|
hass, module_path, module.REQUIREMENTS) # type: ignore
|
||||||
|
|
||||||
if not req_success:
|
if not req_success:
|
||||||
return None
|
raise HomeAssistantError(
|
||||||
|
'Unable to process requirements of mfa module {}'.format(
|
||||||
|
module_name))
|
||||||
|
|
||||||
processed.add(module_name)
|
processed.add(module_name)
|
||||||
return module
|
return module
|
||||||
|
|
|
@ -10,6 +10,7 @@ from voluptuous.humanize import humanize_error
|
||||||
from homeassistant import data_entry_flow, requirements
|
from homeassistant import data_entry_flow, requirements
|
||||||
from homeassistant.core import callback, HomeAssistant
|
from homeassistant.core import callback, HomeAssistant
|
||||||
from homeassistant.const import CONF_ID, CONF_NAME, CONF_TYPE
|
from homeassistant.const import CONF_ID, CONF_NAME, CONF_TYPE
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
from homeassistant.util.decorator import Registry
|
from homeassistant.util.decorator import Registry
|
||||||
|
|
||||||
|
@ -110,33 +111,31 @@ class AuthProvider:
|
||||||
|
|
||||||
async def auth_provider_from_config(
|
async def auth_provider_from_config(
|
||||||
hass: HomeAssistant, store: AuthStore,
|
hass: HomeAssistant, store: AuthStore,
|
||||||
config: Dict[str, Any]) -> Optional[AuthProvider]:
|
config: Dict[str, Any]) -> AuthProvider:
|
||||||
"""Initialize an auth provider from a config."""
|
"""Initialize an auth provider from a config."""
|
||||||
provider_name = config[CONF_TYPE]
|
provider_name = config[CONF_TYPE]
|
||||||
module = await load_auth_provider_module(hass, provider_name)
|
module = await load_auth_provider_module(hass, provider_name)
|
||||||
|
|
||||||
if module is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = module.CONFIG_SCHEMA(config) # type: ignore
|
config = module.CONFIG_SCHEMA(config) # type: ignore
|
||||||
except vol.Invalid as err:
|
except vol.Invalid as err:
|
||||||
_LOGGER.error('Invalid configuration for auth provider %s: %s',
|
_LOGGER.error('Invalid configuration for auth provider %s: %s',
|
||||||
provider_name, humanize_error(config, err))
|
provider_name, humanize_error(config, err))
|
||||||
return None
|
raise
|
||||||
|
|
||||||
return AUTH_PROVIDERS[provider_name](hass, store, config) # type: ignore
|
return AUTH_PROVIDERS[provider_name](hass, store, config) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
async def load_auth_provider_module(
|
async def load_auth_provider_module(
|
||||||
hass: HomeAssistant, provider: str) -> Optional[types.ModuleType]:
|
hass: HomeAssistant, provider: str) -> types.ModuleType:
|
||||||
"""Load an auth provider."""
|
"""Load an auth provider."""
|
||||||
try:
|
try:
|
||||||
module = importlib.import_module(
|
module = importlib.import_module(
|
||||||
'homeassistant.auth.providers.{}'.format(provider))
|
'homeassistant.auth.providers.{}'.format(provider))
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
_LOGGER.error('Unable to load auth provider %s: %s', provider, err)
|
_LOGGER.error('Unable to load auth provider %s: %s', provider, err)
|
||||||
return None
|
raise HomeAssistantError('Unable to load auth provider {}: {}'.format(
|
||||||
|
provider, err))
|
||||||
|
|
||||||
if hass.config.skip_pip or not hasattr(module, 'REQUIREMENTS'):
|
if hass.config.skip_pip or not hasattr(module, 'REQUIREMENTS'):
|
||||||
return module
|
return module
|
||||||
|
@ -154,7 +153,9 @@ async def load_auth_provider_module(
|
||||||
hass, 'auth provider {}'.format(provider), reqs)
|
hass, 'auth provider {}'.format(provider), reqs)
|
||||||
|
|
||||||
if not req_success:
|
if not req_success:
|
||||||
return None
|
raise HomeAssistantError(
|
||||||
|
'Unable to process requirements of auth provider {}'.format(
|
||||||
|
provider))
|
||||||
|
|
||||||
processed.add(provider)
|
processed.add(provider)
|
||||||
return module
|
return module
|
||||||
|
|
|
@ -61,7 +61,6 @@ def from_config_dict(config: Dict[str, Any],
|
||||||
config, hass, config_dir, enable_log, verbose, skip_pip,
|
config, hass, config_dir, enable_log, verbose, skip_pip,
|
||||||
log_rotate_days, log_file, log_no_color)
|
log_rotate_days, log_file, log_no_color)
|
||||||
)
|
)
|
||||||
|
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,8 +93,13 @@ async def async_from_config_dict(config: Dict[str, Any],
|
||||||
try:
|
try:
|
||||||
await conf_util.async_process_ha_core_config(
|
await conf_util.async_process_ha_core_config(
|
||||||
hass, core_config, has_api_password, has_trusted_networks)
|
hass, core_config, has_api_password, has_trusted_networks)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as config_err:
|
||||||
conf_util.async_log_exception(ex, 'homeassistant', core_config, hass)
|
conf_util.async_log_exception(
|
||||||
|
config_err, 'homeassistant', core_config, hass)
|
||||||
|
return None
|
||||||
|
except HomeAssistantError:
|
||||||
|
_LOGGER.error("Home Assistant core failed to initialize. "
|
||||||
|
"Further initialization aborted")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
await hass.async_add_executor_job(
|
await hass.async_add_executor_job(
|
||||||
|
@ -130,7 +134,7 @@ async def async_from_config_dict(config: Dict[str, Any],
|
||||||
res = await core_components.async_setup(hass, config)
|
res = await core_components.async_setup(hass, config)
|
||||||
if not res:
|
if not res:
|
||||||
_LOGGER.error("Home Assistant core failed to initialize. "
|
_LOGGER.error("Home Assistant core failed to initialize. "
|
||||||
"further initialization aborted")
|
"Further initialization aborted")
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
await persistent_notification.async_setup(hass, config)
|
await persistent_notification.async_setup(hass, config)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import re
|
||||||
import shutil
|
import shutil
|
||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
from typing import ( # noqa: F401
|
from typing import ( # noqa: F401
|
||||||
Any, Tuple, Optional, Dict, List, Union, Callable)
|
Any, Tuple, Optional, Dict, List, Union, Callable, Sequence, Set)
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from voluptuous.humanize import humanize_error
|
from voluptuous.humanize import humanize_error
|
||||||
|
@ -23,7 +23,7 @@ from homeassistant.const import (
|
||||||
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
|
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
|
||||||
__version__, CONF_CUSTOMIZE, CONF_CUSTOMIZE_DOMAIN, CONF_CUSTOMIZE_GLOB,
|
__version__, CONF_CUSTOMIZE, CONF_CUSTOMIZE_DOMAIN, CONF_CUSTOMIZE_GLOB,
|
||||||
CONF_WHITELIST_EXTERNAL_DIRS, CONF_AUTH_PROVIDERS, CONF_AUTH_MFA_MODULES,
|
CONF_WHITELIST_EXTERNAL_DIRS, CONF_AUTH_PROVIDERS, CONF_AUTH_MFA_MODULES,
|
||||||
CONF_TYPE)
|
CONF_TYPE, CONF_ID)
|
||||||
from homeassistant.core import callback, DOMAIN as CONF_CORE, HomeAssistant
|
from homeassistant.core import callback, DOMAIN as CONF_CORE, HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.loader import get_component, get_platform
|
from homeassistant.loader import get_component, get_platform
|
||||||
|
@ -128,6 +128,48 @@ some_password: welcome
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _no_duplicate_auth_provider(configs: Sequence[Dict[str, Any]]) \
|
||||||
|
-> Sequence[Dict[str, Any]]:
|
||||||
|
"""No duplicate auth provider config allowed in a list.
|
||||||
|
|
||||||
|
Each type of auth provider can only have one config without optional id.
|
||||||
|
Unique id is required if same type of auth provider used multiple times.
|
||||||
|
"""
|
||||||
|
config_keys = set() # type: Set[Tuple[str, Optional[str]]]
|
||||||
|
for config in configs:
|
||||||
|
key = (config[CONF_TYPE], config.get(CONF_ID))
|
||||||
|
if key in config_keys:
|
||||||
|
raise vol.Invalid(
|
||||||
|
'Duplicate auth provider {} found. Please add unique IDs if '
|
||||||
|
'you want to have the same auth provider twice'.format(
|
||||||
|
config[CONF_TYPE]
|
||||||
|
))
|
||||||
|
config_keys.add(key)
|
||||||
|
return configs
|
||||||
|
|
||||||
|
|
||||||
|
def _no_duplicate_auth_mfa_module(configs: Sequence[Dict[str, Any]]) \
|
||||||
|
-> Sequence[Dict[str, Any]]:
|
||||||
|
"""No duplicate auth mfa module item allowed in a list.
|
||||||
|
|
||||||
|
Each type of mfa module can only have one config without optional id.
|
||||||
|
A global unique id is required if same type of mfa module used multiple
|
||||||
|
times.
|
||||||
|
Note: this is different than auth provider
|
||||||
|
"""
|
||||||
|
config_keys = set() # type: Set[str]
|
||||||
|
for config in configs:
|
||||||
|
key = config.get(CONF_ID, config[CONF_TYPE])
|
||||||
|
if key in config_keys:
|
||||||
|
raise vol.Invalid(
|
||||||
|
'Duplicate mfa module {} found. Please add unique IDs if '
|
||||||
|
'you want to have the same mfa module twice'.format(
|
||||||
|
config[CONF_TYPE]
|
||||||
|
))
|
||||||
|
config_keys.add(key)
|
||||||
|
return configs
|
||||||
|
|
||||||
|
|
||||||
PACKAGES_CONFIG_SCHEMA = vol.Schema({
|
PACKAGES_CONFIG_SCHEMA = vol.Schema({
|
||||||
cv.slug: vol.Schema( # Package names are slugs
|
cv.slug: vol.Schema( # Package names are slugs
|
||||||
{cv.slug: vol.Any(dict, list, None)}) # Only slugs for component names
|
{cv.slug: vol.Any(dict, list, None)}) # Only slugs for component names
|
||||||
|
@ -166,10 +208,16 @@ CORE_CONFIG_SCHEMA = CUSTOMIZE_CONFIG_SCHEMA.extend({
|
||||||
CONF_TYPE: vol.NotIn(['insecure_example'],
|
CONF_TYPE: vol.NotIn(['insecure_example'],
|
||||||
'The insecure_example auth provider'
|
'The insecure_example auth provider'
|
||||||
' is for testing only.')
|
' is for testing only.')
|
||||||
})]),
|
})],
|
||||||
|
_no_duplicate_auth_provider),
|
||||||
vol.Optional(CONF_AUTH_MFA_MODULES):
|
vol.Optional(CONF_AUTH_MFA_MODULES):
|
||||||
vol.All(cv.ensure_list,
|
vol.All(cv.ensure_list,
|
||||||
[auth_mfa_modules.MULTI_FACTOR_AUTH_MODULE_SCHEMA]),
|
[auth_mfa_modules.MULTI_FACTOR_AUTH_MODULE_SCHEMA.extend({
|
||||||
|
CONF_TYPE: vol.NotIn(['insecure_example'],
|
||||||
|
'The insecure_example mfa module'
|
||||||
|
' is for testing only.')
|
||||||
|
})],
|
||||||
|
_no_duplicate_auth_mfa_module),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ from unittest.mock import Mock
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import pytest
|
import pytest
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import data_entry_flow
|
from homeassistant import data_entry_flow
|
||||||
from homeassistant.auth import auth_manager_from_config, auth_store
|
from homeassistant.auth import auth_manager_from_config, auth_store
|
||||||
|
@ -111,11 +112,11 @@ async def test_saving_loading(data, hass):
|
||||||
async def test_not_allow_set_id():
|
async def test_not_allow_set_id():
|
||||||
"""Test we are not allowed to set an ID in config."""
|
"""Test we are not allowed to set an ID in config."""
|
||||||
hass = Mock()
|
hass = Mock()
|
||||||
provider = await auth_provider_from_config(hass, None, {
|
with pytest.raises(vol.Invalid):
|
||||||
'type': 'homeassistant',
|
await auth_provider_from_config(hass, None, {
|
||||||
'id': 'invalid',
|
'type': 'homeassistant',
|
||||||
})
|
'id': 'invalid',
|
||||||
assert provider is None
|
})
|
||||||
|
|
||||||
|
|
||||||
async def test_new_users_populate_values(hass, data):
|
async def test_new_users_populate_values(hass, data):
|
||||||
|
|
|
@ -3,6 +3,7 @@ from datetime import timedelta
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import auth, data_entry_flow
|
from homeassistant import auth, data_entry_flow
|
||||||
from homeassistant.auth import (
|
from homeassistant.auth import (
|
||||||
|
@ -21,33 +22,36 @@ def mock_hass(loop):
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
|
|
||||||
async def test_auth_manager_from_config_validates_config_and_id(mock_hass):
|
async def test_auth_manager_from_config_validates_config(mock_hass):
|
||||||
"""Test get auth providers."""
|
"""Test get auth providers."""
|
||||||
|
with pytest.raises(vol.Invalid):
|
||||||
|
manager = await auth.auth_manager_from_config(mock_hass, [{
|
||||||
|
'name': 'Test Name',
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'users': [],
|
||||||
|
}, {
|
||||||
|
'name': 'Invalid config because no users',
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'id': 'invalid_config',
|
||||||
|
}], [])
|
||||||
|
|
||||||
manager = await auth.auth_manager_from_config(mock_hass, [{
|
manager = await auth.auth_manager_from_config(mock_hass, [{
|
||||||
'name': 'Test Name',
|
'name': 'Test Name',
|
||||||
'type': 'insecure_example',
|
'type': 'insecure_example',
|
||||||
'users': [],
|
'users': [],
|
||||||
}, {
|
|
||||||
'name': 'Invalid config because no users',
|
|
||||||
'type': 'insecure_example',
|
|
||||||
'id': 'invalid_config',
|
|
||||||
}, {
|
}, {
|
||||||
'name': 'Test Name 2',
|
'name': 'Test Name 2',
|
||||||
'type': 'insecure_example',
|
'type': 'insecure_example',
|
||||||
'id': 'another',
|
'id': 'another',
|
||||||
'users': [],
|
'users': [],
|
||||||
}, {
|
|
||||||
'name': 'Wrong because duplicate ID',
|
|
||||||
'type': 'insecure_example',
|
|
||||||
'id': 'another',
|
|
||||||
'users': [],
|
|
||||||
}], [])
|
}], [])
|
||||||
|
|
||||||
providers = [{
|
providers = [{
|
||||||
'name': provider.name,
|
'name': provider.name,
|
||||||
'id': provider.id,
|
'id': provider.id,
|
||||||
'type': provider.type,
|
'type': provider.type,
|
||||||
} for provider in manager.auth_providers]
|
} for provider in manager.auth_providers]
|
||||||
|
|
||||||
assert providers == [{
|
assert providers == [{
|
||||||
'name': 'Test Name',
|
'name': 'Test Name',
|
||||||
'type': 'insecure_example',
|
'type': 'insecure_example',
|
||||||
|
@ -61,6 +65,26 @@ async def test_auth_manager_from_config_validates_config_and_id(mock_hass):
|
||||||
|
|
||||||
async def test_auth_manager_from_config_auth_modules(mock_hass):
|
async def test_auth_manager_from_config_auth_modules(mock_hass):
|
||||||
"""Test get auth modules."""
|
"""Test get auth modules."""
|
||||||
|
with pytest.raises(vol.Invalid):
|
||||||
|
manager = await auth.auth_manager_from_config(mock_hass, [{
|
||||||
|
'name': 'Test Name',
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'users': [],
|
||||||
|
}, {
|
||||||
|
'name': 'Test Name 2',
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'id': 'another',
|
||||||
|
'users': [],
|
||||||
|
}], [{
|
||||||
|
'name': 'Module 1',
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'data': [],
|
||||||
|
}, {
|
||||||
|
'name': 'Invalid config because no data',
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'id': 'another',
|
||||||
|
}])
|
||||||
|
|
||||||
manager = await auth.auth_manager_from_config(mock_hass, [{
|
manager = await auth.auth_manager_from_config(mock_hass, [{
|
||||||
'name': 'Test Name',
|
'name': 'Test Name',
|
||||||
'type': 'insecure_example',
|
'type': 'insecure_example',
|
||||||
|
@ -79,13 +103,7 @@ async def test_auth_manager_from_config_auth_modules(mock_hass):
|
||||||
'type': 'insecure_example',
|
'type': 'insecure_example',
|
||||||
'id': 'another',
|
'id': 'another',
|
||||||
'data': [],
|
'data': [],
|
||||||
}, {
|
|
||||||
'name': 'Duplicate ID',
|
|
||||||
'type': 'insecure_example',
|
|
||||||
'id': 'another',
|
|
||||||
'data': [],
|
|
||||||
}])
|
}])
|
||||||
|
|
||||||
providers = [{
|
providers = [{
|
||||||
'name': provider.name,
|
'name': provider.name,
|
||||||
'type': provider.type,
|
'type': provider.type,
|
||||||
|
|
|
@ -895,9 +895,73 @@ async def test_disallowed_auth_provider_config(hass):
|
||||||
'name': 'Huis',
|
'name': 'Huis',
|
||||||
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
||||||
'time_zone': 'GMT',
|
'time_zone': 'GMT',
|
||||||
CONF_AUTH_PROVIDERS: [
|
CONF_AUTH_PROVIDERS: [{
|
||||||
{'type': 'insecure_example'},
|
'type': 'insecure_example',
|
||||||
]
|
'users': [{
|
||||||
|
'username': 'test-user',
|
||||||
|
'password': 'test-pass',
|
||||||
|
'name': 'Test Name'
|
||||||
|
}],
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
with pytest.raises(Invalid):
|
||||||
|
await config_util.async_process_ha_core_config(hass, core_config)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_disallowed_duplicated_auth_provider_config(hass):
|
||||||
|
"""Test loading insecure example auth provider is disallowed."""
|
||||||
|
core_config = {
|
||||||
|
'latitude': 60,
|
||||||
|
'longitude': 50,
|
||||||
|
'elevation': 25,
|
||||||
|
'name': 'Huis',
|
||||||
|
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
||||||
|
'time_zone': 'GMT',
|
||||||
|
CONF_AUTH_PROVIDERS: [{
|
||||||
|
'type': 'homeassistant',
|
||||||
|
}, {
|
||||||
|
'type': 'homeassistant',
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
with pytest.raises(Invalid):
|
||||||
|
await config_util.async_process_ha_core_config(hass, core_config)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_disallowed_auth_mfa_module_config(hass):
|
||||||
|
"""Test loading insecure example auth mfa module is disallowed."""
|
||||||
|
core_config = {
|
||||||
|
'latitude': 60,
|
||||||
|
'longitude': 50,
|
||||||
|
'elevation': 25,
|
||||||
|
'name': 'Huis',
|
||||||
|
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
||||||
|
'time_zone': 'GMT',
|
||||||
|
CONF_AUTH_MFA_MODULES: [{
|
||||||
|
'type': 'insecure_example',
|
||||||
|
'data': [{
|
||||||
|
'user_id': 'mock-user',
|
||||||
|
'pin': 'test-pin'
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
with pytest.raises(Invalid):
|
||||||
|
await config_util.async_process_ha_core_config(hass, core_config)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_disallowed_duplicated_auth_mfa_module_config(hass):
|
||||||
|
"""Test loading insecure example auth mfa module is disallowed."""
|
||||||
|
core_config = {
|
||||||
|
'latitude': 60,
|
||||||
|
'longitude': 50,
|
||||||
|
'elevation': 25,
|
||||||
|
'name': 'Huis',
|
||||||
|
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
||||||
|
'time_zone': 'GMT',
|
||||||
|
CONF_AUTH_MFA_MODULES: [{
|
||||||
|
'type': 'totp',
|
||||||
|
}, {
|
||||||
|
'type': 'totp',
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
with pytest.raises(Invalid):
|
with pytest.raises(Invalid):
|
||||||
await config_util.async_process_ha_core_config(hass, core_config)
|
await config_util.async_process_ha_core_config(hass, core_config)
|
||||||
|
|
Loading…
Add table
Reference in a new issue