summary refs log tree commit diff
path: root/synapse/config
diff options
context:
space:
mode:
authorWill Hunt <willh@matrix.org>2021-03-22 13:40:27 +0000
committerWill Hunt <willh@matrix.org>2021-03-22 13:40:27 +0000
commit9009d29b81f16d3444f3f5418d3ffbc3f490181f (patch)
treeda77fc6ba6f48e018ac6d9c713016357c4c1a76f /synapse/config
parentMerge tag 'v1.30.0' into hs/hacked-together-event-cache (diff)
parentMerge branch 'master' into develop (diff)
downloadsynapse-9009d29b81f16d3444f3f5418d3ffbc3f490181f.tar.xz
Merge remote-tracking branch 'origin/develop' into hs/hacked-together-event-cache
Diffstat (limited to 'synapse/config')
-rw-r--r--synapse/config/experimental.py4
-rw-r--r--synapse/config/key.py6
-rw-r--r--synapse/config/metrics.py4
-rw-r--r--synapse/config/oidc_config.py44
-rw-r--r--synapse/config/repository.py4
-rw-r--r--synapse/config/saml2_config.py4
-rw-r--r--synapse/config/tracer.py4
7 files changed, 63 insertions, 7 deletions
diff --git a/synapse/config/experimental.py b/synapse/config/experimental.py
index b1c1c51e4d..86f4d9af9d 100644
--- a/synapse/config/experimental.py
+++ b/synapse/config/experimental.py
@@ -27,3 +27,7 @@ class ExperimentalConfig(Config):
 
         # MSC2858 (multiple SSO identity providers)
         self.msc2858_enabled = experimental.get("msc2858_enabled", False)  # type: bool
+        # Spaces (MSC1772, MSC2946, etc)
+        self.spaces_enabled = experimental.get("spaces_enabled", False)  # type: bool
+        # MSC3026 (busy presence state)
+        self.msc3026_enabled = experimental.get("msc3026_enabled", False)  # type: bool
diff --git a/synapse/config/key.py b/synapse/config/key.py
index de964dff13..350ff1d665 100644
--- a/synapse/config/key.py
+++ b/synapse/config/key.py
@@ -404,7 +404,11 @@ def _parse_key_servers(key_servers, federation_verify_certificates):
     try:
         jsonschema.validate(key_servers, TRUSTED_KEY_SERVERS_SCHEMA)
     except jsonschema.ValidationError as e:
-        raise ConfigError("Unable to parse 'trusted_key_servers': " + e.message)
+        raise ConfigError(
+            "Unable to parse 'trusted_key_servers': {}".format(
+                e.message  # noqa: B306, jsonschema.ValidationError.message is a valid attribute
+            )
+        )
 
     for server in key_servers:
         server_name = server["server_name"]
diff --git a/synapse/config/metrics.py b/synapse/config/metrics.py
index dfd27e1523..2b289f4208 100644
--- a/synapse/config/metrics.py
+++ b/synapse/config/metrics.py
@@ -56,7 +56,9 @@ class MetricsConfig(Config):
             try:
                 check_requirements("sentry")
             except DependencyException as e:
-                raise ConfigError(e.message)
+                raise ConfigError(
+                    e.message  # noqa: B306, DependencyException.message is a property
+                )
 
             self.sentry_dsn = config["sentry"].get("dsn")
             if not self.sentry_dsn:
diff --git a/synapse/config/oidc_config.py b/synapse/config/oidc_config.py
index 2bfb537c15..747ab9a7fe 100644
--- a/synapse/config/oidc_config.py
+++ b/synapse/config/oidc_config.py
@@ -15,11 +15,12 @@
 # limitations under the License.
 
 from collections import Counter
-from typing import Iterable, Mapping, Optional, Tuple, Type
+from typing import Iterable, List, Mapping, Optional, Tuple, Type
 
 import attr
 
 from synapse.config._util import validate_config
+from synapse.config.sso import SsoAttributeRequirement
 from synapse.python_dependencies import DependencyException, check_requirements
 from synapse.types import Collection, JsonDict
 from synapse.util.module_loader import load_module
@@ -41,7 +42,9 @@ class OIDCConfig(Config):
         try:
             check_requirements("oidc")
         except DependencyException as e:
-            raise ConfigError(e.message) from e
+            raise ConfigError(
+                e.message  # noqa: B306, DependencyException.message is a property
+            ) from e
 
         # check we don't have any duplicate idp_ids now. (The SSO handler will also
         # check for duplicates when the REST listeners get registered, but that happens
@@ -191,6 +194,24 @@ class OIDCConfig(Config):
         #           which is set to the claims returned by the UserInfo Endpoint and/or
         #           in the ID Token.
         #
+        #   It is possible to configure Synapse to only allow logins if certain attributes
+        #   match particular values in the OIDC userinfo. The requirements can be listed under
+        #   `attribute_requirements` as shown below. All of the listed attributes must
+        #   match for the login to be permitted. Additional attributes can be added to
+        #   userinfo by expanding the `scopes` section of the OIDC config to retrieve
+        #   additional information from the OIDC provider.
+        #
+        #   If the OIDC claim is a list, then the attribute must match any value in the list.
+        #   Otherwise, it must exactly match the value of the claim. Using the example
+        #   below, the `family_name` claim MUST be "Stephensson", but the `groups`
+        #   claim MUST contain "admin".
+        #
+        #   attribute_requirements:
+        #     - attribute: family_name
+        #       value: "Stephensson"
+        #     - attribute: groups
+        #       value: "admin"
+        #
         # See https://github.com/matrix-org/synapse/blob/master/docs/openid.md
         # for information on how to configure these options.
         #
@@ -223,6 +244,9 @@ class OIDCConfig(Config):
           #      localpart_template: "{{{{ user.login }}}}"
           #      display_name_template: "{{{{ user.name }}}}"
           #      email_template: "{{{{ user.email }}}}"
+          #  attribute_requirements:
+          #    - attribute: userGroup
+          #      value: "synapseUsers"
 
           # For use with Keycloak
           #
@@ -232,6 +256,9 @@ class OIDCConfig(Config):
           #  client_id: "synapse"
           #  client_secret: "copy secret generated in Keycloak UI"
           #  scopes: ["openid", "profile"]
+          #  attribute_requirements:
+          #    - attribute: groups
+          #      value: "admin"
 
           # For use with Github
           #
@@ -329,6 +356,10 @@ OIDC_PROVIDER_CONFIG_SCHEMA = {
         },
         "allow_existing_users": {"type": "boolean"},
         "user_mapping_provider": {"type": ["object", "null"]},
+        "attribute_requirements": {
+            "type": "array",
+            "items": SsoAttributeRequirement.JSON_SCHEMA,
+        },
     },
 }
 
@@ -465,6 +496,11 @@ def _parse_oidc_config_dict(
             jwt_header=client_secret_jwt_key_config["jwt_header"],
             jwt_payload=client_secret_jwt_key_config.get("jwt_payload", {}),
         )
+    # parse attribute_requirements from config (list of dicts) into a list of SsoAttributeRequirement
+    attribute_requirements = [
+        SsoAttributeRequirement(**x)
+        for x in oidc_config.get("attribute_requirements", [])
+    ]
 
     return OidcProviderConfig(
         idp_id=idp_id,
@@ -488,6 +524,7 @@ def _parse_oidc_config_dict(
         allow_existing_users=oidc_config.get("allow_existing_users", False),
         user_mapping_provider_class=user_mapping_provider_class,
         user_mapping_provider_config=user_mapping_provider_config,
+        attribute_requirements=attribute_requirements,
     )
 
 
@@ -577,3 +614,6 @@ class OidcProviderConfig:
 
     # the config of the user mapping provider
     user_mapping_provider_config = attr.ib()
+
+    # required attributes to require in userinfo to allow login/registration
+    attribute_requirements = attr.ib(type=List[SsoAttributeRequirement])
diff --git a/synapse/config/repository.py b/synapse/config/repository.py
index 69d9de5a43..061c4ec83f 100644
--- a/synapse/config/repository.py
+++ b/synapse/config/repository.py
@@ -176,7 +176,9 @@ class ContentRepositoryConfig(Config):
                 check_requirements("url_preview")
 
             except DependencyException as e:
-                raise ConfigError(e.message)
+                raise ConfigError(
+                    e.message  # noqa: B306, DependencyException.message is a property
+                )
 
             if "url_preview_ip_range_blacklist" not in config:
                 raise ConfigError(
diff --git a/synapse/config/saml2_config.py b/synapse/config/saml2_config.py
index 4b494f217f..6db9cb5ced 100644
--- a/synapse/config/saml2_config.py
+++ b/synapse/config/saml2_config.py
@@ -76,7 +76,9 @@ class SAML2Config(Config):
         try:
             check_requirements("saml2")
         except DependencyException as e:
-            raise ConfigError(e.message)
+            raise ConfigError(
+                e.message  # noqa: B306, DependencyException.message is a property
+            )
 
         self.saml2_enabled = True
 
diff --git a/synapse/config/tracer.py b/synapse/config/tracer.py
index 0c1a854f09..727a1e7008 100644
--- a/synapse/config/tracer.py
+++ b/synapse/config/tracer.py
@@ -39,7 +39,9 @@ class TracerConfig(Config):
         try:
             check_requirements("opentracing")
         except DependencyException as e:
-            raise ConfigError(e.message)
+            raise ConfigError(
+                e.message  # noqa: B306, DependencyException.message is a property
+            )
 
         # The tracer is enabled so sanitize the config