示例#1
0
    def parse_config(config: dict) -> JinjaOidcMappingConfig:
        subject_claim = config.get("subject_claim", "sub")

        if "localpart_template" not in config:
            raise ConfigError(
                "missing key: oidc_config.user_mapping_provider.config.localpart_template"
            )

        try:
            localpart_template = env.from_string(config["localpart_template"])
        except Exception as e:
            raise ConfigError(
                "invalid jinja template for oidc_config.user_mapping_provider.config.localpart_template: %r"
                % (e,)
            )

        display_name_template = None  # type: Optional[Template]
        if "display_name_template" in config:
            try:
                display_name_template = env.from_string(config["display_name_template"])
            except Exception as e:
                raise ConfigError(
                    "invalid jinja template for oidc_config.user_mapping_provider.config.display_name_template: %r"
                    % (e,)
                )

        return JinjaOidcMappingConfig(
            subject_claim=subject_claim,
            localpart_template=localpart_template,
            display_name_template=display_name_template,
        )
示例#2
0
    def __init__(self, hs: "HomeServer"):
        super().__init__()

        self.hs = hs
        self.store = hs.get_datastores().main
        self.registration_handler = hs.get_registration_handler()

        # this is required by the request_handler wrapper
        self.clock = hs.get_clock()

        # Consent must be configured to create this resource.
        default_consent_version = hs.config.consent.user_consent_version
        consent_template_directory = hs.config.consent.user_consent_template_dir
        if default_consent_version is None or consent_template_directory is None:
            raise ConfigError(
                "Consent resource is enabled but user_consent section is "
                "missing in config file."
            )
        self._default_consent_version = default_consent_version

        # TODO: switch to synapse.util.templates.build_jinja_env
        loader = jinja2.FileSystemLoader(consent_template_directory)
        self._jinja_env = jinja2.Environment(
            loader=loader, autoescape=jinja2.select_autoescape(["html", "htm", "xml"])
        )

        if hs.config.key.form_secret is None:
            raise ConfigError(
                "Consent resource is enabled but form_secret is not set in "
                "config file. It should be set to an arbitrary secret string."
            )

        self._hmac_secret = hs.config.key.form_secret.encode("utf-8")
示例#3
0
    def read_config(self, config: JsonDict, **kwargs: Any) -> None:
        self.spam_checkers: List[Tuple[Any, Dict]] = []

        spam_checkers = config.get("spam_checker") or []
        if isinstance(spam_checkers, dict):
            # The spam_checker config option used to only support one
            # spam checker, and thus was simply a dictionary with module
            # and config keys. Support this old behaviour by checking
            # to see if the option resolves to a dictionary
            self.spam_checkers.append(
                load_module(spam_checkers, ("spam_checker", )))
        elif isinstance(spam_checkers, list):
            for i, spam_checker in enumerate(spam_checkers):
                config_path = ("spam_checker", "<item %i>" % i)
                if not isinstance(spam_checker, dict):
                    raise ConfigError("expected a mapping", config_path)

                self.spam_checkers.append(
                    load_module(spam_checker, config_path))
        else:
            raise ConfigError("spam_checker syntax is incorrect")

        # If this configuration is being used in any way, warn the admin that it is going
        # away soon.
        if self.spam_checkers:
            logger.warning(LEGACY_SPAM_CHECKER_WARNING)
示例#4
0
    def parse_config(config_dict: dict) -> PFSPresenceRouterConfig:
        """Parse a configuration dictionary from the homeserver config, do
        some validation and return a typed PFSPresenceRouterConfig.

        Args:
            config_dict: The configuration dictionary.

        Returns:
            A validated config object.
        """
        try:
            blockchain_sync = int(config_dict.get("blockchain_sync_seconds", "15"))
        except ValueError:
            raise ConfigError("`blockchain_sync_seconds` needs to be an integer")

        try:
            service_registry_address = to_canonical_address(
                to_checksum_address(config_dict.get("service_registry_address"))  # type: ignore
            )
        except (TypeError, ValueError):
            raise ConfigError("`service_registry_address` is not a valid address or missing")

        try:
            ethereum_rpc = config_dict.get("ethereum_rpc")
            parsed_ethereum_rpc = urlparse(ethereum_rpc)
            if not all([parsed_ethereum_rpc.scheme, parsed_ethereum_rpc.netloc]):
                raise ValueError()
        except ValueError:
            raise ConfigError("`ethereum_rpc` is not properly configured")

        return PFSPresenceRouterConfig(
            service_registry_address, ethereum_rpc, blockchain_sync  # type: ignore
        )
示例#5
0
    def __init__(self, hs):
        """

        Args:
            hs (synapse.server.HomeServer):
        """
        self._server_notices_manager = hs.get_server_notices_manager()
        self._store = hs.get_datastore()

        self._users_in_progress = set()

        self._current_consent_version = hs.config.user_consent_version
        self._server_notice_content = hs.config.user_consent_server_notice_content
        self._send_to_guests = hs.config.user_consent_server_notice_to_guests

        if self._server_notice_content is not None:
            if not self._server_notices_manager.is_enabled():
                raise ConfigError(
                    "user_consent configuration requires server notices, but "
                    "server notices are not enabled."
                )
            if "body" not in self._server_notice_content:
                raise ConfigError(
                    "user_consent server_notice_consent must contain a 'body' key."
                )

            self._consent_uri_builder = ConsentURIBuilder(hs.config)
示例#6
0
    def __init__(self, hs):
        """
        Args:
            hs (synapse.server.HomeServer): homeserver
        """
        Resource.__init__(self)

        self.hs = hs
        self.store = hs.get_datastore()
        self.registration_handler = hs.get_registration_handler()

        # this is required by the request_handler wrapper
        self.clock = hs.get_clock()

        self._default_consent_version = hs.config.user_consent_version
        if self._default_consent_version is None:
            raise ConfigError(
                "Consent resource is enabled but user_consent section is "
                "missing in config file.", )

        consent_template_directory = hs.config.user_consent_template_dir

        loader = jinja2.FileSystemLoader(consent_template_directory)
        self._jinja_env = jinja2.Environment(
            loader=loader,
            autoescape=jinja2.select_autoescape(['html', 'htm', 'xml']),
        )

        if hs.config.form_secret is None:
            raise ConfigError(
                "Consent resource is enabled but form_secret is not set in "
                "config file. It should be set to an arbitrary secret string.",
            )

        self._hmac_secret = hs.config.form_secret.encode("utf-8")
示例#7
0
    def __init__(self, hs_config):
        """
        Args:
            hs_config (synapse.config.homeserver.HomeServerConfig):
        """
        if hs_config.form_secret is None:
            raise ConfigError("form_secret not set in config")
        if hs_config.public_baseurl is None:
            raise ConfigError("public_baseurl not set in config")

        self._hmac_secret = hs_config.form_secret.encode("utf-8")
        self._public_baseurl = hs_config.public_baseurl
示例#8
0
    def parse_config(config: dict) -> JinjaOidcMappingConfig:
        subject_claim = config.get("subject_claim", "sub")

        if "localpart_template" not in config:
            raise ConfigError(
                "missing key: oidc_config.user_mapping_provider.config.localpart_template"
            )

        try:
            localpart_template = env.from_string(config["localpart_template"])
        except Exception as e:
            raise ConfigError(
                "invalid jinja template for oidc_config.user_mapping_provider.config.localpart_template: %r"
                % (e,)
            )

        display_name_template = None  # type: Optional[Template]
        if "display_name_template" in config:
            try:
                display_name_template = env.from_string(config["display_name_template"])
            except Exception as e:
                raise ConfigError(
                    "invalid jinja template for oidc_config.user_mapping_provider.config.display_name_template: %r"
                    % (e,)
                )

        extra_attributes = {}  # type Dict[str, Template]
        if "extra_attributes" in config:
            extra_attributes_config = config.get("extra_attributes") or {}
            if not isinstance(extra_attributes_config, dict):
                raise ConfigError(
                    "oidc_config.user_mapping_provider.config.extra_attributes must be a dict"
                )

            for key, value in extra_attributes_config.items():
                try:
                    extra_attributes[key] = env.from_string(value)
                except Exception as e:
                    raise ConfigError(
                        "invalid jinja template for oidc_config.user_mapping_provider.config.extra_attributes.%s: %r"
                        % (key, e)
                    )

        return JinjaOidcMappingConfig(
            subject_claim=subject_claim,
            localpart_template=localpart_template,
            display_name_template=display_name_template,
            extra_attributes=extra_attributes,
        )
示例#9
0
    def read_config(self, config, **kwargs):
        consent_config = config.get("user_consent")
        self.terms_template = self.read_template("terms.html")

        if consent_config is None:
            return
        self.user_consent_version = str(consent_config["version"])
        self.user_consent_template_dir = self.abspath(consent_config["template_dir"])
        if not path.isdir(self.user_consent_template_dir):
            raise ConfigError(
                "Could not find template directory '%s'"
                % (self.user_consent_template_dir,)
            )
        self.user_consent_server_notice_content = consent_config.get(
            "server_notice_content"
        )
        self.block_events_without_consent_error = consent_config.get(
            "block_events_error"
        )
        self.user_consent_server_notice_to_guests = bool(
            consent_config.get("send_server_notice_to_guests", False)
        )
        self.user_consent_at_registration = bool(
            consent_config.get("require_at_registration", False)
        )
        self.user_consent_policy_name = consent_config.get(
            "policy_name", "Privacy Policy"
        )
示例#10
0
def init_tracer(hs: "HomeServer"):
    """Set the whitelists and initialise the JaegerClient tracer"""
    global opentracing
    if not hs.config.opentracer_enabled:
        # We don't have a tracer
        opentracing = None
        return

    if not opentracing or not JaegerConfig:
        raise ConfigError(
            "The server has been configured to use opentracing but opentracing is not "
            "installed.")

    # Pull out the jaeger config if it was given. Otherwise set it to something sensible.
    # See https://github.com/jaegertracing/jaeger-client-python/blob/master/jaeger_client/config.py

    set_homeserver_whitelist(hs.config.opentracer_whitelist)

    from jaeger_client.metrics.prometheus import PrometheusMetricsFactory

    config = JaegerConfig(
        config=hs.config.jaeger_config,
        service_name=f"{hs.config.server_name} {hs.get_instance_name()}",
        scope_manager=LogContextScopeManager(hs.config),
        metrics_factory=PrometheusMetricsFactory(),
    )

    # If we have the rust jaeger reporter available let's use that.
    if RustReporter:
        logger.info("Using rust_python_jaeger_reporter library")
        tracer = config.create_tracer(RustReporter(), config.sampler)
        opentracing.set_global_tracer(tracer)
    else:
        config.initialize_tracer()
示例#11
0
def init_tracer(config):
    """Set the whitelists and initialise the JaegerClient tracer

    Args:
        config (HomeserverConfig): The config used by the homeserver
    """
    global opentracing
    if not config.opentracer_enabled:
        # We don't have a tracer
        opentracing = None
        return

    if not opentracing or not JaegerConfig:
        raise ConfigError(
            "The server has been configured to use opentracing but opentracing is not "
            "installed.")

    # Include the worker name
    name = config.worker_name if config.worker_name else "master"

    # Pull out the jaeger config if it was given. Otherwise set it to something sensible.
    # See https://github.com/jaegertracing/jaeger-client-python/blob/master/jaeger_client/config.py

    set_homeserver_whitelist(config.opentracer_whitelist)

    JaegerConfig(
        config=config.jaeger_config,
        service_name="{} {}".format(config.server_name, name),
        scope_manager=LogContextScopeManager(config),
    ).initialize_tracer()
示例#12
0
 def parse_template_config(option_name: str) -> Optional[Template]:
     if option_name not in config:
         return None
     try:
         return env.from_string(config[option_name])
     except Exception as e:
         raise ConfigError("invalid jinja template",
                           path=[option_name]) from e
示例#13
0
    def __init__(self, hs):
        """
        Args:
            hs (synapse.server.HomeServer): homeserver
        """
        Resource.__init__(self)

        self.hs = hs
        self.store = hs.get_datastore()

        # this is required by the request_handler wrapper
        self.clock = hs.get_clock()

        self._default_consent_version = hs.config.user_consent_version
        if self._default_consent_version is None:
            raise ConfigError(
                "Consent resource is enabled but user_consent section is "
                "missing in config file.",
            )

        # daemonize changes the cwd to /, so make the path absolute now.
        consent_template_directory = path.abspath(
            hs.config.user_consent_template_dir,
        )
        if not path.isdir(consent_template_directory):
            raise ConfigError(
                "Could not find template directory '%s'" % (
                    consent_template_directory,
                ),
            )

        loader = jinja2.FileSystemLoader(consent_template_directory)
        self._jinja_env = jinja2.Environment(
            loader=loader,
            autoescape=jinja2.select_autoescape(['html', 'htm', 'xml']),
        )

        if hs.config.form_secret is None:
            raise ConfigError(
                "Consent resource is enabled but form_secret is not set in "
                "config file. It should be set to an arbitrary secret string.",
            )

        self._hmac_secret = hs.config.form_secret.encode("utf-8")
示例#14
0
    def parse_config(config: dict) -> JinjaOidcMappingConfig:
        subject_claim = config.get("subject_claim", "sub")

        localpart_template = None  # type: Optional[Template]
        if "localpart_template" in config:
            try:
                localpart_template = env.from_string(config["localpart_template"])
            except Exception as e:
                raise ConfigError(
                    "invalid jinja template", path=["localpart_template"]
                ) from e

        display_name_template = None  # type: Optional[Template]
        if "display_name_template" in config:
            try:
                display_name_template = env.from_string(config["display_name_template"])
            except Exception as e:
                raise ConfigError(
                    "invalid jinja template", path=["display_name_template"]
                ) from e

        extra_attributes = {}  # type Dict[str, Template]
        if "extra_attributes" in config:
            extra_attributes_config = config.get("extra_attributes") or {}
            if not isinstance(extra_attributes_config, dict):
                raise ConfigError("must be a dict", path=["extra_attributes"])

            for key, value in extra_attributes_config.items():
                try:
                    extra_attributes[key] = env.from_string(value)
                except Exception as e:
                    raise ConfigError(
                        "invalid jinja template", path=["extra_attributes", key]
                    ) from e

        return JinjaOidcMappingConfig(
            subject_claim=subject_claim,
            localpart_template=localpart_template,
            display_name_template=display_name_template,
            extra_attributes=extra_attributes,
        )
示例#15
0
    def read_config(self, config, **kwargs):
        self.spam_checkers = []  # type: List[Tuple[Any, Dict]]

        spam_checkers = config.get("spam_checker") or []
        if isinstance(spam_checkers, dict):
            # The spam_checker config option used to only support one
            # spam checker, and thus was simply a dictionary with module
            # and config keys. Support this old behaviour by checking
            # to see if the option resolves to a dictionary
            self.spam_checkers.append(
                load_module(spam_checkers, ("spam_checker", )))
        elif isinstance(spam_checkers, list):
            for i, spam_checker in enumerate(spam_checkers):
                config_path = ("spam_checker", "<item %i>" % i)
                if not isinstance(spam_checker, dict):
                    raise ConfigError("expected a mapping", config_path)

                self.spam_checkers.append(
                    load_module(spam_checker, config_path))
        else:
            raise ConfigError("spam_checker syntax is incorrect")
示例#16
0
    def parse_config(config: dict) -> SamlConfig:
        """Parse the dict provided by the homeserver's config
        Args:
            config: A dictionary containing configuration options for this provider
        Returns:
            SamlConfig: A custom config object for this module
        """
        # Parse config options and use defaults where necessary
        mxid_source_attribute = config.get("mxid_source_attribute", "uid")
        mapping_type = config.get("mxid_mapping", "hexencode")

        # Retrieve the associating mapping function
        try:
            mxid_mapper = MXID_MAPPER_MAP[mapping_type]
        except KeyError:
            raise ConfigError(
                "saml2_config.user_mapping_provider.config: '%s' is not a valid "
                "mxid_mapping value" % (mapping_type, ))

        return SamlConfig(mxid_source_attribute, mxid_mapper)
示例#17
0
def init_tracer(config):
    """Set the whitelists and initialise the JaegerClient tracer

    Args:
        config (HomeserverConfig): The config used by the homeserver
    """
    global opentracing
    if not config.opentracer_enabled:
        # We don't have a tracer
        opentracing = None
        return

    if not opentracing or not JaegerConfig:
        raise ConfigError(
            "The server has been configured to use opentracing but opentracing is not "
            "installed.")

    # Include the worker name
    name = config.worker_name if config.worker_name else "master"

    set_homeserver_whitelist(config.opentracer_whitelist)
    jaeger_config = JaegerConfig(
        config={
            "sampler": {
                "type": "const",
                "param": 1
            },
            "logging": True
        },
        service_name="{} {}".format(config.server_name, name),
        scope_manager=LogContextScopeManager(config),
    )
    jaeger_config.initialize_tracer()

    # Set up tags to be opentracing's tags
    global tags
    tags = opentracing.tags
示例#18
0
文件: register.py 项目: Fnux/synapse
def _calculate_registration_flows(
        config: HomeServerConfig,
        auth_handler: AuthHandler) -> List[List[str]]:
    """Get a suitable flows list for registration

    Args:
        config: server configuration
        auth_handler: authorization handler

    Returns: a list of supported flows
    """
    # FIXME: need a better error than "no auth flow found" for scenarios
    # where we required 3PID for registration but the user didn't give one
    require_email = "email" in config.registration.registrations_require_3pid
    require_msisdn = "msisdn" in config.registration.registrations_require_3pid

    show_msisdn = True
    show_email = True

    if config.registration.disable_msisdn_registration:
        show_msisdn = False
        require_msisdn = False

    enabled_auth_types = auth_handler.get_enabled_auth_types()
    if LoginType.EMAIL_IDENTITY not in enabled_auth_types:
        show_email = False
        if require_email:
            raise ConfigError(
                "Configuration requires email address at registration, but email "
                "validation is not configured")

    if LoginType.MSISDN not in enabled_auth_types:
        show_msisdn = False
        if require_msisdn:
            raise ConfigError(
                "Configuration requires msisdn at registration, but msisdn "
                "validation is not configured")

    flows = []

    # only support 3PIDless registration if no 3PIDs are required
    if not require_email and not require_msisdn:
        # Add a dummy step here, otherwise if a client completes
        # recaptcha first we'll assume they were going for this flow
        # and complete the request, when they could have been trying to
        # complete one of the flows with email/msisdn auth.
        flows.append([LoginType.DUMMY])

    # only support the email-only flow if we don't require MSISDN 3PIDs
    if show_email and not require_msisdn:
        flows.append([LoginType.EMAIL_IDENTITY])

    # only support the MSISDN-only flow if we don't require email 3PIDs
    if show_msisdn and not require_email:
        flows.append([LoginType.MSISDN])

    if show_email and show_msisdn:
        # always let users provide both MSISDN & email
        flows.append([LoginType.MSISDN, LoginType.EMAIL_IDENTITY])

    # Prepend m.login.terms to all flows if we're requiring consent
    if config.consent.user_consent_at_registration:
        for flow in flows:
            flow.insert(0, LoginType.TERMS)

    # Prepend recaptcha to all flows if we're requiring captcha
    if config.captcha.enable_registration_captcha:
        for flow in flows:
            flow.insert(0, LoginType.RECAPTCHA)

    # Prepend registration token to all flows if we're requiring a token
    if config.registration.registration_requires_token:
        for flow in flows:
            flow.insert(0, LoginType.REGISTRATION_TOKEN)

    return flows
示例#19
0
 def __init__(self, hs_config: HomeServerConfig):
     if hs_config.key.form_secret is None:
         raise ConfigError("form_secret not set in config")
     self._hmac_secret = hs_config.key.form_secret.encode("utf-8")
     self._public_baseurl = hs_config.server.public_baseurl