Esempio n. 1
0
    def run(self):  # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        with log_context({'instance': 'service connection'}):
            logger.debug("ServiceConnectionThread started...")
            self.running = True
            self.connected = False
            self.cancelled = False

            try:  # pylint: disable=too-many-nested-blocks
                verify_server_cert = (
                    config.get('global', 'verify_server_cert')
                    or config.get('global', 'verify_server_cert_by_ca'))
                ca_cert_file = config.ca_cert_file
                self.prepare_ca_cert_file()

                compression = config.get('config_service', 'compression')
                if "localhost" in self._configServiceUrl or "127.0.0.1" in self._configServiceUrl:
                    compression = False
                    verify_server_cert = False

                if verify_server_cert:
                    if os.path.exists(ca_cert_file):
                        logger.info(
                            "Server verification enabled, using CA cert file '%s'",
                            ca_cert_file)
                    else:
                        logger.error(
                            "Server verification enabled, but CA cert file '%s' not found, skipping verification",
                            ca_cert_file)
                        ca_cert_file = None
                        verify_server_cert = False

                tryNum = 0
                while not self.cancelled and not self.connected:
                    tryNum += 1
                    try:
                        logger.notice("Connecting to config server '%s' #%d",
                                      self._configServiceUrl, tryNum)
                        self.setStatusMessage(
                            _("Connecting to config server '%s' #%d") %
                            (self._configServiceUrl, tryNum))
                        if len(self._username.split('.')) < 3:
                            raise Exception(
                                f"Domain missing in username '{self._username}'"
                            )

                        logger.debug(
                            "JSONRPCBackend address=%s, verify_server_cert=%s, ca_cert_file=%s, proxy_url=%s, application=%s",
                            self._configServiceUrl, verify_server_cert,
                            ca_cert_file, config.get('global', 'proxy_url'),
                            f"opsiclientd/{__version__}")

                        self.configService = JSONRPCBackend(
                            address=self._configServiceUrl,
                            username=self._username,
                            password=self._password,
                            verify_server_cert=verify_server_cert,
                            ca_cert_file=ca_cert_file,
                            proxy_url=config.get('global', 'proxy_url'),
                            application=f"opsiclientd/{__version__}",
                            compression=compression,
                            ip_version=config.get('global', 'ip_version'))
                        self.configService.accessControl_authenticated()  # pylint: disable=no-member
                        self.connected = True
                        self.connectionError = None
                        serverVersion = self.configService.serverVersion
                        self.setStatusMessage(
                            _("Connected to config server '%s'") %
                            self._configServiceUrl)
                        logger.notice(
                            "Connected to config server '%s' (name=%s, version=%s)",
                            self._configServiceUrl,
                            self.configService.serverName, serverVersion)

                        if serverVersion and (serverVersion[0] > 4 or
                                              (serverVersion[0] == 4
                                               and serverVersion[1] > 1)):
                            if not os.path.exists(
                                    config.ca_cert_file
                            ) or verify_server_cert or config.get(
                                    'global', 'install_opsi_ca_into_os_store'):
                                # Renew CA if not exists or connection is verified
                                try:
                                    update_ca_cert(self.configService,
                                                   allow_remove=True)
                                except Exception as err:  # pylint: disable=broad-except
                                    logger.error(err, exc_info=True)
                    except OpsiServiceVerificationError as verificationError:
                        self.connectionError = forceUnicode(verificationError)
                        self.setStatusMessage(
                            _("Failed to connect to config server '%s': Service verification failure"
                              ) % self._configServiceUrl)
                        logger.error(
                            "Failed to connect to config server '%s': %s",
                            self._configServiceUrl, verificationError)
                        break
                    except Exception as error:  # pylint: disable=broad-except
                        self.connectionError = forceUnicode(error)
                        self.setStatusMessage(
                            _("Failed to connect to config server '%s': %s") %
                            (self._configServiceUrl, forceUnicode(error)))
                        logger.info(
                            "Failed to connect to config server '%s': %s",
                            self._configServiceUrl, error)
                        logger.debug(error, exc_info=True)

                        if isinstance(error, OpsiAuthenticationError):
                            fqdn = System.getFQDN()
                            try:
                                fqdn = forceFqdn(fqdn)
                            except Exception as fqdnError:  # pylint: disable=broad-except
                                logger.warning(
                                    "Failed to get fqdn from os, got '%s': %s",
                                    fqdn, fqdnError)
                                break

                            if self._username != fqdn:
                                logger.notice(
                                    "Connect failed with username '%s', got fqdn '%s' from os, trying fqdn",
                                    self._username, fqdn)
                                self._username = fqdn
                            else:
                                break

                        if 'is not supported by the backend' in self.connectionError.lower(
                        ):
                            try:
                                from cryptography.hazmat.backends import default_backend  # pylint: disable=import-outside-toplevel
                                logger.debug(
                                    "Got the following crypto backends: %s",
                                    default_backend()._backends)  # pylint: disable=no-member,protected-access
                            except Exception as cryptoCheckError:  # pylint: disable=broad-except
                                logger.debug(
                                    "Failed to get info about installed crypto modules: %s",
                                    cryptoCheckError)

                        for _unused in range(
                                3):  # Sleeping before the next retry
                            time.sleep(1)
            except Exception as err:  # pylint: disable=broad-except
                logger.error(err, exc_info=True)
            finally:
                self.running = False
Esempio n. 2
0
    def __init__(self):
        baseDir = self._getBaseDirectory()

        self._temporaryConfigServiceUrls = []
        self._temporaryDepotDrive = []
        self._temporary_depot_path = None
        self._config_file_mtime = 0
        self.disabledEventTypes = []

        self._config = {
            "system": {
                "program_files_dir": "",
            },
            "global": {
                "base_dir":
                baseDir,
                "config_file":
                os.path.join(baseDir, "opsiclientd", "opsiclientd.conf"),
                "log_file":
                "opsiclientd.log",
                "log_level":
                LOG_NOTICE,
                "keep_rotated_logs":
                10,
                "max_log_size":
                5,  # In MB
                "max_log_transfer_size":
                5,  # In MB
                "host_id":
                System.getFQDN().lower(),
                "opsi_host_key":
                "",
                "wait_for_gui_timeout":
                120,
                "block_login_notifier":
                "",
                "verify_server_cert":
                False,
                "verify_server_cert_by_ca":
                False,
                "trust_uib_opsi_ca":
                True,
                "install_opsi_ca_into_os_store":
                False,
                "proxy_url":
                "system",
                "suspend_bitlocker_on_reboot":
                False,
                "ip_version":
                "auto"
            },
            "config_service": {
                "url": [],
                "compression": True,
                "connection_timeout": 10,
                "user_cancelable_after": 0,
                "sync_time_from_service": False
            },
            "depot_server": {
                # The id of the depot the client is assigned to
                "master_depot_id": "",
                # The id of the depot currently set as (dynamic) depot
                "depot_id": "",
                "url": "",
                "drive": "",
                "username": "******",
            },
            "cache_service": {
                "product_cache_max_size": 6000000000,
                "extension_config_dir": "",
                "include_product_group_ids": [],
                "exclude_product_group_ids": []
            },
            "control_server": {
                "interface":
                "0.0.0.0",
                "port":
                4441,
                "ssl_server_key_file":
                os.path.join(baseDir, "opsiclientd", "opsiclientd.pem"),
                "ssl_server_cert_file":
                os.path.join(baseDir, "opsiclientd", "opsiclientd.pem"),
                "static_dir":
                os.path.join(baseDir, "opsiclientd", "static_html"),
                "max_authentication_failures":
                5,
                "kiosk_api_active":
                True,
                "process_actions_event":
                "auto"
            },
            "notification_server": {
                "interface": "127.0.0.1",
                "start_port": 44000,
                "popup_port": 45000,
            },
            "opsiclientd_rpc": {
                "command": "",
            },
            "opsiclientd_notifier": {
                "command": "",
            },
            "action_processor": {
                "local_dir": "",
                "remote_dir": "",
                "remote_common_dir": "",
                "filename": "",
                "command": "",
                "run_as_user": "******",
                "create_user": True,
                "delete_user": True,
                "create_environment": False,
            }
        }

        self._applySystemSpecificConfiguration()