Exemple #1
0
    def test_generate_config_generates_files(self):
        HomeServerConfig.load_or_generate_config(
            "",
            [
                "--generate-config",
                "-c",
                self.file,
                "--report-stats=yes",
                "-H",
                "lemurs.win",
            ],
        )

        self.assertSetEqual(
            set(
                [
                    "homeserver.yaml",
                    "lemurs.win.log.config",
                    "lemurs.win.signing.key",
                    "lemurs.win.tls.crt",
                    "lemurs.win.tls.dh",
                    "lemurs.win.tls.key",
                ]
            ),
            set(os.listdir(self.dir)),
        )

        self.assert_log_filename_is(
            os.path.join(self.dir, "lemurs.win.log.config"),
            os.path.join(os.getcwd(), "homeserver.log"),
        )
Exemple #2
0
 def _run_first_time_setup(self):
     self.create_config_dir()
     if 'riot_web' in self.plugins:
         riot = self.plugins['riot_web'].Controller()
         web_client_location = os.path.join(riot.config_dir, 'webapp')
     else:
         web_client_location = None
     configs = {
         'domain': os.environ['NOTEWORTHY_DOMAIN'],
         'registration_shared_secret': self._get_new_secret(),
         'macaroon_secret_key': self._get_new_secret(),
         'form_secret': self._get_new_secret(),
         'web_client_location': web_client_location,
         'config_dir': self.config_dir,
         'homeserver_log_config': self.log_config_file,
         'homeserver_log_target': self.log_file
     }
     homeserver_tmpl = os.path.join(self.deploy_dir, 'homeserver.tmpl.yaml')
     homeserver_target = os.path.join(self.config_dir, 'homeserver.yaml')
     self._generate_file_from_template(homeserver_tmpl, homeserver_target,
                                       configs)
     logconfig_tmpl = os.path.join(self.deploy_dir, 'log.config.tmpl.yaml')
     self._generate_file_from_template(logconfig_tmpl, self.log_config_file,
                                       configs)
     from synapse.config.homeserver import HomeServerConfig
     HomeServerConfig.load_or_generate_config(
         'Noteworthy Messenger',
         ['-c', homeserver_target, '--generate-missing-configs'])
    def test_generate_config_generates_files(self):
        with redirect_stdout(StringIO()):
            HomeServerConfig.load_or_generate_config(
                "",
                [
                    "--generate-config",
                    "-c",
                    self.file,
                    "--report-stats=yes",
                    "-H",
                    "lemurs.win",
                ],
            )

        self.assertSetEqual(
            {
                "homeserver.yaml", "lemurs.win.log.config",
                "lemurs.win.signing.key"
            },
            set(os.listdir(self.dir)),
        )

        self.assert_log_filename_is(
            os.path.join(self.dir, "lemurs.win.log.config"),
            os.path.join(os.getcwd(), "homeserver.log"),
        )
Exemple #4
0
 def generate_config(self):
     HomeServerConfig.load_or_generate_config("", [
         "--generate-config",
         "-c", self.file,
         "--report-stats=yes",
         "-H", "lemurs.win"
     ])
Exemple #5
0
 def generate_config(self):
     HomeServerConfig.load_or_generate_config("", [
         "--generate-config",
         "-c", self.file,
         "--report-stats=yes",
         "-H", "lemurs.win"
     ])
Exemple #6
0
 def generate_config(self):
     with redirect_stdout(StringIO()):
         HomeServerConfig.load_or_generate_config(
             "",
             [
                 "--generate-config",
                 "-c",
                 self.config_file,
                 "--report-stats=yes",
                 "-H",
                 "lemurs.win",
             ],
         )
Exemple #7
0
    def test_disable_registration(self):
        self.generate_config()
        self.add_lines_to_config(
            ["enable_registration: true", "disable_registration: true"])
        # Check that disable_registration clobbers enable_registration.
        config = HomeServerConfig.load_config("", ["-c", self.file])
        self.assertFalse(config.registration.enable_registration)

        config = HomeServerConfig.load_or_generate_config(
            "", ["-c", self.file])
        self.assertFalse(config.registration.enable_registration)

        # Check that either config value is clobbered by the command line.
        config = HomeServerConfig.load_or_generate_config(
            "", ["-c", self.file, "--enable-registration"])
        self.assertTrue(config.registration.enable_registration)
Exemple #8
0
 def test_load_succeeds_if_macaroon_secret_key_missing(self):
     self.generate_config_and_remove_lines_containing("macaroon")
     config1 = HomeServerConfig.load_config("", ["-c", self.file])
     config2 = HomeServerConfig.load_config("", ["-c", self.file])
     config3 = HomeServerConfig.load_or_generate_config("", ["-c", self.file])
     self.assertEqual(config1.macaroon_secret_key, config2.macaroon_secret_key)
     self.assertEqual(config1.macaroon_secret_key, config3.macaroon_secret_key)
Exemple #9
0
    def test_generates_and_loads_macaroon_secret_key(self):
        self.generate_config()

        with open(self.config_file) as f:
            raw = yaml.safe_load(f)
        self.assertIn("macaroon_secret_key", raw)

        config = HomeServerConfig.load_config("", ["-c", self.config_file])
        self.assertTrue(
            hasattr(config.key, "macaroon_secret_key"),
            "Want config to have attr macaroon_secret_key",
        )
        if len(config.key.macaroon_secret_key) < 5:
            self.fail(
                "Want macaroon secret key to be string of at least length 5,"
                "was: %r" % (config.key.macaroon_secret_key, ))

        config2 = HomeServerConfig.load_or_generate_config(
            "", ["-c", self.config_file])
        assert config2 is not None
        self.assertTrue(
            hasattr(config2.key, "macaroon_secret_key"),
            "Want config to have attr macaroon_secret_key",
        )
        if len(config2.key.macaroon_secret_key) < 5:
            self.fail(
                "Want macaroon secret key to be string of at least length 5,"
                "was: %r" % (config2.key.macaroon_secret_key, ))
Exemple #10
0
    def test_generates_and_loads_macaroon_secret_key(self):
        self.generate_config()

        with open(self.file, "r") as f:
            raw = yaml.load(f)
        self.assertIn("macaroon_secret_key", raw)

        config = HomeServerConfig.load_config("", ["-c", self.file])
        self.assertTrue(
            hasattr(config, "macaroon_secret_key"),
            "Want config to have attr macaroon_secret_key",
        )
        if len(config.macaroon_secret_key) < 5:
            self.fail(
                "Want macaroon secret key to be string of at least length 5,"
                "was: %r" % (config.macaroon_secret_key,)
            )

        config = HomeServerConfig.load_or_generate_config("", ["-c", self.file])
        self.assertTrue(
            hasattr(config, "macaroon_secret_key"),
            "Want config to have attr macaroon_secret_key",
        )
        if len(config.macaroon_secret_key) < 5:
            self.fail(
                "Want macaroon secret key to be string of at least length 5,"
                "was: %r" % (config.macaroon_secret_key,)
            )
Exemple #11
0
 def test_load_succeeds_if_macaroon_secret_key_missing(self):
     self.generate_config_and_remove_lines_containing("macaroon")
     config1 = HomeServerConfig.load_config("", ["-c", self.file])
     config2 = HomeServerConfig.load_config("", ["-c", self.file])
     config3 = HomeServerConfig.load_or_generate_config("", ["-c", self.file])
     self.assertEqual(config1.macaroon_secret_key, config2.macaroon_secret_key)
     self.assertEqual(config1.macaroon_secret_key, config3.macaroon_secret_key)
Exemple #12
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver", config_options)
    except ConfigError as e:
        sys.stderr.write("\n")
        for f in format_config_error(e):
            sys.stderr.write(f)
        sys.stderr.write("\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts
    synapse.util.caches.TRACK_MEMORY_USAGE = config.caches.track_memory_usage

    if config.server.gc_seconds:
        synapse.metrics.MIN_TIME_BETWEEN_GCS = config.server.gc_seconds

    hs = SynapseHomeServer(
        config.server_name,
        config=config,
        version_string="Synapse/" + get_version_string(synapse),
    )

    synapse.config.logger.setup_logging(hs, config, use_worker_options=False)

    logger.info("Setting up server")

    try:
        hs.setup()
    except Exception as e:
        handle_startup_exception(e)

    async def start():
        # Load the OIDC provider metadatas, if OIDC is enabled.
        if hs.config.oidc_enabled:
            oidc = hs.get_oidc_handler()
            # Loading the provider metadata also ensures the provider config is valid.
            await oidc.load_metadata()

        await _base.start(hs)

        hs.get_datastore().db_pool.updates.start_doing_background_updates()

    register_start(start)

    return hs
Exemple #13
0
    def test_disable_registration(self):
        self.generate_config()
        self.add_lines_to_config(
            ["enable_registration: true", "disable_registration: true"]
        )
        # Check that disable_registration clobbers enable_registration.
        config = HomeServerConfig.load_config("", ["-c", self.file])
        self.assertFalse(config.enable_registration)

        config = HomeServerConfig.load_or_generate_config("", ["-c", self.file])
        self.assertFalse(config.enable_registration)

        # Check that either config value is clobbered by the command line.
        config = HomeServerConfig.load_or_generate_config(
            "", ["-c", self.file, "--enable-registration"]
        )
        self.assertTrue(config.enable_registration)
Exemple #14
0
    def test_generate_config_generates_files(self):
        HomeServerConfig.load_or_generate_config("", [
            "--generate-config",
            "-c", self.file,
            "--report-stats=yes",
            "-H", "lemurs.win"
        ])

        self.assertSetEqual(
            set([
                "homeserver.yaml",
                "lemurs.win.log.config",
                "lemurs.win.signing.key",
                "lemurs.win.tls.crt",
                "lemurs.win.tls.dh",
                "lemurs.win.tls.key",
            ]),
            set(os.listdir(self.dir))
        )
Exemple #15
0
    def test_generate_config_generates_files(self):
        HomeServerConfig.load_or_generate_config("", [
            "--generate-config", "-c", self.file, "--report-stats=yes", "-H",
            "lemurs.win"
        ])

        self.assertSetEqual(
            set([
                "homeserver.yaml",
                "lemurs.win.log.config",
                "lemurs.win.signing.key",
                "lemurs.win.tls.crt",
                "lemurs.win.tls.dh",
                "lemurs.win.tls.key",
            ]), set(os.listdir(self.dir)))

        self.assert_log_filename_is(
            os.path.join(self.dir, "lemurs.win.log.config"),
            os.path.join(os.getcwd(), "homeserver.log"),
        )
Exemple #16
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver",
            config_options,
        )
    except ConfigError as e:
        sys.stderr.write("\n" + str(e) + "\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    sighup_callbacks = []
    synapse.config.logger.setup_logging(
        config,
        use_worker_options=False,
        register_sighup=sighup_callbacks.append
    )

    def handle_sighup(*args, **kwargs):
        for i in sighup_callbacks:
            i(*args, **kwargs)

    if hasattr(signal, "SIGHUP"):
        signal.signal(signal.SIGHUP, handle_sighup)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    database_engine = create_engine(config.database_config)
    config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection

    hs = SynapseHomeServer(
        config.server_name,
        db_config=config.database_config,
        config=config,
        version_string="Synapse/" + get_version_string(synapse),
        database_engine=database_engine,
    )

    logger.info("Preparing database: %s...", config.database_config['name'])

    try:
        with hs.get_db_conn(run_new_connection=False) as db_conn:
            prepare_database(db_conn, database_engine, config=config)
            database_engine.on_new_connection(db_conn)

            hs.run_startup_checks(db_conn, database_engine)

            db_conn.commit()
    except UpgradeDatabaseException:
        sys.stderr.write(
            "\nFailed to upgrade database.\n"
            "Have you checked for version specific instructions in"
            " UPGRADES.rst?\n"
        )
        sys.exit(1)

    logger.info("Database prepared in %s.", config.database_config['name'])

    hs.setup()

    def refresh_certificate(*args):
        """
        Refresh the TLS certificates that Synapse is using by re-reading them
        from disk and updating the TLS context factories to use them.
        """
        logging.info("Reloading certificate from disk...")
        hs.config.read_certificate_from_disk()
        hs.tls_server_context_factory = context_factory.ServerContextFactory(config)
        hs.tls_client_options_factory = context_factory.ClientTLSOptionsFactory(
            config
        )
        logging.info("Certificate reloaded.")

        logging.info("Updating context factories...")
        for i in hs._listening_services:
            if isinstance(i.factory, TLSMemoryBIOFactory):
                i.factory = TLSMemoryBIOFactory(
                    hs.tls_server_context_factory,
                    False,
                    i.factory.wrappedFactory
                )
        logging.info("Context factories updated.")

    sighup_callbacks.append(refresh_certificate)

    @defer.inlineCallbacks
    def start():
        try:
            # Check if the certificate is still valid.
            cert_days_remaining = hs.config.is_disk_cert_valid()

            if hs.config.acme_enabled:
                # If ACME is enabled, we might need to provision a certificate
                # before starting.
                acme = hs.get_acme_handler()

                # Start up the webservices which we will respond to ACME
                # challenges with.
                yield acme.start_listening()

                # We want to reprovision if cert_days_remaining is None (meaning no
                # certificate exists), or the days remaining number it returns
                # is less than our re-registration threshold.
                if (cert_days_remaining is None) or (
                    not cert_days_remaining > hs.config.acme_reprovision_threshold
                ):
                    yield acme.provision_certificate()

            # Read the certificate from disk and build the context factories for
            # TLS.
            hs.config.read_certificate_from_disk()
            hs.tls_server_context_factory = context_factory.ServerContextFactory(config)
            hs.tls_client_options_factory = context_factory.ClientTLSOptionsFactory(
                config
            )

            # It is now safe to start your Synapse.
            hs.start_listening()
            hs.get_pusherpool().start()
            hs.get_datastore().start_profiling()
            hs.get_datastore().start_doing_background_updates()
        except Exception as e:
            # If a DeferredList failed (like in listening on the ACME listener),
            # we need to print the subfailure explicitly.
            if isinstance(e, defer.FirstError):
                e.subFailure.printTraceback(sys.stderr)
                sys.exit(1)

            # Something else went wrong when starting. Print it and bail out.
            traceback.print_exc(file=sys.stderr)
            sys.exit(1)

    reactor.callWhenRunning(start)

    return hs
Exemple #17
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver",
            config_options,
        )
    except ConfigError as e:
        sys.stderr.write("\n" + str(e) + "\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    synapse.config.logger.setup_logging(config, use_worker_options=False)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    tls_server_context_factory = context_factory.ServerContextFactory(config)
    tls_client_options_factory = context_factory.ClientTLSOptionsFactory(config)

    database_engine = create_engine(config.database_config)
    config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection

    hs = SynapseHomeServer(
        config.server_name,
        db_config=config.database_config,
        tls_server_context_factory=tls_server_context_factory,
        tls_client_options_factory=tls_client_options_factory,
        config=config,
        version_string="Synapse/" + get_version_string(synapse),
        database_engine=database_engine,
    )

    logger.info("Preparing database: %s...", config.database_config['name'])

    try:
        with hs.get_db_conn(run_new_connection=False) as db_conn:
            prepare_database(db_conn, database_engine, config=config)
            database_engine.on_new_connection(db_conn)

            hs.run_startup_checks(db_conn, database_engine)

            db_conn.commit()
    except UpgradeDatabaseException:
        sys.stderr.write(
            "\nFailed to upgrade database.\n"
            "Have you checked for version specific instructions in"
            " UPGRADES.rst?\n"
        )
        sys.exit(1)

    logger.info("Database prepared in %s.", config.database_config['name'])

    hs.setup()
    hs.start_listening()

    def start():
        hs.get_pusherpool().start()
        hs.get_datastore().start_profiling()
        hs.get_datastore().start_doing_background_updates()

    reactor.callWhenRunning(start)

    return hs
Exemple #18
0
 def test_load_fails_if_server_name_missing(self):
     self.generate_config_and_remove_lines_containing("server_name")
     with self.assertRaises(Exception):
         HomeServerConfig.load_config("", ["-c", self.file])
     with self.assertRaises(Exception):
         HomeServerConfig.load_or_generate_config("", ["-c", self.file])
Exemple #19
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver",
            config_options,
        )
    except ConfigError as e:
        sys.stderr.write("\n" + e.message + "\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    config.setup_logging()

    # check any extra requirements we have now we have a config
    check_requirements(config)

    version_string = get_version_string("Synapse", synapse)

    logger.info("Server hostname: %s", config.server_name)
    logger.info("Server version: %s", version_string)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    tls_server_context_factory = context_factory.ServerContextFactory(config)

    database_engine = create_engine(config.database_config)
    config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection

    hs = SynapseHomeServer(
        config.server_name,
        db_config=config.database_config,
        tls_server_context_factory=tls_server_context_factory,
        config=config,
        content_addr=config.content_addr,
        version_string=version_string,
        database_engine=database_engine,
    )

    logger.info("Preparing database: %s...", config.database_config['name'])

    try:
        db_conn = hs.get_db_conn(run_new_connection=False)
        prepare_database(db_conn, database_engine, config=config)
        database_engine.on_new_connection(db_conn)

        hs.run_startup_checks(db_conn, database_engine)

        db_conn.commit()
    except UpgradeDatabaseException:
        sys.stderr.write(
            "\nFailed to upgrade database.\n"
            "Have you checked for version specific instructions in"
            " UPGRADES.rst?\n"
        )
        sys.exit(1)

    logger.info("Database prepared in %s.", config.database_config['name'])

    hs.setup()
    hs.start_listening()

    def start():
        hs.get_pusherpool().start()
        hs.get_state_handler().start_caching()
        hs.get_datastore().start_profiling()
        hs.get_datastore().start_doing_background_updates()
        hs.get_replication_layer().start_get_pdu_cache()

    reactor.callWhenRunning(start)

    return hs
Exemple #20
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver", config_options)
    except ConfigError as e:
        sys.stderr.write("\n")
        for f in format_config_error(e):
            sys.stderr.write(f)
        sys.stderr.write("\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    hs = SynapseHomeServer(
        config.server_name,
        config=config,
        version_string="Synapse/" + get_version_string(synapse),
    )

    synapse.config.logger.setup_logging(hs, config, use_worker_options=False)

    logger.info("Setting up server")

    try:
        hs.setup()
    except IncorrectDatabaseSetup as e:
        quit_with_error(str(e))
    except UpgradeDatabaseException as e:
        quit_with_error("Failed to upgrade database: %s" % (e, ))

    async def do_acme() -> bool:
        """
        Reprovision an ACME certificate, if it's required.

        Returns:
            Whether the cert has been updated.
        """
        acme = hs.get_acme_handler()

        # Check how long the certificate is active for.
        cert_days_remaining = hs.config.is_disk_cert_valid(
            allow_self_signed=False)

        # We want to reprovision if cert_days_remaining is None (meaning no
        # certificate exists), or the days remaining number it returns
        # is less than our re-registration threshold.
        provision = False

        if (cert_days_remaining is None
                or cert_days_remaining < hs.config.acme_reprovision_threshold):
            provision = True

        if provision:
            await acme.provision_certificate()

        return provision

    async def reprovision_acme():
        """
        Provision a certificate from ACME, if required, and reload the TLS
        certificate if it's renewed.
        """
        reprovisioned = await do_acme()
        if reprovisioned:
            _base.refresh_certificate(hs)

    async def start():
        # Run the ACME provisioning code, if it's enabled.
        if hs.config.acme_enabled:
            acme = hs.get_acme_handler()
            # Start up the webservices which we will respond to ACME
            # challenges with, and then provision.
            await acme.start_listening()
            await do_acme()

            # Check if it needs to be reprovisioned every day.
            hs.get_clock().looping_call(reprovision_acme, 24 * 60 * 60 * 1000)

        # Load the OIDC provider metadatas, if OIDC is enabled.
        if hs.config.oidc_enabled:
            oidc = hs.get_oidc_handler()
            # Loading the provider metadata also ensures the provider config is valid.
            await oidc.load_metadata()

        await _base.start(hs, config.listeners)

        hs.get_datastore().db_pool.updates.start_doing_background_updates()

    register_start(start)

    return hs
Exemple #21
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver",
            config_options,
        )
    except ConfigError as e:
        sys.stderr.write("\n" + str(e) + "\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    synapse.config.logger.setup_logging(
        config,
        use_worker_options=False
    )

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    database_engine = create_engine(config.database_config)
    config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection

    hs = SynapseHomeServer(
        config.server_name,
        db_config=config.database_config,
        config=config,
        version_string="Synapse/" + get_version_string(synapse),
        database_engine=database_engine,
    )

    logger.info("Preparing database: %s...", config.database_config['name'])

    try:
        with hs.get_db_conn(run_new_connection=False) as db_conn:
            prepare_database(db_conn, database_engine, config=config)
            database_engine.on_new_connection(db_conn)

            hs.run_startup_checks(db_conn, database_engine)

            db_conn.commit()
    except UpgradeDatabaseException:
        sys.stderr.write(
            "\nFailed to upgrade database.\n"
            "Have you checked for version specific instructions in"
            " UPGRADES.rst?\n"
        )
        sys.exit(1)

    logger.info("Database prepared in %s.", config.database_config['name'])

    hs.setup()
    hs.setup_master()

    @defer.inlineCallbacks
    def do_acme():
        """
        Reprovision an ACME certificate, if it's required.

        Returns:
            Deferred[bool]: Whether the cert has been updated.
        """
        acme = hs.get_acme_handler()

        # Check how long the certificate is active for.
        cert_days_remaining = hs.config.is_disk_cert_valid(
            allow_self_signed=False
        )

        # We want to reprovision if cert_days_remaining is None (meaning no
        # certificate exists), or the days remaining number it returns
        # is less than our re-registration threshold.
        provision = False

        if (
            cert_days_remaining is None or
            cert_days_remaining < hs.config.acme_reprovision_threshold
        ):
            provision = True

        if provision:
            yield acme.provision_certificate()

        defer.returnValue(provision)

    @defer.inlineCallbacks
    def reprovision_acme():
        """
        Provision a certificate from ACME, if required, and reload the TLS
        certificate if it's renewed.
        """
        reprovisioned = yield do_acme()
        if reprovisioned:
            _base.refresh_certificate(hs)

    @defer.inlineCallbacks
    def start():
        try:
            # Run the ACME provisioning code, if it's enabled.
            if hs.config.acme_enabled:
                acme = hs.get_acme_handler()
                # Start up the webservices which we will respond to ACME
                # challenges with, and then provision.
                yield acme.start_listening()
                yield do_acme()

                # Check if it needs to be reprovisioned every day.
                hs.get_clock().looping_call(
                    reprovision_acme,
                    24 * 60 * 60 * 1000
                )

            _base.start(hs, config.listeners)

            hs.get_pusherpool().start()
            hs.get_datastore().start_doing_background_updates()
        except Exception:
            # Print the exception and bail out.
            print("Error during startup:", file=sys.stderr)

            # this gives better tracebacks than traceback.print_exc()
            Failure().printTraceback(file=sys.stderr)

            if reactor.running:
                reactor.stop()
            sys.exit(1)

    reactor.callWhenRunning(start)

    return hs
Exemple #22
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver",
            config_options,
        )
    except ConfigError as e:
        sys.stderr.write("\n" + str(e) + "\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    synapse.config.logger.setup_logging(config, use_worker_options=False)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    database_engine = create_engine(config.database_config)
    config.database_config["args"][
        "cp_openfun"] = database_engine.on_new_connection

    hs = SynapseHomeServer(
        config.server_name,
        db_config=config.database_config,
        config=config,
        version_string="Synapse/" + get_version_string(synapse),
        database_engine=database_engine,
    )

    logger.info("Preparing database: %s...", config.database_config['name'])

    try:
        with hs.get_db_conn(run_new_connection=False) as db_conn:
            prepare_database(db_conn, database_engine, config=config)
            database_engine.on_new_connection(db_conn)

            hs.run_startup_checks(db_conn, database_engine)

            db_conn.commit()
    except UpgradeDatabaseException:
        sys.stderr.write(
            "\nFailed to upgrade database.\n"
            "Have you checked for version specific instructions in"
            " UPGRADES.rst?\n")
        sys.exit(1)

    logger.info("Database prepared in %s.", config.database_config['name'])

    hs.setup()

    @defer.inlineCallbacks
    def do_acme():
        """
        Reprovision an ACME certificate, if it's required.

        Returns:
            Deferred[bool]: Whether the cert has been updated.
        """
        acme = hs.get_acme_handler()

        # Check how long the certificate is active for.
        cert_days_remaining = hs.config.is_disk_cert_valid(
            allow_self_signed=False)

        # We want to reprovision if cert_days_remaining is None (meaning no
        # certificate exists), or the days remaining number it returns
        # is less than our re-registration threshold.
        provision = False

        if (cert_days_remaining is None
                or cert_days_remaining < hs.config.acme_reprovision_threshold):
            provision = True

        if provision:
            yield acme.provision_certificate()

        defer.returnValue(provision)

    @defer.inlineCallbacks
    def reprovision_acme():
        """
        Provision a certificate from ACME, if required, and reload the TLS
        certificate if it's renewed.
        """
        reprovisioned = yield do_acme()
        if reprovisioned:
            _base.refresh_certificate(hs)

    @defer.inlineCallbacks
    def start():
        try:
            # Run the ACME provisioning code, if it's enabled.
            if hs.config.acme_enabled:
                acme = hs.get_acme_handler()
                # Start up the webservices which we will respond to ACME
                # challenges with, and then provision.
                yield acme.start_listening()
                yield do_acme()

                # Check if it needs to be reprovisioned every day.
                hs.get_clock().looping_call(reprovision_acme,
                                            24 * 60 * 60 * 1000)

            _base.start(hs, config.listeners)

            hs.get_pusherpool().start()
            hs.get_datastore().start_doing_background_updates()
        except Exception:
            # Print the exception and bail out.
            print("Error during startup:", file=sys.stderr)

            # this gives better tracebacks than traceback.print_exc()
            Failure().printTraceback(file=sys.stderr)

            if reactor.running:
                reactor.stop()
            sys.exit(1)

    reactor.callWhenRunning(start)

    return hs
Exemple #23
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver",
            config_options,
        )
    except ConfigError as e:
        sys.stderr.write("\n" + e.message + "\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    synapse.config.logger.setup_logging(config, use_worker_options=False)

    # check any extra requirements we have now we have a config
    check_requirements(config)

    version_string = "Synapse/" + get_version_string(synapse)

    logger.info("Server hostname: %s", config.server_name)
    logger.info("Server version: %s", version_string)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    tls_server_context_factory = context_factory.ServerContextFactory(config)

    database_engine = create_engine(config.database_config)
    config.database_config["args"][
        "cp_openfun"] = database_engine.on_new_connection

    hs = SynapseHomeServer(
        config.server_name,
        db_config=config.database_config,
        tls_server_context_factory=tls_server_context_factory,
        config=config,
        version_string=version_string,
        database_engine=database_engine,
    )

    logger.info("Preparing database: %s...", config.database_config['name'])

    try:
        db_conn = hs.get_db_conn(run_new_connection=False)
        prepare_database(db_conn, database_engine, config=config)
        database_engine.on_new_connection(db_conn)

        hs.run_startup_checks(db_conn, database_engine)

        db_conn.commit()
    except UpgradeDatabaseException:
        sys.stderr.write(
            "\nFailed to upgrade database.\n"
            "Have you checked for version specific instructions in"
            " UPGRADES.rst?\n")
        sys.exit(1)

    logger.info("Database prepared in %s.", config.database_config['name'])

    hs.setup()
    hs.start_listening()

    def start():
        hs.get_pusherpool().start()
        hs.get_state_handler().start_caching()
        hs.get_datastore().start_profiling()
        hs.get_datastore().start_doing_background_updates()
        hs.get_replication_layer().start_get_pdu_cache()

        register_memory_metrics(hs)

    reactor.callWhenRunning(start)

    return hs
Exemple #24
0
def setup(config_options: List[str]) -> SynapseHomeServer:
    """
    Args:
        config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`.

    Returns:
        A homeserver instance.
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver", config_options)
    except ConfigError as e:
        sys.stderr.write("\n")
        for f in format_config_error(e):
            sys.stderr.write(f)
        sys.stderr.write("\n")
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    if config.worker.worker_app:
        raise ConfigError(
            "You have specified `worker_app` in the config but are attempting to start a non-worker "
            "instance. Please use `python -m synapse.app.generic_worker` instead (or remove the option if this is the main process)."
        )
        sys.exit(1)

    events.USE_FROZEN_DICTS = config.server.use_frozen_dicts
    synapse.util.caches.TRACK_MEMORY_USAGE = config.caches.track_memory_usage

    if config.server.gc_seconds:
        synapse.metrics.MIN_TIME_BETWEEN_GCS = config.server.gc_seconds

    if (config.registration.enable_registration and
            not config.registration.enable_registration_without_verification):
        if (not config.captcha.enable_registration_captcha
                and not config.registration.registrations_require_3pid
                and not config.registration.registration_requires_token):

            raise ConfigError(
                "You have enabled open registration without any verification. This is a known vector for "
                "spam and abuse. If you would like to allow public registration, please consider adding email, "
                "captcha, or token-based verification. Otherwise this check can be removed by setting the "
                "`enable_registration_without_verification` config option to `true`."
            )

    hs = SynapseHomeServer(
        config.server.server_name,
        config=config,
        version_string="Synapse/" +
        get_distribution_version_string("matrix-synapse"),
    )

    synapse.config.logger.setup_logging(hs, config, use_worker_options=False)

    logger.info("Setting up server")

    try:
        hs.setup()
    except Exception as e:
        handle_startup_exception(e)

    async def start() -> None:
        # Load the OIDC provider metadatas, if OIDC is enabled.
        if hs.config.oidc.oidc_enabled:
            oidc = hs.get_oidc_handler()
            # Loading the provider metadata also ensures the provider config is valid.
            await oidc.load_metadata()

        await _base.start(hs)

        hs.get_datastores(
        ).main.db_pool.updates.start_doing_background_updates()

    register_start(start)

    return hs
Exemple #25
0
 def test_load_fails_if_server_name_missing(self):
     self.generate_config_and_remove_lines_containing("server_name")
     with self.assertRaises(ConfigError):
         HomeServerConfig.load_config("", ["-c", self.file])
     with self.assertRaises(ConfigError):
         HomeServerConfig.load_or_generate_config("", ["-c", self.file])
Exemple #26
0
def setup(config_options):
    """
    Args:
        config_options_options: The options passed to Synapse. Usually
            `sys.argv[1:]`.

    Returns:
        HomeServer
    """
    try:
        config = HomeServerConfig.load_or_generate_config(
            "Synapse Homeserver", config_options)
    except ConfigError as e:
        sys.stderr.write("\nERROR: %s\n" % (e, ))
        sys.exit(1)

    if not config:
        # If a config isn't returned, and an exception isn't raised, we're just
        # generating config files and shouldn't try to continue.
        sys.exit(0)

    events.USE_FROZEN_DICTS = config.use_frozen_dicts

    hs = SynapseHomeServer(
        config.server_name,
        config=config,
        version_string="Synapse/" + get_version_string(synapse),
    )

    synapse.config.logger.setup_logging(hs, config, use_worker_options=False)

    logger.info("Setting up server")

    try:
        hs.setup()
    except IncorrectDatabaseSetup as e:
        quit_with_error(str(e))
    except UpgradeDatabaseException as e:
        quit_with_error("Failed to upgrade database: %s" % (e, ))

    hs.setup_master()

    @defer.inlineCallbacks
    def do_acme():
        """
        Reprovision an ACME certificate, if it's required.

        Returns:
            Deferred[bool]: Whether the cert has been updated.
        """
        acme = hs.get_acme_handler()

        # Check how long the certificate is active for.
        cert_days_remaining = hs.config.is_disk_cert_valid(
            allow_self_signed=False)

        # We want to reprovision if cert_days_remaining is None (meaning no
        # certificate exists), or the days remaining number it returns
        # is less than our re-registration threshold.
        provision = False

        if (cert_days_remaining is None
                or cert_days_remaining < hs.config.acme_reprovision_threshold):
            provision = True

        if provision:
            yield acme.provision_certificate()

        return provision

    @defer.inlineCallbacks
    def reprovision_acme():
        """
        Provision a certificate from ACME, if required, and reload the TLS
        certificate if it's renewed.
        """
        reprovisioned = yield do_acme()
        if reprovisioned:
            _base.refresh_certificate(hs)

    @defer.inlineCallbacks
    def start():
        try:
            # Run the ACME provisioning code, if it's enabled.
            if hs.config.acme_enabled:
                acme = hs.get_acme_handler()
                # Start up the webservices which we will respond to ACME
                # challenges with, and then provision.
                yield acme.start_listening()
                yield do_acme()

                # Check if it needs to be reprovisioned every day.
                hs.get_clock().looping_call(reprovision_acme,
                                            24 * 60 * 60 * 1000)

            _base.start(hs, config.listeners)

            hs.get_pusherpool().start()
            hs.get_datastore().db.updates.start_doing_background_updates()
        except Exception:
            # Print the exception and bail out.
            print("Error during startup:", file=sys.stderr)

            # this gives better tracebacks than traceback.print_exc()
            Failure().printTraceback(file=sys.stderr)

            if reactor.running:
                reactor.stop()
            sys.exit(1)

    reactor.callWhenRunning(start)

    return hs