|
25 | 25 | from twisted.internet import defer
|
26 | 26 | from twisted.internet.defer import Deferred, ensureDeferred
|
27 | 27 | from twisted.test.proto_helpers import MemoryReactor
|
| 28 | +from twisted.web.resource import NoResource, Resource |
28 | 29 |
|
29 |
| -from synapse.api.errors import SynapseError |
| 30 | +from synapse.api.errors import HttpResponseException, SynapseError |
30 | 31 | from synapse.crypto import keyring
|
31 | 32 | from synapse.crypto.keyring import (
|
| 33 | + InternalWorkerRequestKeyFetcher, |
32 | 34 | PerspectivesKeyFetcher,
|
33 | 35 | ServerKeyFetcher,
|
34 | 36 | StoreKeyFetcher,
|
|
39 | 41 | current_context,
|
40 | 42 | make_deferred_yieldable,
|
41 | 43 | )
|
| 44 | +from synapse.rest.key.v2 import KeyResource |
42 | 45 | from synapse.server import HomeServer
|
43 | 46 | from synapse.storage.keys import FetchKeyResult
|
44 | 47 | from synapse.types import JsonDict
|
45 | 48 | from synapse.util import Clock
|
| 49 | +from synapse.util.httpresourcetree import create_resource_tree |
46 | 50 |
|
47 | 51 | from tests import unittest
|
| 52 | +from tests.replication._base import BaseMultiWorkerStreamTestCase |
48 | 53 | from tests.test_utils import make_awaitable
|
49 | 54 | from tests.unittest import logcontext_clean, override_config
|
50 | 55 |
|
@@ -757,6 +762,79 @@ def get_key_from_perspectives(response: JsonDict) -> Dict[str, FetchKeyResult]:
|
757 | 762 | self.assertEqual(keys, {}, "Expected empty dict with missing origin server sig")
|
758 | 763 |
|
759 | 764 |
|
| 765 | +class InternalWorkerRequestKeyFetcherTestCase(BaseMultiWorkerStreamTestCase): |
| 766 | + def create_test_resource(self) -> Resource: # type: ignore[override] |
| 767 | + return create_resource_tree( |
| 768 | + {"/_matrix/key/v2": KeyResource(self.hs)}, root_resource=NoResource() |
| 769 | + ) |
| 770 | + |
| 771 | + def default_config(self) -> Dict[str, Any]: |
| 772 | + config = super().default_config() |
| 773 | + config.update( |
| 774 | + federation_sender_instances=["federation_sender1"], |
| 775 | + instance_map={ |
| 776 | + "federation_sender1": {"host": "testserv", "port": 1001}, |
| 777 | + }, |
| 778 | + ) |
| 779 | + return config |
| 780 | + |
| 781 | + def test_key_fetching_works_across_workers(self) -> None: |
| 782 | + """Test that a non-fed-sender worker requests keys via a fed-sender.""" |
| 783 | + mock_http_client = Mock() |
| 784 | + |
| 785 | + # 1. Mock out the response from the notary server. |
| 786 | + async def mock_post_json(*args: Any, **kwargs: Any) -> JsonDict: |
| 787 | + """Mock the request to the notary server.""" |
| 788 | + if kwargs.get("path") != "/_matrix/key/v2/query": |
| 789 | + raise HttpResponseException(500, "ruh", b"roh") |
| 790 | + return {"server_keys": []} |
| 791 | + |
| 792 | + mock_http_client.post_json = mock_post_json |
| 793 | + |
| 794 | + # 2. Build a valid response to /_matrix/key/v2/server for the server being |
| 795 | + # queried. |
| 796 | + SERVER_NAME = "server2" |
| 797 | + testkey = signedjson.key.generate_signing_key("ver1") |
| 798 | + testverifykey = signedjson.key.get_verify_key(testkey) |
| 799 | + testverifykey_id = "ed25519:ver1" |
| 800 | + VALID_UNTIL_TS = 200 * 1000 |
| 801 | + response = { |
| 802 | + "server_name": SERVER_NAME, |
| 803 | + "old_verify_keys": {}, |
| 804 | + "valid_until_ts": VALID_UNTIL_TS, |
| 805 | + "verify_keys": { |
| 806 | + testverifykey_id: { |
| 807 | + "key": signedjson.key.encode_verify_key_base64(testverifykey) |
| 808 | + } |
| 809 | + }, |
| 810 | + } |
| 811 | + signedjson.sign.sign_json(response, SERVER_NAME, testkey) |
| 812 | + |
| 813 | + async def mock_get_json(*args: Any, **kwargs: Any) -> JsonDict: |
| 814 | + if kwargs.get("path") != "/_matrix/key/v2/server": |
| 815 | + raise HttpResponseException(500, "ruh", b"roh") |
| 816 | + return response |
| 817 | + |
| 818 | + mock_http_client.get_json = mock_get_json |
| 819 | + |
| 820 | + # 3. Make a federation homeserver to actually make the request. |
| 821 | + self.make_worker_hs( |
| 822 | + "synapse.app.generic_worker", |
| 823 | + { |
| 824 | + "worker_name": "federation_sender1", |
| 825 | + "federation_sender_instances": ["federation_sender1"], |
| 826 | + }, |
| 827 | + federation_http_client=mock_http_client, |
| 828 | + ) |
| 829 | + |
| 830 | + # 4. Use the via-fed-sender fetcher to get keys. |
| 831 | + fetcher = InternalWorkerRequestKeyFetcher(self.hs) |
| 832 | + result = self.get_success( |
| 833 | + fetcher.get_keys(SERVER_NAME, [testverifykey_id], 0), by=0.1 |
| 834 | + ) |
| 835 | + print(result) |
| 836 | + |
| 837 | + |
760 | 838 | def get_key_id(key: SigningKey) -> str:
|
761 | 839 | """Get the matrix ID tag for a given SigningKey or VerifyKey"""
|
762 | 840 | return "%s:%s" % (key.alg, key.version)
|
0 commit comments