示例#1
0
    async def load_backend(self) -> bool:
        """Load backend details."""
        # Load instance data from backend
        try:
            async with async_timeout.timeout(30):
                resp = await cloud_api.async_remote_register(self.cloud)
            resp.raise_for_status()
        except (asyncio.TimeoutError, aiohttp.ClientError) as err:
            msg = "Can't update remote details from Home Assistant cloud"
            if isinstance(err, aiohttp.ClientResponseError):
                msg += f" ({err.status})"  # pylint: disable=no-member
            elif isinstance(err, asyncio.TimeoutError):
                msg += " (timeout)"
            _LOGGER.error(msg)
            return False
        data = await resp.json()

        # Extract data
        _LOGGER.debug("Retrieve instance data: %s", data)
        domain = data["domain"]
        email = data["email"]
        server = data["server"]

        # Cache data
        self._instance_domain = domain
        self._snitun_server = server

        # Set instance details for certificate
        self._acme = AcmeHandler(self.cloud, domain, email)

        # Load exists certificate
        await self._acme.load_certificate()

        # Domain changed / revoke CA
        ca_domain = self._acme.common_name
        if ca_domain and ca_domain != domain:
            _LOGGER.warning("Invalid certificate found: %s", ca_domain)
            await self._acme.reset_acme()

        self._info_loaded.set()

        should_create_cert = not self._acme.certificate_available

        if should_create_cert or self._acme.expire_date < utils.utcnow() + timedelta(
            days=RENEW_IF_EXPIRES_DAYS
        ):
            try:
                await self._acme.issue_certificate()
            except AcmeClientError:
                self.cloud.client.user_message(
                    "cloud_remote_acme",
                    "Home Assistant Cloud",
                    const.MESSAGE_REMOTE_SETUP,
                )
                return
            else:
                if should_create_cert:
                    self.cloud.client.user_message(
                        "cloud_remote_acme",
                        "Home Assistant Cloud",
                        const.MESSAGE_REMOTE_READY,
                    )

        await self._acme.hardening_files()

        if self.cloud.client.aiohttp_runner is None:
            _LOGGER.debug("Waiting for aiohttp runner to come available")

            # aiohttp_runner comes available when Home Assistant has started.
            while self.cloud.client.aiohttp_runner is None:
                await asyncio.sleep(1)

        # Setup snitun / aiohttp wrapper
        _LOGGER.debug("Initializing SniTun")
        context = await self._create_context()
        self._snitun = SniTunClientAioHttp(
            self.cloud.client.aiohttp_runner,
            context,
            snitun_server=self._snitun_server,
            snitun_port=443,
        )

        _LOGGER.debug("Starting SniTun")
        is_cloud_request.set(True)
        await self._snitun.start()
        self.cloud.client.dispatcher_message(const.DISPATCH_REMOTE_BACKEND_UP)

        _LOGGER.debug(
            "Connecting remote backend: %s", self.cloud.client.remote_autostart
        )
        # Connect to remote is autostart enabled
        if self.cloud.client.remote_autostart:
            self.cloud.run_task(self.connect())

        return True
示例#2
0
    async def load_backend(self) -> None:
        """Load backend details."""
        if self._snitun:
            return

        # Setup background task for ACME certification handler
        if not self._acme_task:
            self._acme_task = self.cloud.run_task(self._certificate_handler())

        # Load instance data from backend
        try:
            async with async_timeout.timeout(15):
                resp = await cloud_api.async_remote_register(self.cloud)
            assert resp.status == 200
        except (asyncio.TimeoutError, AssertionError):
            _LOGGER.error(
                "Can't update remote details from Home Assistant cloud")
            return
        data = await resp.json()

        # Extract data
        _LOGGER.debug("Retrieve instance data: %s", data)
        domain = data["domain"]
        email = data["email"]
        server = data["server"]

        # Set instance details for certificate
        self._acme = AcmeHandler(self.cloud, domain, email)

        # Load exists certificate
        await self._acme.load_certificate()

        # Domain changed / revoke CA
        ca_domain = self._acme.common_name
        if ca_domain is not None and ca_domain != domain:
            _LOGGER.warning("Invalid certificate found: %s", ca_domain)
            await self._acme.reset_acme()

        # Issue a certificate
        if not self._acme.is_valid_certificate:
            try:
                await self._acme.issue_certificate()
            except AcmeClientError:
                self.cloud.client.user_message(
                    "cloud_remote_acme",
                    "Home Assistant Cloud",
                    const.MESSAGE_REMOTE_SETUP,
                )
                return
            else:
                self.cloud.client.user_message(
                    "cloud_remote_acme",
                    "Home Assistant Cloud",
                    const.MESSAGE_REMOTE_READY,
                )
        await self._acme.hardening_files()

        # Setup snitun / aiohttp wrapper
        context = await self._create_context()
        self._snitun = SniTunClientAioHttp(
            self.cloud.client.aiohttp_runner,
            context,
            snitun_server=server,
            snitun_port=443,
        )

        # Cache data
        self._instance_domain = domain
        self._snitun_server = server

        await self._snitun.start()
        self.cloud.client.dispatcher_message(const.DISPATCH_REMOTE_BACKEND_UP)

        # Connect to remote is autostart enabled
        if self.cloud.client.remote_autostart:
            self.cloud.run_task(self.connect())
示例#3
0
async def test_init_client():
    """Init aiohttp client for test."""

    with patch("snitun.utils.aiohttp_client.SockSite"):
        client = SniTunClientAioHttp(None, None, "127.0.0.1")