diff --git a/homeassistant/auth/providers/trusted_networks.py b/homeassistant/auth/providers/trusted_networks.py index bc995368fec..0cf79c3cc95 100644 --- a/homeassistant/auth/providers/trusted_networks.py +++ b/homeassistant/auth/providers/trusted_networks.py @@ -190,7 +190,7 @@ class TrustedNetworksLoginFlow(LoginFlow): ).async_validate_access(self._ip_address) except InvalidAuthError: - return self.async_abort(reason="not_whitelisted") + return self.async_abort(reason="not_allowed") if user_input is not None: return await self.async_finish(user_input) diff --git a/homeassistant/components/file/sensor.py b/homeassistant/components/file/sensor.py index 3f6d69325f0..e928541a724 100644 --- a/homeassistant/components/file/sensor.py +++ b/homeassistant/components/file/sensor.py @@ -40,7 +40,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= if hass.config.is_allowed_path(file_path): async_add_entities([FileSensor(name, file_path, unit, value_template)], True) else: - _LOGGER.error("'%s' is not a whitelisted directory", file_path) + _LOGGER.error("'%s' is not an allowed directory", file_path) class FileSensor(Entity): diff --git a/homeassistant/components/logi_circle/camera.py b/homeassistant/components/logi_circle/camera.py index ec8f1595168..20bc829d75d 100644 --- a/homeassistant/components/logi_circle/camera.py +++ b/homeassistant/components/logi_circle/camera.py @@ -172,7 +172,7 @@ class LogiCam(Camera): filename.hass = self.hass stream_file = filename.async_render(variables={ATTR_ENTITY_ID: self.entity_id}) - # Respect configured path whitelist. + # Respect configured allowed paths. if not self.hass.config.is_allowed_path(stream_file): _LOGGER.error("Can't write %s, no access to path!", stream_file) return @@ -191,7 +191,7 @@ class LogiCam(Camera): variables={ATTR_ENTITY_ID: self.entity_id} ) - # Respect configured path whitelist. + # Respect configured allowed paths. if not self.hass.config.is_allowed_path(snapshot_file): _LOGGER.error("Can't write %s, no access to path!", snapshot_file) return diff --git a/homeassistant/components/watson_iot/__init__.py b/homeassistant/components/watson_iot/__init__.py index b0500806b84..ecb546f4a8c 100644 --- a/homeassistant/components/watson_iot/__init__.py +++ b/homeassistant/components/watson_iot/__init__.py @@ -74,10 +74,10 @@ def setup(hass, config): include = conf[CONF_INCLUDE] exclude = conf[CONF_EXCLUDE] - whitelist_e = set(include[CONF_ENTITIES]) - whitelist_d = set(include[CONF_DOMAINS]) - blacklist_e = set(exclude[CONF_ENTITIES]) - blacklist_d = set(exclude[CONF_DOMAINS]) + include_e = set(include[CONF_ENTITIES]) + include_d = set(include[CONF_DOMAINS]) + exclude_e = set(exclude[CONF_ENTITIES]) + exclude_d = set(exclude[CONF_DOMAINS]) client_args = { "org": conf[CONF_ORG], @@ -94,13 +94,13 @@ def setup(hass, config): if ( state is None or state.state in (STATE_UNKNOWN, "", STATE_UNAVAILABLE) - or state.entity_id in blacklist_e - or state.domain in blacklist_d + or state.entity_id in exclude_e + or state.domain in exclude_d ): return - if (whitelist_e and state.entity_id not in whitelist_e) or ( - whitelist_d and state.domain not in whitelist_d + if (include_e and state.entity_id not in include_e) or ( + include_d and state.domain not in include_d ): return diff --git a/homeassistant/components/xmpp/notify.py b/homeassistant/components/xmpp/notify.py index 7388c11f70f..78dc3c43032 100644 --- a/homeassistant/components/xmpp/notify.py +++ b/homeassistant/components/xmpp/notify.py @@ -301,7 +301,7 @@ async def async_send_message( _LOGGER.info("Uploading file from path, %s", path) if not hass.config.is_allowed_path(path): - raise PermissionError("Could not access file. Not in whitelist") + raise PermissionError("Could not access file. Path not allowed") with open(path, "rb") as upfile: _LOGGER.debug("Reading file %s", path) diff --git a/homeassistant/config.py b/homeassistant/config.py index 894d0bb5379..2ffa69b4ff2 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -20,6 +20,7 @@ from homeassistant.const import ( ATTR_ASSUMED_STATE, ATTR_FRIENDLY_NAME, ATTR_HIDDEN, + CONF_ALLOWLIST_EXTERNAL_DIRS, CONF_ALLOWLIST_EXTERNAL_URLS, CONF_AUTH_MFA_MODULES, CONF_AUTH_PROVIDERS, @@ -39,7 +40,7 @@ from homeassistant.const import ( CONF_TYPE, CONF_UNIT_SYSTEM, CONF_UNIT_SYSTEM_IMPERIAL, - CONF_WHITELIST_EXTERNAL_DIRS, + LEGACY_CONF_WHITELIST_EXTERNAL_DIRS, TEMP_CELSIUS, __version__, ) @@ -183,7 +184,10 @@ CORE_CONFIG_SCHEMA = CUSTOMIZE_CONFIG_SCHEMA.extend( CONF_TIME_ZONE: cv.time_zone, vol.Optional(CONF_INTERNAL_URL): cv.url, vol.Optional(CONF_EXTERNAL_URL): cv.url, - vol.Optional(CONF_WHITELIST_EXTERNAL_DIRS): vol.All( + vol.Optional(CONF_ALLOWLIST_EXTERNAL_DIRS): vol.All( + cv.ensure_list, [vol.IsDir()] # pylint: disable=no-value-for-parameter + ), + vol.Optional(LEGACY_CONF_WHITELIST_EXTERNAL_DIRS): vol.All( cv.ensure_list, [vol.IsDir()] # pylint: disable=no-value-for-parameter ), vol.Optional(CONF_ALLOWLIST_EXTERNAL_URLS): vol.All(cv.ensure_list, [cv.url]), @@ -500,9 +504,19 @@ async def async_process_ha_core_config(hass: HomeAssistant, config: Dict) -> Non hac.set_time_zone(config[CONF_TIME_ZONE]) # Init whitelist external dir - hac.whitelist_external_dirs = {hass.config.path("www")} - if CONF_WHITELIST_EXTERNAL_DIRS in config: - hac.whitelist_external_dirs.update(set(config[CONF_WHITELIST_EXTERNAL_DIRS])) + hac.allowlist_external_dirs = {hass.config.path("www")} + if CONF_ALLOWLIST_EXTERNAL_DIRS in config: + hac.allowlist_external_dirs.update(set(config[CONF_ALLOWLIST_EXTERNAL_DIRS])) + + elif LEGACY_CONF_WHITELIST_EXTERNAL_DIRS in config: + _LOGGER.warning( + "Key %s has been replaced with %s. Please update your config", + CONF_ALLOWLIST_EXTERNAL_DIRS, + LEGACY_CONF_WHITELIST_EXTERNAL_DIRS, + ) + hac.allowlist_external_dirs.update( + set(config[LEGACY_CONF_WHITELIST_EXTERNAL_DIRS]) + ) # Init whitelist external URL list – make sure to add / to every URL that doesn't # already have it so that we can properly test "path ownership" diff --git a/homeassistant/const.py b/homeassistant/const.py index 0d19dc268c8..f3ed345682e 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -44,7 +44,6 @@ CONF_BASE = "base" CONF_BEFORE = "before" CONF_BELOW = "below" CONF_BINARY_SENSORS = "binary_sensors" -CONF_BLACKLIST = "blacklist" CONF_BRIGHTNESS = "brightness" CONF_BROADCAST_ADDRESS = "broadcast_address" CONF_BROADCAST_PORT = "broadcast_port" @@ -181,7 +180,8 @@ CONF_WEBHOOK_ID = "webhook_id" CONF_WEEKDAY = "weekday" CONF_WHILE = "while" CONF_WHITELIST = "whitelist" -CONF_WHITELIST_EXTERNAL_DIRS = "whitelist_external_dirs" +CONF_ALLOWLIST_EXTERNAL_DIRS = "allowlist_external_dirs" +LEGACY_CONF_WHITELIST_EXTERNAL_DIRS = "whitelist_external_dirs" CONF_WHITE_VALUE = "white_value" CONF_XY = "xy" CONF_ZONE = "zone" diff --git a/homeassistant/core.py b/homeassistant/core.py index fe85e7e368c..fb6db49139d 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -1320,7 +1320,7 @@ class Config: self.config_dir: Optional[str] = None # List of allowed external dirs to access - self.whitelist_external_dirs: Set[str] = set() + self.allowlist_external_dirs: Set[str] = set() # List of allowed external URLs that integrations may use self.allowlist_external_urls: Set[str] = set() @@ -1370,9 +1370,9 @@ class Config: except (FileNotFoundError, RuntimeError, PermissionError): return False - for whitelisted_path in self.whitelist_external_dirs: + for allowed_path in self.allowlist_external_dirs: try: - thepath.relative_to(whitelisted_path) + thepath.relative_to(allowed_path) return True except ValueError: pass @@ -1397,7 +1397,9 @@ class Config: "time_zone": time_zone, "components": self.components, "config_dir": self.config_dir, - "whitelist_external_dirs": self.whitelist_external_dirs, + # legacy, backwards compat + "whitelist_external_dirs": self.allowlist_external_dirs, + "allowlist_external_dirs": self.allowlist_external_dirs, "allowlist_external_urls": self.allowlist_external_urls, "version": __version__, "config_source": self.config_source, diff --git a/tests/auth/providers/test_trusted_networks.py b/tests/auth/providers/test_trusted_networks.py index 4baa9d8da00..3156c40f876 100644 --- a/tests/auth/providers/test_trusted_networks.py +++ b/tests/auth/providers/test_trusted_networks.py @@ -151,7 +151,7 @@ async def test_login_flow(manager, provider): flow = await provider.async_login_flow({"ip_address": ip_address("127.0.0.1")}) step = await flow.async_step_init() assert step["type"] == "abort" - assert step["reason"] == "not_whitelisted" + assert step["reason"] == "not_allowed" # from trusted network, list users flow = await provider.async_login_flow({"ip_address": ip_address("192.168.0.1")}) @@ -190,7 +190,7 @@ async def test_trusted_users_login(manager_with_user, provider_with_user): ) step = await flow.async_step_init() assert step["type"] == "abort" - assert step["reason"] == "not_whitelisted" + assert step["reason"] == "not_allowed" # from trusted network, list users intersect trusted_users flow = await provider_with_user.async_login_flow( @@ -274,7 +274,7 @@ async def test_trusted_group_login(manager_with_user, provider_with_user): ) step = await flow.async_step_init() assert step["type"] == "abort" - assert step["reason"] == "not_whitelisted" + assert step["reason"] == "not_allowed" # from trusted network, list users intersect trusted_users flow = await provider_with_user.async_login_flow( @@ -313,7 +313,7 @@ async def test_bypass_login_flow(manager_bypass_login, provider_bypass_login): ) step = await flow.async_step_init() assert step["type"] == "abort" - assert step["reason"] == "not_whitelisted" + assert step["reason"] == "not_allowed" # from trusted network, only one available user, bypass the login flow flow = await provider_bypass_login.async_login_flow( diff --git a/tests/components/api/test_init.py b/tests/components/api/test_init.py index 24a1532dead..e54af925dec 100644 --- a/tests/components/api/test_init.py +++ b/tests/components/api/test_init.py @@ -212,6 +212,8 @@ async def test_api_get_config(hass, mock_api_client): result["components"] = set(result["components"]) if "whitelist_external_dirs" in result: result["whitelist_external_dirs"] = set(result["whitelist_external_dirs"]) + if "allowlist_external_dirs" in result: + result["allowlist_external_dirs"] = set(result["allowlist_external_dirs"]) if "allowlist_external_urls" in result: result["allowlist_external_urls"] = set(result["allowlist_external_urls"]) diff --git a/tests/components/filesize/test_sensor.py b/tests/components/filesize/test_sensor.py index 11709296375..6d35ab0d88e 100644 --- a/tests/components/filesize/test_sensor.py +++ b/tests/components/filesize/test_sensor.py @@ -23,7 +23,7 @@ class TestFileSensor(unittest.TestCase): def setup_method(self, method): """Set up things to be run when tests are started.""" self.hass = get_test_home_assistant() - self.hass.config.whitelist_external_dirs = {TEST_DIR} + self.hass.config.allowlist_external_dirs = {TEST_DIR} def teardown_method(self, method): """Stop everything that was started.""" diff --git a/tests/components/folder/test_sensor.py b/tests/components/folder/test_sensor.py index 9578eadc915..72185d4eda3 100644 --- a/tests/components/folder/test_sensor.py +++ b/tests/components/folder/test_sensor.py @@ -28,7 +28,7 @@ class TestFolderSensor(unittest.TestCase): self.hass = get_test_home_assistant() if not os.path.isdir(TEST_DIR): os.mkdir(TEST_DIR) - self.hass.config.whitelist_external_dirs = {TEST_DIR} + self.hass.config.allowlist_external_dirs = {TEST_DIR} def teardown_method(self, method): """Stop everything that was started.""" diff --git a/tests/components/folder_watcher/test_init.py b/tests/components/folder_watcher/test_init.py index 997bac23f22..1123a5907fb 100644 --- a/tests/components/folder_watcher/test_init.py +++ b/tests/components/folder_watcher/test_init.py @@ -19,7 +19,7 @@ async def test_invalid_path_setup(hass): async def test_valid_path_setup(hass): """Test that a valid path is setup.""" cwd = os.path.join(os.path.dirname(__file__)) - hass.config.whitelist_external_dirs = {cwd} + hass.config.allowlist_external_dirs = {cwd} with patch.object(folder_watcher, "Watcher"): assert await async_setup_component( hass, diff --git a/tests/components/history/test_init.py b/tests/components/history/test_init.py index 56318f3e9fb..b50ea339683 100644 --- a/tests/components/history/test_init.py +++ b/tests/components/history/test_init.py @@ -730,7 +730,7 @@ class TestComponentHistory(unittest.TestCase): ): # This state will be skipped only different in time set_state(mp, "YouTube", attributes={"media_title": str(sentinel.mt3)}) - # This state will be skipped because domain blacklisted + # This state will be skipped because domain is excluded set_state(zone, "zoning") set_state(script_nc, "off") states[script_c].append( diff --git a/tests/components/influxdb/test_init.py b/tests/components/influxdb/test_init.py index d9b41ed967c..02a98a527ac 100644 --- a/tests/components/influxdb/test_init.py +++ b/tests/components/influxdb/test_init.py @@ -188,7 +188,7 @@ async def _setup(hass, mock_influx_client, config_ext, get_write_api): config = { "influxdb": { "host": "host", - "exclude": {"entities": ["fake.blacklisted"], "domains": ["another_fake"]}, + "exclude": {"entities": ["fake.excluded"], "domains": ["another_fake"]}, } } config["influxdb"].update(config_ext) diff --git a/tests/components/minio/test_minio.py b/tests/components/minio/test_minio.py index 88f7418d2d4..8cde32f7870 100644 --- a/tests/components/minio/test_minio.py +++ b/tests/components/minio/test_minio.py @@ -54,7 +54,7 @@ def minio_client_event_fixture(): async def test_minio_services(hass, caplog, minio_client): """Test Minio services.""" - hass.config.whitelist_external_dirs = set("/test") + hass.config.allowlist_external_dirs = {"/test"} await async_setup_component( hass, diff --git a/tests/components/mobile_app/test_webhook.py b/tests/components/mobile_app/test_webhook.py index 790ebc56bf6..195c60d830c 100644 --- a/tests/components/mobile_app/test_webhook.py +++ b/tests/components/mobile_app/test_webhook.py @@ -171,8 +171,8 @@ async def test_webhook_handle_get_config(hass, create_registrations, webhook_cli json = await resp.json() if "components" in json: json["components"] = set(json["components"]) - if "whitelist_external_dirs" in json: - json["whitelist_external_dirs"] = set(json["whitelist_external_dirs"]) + if "allowlist_external_dirs" in json: + json["allowlist_external_dirs"] = set(json["allowlist_external_dirs"]) hass_config = hass.config.as_dict() diff --git a/tests/components/owntracks/test_device_tracker.py b/tests/components/owntracks/test_device_tracker.py index 7f066346d5a..9f47c63aa85 100644 --- a/tests/components/owntracks/test_device_tracker.py +++ b/tests/components/owntracks/test_device_tracker.py @@ -1228,8 +1228,8 @@ async def test_waypoint_import_simple(hass, context): assert wayp is not None -async def test_waypoint_import_blacklist(hass, context): - """Test import of list of waypoints for blacklisted user.""" +async def test_waypoint_import_block(hass, context): + """Test import of list of waypoints for blocked user.""" waypoints_message = WAYPOINTS_EXPORTED_MESSAGE.copy() await send_message(hass, WAYPOINTS_TOPIC_BLOCKED, waypoints_message) # Check if it made it into states diff --git a/tests/components/websocket_api/test_commands.py b/tests/components/websocket_api/test_commands.py index 6f7b288f292..57724fb54c6 100644 --- a/tests/components/websocket_api/test_commands.py +++ b/tests/components/websocket_api/test_commands.py @@ -234,6 +234,10 @@ async def test_get_config(hass, websocket_client): msg["result"]["whitelist_external_dirs"] = set( msg["result"]["whitelist_external_dirs"] ) + if "allowlist_external_dirs" in msg["result"]: + msg["result"]["allowlist_external_dirs"] = set( + msg["result"]["allowlist_external_dirs"] + ) if "allowlist_external_urls" in msg["result"]: msg["result"]["allowlist_external_urls"] = set( msg["result"]["allowlist_external_urls"] diff --git a/tests/test_config.py b/tests/test_config.py index c27ebb2b6e8..22b5987f69c 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -353,7 +353,7 @@ async def test_loading_configuration_from_storage(hass, hass_storage): "version": 1, } await config_util.async_process_ha_core_config( - hass, {"whitelist_external_dirs": "/etc"} + hass, {"allowlist_external_dirs": "/etc"} ) assert hass.config.latitude == 55 @@ -364,8 +364,8 @@ async def test_loading_configuration_from_storage(hass, hass_storage): assert hass.config.time_zone.zone == "Europe/Copenhagen" assert hass.config.external_url == "https://www.example.com" assert hass.config.internal_url == "http://example.local" - assert len(hass.config.whitelist_external_dirs) == 2 - assert "/etc" in hass.config.whitelist_external_dirs + assert len(hass.config.allowlist_external_dirs) == 2 + assert "/etc" in hass.config.allowlist_external_dirs assert hass.config.config_source == SOURCE_STORAGE @@ -387,7 +387,7 @@ async def test_updating_configuration(hass, hass_storage): } hass_storage["core.config"] = dict(core_data) await config_util.async_process_ha_core_config( - hass, {"whitelist_external_dirs": "/etc"} + hass, {"allowlist_external_dirs": "/etc"} ) await hass.config.async_update(latitude=50) @@ -412,7 +412,7 @@ async def test_override_stored_configuration(hass, hass_storage): "version": 1, } await config_util.async_process_ha_core_config( - hass, {"latitude": 60, "whitelist_external_dirs": "/etc"} + hass, {"latitude": 60, "allowlist_external_dirs": "/etc"} ) assert hass.config.latitude == 60 @@ -421,8 +421,8 @@ async def test_override_stored_configuration(hass, hass_storage): assert hass.config.location_name == "Home" assert hass.config.units.name == CONF_UNIT_SYSTEM_METRIC assert hass.config.time_zone.zone == "Europe/Copenhagen" - assert len(hass.config.whitelist_external_dirs) == 2 - assert "/etc" in hass.config.whitelist_external_dirs + assert len(hass.config.allowlist_external_dirs) == 2 + assert "/etc" in hass.config.allowlist_external_dirs assert hass.config.config_source == config_util.SOURCE_YAML @@ -437,7 +437,7 @@ async def test_loading_configuration(hass): "name": "Huis", CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL, "time_zone": "America/New_York", - "whitelist_external_dirs": "/etc", + "allowlist_external_dirs": "/etc", "external_url": "https://www.example.com", "internal_url": "http://example.local", }, @@ -451,8 +451,8 @@ async def test_loading_configuration(hass): assert hass.config.time_zone.zone == "America/New_York" assert hass.config.external_url == "https://www.example.com" assert hass.config.internal_url == "http://example.local" - assert len(hass.config.whitelist_external_dirs) == 2 - assert "/etc" in hass.config.whitelist_external_dirs + assert len(hass.config.allowlist_external_dirs) == 2 + assert "/etc" in hass.config.allowlist_external_dirs assert hass.config.config_source == config_util.SOURCE_YAML diff --git a/tests/test_core.py b/tests/test_core.py index ffd3dad66f8..884c5e98125 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -915,6 +915,7 @@ class TestConfig(unittest.TestCase): "components": set(), "config_dir": "/test/ha-config", "whitelist_external_dirs": set(), + "allowlist_external_dirs": set(), "allowlist_external_urls": set(), "version": __version__, "config_source": "default", @@ -931,7 +932,7 @@ class TestConfig(unittest.TestCase): with TemporaryDirectory() as tmp_dir: # The created dir is in /tmp. This is a symlink on OS X # causing this test to fail unless we resolve path first. - self.config.whitelist_external_dirs = {os.path.realpath(tmp_dir)} + self.config.allowlist_external_dirs = {os.path.realpath(tmp_dir)} test_file = os.path.join(tmp_dir, "test.jpg") with open(test_file, "w") as tmp_file: @@ -941,7 +942,7 @@ class TestConfig(unittest.TestCase): for path in valid: assert self.config.is_allowed_path(path) - self.config.whitelist_external_dirs = {"/home", "/var"} + self.config.allowlist_external_dirs = {"/home", "/var"} unvalid = [ "/hass/config/secure",