async def start(self) -> None: """Start the aiohttp server.""" context: ssl.SSLContext | None if self.ssl_certificate: try: if self.ssl_profile == SSL_INTERMEDIATE: context = ssl_util.server_context_intermediate() else: context = ssl_util.server_context_modern() await self.hass.async_add_executor_job( context.load_cert_chain, self.ssl_certificate, self.ssl_key ) except OSError as error: _LOGGER.error( "Could not read SSL certificate from %s: %s", self.ssl_certificate, error, ) return if self.ssl_peer_certificate: context.verify_mode = ssl.CERT_REQUIRED await self.hass.async_add_executor_job( context.load_verify_locations, self.ssl_peer_certificate ) else: context = None # Aiohttp freezes apps after start so that no changes can be made. # However in Home Assistant components can be discovered after boot. # This will now raise a RunTimeError. # To work around this we now prevent the router from getting frozen # pylint: disable=protected-access self.app._router.freeze = lambda: None # type: ignore[assignment] self.runner = web.AppRunner(self.app) await self.runner.setup() self.site = HomeAssistantTCPSite( self.runner, self.server_host, self.server_port, ssl_context=context ) try: await self.site.start() except OSError as error: _LOGGER.error( "Failed to create HTTP server at port %d: %s", self.server_port, error ) _LOGGER.info("Now listening on port %d", self.server_port)
async def start(self): """Start the aiohttp server.""" # We misunderstood the startup signal. You're not allowed to change # anything during startup. Temp workaround. # pylint: disable=protected-access self.app._on_startup.freeze() await self.app.startup() if self.ssl_certificate: try: if self.ssl_profile == SSL_INTERMEDIATE: context = ssl_util.server_context_intermediate() else: context = ssl_util.server_context_modern() await self.hass.async_add_executor_job( context.load_cert_chain, self.ssl_certificate, self.ssl_key) except OSError as error: _LOGGER.error("Could not read SSL certificate from %s: %s", self.ssl_certificate, error) return if self.ssl_peer_certificate: context.verify_mode = ssl.CERT_REQUIRED await self.hass.async_add_executor_job( context.load_verify_locations, self.ssl_peer_certificate) else: context = None # Aiohttp freezes apps after start so that no changes can be made. # However in Home Assistant components can be discovered after boot. # This will now raise a RunTimeError. # To work around this we now prevent the router from getting frozen self.app._router.freeze = lambda: None self.runner = web.AppRunner(self.app) await self.runner.setup() self.site = web.TCPSite(self.runner, self.server_host, self.server_port, ssl_context=context) try: await self.site.start() except OSError as error: _LOGGER.error("Failed to create HTTP server at port %d: %s", self.server_port, error)
def _create_ssl_context(self) -> ssl.SSLContext | None: context: ssl.SSLContext | None = None assert self.ssl_certificate is not None try: if self.ssl_profile == SSL_INTERMEDIATE: context = ssl_util.server_context_intermediate() else: context = ssl_util.server_context_modern() context.load_cert_chain(self.ssl_certificate, self.ssl_key) except OSError as error: if not self.hass.config.safe_mode: raise HomeAssistantError( f"Could not use SSL certificate from {self.ssl_certificate}: {error}" ) from error _LOGGER.error( "Could not read SSL certificate from %s: %s", self.ssl_certificate, error, ) try: context = self._create_emergency_ssl_context() except OSError as error2: _LOGGER.error( "Could not create an emergency self signed ssl certificate: %s", error2, ) context = None else: _LOGGER.critical( "Home Assistant is running in safe mode with an emergency self signed ssl certificate because the configured SSL certificate was not usable" ) return context if self.ssl_peer_certificate: if context is None: raise HomeAssistantError( "Failed to create ssl context, no fallback available because a peer certificate is required." ) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(self.ssl_peer_certificate) return context