def __init__(self, config: HaConfig, security: Optional[HaSecurityConfig] = None, loop=None) -> None: self._config: HaConfig = config self._keepalive_task: Dict[KeepAlive, asyncio.Task] = {} self._manager_task: Dict[HaManager, asyncio.Task] = {} self._reconciliator_task: Dict[Reconciliator, asyncio.Task] = {} self._gen_sub: Generator[str, None, None] = self.generate_sub_name() self.loop: asyncio.unix_events._UnixSelectorEventLoop = ( loop or asyncio.get_event_loop()) self._url_to_reset_lock = asyncio.Lock(loop=self.loop) self._ideal_map_lock: asyncio.Lock = asyncio.Lock(loop=self.loop) self._client_lock: asyncio.Lock = asyncio.Lock(loop=self.loop) self.clients: Dict[Client, ServerInfo] = {} self.active_client: Optional[Client] = None # full type: Dict[str, SortedDict[str, VirtualSubscription]] self.ideal_map: Dict[str, SortedDict] = {} self.sub_names: Set[str] = set() self.url_to_reset: Set[str] = set() self.is_running = False if config.ha_mode != HaMode.WARM: # TODO # Check if transparent redundancy support exist for the server (nodeid=2035) # and prevent using HaClient with such servers. raise NotImplementedError( f"{config.ha_mode} not currently supported by HaClient") for url in self.urls: c = Client(url, timeout=self._config.request_timeout, loop=self.loop) # timeouts for the session and secure channel are in ms c.session_timeout = self._config.session_timeout * 1000 c.secure_channel_timeout = self._config.secure_channel_timeout * 1000 c.description = self._config.session_name server_info = ServerInfo(url) self.clients[c] = server_info self.ideal_map[url] = SortedDict() # security can also be set via the set_security method self.security_config: HaSecurityConfig = (security if security else HaSecurityConfig()) self.manager = HaManager(self, self._config.manager_timer) self.reconciliator = Reconciliator(self._config.reconciliator_timer, self)
async def test_secure_channel_key_expiration(srv_crypto_one_cert, mocker): timeout = 1 _, cert = srv_crypto_one_cert clt = Client(uri_crypto_cert) clt.secure_channel_timeout = timeout * 1000 user_cert = uacrypto.CertProperties(peer_creds['certificate'], "DER") user_key = uacrypto.CertProperties( path=peer_creds['private_key'], extension="PEM", ) server_cert = uacrypto.CertProperties(cert) await clt.set_security(security_policies.SecurityPolicyBasic256Sha256, user_cert, user_key, server_certificate=server_cert, mode=ua.MessageSecurityMode.SignAndEncrypt) async with clt: assert clt.uaclient.security_policy.symmetric_cryptography.Prev_Verifier is None assert clt.uaclient.security_policy.symmetric_cryptography.Prev_Decryptor is None await asyncio.sleep(timeout) sym_crypto = clt.uaclient.security_policy.symmetric_cryptography prev_verifier = sym_crypto.Prev_Verifier prev_decryptor = sym_crypto.Prev_Decryptor assert isinstance(prev_verifier, Verifier) assert isinstance(prev_decryptor, Decryptor) mock_decry_reset = mocker.patch.object(prev_verifier, "reset", wraps=prev_verifier.reset) mock_verif_reset = mocker.patch.object(prev_decryptor, "reset", wraps=prev_decryptor.reset) assert mock_decry_reset.call_count == 0 assert mock_verif_reset.call_count == 0 await asyncio.sleep(timeout * 0.3) assert await clt.get_objects_node().get_children() assert sym_crypto.key_expiration > 0 assert sym_crypto.prev_key_expiration > 0 assert sym_crypto.key_expiration > sym_crypto.prev_key_expiration assert mock_decry_reset.call_count == 1 assert mock_verif_reset.call_count == 1 assert clt.uaclient.security_policy.symmetric_cryptography.Prev_Verifier is None assert clt.uaclient.security_policy.symmetric_cryptography.Prev_Decryptor is None