Fix KNX secure config switching from manual to keyfile (#82724)

This commit is contained in:
Matthias Alphart 2022-11-28 10:18:45 +01:00 committed by GitHub
parent 8a20a90324
commit e738df502b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 111 additions and 8 deletions

View File

@ -313,7 +313,6 @@ class KNXCommonFlow(ABC, FlowHandler):
if user_input is not None: if user_input is not None:
self.new_entry_data |= KNXConfigEntryData( self.new_entry_data |= KNXConfigEntryData(
connection_type=CONF_KNX_TUNNELING_TCP_SECURE,
device_authentication=user_input[CONF_KNX_SECURE_DEVICE_AUTHENTICATION], device_authentication=user_input[CONF_KNX_SECURE_DEVICE_AUTHENTICATION],
user_id=user_input[CONF_KNX_SECURE_USER_ID], user_id=user_input[CONF_KNX_SECURE_USER_ID],
user_password=user_input[CONF_KNX_SECURE_USER_PASSWORD], user_password=user_input[CONF_KNX_SECURE_USER_PASSWORD],
@ -428,10 +427,13 @@ class KNXCommonFlow(ABC, FlowHandler):
if not errors: if not errors:
self.new_entry_data |= KNXConfigEntryData( self.new_entry_data |= KNXConfigEntryData(
backbone_key=None,
sync_latency_tolerance=None,
knxkeys_filename=storage_key, knxkeys_filename=storage_key,
knxkeys_password=user_input[CONF_KNX_KNXKEY_PASSWORD], knxkeys_password=user_input[CONF_KNX_KNXKEY_PASSWORD],
backbone_key=None,
sync_latency_tolerance=None,
device_authentication=None,
user_id=None,
user_password=None,
) )
if ( if (
self.new_entry_data[CONF_KNX_CONNECTION_TYPE] self.new_entry_data[CONF_KNX_CONNECTION_TYPE]
@ -442,10 +444,11 @@ class KNXCommonFlow(ABC, FlowHandler):
title = f"Secure Tunneling @ {self.new_entry_data[CONF_HOST]}" title = f"Secure Tunneling @ {self.new_entry_data[CONF_HOST]}"
return self.finish_flow(title=title) return self.finish_flow(title=title)
if _default_filename := self.initial_data.get(CONF_KNX_KNXKEY_FILENAME):
_default_filename = _default_filename.lstrip(CONST_KNX_STORAGE_KEY)
fields = { fields = {
vol.Required( vol.Required(
CONF_KNX_KNXKEY_FILENAME, CONF_KNX_KNXKEY_FILENAME, default=_default_filename
default=self.initial_data.get(CONF_KNX_KNXKEY_FILENAME),
): selector.TextSelector(), ): selector.TextSelector(),
vol.Required( vol.Required(
CONF_KNX_KNXKEY_PASSWORD, CONF_KNX_KNXKEY_PASSWORD,

View File

@ -90,9 +90,9 @@ class KNXConfigEntryData(TypedDict, total=False):
host: str host: str
port: int port: int
user_id: int user_id: int | None
user_password: str user_password: str | None
device_authentication: str device_authentication: str | None
knxkeys_filename: str knxkeys_filename: str
knxkeys_password: str knxkeys_password: str
backbone_key: str | None backbone_key: str | None

View File

@ -383,6 +383,9 @@ async def test_routing_secure_keyfile(
CONF_KNX_KNXKEY_PASSWORD: "password", CONF_KNX_KNXKEY_PASSWORD: "password",
CONF_KNX_ROUTING_BACKBONE_KEY: None, CONF_KNX_ROUTING_BACKBONE_KEY: None,
CONF_KNX_ROUTING_SYNC_LATENCY_TOLERANCE: None, CONF_KNX_ROUTING_SYNC_LATENCY_TOLERANCE: None,
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: None,
CONF_KNX_SECURE_USER_ID: None,
CONF_KNX_SECURE_USER_PASSWORD: None,
CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.123", CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.123",
} }
assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_setup_entry.mock_calls) == 1
@ -876,6 +879,9 @@ async def test_configure_secure_knxkeys(hass: HomeAssistant):
CONF_KNX_KNXKEY_PASSWORD: "password", CONF_KNX_KNXKEY_PASSWORD: "password",
CONF_KNX_ROUTING_BACKBONE_KEY: None, CONF_KNX_ROUTING_BACKBONE_KEY: None,
CONF_KNX_ROUTING_SYNC_LATENCY_TOLERANCE: None, CONF_KNX_ROUTING_SYNC_LATENCY_TOLERANCE: None,
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: None,
CONF_KNX_SECURE_USER_ID: None,
CONF_KNX_SECURE_USER_PASSWORD: None,
CONF_HOST: "192.168.0.1", CONF_HOST: "192.168.0.1",
CONF_PORT: 3675, CONF_PORT: 3675,
CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.240", CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.240",
@ -999,6 +1005,100 @@ async def test_options_flow_connection_type(
} }
async def test_options_flow_secure_manual_to_keyfile(hass: HomeAssistant) -> None:
"""Test options flow changing secure credential source."""
mock_config_entry = MockConfigEntry(
title="KNX",
domain="knx",
data={
**DEFAULT_ENTRY_DATA,
CONF_KNX_CONNECTION_TYPE: CONF_KNX_TUNNELING_TCP_SECURE,
CONF_KNX_SECURE_USER_ID: 2,
CONF_KNX_SECURE_USER_PASSWORD: "password",
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: "device_auth",
CONF_KNX_KNXKEY_FILENAME: "knx/testcase.knxkeys",
CONF_KNX_KNXKEY_PASSWORD: "invalid_password",
CONF_HOST: "192.168.0.1",
CONF_PORT: 3675,
CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.240",
CONF_KNX_ROUTE_BACK: False,
CONF_KNX_LOCAL_IP: None,
},
)
mock_config_entry.add_to_hass(hass)
gateway = _gateway_descriptor(
"192.168.0.1",
3675,
supports_tunnelling_tcp=True,
requires_secure=True,
)
menu_step = await hass.config_entries.options.async_init(mock_config_entry.entry_id)
with patch(
"homeassistant.components.knx.config_flow.GatewayScanner"
) as gateway_scanner_mock:
gateway_scanner_mock.return_value = GatewayScannerMock([gateway])
result = await hass.config_entries.options.async_configure(
menu_step["flow_id"],
{"next_step_id": "connection_type"},
)
assert result.get("type") == FlowResultType.FORM
assert result.get("step_id") == "connection_type"
result2 = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
CONF_KNX_CONNECTION_TYPE: CONF_KNX_TUNNELING,
},
)
assert result2["type"] == FlowResultType.FORM
assert result2["step_id"] == "tunnel"
assert not result2["errors"]
result3 = await hass.config_entries.options.async_configure(
result2["flow_id"],
{CONF_KNX_GATEWAY: str(gateway)},
)
assert result3["type"] == FlowResultType.MENU
assert result3["step_id"] == "secure_key_source"
result4 = await hass.config_entries.options.async_configure(
result3["flow_id"],
{"next_step_id": "secure_knxkeys"},
)
assert result4["type"] == FlowResultType.FORM
assert result4["step_id"] == "secure_knxkeys"
assert not result4["errors"]
with patch(
"homeassistant.components.knx.config_flow.load_keyring", return_value=True
):
secure_knxkeys = await hass.config_entries.options.async_configure(
result4["flow_id"],
{
CONF_KNX_KNXKEY_FILENAME: "testcase.knxkeys",
CONF_KNX_KNXKEY_PASSWORD: "password",
},
)
assert secure_knxkeys["type"] == FlowResultType.CREATE_ENTRY
assert mock_config_entry.data == {
**DEFAULT_ENTRY_DATA,
CONF_KNX_CONNECTION_TYPE: CONF_KNX_TUNNELING_TCP_SECURE,
CONF_KNX_KNXKEY_FILENAME: "knx/testcase.knxkeys",
CONF_KNX_KNXKEY_PASSWORD: "password",
CONF_KNX_SECURE_DEVICE_AUTHENTICATION: None,
CONF_KNX_SECURE_USER_ID: None,
CONF_KNX_SECURE_USER_PASSWORD: None,
CONF_KNX_ROUTING_BACKBONE_KEY: None,
CONF_KNX_ROUTING_SYNC_LATENCY_TOLERANCE: None,
CONF_HOST: "192.168.0.1",
CONF_PORT: 3675,
CONF_KNX_INDIVIDUAL_ADDRESS: "0.0.240",
CONF_KNX_ROUTE_BACK: False,
CONF_KNX_LOCAL_IP: None,
}
async def test_options_communication_settings( async def test_options_communication_settings(
hass: HomeAssistant, mock_config_entry: MockConfigEntry hass: HomeAssistant, mock_config_entry: MockConfigEntry
) -> None: ) -> None: