mirror of
https://github.com/element-hq/synapse.git
synced 2026-09-27 13:40:21 +00:00
Adds a `redis.username` config option. Details: A `username` without a `password` (or `password_path`) is refused at startup. Redis has no wire form for a username without a password, and txredisapi only sends `AUTH` when a password is set, so the username would otherwise be silently ignored. An explicitly empty password is accepted, since that is how a `nopass` ACL user is configured. This relies on txredisapi 1.4.12, the first release to accept a `username` kwarg. That upstream support was contributed by @karolyi specifically to unblock this. Fixes #19238. ### Pull Request Checklist <!-- Please read https://element-hq.github.io/synapse/latest/development/contributing_guide.html before submitting your pull request --> * [X] Pull request is based on the develop branch * [X] Pull request includes a [changelog file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog). The entry should: - Be a short description of your change which makes sense to users. "Fixed a bug that prevented receiving messages from other servers." instead of "Moved X method from `EventStore` to `EventWorkerStore`.". - Use markdown where necessary, mostly for `code blocks`. - End with either a period (.) or an exclamation mark (!). - Start with a capital letter. - Feel free to credit yourself, by adding a sentence "Contributed by @github_username." or "Contributed by [Your Name]." to the end of the entry. * [X] [Code style](https://element-hq.github.io/synapse/latest/code_style.html) is correct (run the [linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters)) --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
#
|
|
# This file is licensed under the Affero General Public License (AGPL) version 3.
|
|
#
|
|
# Copyright (C) 2026 Element Creations Ltd
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# See the GNU Affero General Public License for more details:
|
|
# <https://www.gnu.org/licenses/agpl-3.0.html>.
|
|
#
|
|
#
|
|
|
|
from typing import Any
|
|
|
|
from tests.replication._base import BaseMultiWorkerStreamTestCase
|
|
|
|
|
|
class RedisUsernameAuthTestCase(BaseMultiWorkerStreamTestCase):
|
|
"""Tests that Synapse authenticates to Redis with a username *and* password
|
|
when both are configured, rather than with a bare password.
|
|
"""
|
|
|
|
USERNAME = b"synapse-user"
|
|
PASSWORD = b"correct-horse-battery-staple"
|
|
|
|
def default_config(self) -> dict[str, Any]:
|
|
config = super().default_config()
|
|
config["redis"]["username"] = self.USERNAME.decode("utf-8")
|
|
config["redis"]["password"] = self.PASSWORD.decode("utf-8")
|
|
return config
|
|
|
|
def test_auth_sent_with_username(self) -> None:
|
|
"""Both Redis connections the main process opens (one outbound, one
|
|
subscriber) send `AUTH <username> <password>`.
|
|
"""
|
|
# Let the AUTH replies flow back; nothing here needs virtual time to pass.
|
|
self.reactor.advance(0)
|
|
|
|
self.assertEqual(
|
|
self._redis_server.auth_attempts,
|
|
[(self.USERNAME, self.PASSWORD)] * 2,
|
|
)
|
|
|
|
def test_workers_authenticate_with_username_too(self) -> None:
|
|
"""A worker authenticates the same way as the main process, and both end
|
|
up subscribed to the replication stream over those connections.
|
|
"""
|
|
self.make_worker_hs("synapse.app.generic_worker")
|
|
|
|
# Let the AUTH and SUBSCRIBE replies flow back.
|
|
self.reactor.advance(0)
|
|
|
|
self.assertEqual(
|
|
self._redis_server.auth_attempts,
|
|
[(self.USERNAME, self.PASSWORD)] * 4,
|
|
)
|
|
self.assertEqual(len(self._redis_server._subscribers_by_channel[b"test"]), 2)
|