Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 70c6f50

Browse files
committed
Merge commit 'db131b6b2' into anoa/dinsic_release_1_21_x
* commit 'db131b6b2': Change the default log config to reduce disk I/O and storage (#8040) Implement login blocking based on SAML attributes (#8052) Add an assertion on prev_events in create_new_client_event (#8041) Typo Lint why mypy why Lint Incorporate review Incorporate review Fix PUT /pushrules to use the right rule IDs Back out the database hack and replace it with a temporary config setting Fix cache name Fix cache invalidation calls Lint Changelog Implement new experimental push rules with a database hack to enable them
2 parents 76a6aa1 + db131b6 commit 70c6f50

File tree

16 files changed

+476
-35
lines changed

16 files changed

+476
-35
lines changed

changelog.d/7997.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Implement new experimental push rules for some users.

changelog.d/8040.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Change the default log config to reduce disk I/O and storage for new servers.

changelog.d/8041.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add an assertion on prev_events in create_new_client_event.

changelog.d/8052.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow login to be blocked based on the values of SAML attributes.

docs/sample_config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,6 +1577,17 @@ saml2_config:
15771577
#
15781578
#grandfathered_mxid_source_attribute: upn
15791579

1580+
# It is possible to configure Synapse to only allow logins if SAML attributes
1581+
# match particular values. The requirements can be listed under
1582+
# `attribute_requirements` as shown below. All of the listed attributes must
1583+
# match for the login to be permitted.
1584+
#
1585+
#attribute_requirements:
1586+
# - attribute: userGroup
1587+
# value: "staff"
1588+
# - attribute: department
1589+
# value: "sales"
1590+
15801591
# Directory in which Synapse will try to find the template files below.
15811592
# If not set, default templates from within the Synapse package will be used.
15821593
#

docs/sample_log_config.yaml

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,29 @@ filters:
1818

1919
handlers:
2020
file:
21-
class: logging.handlers.RotatingFileHandler
21+
class: logging.handlers.TimedRotatingFileHandler
2222
formatter: precise
2323
filename: /var/log/matrix-synapse/homeserver.log
24-
maxBytes: 104857600
25-
backupCount: 10
26-
filters: [context]
24+
when: midnight
25+
backupCount: 3 # Does not include the current log file.
2726
encoding: utf8
27+
28+
# Default to buffering writes to log file for efficiency. This means that
29+
# will be a delay for INFO/DEBUG logs to get written, but WARNING/ERROR
30+
# logs will still be flushed immediately.
31+
buffer:
32+
class: logging.handlers.MemoryHandler
33+
filters: [context]
34+
target: file
35+
# The capacity is the number of log lines that are buffered before
36+
# being written to disk. Increasing this will lead to better
37+
# performance, at the expensive of it taking longer for log lines to
38+
# be written to disk.
39+
capacity: 10
40+
flushLevel: 30 # Flush for WARNING logs as well
41+
42+
# A handler that writes logs to stderr. Unused by default, but can be used
43+
# instead of "buffer" and "file" in the logger handlers.
2844
console:
2945
class: logging.StreamHandler
3046
formatter: precise
@@ -36,8 +52,23 @@ loggers:
3652
# information such as access tokens.
3753
level: INFO
3854

55+
twisted:
56+
# We send the twisted logging directly to the file handler,
57+
# to work around https://github.com/matrix-org/synapse/issues/3471
58+
# when using "buffer" logger. Use "console" to log to stderr instead.
59+
handlers: [file]
60+
propagate: false
61+
3962
root:
4063
level: INFO
41-
handlers: [file, console]
64+
65+
# Write logs to the `buffer` handler, which will buffer them together in memory,
66+
# then write them to a file.
67+
#
68+
# Replace "buffer" with "console" to log to stderr instead. (Note that you'll
69+
# also need to update the configuation for the `twisted` logger above, in
70+
# this case.)
71+
#
72+
handlers: [buffer]
4273

4374
disable_existing_loggers: false

synapse/config/_util.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright 2020 The Matrix.org Foundation C.I.C.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
from typing import Any, List
16+
17+
import jsonschema
18+
19+
from synapse.config._base import ConfigError
20+
from synapse.types import JsonDict
21+
22+
23+
def validate_config(json_schema: JsonDict, config: Any, config_path: List[str]) -> None:
24+
"""Validates a config setting against a JsonSchema definition
25+
26+
This can be used to validate a section of the config file against a schema
27+
definition. If the validation fails, a ConfigError is raised with a textual
28+
description of the problem.
29+
30+
Args:
31+
json_schema: the schema to validate against
32+
config: the configuration value to be validated
33+
config_path: the path within the config file. This will be used as a basis
34+
for the error message.
35+
"""
36+
try:
37+
jsonschema.validate(config, json_schema)
38+
except jsonschema.ValidationError as e:
39+
# copy `config_path` before modifying it.
40+
path = list(config_path)
41+
for p in list(e.path):
42+
if isinstance(p, int):
43+
path.append("<item %i>" % p)
44+
else:
45+
path.append(str(p))
46+
47+
raise ConfigError(
48+
"Unable to parse configuration: %s at %s" % (e.message, ".".join(path))
49+
)

synapse/config/logger.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,29 @@
6262
6363
handlers:
6464
file:
65-
class: logging.handlers.RotatingFileHandler
65+
class: logging.handlers.TimedRotatingFileHandler
6666
formatter: precise
6767
filename: ${log_file}
68-
maxBytes: 104857600
69-
backupCount: 10
70-
filters: [context]
68+
when: midnight
69+
backupCount: 3 # Does not include the current log file.
7170
encoding: utf8
71+
72+
# Default to buffering writes to log file for efficiency. This means that
73+
# will be a delay for INFO/DEBUG logs to get written, but WARNING/ERROR
74+
# logs will still be flushed immediately.
75+
buffer:
76+
class: logging.handlers.MemoryHandler
77+
filters: [context]
78+
target: file
79+
# The capacity is the number of log lines that are buffered before
80+
# being written to disk. Increasing this will lead to better
81+
# performance, at the expensive of it taking longer for log lines to
82+
# be written to disk.
83+
capacity: 10
84+
flushLevel: 30 # Flush for WARNING logs as well
85+
86+
# A handler that writes logs to stderr. Unused by default, but can be used
87+
# instead of "buffer" and "file" in the logger handlers.
7288
console:
7389
class: logging.StreamHandler
7490
formatter: precise
@@ -80,9 +96,24 @@
8096
# information such as access tokens.
8197
level: INFO
8298
99+
twisted:
100+
# We send the twisted logging directly to the file handler,
101+
# to work around https://github.com/matrix-org/synapse/issues/3471
102+
# when using "buffer" logger. Use "console" to log to stderr instead.
103+
handlers: [file]
104+
propagate: false
105+
83106
root:
84107
level: INFO
85-
handlers: [file, console]
108+
109+
# Write logs to the `buffer` handler, which will buffer them together in memory,
110+
# then write them to a file.
111+
#
112+
# Replace "buffer" with "console" to log to stderr instead. (Note that you'll
113+
# also need to update the configuation for the `twisted` logger above, in
114+
# this case.)
115+
#
116+
handlers: [buffer]
86117
87118
disable_existing_loggers: false
88119
"""

synapse/config/saml2_config.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
# limitations under the License.
1616

1717
import logging
18+
from typing import Any, List
1819

20+
import attr
1921
import jinja2
2022
import pkg_resources
2123

2224
from synapse.python_dependencies import DependencyException, check_requirements
2325
from synapse.util.module_loader import load_module, load_python_module
2426

2527
from ._base import Config, ConfigError
28+
from ._util import validate_config
2629

2730
logger = logging.getLogger(__name__)
2831

@@ -80,6 +83,11 @@ def read_config(self, config, **kwargs):
8083

8184
self.saml2_enabled = True
8285

86+
attribute_requirements = saml2_config.get("attribute_requirements") or []
87+
self.attribute_requirements = _parse_attribute_requirements_def(
88+
attribute_requirements
89+
)
90+
8391
self.saml2_grandfathered_mxid_source_attribute = saml2_config.get(
8492
"grandfathered_mxid_source_attribute", "uid"
8593
)
@@ -341,6 +349,17 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
341349
#
342350
#grandfathered_mxid_source_attribute: upn
343351
352+
# It is possible to configure Synapse to only allow logins if SAML attributes
353+
# match particular values. The requirements can be listed under
354+
# `attribute_requirements` as shown below. All of the listed attributes must
355+
# match for the login to be permitted.
356+
#
357+
#attribute_requirements:
358+
# - attribute: userGroup
359+
# value: "staff"
360+
# - attribute: department
361+
# value: "sales"
362+
344363
# Directory in which Synapse will try to find the template files below.
345364
# If not set, default templates from within the Synapse package will be used.
346365
#
@@ -368,3 +387,34 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
368387
""" % {
369388
"config_dir_path": config_dir_path
370389
}
390+
391+
392+
@attr.s(frozen=True)
393+
class SamlAttributeRequirement:
394+
"""Object describing a single requirement for SAML attributes."""
395+
396+
attribute = attr.ib(type=str)
397+
value = attr.ib(type=str)
398+
399+
JSON_SCHEMA = {
400+
"type": "object",
401+
"properties": {"attribute": {"type": "string"}, "value": {"type": "string"}},
402+
"required": ["attribute", "value"],
403+
}
404+
405+
406+
ATTRIBUTE_REQUIREMENTS_SCHEMA = {
407+
"type": "array",
408+
"items": SamlAttributeRequirement.JSON_SCHEMA,
409+
}
410+
411+
412+
def _parse_attribute_requirements_def(
413+
attribute_requirements: Any,
414+
) -> List[SamlAttributeRequirement]:
415+
validate_config(
416+
ATTRIBUTE_REQUIREMENTS_SCHEMA,
417+
attribute_requirements,
418+
config_path=["saml2_config", "attribute_requirements"],
419+
)
420+
return [SamlAttributeRequirement(**x) for x in attribute_requirements]

synapse/handlers/message.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,15 @@ async def create_new_client_event(
771771
else:
772772
prev_event_ids = await self.store.get_prev_events_for_room(builder.room_id)
773773

774+
# we now ought to have some prev_events (unless it's a create event).
775+
#
776+
# do a quick sanity check here, rather than waiting until we've created the
777+
# event and then try to auth it (which fails with a somewhat confusing "No
778+
# create event in auth events")
779+
assert (
780+
builder.type == EventTypes.Create or len(prev_event_ids) > 0
781+
), "Attempting to create an event with no prev_events"
782+
774783
event = await builder.build(prev_event_ids=prev_event_ids)
775784
context = await self.state.compute_event_context(event)
776785
if requester:

0 commit comments

Comments
 (0)