Inline `_check_event_auth` for outliers (#10926)
* Inline `_check_event_auth` for outliers When we are persisting an outlier, most of `_check_event_auth` is redundant: * `_update_auth_events_and_context_for_auth` does nothing, because the `input_auth_events` are (now) exactly the event's auth_events, which means that `missing_auth` is empty. * we don't care about soft-fail, kicking guest users or `send_on_behalf_of` for outliers ... so the only thing that matters is the auth itself, so let's just do that. * `_auth_and_persist_fetched_events_inner`: de-async `prep` `prep` no longer calls any `async` methods, so let's make it synchronous. * Simplify `_check_event_auth` We no longer need to support outliers here, which makes things rather simpler. * changelog * lint
This commit is contained in:
parent
eb2c7e51c4
commit
2622b28c5c
|
@ -0,0 +1 @@
|
||||||
|
Clean up some of the federation event authentication code for clarity.
|
|
@ -68,11 +68,7 @@ from synapse.types import (
|
||||||
UserID,
|
UserID,
|
||||||
get_domain_from_id,
|
get_domain_from_id,
|
||||||
)
|
)
|
||||||
from synapse.util.async_helpers import (
|
from synapse.util.async_helpers import Linearizer, concurrently_execute
|
||||||
Linearizer,
|
|
||||||
concurrently_execute,
|
|
||||||
yieldable_gather_results,
|
|
||||||
)
|
|
||||||
from synapse.util.iterutils import batch_iter
|
from synapse.util.iterutils import batch_iter
|
||||||
from synapse.util.retryutils import NotRetryingDestination
|
from synapse.util.retryutils import NotRetryingDestination
|
||||||
from synapse.util.stringutils import shortstr
|
from synapse.util.stringutils import shortstr
|
||||||
|
@ -1189,7 +1185,10 @@ class FederationEventHandler:
|
||||||
allow_rejected=True,
|
allow_rejected=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def prep(event: EventBase) -> Optional[Tuple[EventBase, EventContext]]:
|
room_version = await self._store.get_room_version_id(room_id)
|
||||||
|
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]
|
||||||
|
|
||||||
|
def prep(event: EventBase) -> Optional[Tuple[EventBase, EventContext]]:
|
||||||
with nested_logging_context(suffix=event.event_id):
|
with nested_logging_context(suffix=event.event_id):
|
||||||
auth = {}
|
auth = {}
|
||||||
for auth_event_id in event.auth_event_ids():
|
for auth_event_id in event.auth_event_ids():
|
||||||
|
@ -1207,17 +1206,15 @@ class FederationEventHandler:
|
||||||
auth[(ae.type, ae.state_key)] = ae
|
auth[(ae.type, ae.state_key)] = ae
|
||||||
|
|
||||||
context = EventContext.for_outlier()
|
context = EventContext.for_outlier()
|
||||||
context = await self._check_event_auth(
|
try:
|
||||||
origin,
|
event_auth.check(room_version_obj, event, auth_events=auth)
|
||||||
event,
|
except AuthError as e:
|
||||||
context,
|
logger.warning("Rejecting %r because %s", event, e)
|
||||||
claimed_auth_event_map=auth,
|
context.rejected = RejectedReason.AUTH_ERROR
|
||||||
)
|
|
||||||
return event, context
|
return event, context
|
||||||
|
|
||||||
events_to_persist = (
|
events_to_persist = (x for x in (prep(event) for event in fetched_events) if x)
|
||||||
x for x in await yieldable_gather_results(prep, fetched_events) if x
|
|
||||||
)
|
|
||||||
await self.persist_events_and_notify(room_id, tuple(events_to_persist))
|
await self.persist_events_and_notify(room_id, tuple(events_to_persist))
|
||||||
|
|
||||||
async def _check_event_auth(
|
async def _check_event_auth(
|
||||||
|
@ -1226,7 +1223,6 @@ class FederationEventHandler:
|
||||||
event: EventBase,
|
event: EventBase,
|
||||||
context: EventContext,
|
context: EventContext,
|
||||||
state: Optional[Iterable[EventBase]] = None,
|
state: Optional[Iterable[EventBase]] = None,
|
||||||
claimed_auth_event_map: Optional[StateMap[EventBase]] = None,
|
|
||||||
backfilled: bool = False,
|
backfilled: bool = False,
|
||||||
) -> EventContext:
|
) -> EventContext:
|
||||||
"""
|
"""
|
||||||
|
@ -1242,42 +1238,36 @@ class FederationEventHandler:
|
||||||
The state events used to check the event for soft-fail. If this is
|
The state events used to check the event for soft-fail. If this is
|
||||||
not provided the current state events will be used.
|
not provided the current state events will be used.
|
||||||
|
|
||||||
claimed_auth_event_map:
|
|
||||||
A map of (type, state_key) => event for the event's claimed auth_events.
|
|
||||||
Possibly including events that were rejected, or are in the wrong room.
|
|
||||||
|
|
||||||
Only populated when populating outliers.
|
|
||||||
|
|
||||||
backfilled: True if the event was backfilled.
|
backfilled: True if the event was backfilled.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The updated context object.
|
The updated context object.
|
||||||
"""
|
"""
|
||||||
# claimed_auth_event_map should be given iff the event is an outlier
|
# This method should only be used for non-outliers
|
||||||
assert bool(claimed_auth_event_map) == event.internal_metadata.outlier
|
assert not event.internal_metadata.outlier
|
||||||
|
|
||||||
room_version = await self._store.get_room_version_id(event.room_id)
|
room_version = await self._store.get_room_version_id(event.room_id)
|
||||||
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]
|
room_version_obj = KNOWN_ROOM_VERSIONS[room_version]
|
||||||
|
|
||||||
if claimed_auth_event_map:
|
# calculate what the auth events *should* be, to use as a basis for auth.
|
||||||
# if we have a copy of the auth events from the event, use that as the
|
|
||||||
# basis for auth.
|
|
||||||
auth_events = claimed_auth_event_map
|
|
||||||
else:
|
|
||||||
# otherwise, we calculate what the auth events *should* be, and use that
|
|
||||||
prev_state_ids = await context.get_prev_state_ids()
|
prev_state_ids = await context.get_prev_state_ids()
|
||||||
auth_events_ids = self._event_auth_handler.compute_auth_events(
|
auth_events_ids = self._event_auth_handler.compute_auth_events(
|
||||||
event, prev_state_ids, for_verification=True
|
event, prev_state_ids, for_verification=True
|
||||||
)
|
)
|
||||||
auth_events_x = await self._store.get_events(auth_events_ids)
|
auth_events_x = await self._store.get_events(auth_events_ids)
|
||||||
auth_events = {(e.type, e.state_key): e for e in auth_events_x.values()}
|
calculated_auth_event_map = {
|
||||||
|
(e.type, e.state_key): e for e in auth_events_x.values()
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
(
|
(
|
||||||
context,
|
context,
|
||||||
auth_events_for_auth,
|
auth_events_for_auth,
|
||||||
) = await self._update_auth_events_and_context_for_auth(
|
) = await self._update_auth_events_and_context_for_auth(
|
||||||
origin, event, context, auth_events
|
origin,
|
||||||
|
event,
|
||||||
|
context,
|
||||||
|
calculated_auth_event_map=calculated_auth_event_map,
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
# We don't really mind if the above fails, so lets not fail
|
# We don't really mind if the above fails, so lets not fail
|
||||||
|
@ -1289,7 +1279,7 @@ class FederationEventHandler:
|
||||||
"Ignoring failure and continuing processing of event.",
|
"Ignoring failure and continuing processing of event.",
|
||||||
event.event_id,
|
event.event_id,
|
||||||
)
|
)
|
||||||
auth_events_for_auth = auth_events
|
auth_events_for_auth = calculated_auth_event_map
|
||||||
|
|
||||||
try:
|
try:
|
||||||
event_auth.check(room_version_obj, event, auth_events=auth_events_for_auth)
|
event_auth.check(room_version_obj, event, auth_events=auth_events_for_auth)
|
||||||
|
@ -1425,7 +1415,7 @@ class FederationEventHandler:
|
||||||
origin: str,
|
origin: str,
|
||||||
event: EventBase,
|
event: EventBase,
|
||||||
context: EventContext,
|
context: EventContext,
|
||||||
input_auth_events: StateMap[EventBase],
|
calculated_auth_event_map: StateMap[EventBase],
|
||||||
) -> Tuple[EventContext, StateMap[EventBase]]:
|
) -> Tuple[EventContext, StateMap[EventBase]]:
|
||||||
"""Helper for _check_event_auth. See there for docs.
|
"""Helper for _check_event_auth. See there for docs.
|
||||||
|
|
||||||
|
@ -1443,19 +1433,17 @@ class FederationEventHandler:
|
||||||
event:
|
event:
|
||||||
context:
|
context:
|
||||||
|
|
||||||
input_auth_events:
|
calculated_auth_event_map:
|
||||||
Map from (event_type, state_key) to event
|
Our calculated auth_events based on the state of the room
|
||||||
|
at the event's position in the DAG.
|
||||||
Normally, our calculated auth_events based on the state of the room
|
|
||||||
at the event's position in the DAG, though occasionally (eg if the
|
|
||||||
event is an outlier), may be the auth events claimed by the remote
|
|
||||||
server.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
updated context, updated auth event map
|
updated context, updated auth event map
|
||||||
"""
|
"""
|
||||||
# take a copy of input_auth_events before we modify it.
|
assert not event.internal_metadata.outlier
|
||||||
auth_events: MutableStateMap[EventBase] = dict(input_auth_events)
|
|
||||||
|
# take a copy of calculated_auth_event_map before we modify it.
|
||||||
|
auth_events: MutableStateMap[EventBase] = dict(calculated_auth_event_map)
|
||||||
|
|
||||||
event_auth_events = set(event.auth_event_ids())
|
event_auth_events = set(event.auth_event_ids())
|
||||||
|
|
||||||
|
@ -1496,15 +1484,6 @@ class FederationEventHandler:
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if event.internal_metadata.is_outlier():
|
|
||||||
# XXX: given that, for an outlier, we'll be working with the
|
|
||||||
# event's *claimed* auth events rather than those we calculated:
|
|
||||||
# (a) is there any point in this test, since different_auth below will
|
|
||||||
# obviously be empty
|
|
||||||
# (b) alternatively, why don't we do it earlier?
|
|
||||||
logger.info("Skipping auth_event fetch for outlier")
|
|
||||||
return context, auth_events
|
|
||||||
|
|
||||||
different_auth = event_auth_events.difference(
|
different_auth = event_auth_events.difference(
|
||||||
e.event_id for e in auth_events.values()
|
e.event_id for e in auth_events.values()
|
||||||
)
|
)
|
||||||
|
|
|
@ -82,7 +82,6 @@ class MessageAcceptTests(unittest.HomeserverTestCase):
|
||||||
event,
|
event,
|
||||||
context,
|
context,
|
||||||
state=None,
|
state=None,
|
||||||
claimed_auth_event_map=None,
|
|
||||||
backfilled=False,
|
backfilled=False,
|
||||||
):
|
):
|
||||||
return context
|
return context
|
||||||
|
|
Loading…
Reference in New Issue