You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

122 lines
4.3 KiB

  1. # Copyright 2023 The Matrix.org Foundation C.I.C.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the 'License');
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an 'AS IS' BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from typing import List, Optional, Tuple
  15. from twisted.test.proto_helpers import MemoryReactor
  16. from synapse.server import HomeServer
  17. from synapse.storage._base import db_to_json
  18. from synapse.storage.database import LoggingTransaction
  19. from synapse.types import JsonDict
  20. from synapse.util import Clock
  21. from tests.unittest import HomeserverTestCase
  22. class EndToEndKeyWorkerStoreTestCase(HomeserverTestCase):
  23. def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
  24. self.store = hs.get_datastores().main
  25. def test_get_master_cross_signing_key_updatable_before(self) -> None:
  26. # Should return False, None when there is no master key.
  27. alice = "@alice:test"
  28. exists, timestamp = self.get_success(
  29. self.store.get_master_cross_signing_key_updatable_before(alice)
  30. )
  31. self.assertIs(exists, False)
  32. self.assertIsNone(timestamp)
  33. # Upload a master key.
  34. dummy_key = {"keys": {"a": "b"}}
  35. self.get_success(
  36. self.store.set_e2e_cross_signing_key(alice, "master", dummy_key)
  37. )
  38. # Should now find that the key exists.
  39. exists, timestamp = self.get_success(
  40. self.store.get_master_cross_signing_key_updatable_before(alice)
  41. )
  42. self.assertIs(exists, True)
  43. self.assertIsNone(timestamp)
  44. # Write an updateable_before timestamp.
  45. written_timestamp = self.get_success(
  46. self.store.allow_master_cross_signing_key_replacement_without_uia(
  47. alice, 1000
  48. )
  49. )
  50. # Should now find that the key exists.
  51. exists, timestamp = self.get_success(
  52. self.store.get_master_cross_signing_key_updatable_before(alice)
  53. )
  54. self.assertIs(exists, True)
  55. self.assertEqual(timestamp, written_timestamp)
  56. def test_master_replacement_only_applies_to_latest_master_key(
  57. self,
  58. ) -> None:
  59. """We shouldn't allow updates w/o UIA to old master keys or other key types."""
  60. alice = "@alice:test"
  61. # Upload two master keys.
  62. key1 = {"keys": {"a": "b"}}
  63. key2 = {"keys": {"c": "d"}}
  64. key3 = {"keys": {"e": "f"}}
  65. self.get_success(self.store.set_e2e_cross_signing_key(alice, "master", key1))
  66. self.get_success(self.store.set_e2e_cross_signing_key(alice, "other", key2))
  67. self.get_success(self.store.set_e2e_cross_signing_key(alice, "master", key3))
  68. # Third key should be the current one.
  69. key = self.get_success(
  70. self.store.get_e2e_cross_signing_key(alice, "master", alice)
  71. )
  72. self.assertEqual(key, key3)
  73. timestamp = self.get_success(
  74. self.store.allow_master_cross_signing_key_replacement_without_uia(
  75. alice, 1000
  76. )
  77. )
  78. assert timestamp is not None
  79. def check_timestamp_column(
  80. txn: LoggingTransaction,
  81. ) -> List[Tuple[JsonDict, Optional[int]]]:
  82. """Fetch all rows for Alice's keys."""
  83. txn.execute(
  84. """
  85. SELECT keydata, updatable_without_uia_before_ms
  86. FROM e2e_cross_signing_keys
  87. WHERE user_id = ?
  88. ORDER BY stream_id ASC;
  89. """,
  90. (alice,),
  91. )
  92. return [(db_to_json(keydata), ts) for keydata, ts in txn.fetchall()]
  93. values = self.get_success(
  94. self.store.db_pool.runInteraction(
  95. "check_timestamp_column",
  96. check_timestamp_column,
  97. )
  98. )
  99. self.assertEqual(
  100. values,
  101. [
  102. (key1, None),
  103. (key2, None),
  104. (key3, timestamp),
  105. ],
  106. )