From 32e14d81813f0d486445cbd4ceb4880d432ef5db Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Tue, 14 Apr 2015 19:10:09 +0100 Subject: Return a sha256 fingerprint rather than the entire tls certificate --- synapse/storage/__init__.py | 2 +- synapse/storage/schema/delta/16/server_keys.sql | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 synapse/storage/schema/delta/16/server_keys.sql (limited to 'synapse/storage') diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index f4dec70393..09f24a5c8e 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -51,7 +51,7 @@ logger = logging.getLogger(__name__) # Remember to update this number every time a change is made to database # schema files, so the users will be informed on server restarts. -SCHEMA_VERSION = 15 +SCHEMA_VERSION = 16 dir_path = os.path.abspath(os.path.dirname(__file__)) diff --git a/synapse/storage/schema/delta/16/server_keys.sql b/synapse/storage/schema/delta/16/server_keys.sql new file mode 100644 index 0000000000..d9b10d87f3 --- /dev/null +++ b/synapse/storage/schema/delta/16/server_keys.sql @@ -0,0 +1,24 @@ +/* Copyright 2015 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CREATE TABLE IF NOT EXISTS server_keys ( + server_name TEXT, -- Server name. + key_id TEXT, -- Requested key id. + from_server TEXT, -- Which server the keys were fetched from. + ts_added_ms INTEGER, -- When the keys were fetched + ts_expires_ms INTEGER, -- When this version of the keys exipires. + key_json BLOB, -- JSON certificate for the remote server. + CONSTRAINT uniqueness UNIQUE (server_name, key_id) +); -- cgit 1.5.1 From a429515bdda30c600359f7e0012b5dc967edde3f Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Wed, 15 Apr 2015 16:58:35 +0100 Subject: Add methods for storing and retrieving the raw key json --- synapse/storage/keys.py | 56 +++++++++++++++++++++++++ synapse/storage/schema/delta/16/server_keys.sql | 6 +-- 2 files changed, 59 insertions(+), 3 deletions(-) (limited to 'synapse/storage') diff --git a/synapse/storage/keys.py b/synapse/storage/keys.py index 09d1e63657..8b08d42859 100644 --- a/synapse/storage/keys.py +++ b/synapse/storage/keys.py @@ -118,3 +118,59 @@ class KeyStore(SQLBaseStore): }, or_ignore=True, ) + + def store_server_keys_json(self, server_name, key_id, from_server, + ts_now_ms, ts_expires_ms, key_json_bytes): + """Stores the JSON bytes for a set of keys from a server + The JSON should be signed by the originating server, the intermediate + server, and by this server. Updates the value for the + (server_name, key_id, from_server) triplet if one already existed. + Args: + server_name (str): The name of the server. + key_id (str): The identifer of the key this JSON is for. + from_server (str): The server this JSON was fetched from. + ts_now_ms (int): The time now in milliseconds. + ts_valid_until_ms (int): The time when this json stops being valid. + key_json (bytes): The encoded JSON. + """ + return self._simple_insert( + table="server_keys_json", + values={ + "server_name": server_name, + "key_id": key_id, + "from_server": from_server, + "ts_added_ms": ts_now_ms, + "ts_valid_until_ms": ts_valid_until_ms, + "key_json": key_json_bytes, + }, + or_replace=True, + ) + + def get_server_keys_json(self, server_keys): + """Retrive the key json for a list of server_keys and key ids. + If no keys are found for a given server, key_id and source then + that server, key_id, and source triplet will be missing from the + returned dictionary. The JSON is returned as a byte array so that it + can be efficiently used in an HTTP response. + Args: + server_keys (list): List of (server_name, key_id, source) triplets. + Returns: + Dict mapping (server_name, key_id, source) triplets to dicts with + "ts_valid_until_ms" and "key_json" keys. + """ + def _get_server_keys_json_txn(txn): + results = {} + for server_name, key_id, from_server in server_keys: + rows = _simple_select_list_txn( + keyvalues={ + "server_name": server_name, + "key_id": key_id, + "from_server": from_server, + }, + retcols=("ts_valid_until_ms", "key_json"), + ) + results[(server_name, key_id, from_server)] = rows + return results + return runInteraction( + "get_server_keys_json", _get_server_keys_json_txn + ) diff --git a/synapse/storage/schema/delta/16/server_keys.sql b/synapse/storage/schema/delta/16/server_keys.sql index d9b10d87f3..9cb589ff6d 100644 --- a/synapse/storage/schema/delta/16/server_keys.sql +++ b/synapse/storage/schema/delta/16/server_keys.sql @@ -13,12 +13,12 @@ * limitations under the License. */ -CREATE TABLE IF NOT EXISTS server_keys ( +CREATE TABLE IF NOT EXISTS server_keys_json ( server_name TEXT, -- Server name. key_id TEXT, -- Requested key id. from_server TEXT, -- Which server the keys were fetched from. ts_added_ms INTEGER, -- When the keys were fetched - ts_expires_ms INTEGER, -- When this version of the keys exipires. + ts_valid_until_ms INTEGER, -- When this version of the keys exipires. key_json BLOB, -- JSON certificate for the remote server. - CONSTRAINT uniqueness UNIQUE (server_name, key_id) + CONSTRAINT uniqueness UNIQUE (server_name, key_id, from_server) ); -- cgit 1.5.1 From f30d47c87651f92b69be224e016bda2cd7285f04 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Wed, 22 Apr 2015 14:21:08 +0100 Subject: Implement remote key lookup api --- synapse/config/server.py | 4 +- synapse/crypto/keyclient.py | 6 +- synapse/crypto/keyring.py | 75 +++++++------ synapse/rest/key/v2/__init__.py | 10 +- synapse/rest/key/v2/local_key_resource.py | 9 +- synapse/rest/key/v2/remote_key_resource.py | 174 +++++++++++++++++++++++++++++ synapse/storage/keys.py | 35 +++--- 7 files changed, 252 insertions(+), 61 deletions(-) create mode 100644 synapse/rest/key/v2/remote_key_resource.py (limited to 'synapse/storage') diff --git a/synapse/config/server.py b/synapse/config/server.py index 050ab90403..a26fb115f2 100644 --- a/synapse/config/server.py +++ b/synapse/config/server.py @@ -62,7 +62,7 @@ class ServerConfig(Config): server_group.add_argument("--old-signing-key-path", help="The old signing keys") server_group.add_argument("--key-refresh-interval", - default=24 * 60 * 60 * 1000, # 1 Day + default=24 * 60 * 60 * 1000, # 1 Day help="How long a key response is valid for." " Used to set the exipiry in /key/v2/." " Controls how frequently servers will" @@ -156,5 +156,5 @@ class ServerConfig(Config): args.old_signing_key_path = base_key_name + ".old.signing.keys" if not os.path.exists(args.old_signing_key_path): - with open(args.old_signing_key_path, "w") as old_signing_key_file: + with open(args.old_signing_key_path, "w"): pass diff --git a/synapse/crypto/keyclient.py b/synapse/crypto/keyclient.py index 2452c7a26e..4911f0896b 100644 --- a/synapse/crypto/keyclient.py +++ b/synapse/crypto/keyclient.py @@ -26,7 +26,7 @@ import logging logger = logging.getLogger(__name__) KEY_API_V1 = b"/_matrix/key/v1/" -KEY_API_V2 = b"/_matrix/key/v2/local" + @defer.inlineCallbacks def fetch_server_key(server_name, ssl_context_factory, path=KEY_API_V1): @@ -94,8 +94,8 @@ class SynapseKeyClientProtocol(HTTPClient): if status != b"200": # logger.info("Non-200 response from %s: %s %s", # self.transport.getHost(), status, message) - error = SynapseKeyClientError("Non-200 response %r from %r" % - (status, self.host) + error = SynapseKeyClientError( + "Non-200 response %r from %r" % (status, self.host) ) error.status = status self.errback(error) diff --git a/synapse/crypto/keyring.py b/synapse/crypto/keyring.py index 5528d0a280..17ac66731c 100644 --- a/synapse/crypto/keyring.py +++ b/synapse/crypto/keyring.py @@ -15,7 +15,9 @@ from synapse.crypto.keyclient import fetch_server_key from twisted.internet import defer -from syutil.crypto.jsonsign import verify_signed_json, signature_ids +from syutil.crypto.jsonsign import ( + verify_signed_json, signature_ids, sign_json, encode_canonical_json +) from syutil.crypto.signing_key import ( is_signing_algorithm_supported, decode_verify_key_bytes ) @@ -26,6 +28,8 @@ from synapse.util.retryutils import get_retry_limiter from OpenSSL import crypto +import urllib +import hashlib import logging @@ -37,6 +41,7 @@ class Keyring(object): self.store = hs.get_datastore() self.clock = hs.get_clock() self.client = hs.get_http_client() + self.config = hs.get_config() self.perspective_servers = {} self.hs = hs @@ -127,7 +132,6 @@ class Keyring(object): server_name, key_ids ) - for key_id in key_ids: if key_id in keys: defer.returnValue(keys[key_id]) @@ -142,17 +146,18 @@ class Keyring(object): perspective_name, self.clock, self.store ) - responses = yield self.client.post_json( - destination=perspective_name, - path=b"/_matrix/key/v2/query", - data={u"server_keys": {server_name: list(key_ids)}}, - ) + with limiter: + responses = yield self.client.post_json( + destination=perspective_name, + path=b"/_matrix/key/v2/query", + data={u"server_keys": {server_name: list(key_ids)}}, + ) - keys = dict() + keys = {} for response in responses: if (u"signatures" not in response - or perspective_name not in response[u"signatures"]): + or perspective_name not in response[u"signatures"]): raise ValueError( "Key response not signed by perspective server" " %r" % (perspective_name,) @@ -181,7 +186,9 @@ class Keyring(object): " server %r" % (perspective_name,) ) - response_keys = process_v2_response(self, server_name, key_ids) + response_keys = yield self.process_v2_response( + server_name, perspective_name, response + ) keys.update(response_keys) @@ -202,15 +209,15 @@ class Keyring(object): if requested_key_id in keys: continue - (response_json, tls_certificate) = yield fetch_server_key( + (response, tls_certificate) = yield fetch_server_key( server_name, self.hs.tls_context_factory, - path="/_matrix/key/v2/server/%s" % ( + path=(b"/_matrix/key/v2/server/%s" % ( urllib.quote(requested_key_id), - ), + )).encode("ascii"), ) if (u"signatures" not in response - or server_name not in response[u"signatures"]): + or server_name not in response[u"signatures"]): raise ValueError("Key response not signed by remote server") if "tls_fingerprints" not in response: @@ -223,17 +230,18 @@ class Keyring(object): sha256_fingerprint_b64 = encode_base64(sha256_fingerprint) response_sha256_fingerprints = set() - for fingerprint in response_json[u"tls_fingerprints"]: + for fingerprint in response[u"tls_fingerprints"]: if u"sha256" in fingerprint: response_sha256_fingerprints.add(fingerprint[u"sha256"]) - if sha256_fingerprint not in response_sha256_fingerprints: + if sha256_fingerprint_b64 not in response_sha256_fingerprints: raise ValueError("TLS certificate not allowed by fingerprints") response_keys = yield self.process_v2_response( server_name=server_name, from_server=server_name, - response_json=response_json, + requested_id=requested_key_id, + response_json=response, ) keys.update(response_keys) @@ -244,19 +252,15 @@ class Keyring(object): verify_keys=keys, ) - for key_id in key_ids: - if key_id in verify_keys: - defer.returnValue(verify_keys[key_id]) - return - - raise ValueError("No verification key found for given key ids") + defer.returnValue(keys) @defer.inlineCallbacks - def process_v2_response(self, server_name, from_server, json_response): - time_now_ms = clock.time_msec() + def process_v2_response(self, server_name, from_server, response_json, + requested_id=None): + time_now_ms = self.clock.time_msec() response_keys = {} verify_keys = {} - for key_id, key_data in response["verify_keys"].items(): + for key_id, key_data in response_json["verify_keys"].items(): if is_signing_algorithm_supported(key_id): key_base64 = key_data["key"] key_bytes = decode_base64(key_base64) @@ -264,7 +268,7 @@ class Keyring(object): verify_keys[key_id] = verify_key old_verify_keys = {} - for key_id, key_data in response["verify_keys"].items(): + for key_id, key_data in response_json["old_verify_keys"].items(): if is_signing_algorithm_supported(key_id): key_base64 = key_data["key"] key_bytes = decode_base64(key_base64) @@ -273,21 +277,21 @@ class Keyring(object): verify_key.time_added = time_now_ms old_verify_keys[key_id] = verify_key - for key_id in response["signatures"][server_name]: - if key_id not in response["verify_keys"]: + for key_id in response_json["signatures"][server_name]: + if key_id not in response_json["verify_keys"]: raise ValueError( "Key response must include verification keys for all" " signatures" ) if key_id in verify_keys: verify_signed_json( - response, + response_json, server_name, verify_keys[key_id] ) signed_key_json = sign_json( - response, + response_json, self.config.server_name, self.config.signing_key[0], ) @@ -295,7 +299,9 @@ class Keyring(object): signed_key_json_bytes = encode_canonical_json(signed_key_json) ts_valid_until_ms = signed_key_json[u"valid_until"] - updated_key_ids = set([requested_key_id]) + updated_key_ids = set() + if requested_id is not None: + updated_key_ids.add(requested_id) updated_key_ids.update(verify_keys) updated_key_ids.update(old_verify_keys) @@ -307,8 +313,8 @@ class Keyring(object): server_name=server_name, key_id=key_id, from_server=server_name, - ts_now_ms=ts_now_ms, - ts_valid_until_ms=valid_until, + ts_now_ms=time_now_ms, + ts_expires_ms=ts_valid_until_ms, key_json_bytes=signed_key_json_bytes, ) @@ -373,7 +379,6 @@ class Keyring(object): verify_keys[key_id] ) - yield self.store.store_server_certificate( server_name, server_name, diff --git a/synapse/rest/key/v2/__init__.py b/synapse/rest/key/v2/__init__.py index b79ed02590..1c14791b09 100644 --- a/synapse/rest/key/v2/__init__.py +++ b/synapse/rest/key/v2/__init__.py @@ -13,7 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +from twisted.web.resource import Resource from .local_key_resource import LocalKey +from .remote_key_resource import RemoteKey -class KeyApiV2Resource(LocalKey): - pass + +class KeyApiV2Resource(Resource): + def __init__(self, hs): + Resource.__init__(self) + self.putChild("server", LocalKey(hs)) + self.putChild("query", RemoteKey(hs)) diff --git a/synapse/rest/key/v2/local_key_resource.py b/synapse/rest/key/v2/local_key_resource.py index 1c0e0717c1..982a460962 100644 --- a/synapse/rest/key/v2/local_key_resource.py +++ b/synapse/rest/key/v2/local_key_resource.py @@ -31,7 +31,7 @@ class LocalKey(Resource): """HTTP resource containing encoding the TLS X.509 certificate and NACL signature verification keys for this server:: - GET /_matrix/key/v2/ HTTP/1.1 + GET /_matrix/key/v2/server/a.key.id HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json @@ -56,6 +56,8 @@ class LocalKey(Resource): } """ + isLeaf = True + def __init__(self, hs): self.version_string = hs.version_string self.config = hs.config @@ -68,7 +70,6 @@ class LocalKey(Resource): self.expires = int(time_now_msec + refresh_interval) self.response_body = encode_canonical_json(self.response_json_object()) - def response_json_object(self): verify_keys = {} for key in self.config.signing_key: @@ -120,7 +121,3 @@ class LocalKey(Resource): request, 200, self.response_body, version_string=self.version_string ) - - def getChild(self, name, request): - if name == '': - return self diff --git a/synapse/rest/key/v2/remote_key_resource.py b/synapse/rest/key/v2/remote_key_resource.py new file mode 100644 index 0000000000..cf6f2c2e73 --- /dev/null +++ b/synapse/rest/key/v2/remote_key_resource.py @@ -0,0 +1,174 @@ +from synapse.http.server import request_handler, respond_with_json_bytes +from synapse.api.errors import SynapseError, Codes + +from twisted.web.resource import Resource +from twisted.web.server import NOT_DONE_YET +from twisted.internet import defer + + +from io import BytesIO +import json +import logging +logger = logging.getLogger(__name__) + + +class RemoteKey(Resource): + """HTTP resource for retreiving the TLS certificate and NACL signature + verification keys for a collection of servers. Checks that the reported + X.509 TLS certificate matches the one used in the HTTPS connection. Checks + that the NACL signature for the remote server is valid. Returns a dict of + JSON signed by both the remote server and by this server. + + Supports individual GET APIs and a bulk query POST API. + + Requsts: + + GET /_matrix/key/v2/query/remote.server.example.com HTTP/1.1 + + GET /_matrix/key/v2/query/remote.server.example.com/a.key.id HTTP/1.1 + + POST /_matrix/v2/query HTTP/1.1 + Content-Type: application/json + { + "server_keys": { "remote.server.example.com": ["a.key.id"] } + } + + Response: + + HTTP/1.1 200 OK + Content-Type: application/json + { + "server_keys": [ + { + "server_name": "remote.server.example.com" + "valid_until": # posix timestamp + "verify_keys": { + "a.key.id": { # The identifier for a key. + key: "" # base64 encoded verification key. + } + } + "old_verify_keys": { + "an.old.key.id": { # The identifier for an old key. + key: "", # base64 encoded key + expired: 0, # when th e + } + } + "tls_fingerprints": [ + { "sha256": # fingerprint } + ] + "signatures": { + "remote.server.example.com": {...} + "this.server.example.com": {...} + } + } + ] + } + """ + + isLeaf = True + + def __init__(self, hs): + self.keyring = hs.get_keyring() + self.store = hs.get_datastore() + self.version_string = hs.version_string + self.clock = hs.get_clock() + + def render_GET(self, request): + self.async_render_GET(request) + return NOT_DONE_YET + + @request_handler + @defer.inlineCallbacks + def async_render_GET(self, request): + if len(request.postpath) == 1: + server, = request.postpath + query = {server: [None]} + elif len(request.postpath) == 2: + server, key_id = request.postpath + query = {server: [key_id]} + else: + raise SynapseError( + 404, "Not found %r" % request.postpath, Codes.NOT_FOUND + ) + yield self.query_keys(request, query, query_remote_on_cache_miss=True) + + def render_POST(self, request): + self.async_render_POST(request) + return NOT_DONE_YET + + @request_handler + @defer.inlineCallbacks + def async_render_POST(self, request): + try: + content = json.loads(request.content.read()) + if type(content) != dict: + raise ValueError() + except ValueError: + raise SynapseError( + 400, "Content must be JSON object.", errcode=Codes.NOT_JSON + ) + + query = content["server_keys"] + + yield self.query_keys(request, query, query_remote_on_cache_miss=True) + + @defer.inlineCallbacks + def query_keys(self, request, query, query_remote_on_cache_miss=False): + store_queries = [] + for server_name, key_ids in query.items(): + for key_id in key_ids: + store_queries.append((server_name, key_id, None)) + + cached = yield self.store.get_server_keys_json(store_queries) + + json_results = [] + + time_now_ms = self.clock.time_msec() + + cache_misses = dict() + for (server_name, key_id, from_server), results in cached.items(): + results = [ + (result["ts_added_ms"], result) for result in results + if result["ts_valid_until_ms"] > time_now_ms + ] + + if not results: + if key_id is not None: + cache_misses.setdefault(server_name, set()).add(key_id) + continue + + if key_id is not None: + most_recent_result = max(results) + json_results.append(most_recent_result[-1]["key_json"]) + else: + for result in results: + json_results.append(result[-1]["key_json"]) + + if cache_misses and query_remote_on_cache_miss: + for server_name, key_ids in cache_misses.items(): + try: + yield self.keyring.get_server_verify_key_v2_direct( + server_name, key_ids + ) + except: + logger.exception("Failed to get key for %r", server_name) + pass + yield self.query_keys( + request, query, query_remote_on_cache_miss=False + ) + else: + result_io = BytesIO() + result_io.write(b"{\"server_keys\":") + sep = b"[" + for json_bytes in json_results: + result_io.write(sep) + result_io.write(json_bytes) + sep = b"," + if sep == b"[": + result_io.write(sep) + result_io.write(b"]}") + + respond_with_json_bytes( + request, 200, result_io.getvalue(), + version_string=self.version_string + ) diff --git a/synapse/storage/keys.py b/synapse/storage/keys.py index 8b08d42859..22b158d71e 100644 --- a/synapse/storage/keys.py +++ b/synapse/storage/keys.py @@ -140,8 +140,8 @@ class KeyStore(SQLBaseStore): "key_id": key_id, "from_server": from_server, "ts_added_ms": ts_now_ms, - "ts_valid_until_ms": ts_valid_until_ms, - "key_json": key_json_bytes, + "ts_valid_until_ms": ts_expires_ms, + "key_json": buffer(key_json_bytes), }, or_replace=True, ) @@ -149,9 +149,9 @@ class KeyStore(SQLBaseStore): def get_server_keys_json(self, server_keys): """Retrive the key json for a list of server_keys and key ids. If no keys are found for a given server, key_id and source then - that server, key_id, and source triplet will be missing from the - returned dictionary. The JSON is returned as a byte array so that it - can be efficiently used in an HTTP response. + that server, key_id, and source triplet entry will be an empty list. + The JSON is returned as a byte array so that it can be efficiently + used in an HTTP response. Args: server_keys (list): List of (server_name, key_id, source) triplets. Returns: @@ -161,16 +161,25 @@ class KeyStore(SQLBaseStore): def _get_server_keys_json_txn(txn): results = {} for server_name, key_id, from_server in server_keys: - rows = _simple_select_list_txn( - keyvalues={ - "server_name": server_name, - "key_id": key_id, - "from_server": from_server, - }, - retcols=("ts_valid_until_ms", "key_json"), + keyvalues = {"server_name": server_name} + if key_id is not None: + keyvalues["key_id"] = key_id + if from_server is not None: + keyvalues["from_server"] = from_server + rows = self._simple_select_list_txn( + txn, + "server_keys_json", + keyvalues=keyvalues, + retcols=( + "key_id", + "from_server", + "ts_added_ms", + "ts_valid_until_ms", + "key_json", + ), ) results[(server_name, key_id, from_server)] = rows return results - return runInteraction( + return self.runInteraction( "get_server_keys_json", _get_server_keys_json_txn ) -- cgit 1.5.1 From b96c133034d30a49f8f2567b26d539ee96ff6122 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Tue, 28 Apr 2015 10:50:00 +0100 Subject: Add server_keys.sql to the current delta rather than creating a new delta --- synapse/storage/schema/delta/15/server_keys.sql | 24 ++++++++++++++++++++++++ synapse/storage/schema/delta/16/server_keys.sql | 24 ------------------------ 2 files changed, 24 insertions(+), 24 deletions(-) create mode 100644 synapse/storage/schema/delta/15/server_keys.sql delete mode 100644 synapse/storage/schema/delta/16/server_keys.sql (limited to 'synapse/storage') diff --git a/synapse/storage/schema/delta/15/server_keys.sql b/synapse/storage/schema/delta/15/server_keys.sql new file mode 100644 index 0000000000..9cb589ff6d --- /dev/null +++ b/synapse/storage/schema/delta/15/server_keys.sql @@ -0,0 +1,24 @@ +/* Copyright 2015 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CREATE TABLE IF NOT EXISTS server_keys_json ( + server_name TEXT, -- Server name. + key_id TEXT, -- Requested key id. + from_server TEXT, -- Which server the keys were fetched from. + ts_added_ms INTEGER, -- When the keys were fetched + ts_valid_until_ms INTEGER, -- When this version of the keys exipires. + key_json BLOB, -- JSON certificate for the remote server. + CONSTRAINT uniqueness UNIQUE (server_name, key_id, from_server) +); diff --git a/synapse/storage/schema/delta/16/server_keys.sql b/synapse/storage/schema/delta/16/server_keys.sql deleted file mode 100644 index 9cb589ff6d..0000000000 --- a/synapse/storage/schema/delta/16/server_keys.sql +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2015 OpenMarket Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -CREATE TABLE IF NOT EXISTS server_keys_json ( - server_name TEXT, -- Server name. - key_id TEXT, -- Requested key id. - from_server TEXT, -- Which server the keys were fetched from. - ts_added_ms INTEGER, -- When the keys were fetched - ts_valid_until_ms INTEGER, -- When this version of the keys exipires. - key_json BLOB, -- JSON certificate for the remote server. - CONSTRAINT uniqueness UNIQUE (server_name, key_id, from_server) -); -- cgit 1.5.1 From 55e1bc89202244430fecea82e9b5615fa6254026 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Tue, 28 Apr 2015 10:54:15 +0100 Subject: And don't bump the schema version unnecessarily --- synapse/storage/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse/storage') diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index 09f24a5c8e..f4dec70393 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -51,7 +51,7 @@ logger = logging.getLogger(__name__) # Remember to update this number every time a change is made to database # schema files, so the users will be informed on server restarts. -SCHEMA_VERSION = 16 +SCHEMA_VERSION = 15 dir_path = os.path.abspath(os.path.dirname(__file__)) -- cgit 1.5.1 From a9549fdce3fcb383e3d4725bce2d408f1d96b7d3 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Wed, 29 Apr 2015 13:16:09 +0100 Subject: Use bytea rather than BLOB --- synapse/storage/schema/delta/15/server_keys.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse/storage') diff --git a/synapse/storage/schema/delta/15/server_keys.sql b/synapse/storage/schema/delta/15/server_keys.sql index 9cb589ff6d..513c30a717 100644 --- a/synapse/storage/schema/delta/15/server_keys.sql +++ b/synapse/storage/schema/delta/15/server_keys.sql @@ -19,6 +19,6 @@ CREATE TABLE IF NOT EXISTS server_keys_json ( from_server TEXT, -- Which server the keys were fetched from. ts_added_ms INTEGER, -- When the keys were fetched ts_valid_until_ms INTEGER, -- When this version of the keys exipires. - key_json BLOB, -- JSON certificate for the remote server. + key_json bytea, -- JSON certificate for the remote server. CONSTRAINT uniqueness UNIQUE (server_name, key_id, from_server) ); -- cgit 1.5.1 From e26a3d8d9ed081aae8f0e29a14b710023a41907e Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Wed, 29 Apr 2015 13:32:32 +0100 Subject: bump database schema version --- synapse/storage/__init__.py | 2 +- synapse/storage/schema/delta/15/server_keys.sql | 24 ------------------------ synapse/storage/schema/delta/17/server_keys.sql | 24 ++++++++++++++++++++++++ 3 files changed, 25 insertions(+), 25 deletions(-) delete mode 100644 synapse/storage/schema/delta/15/server_keys.sql create mode 100644 synapse/storage/schema/delta/17/server_keys.sql (limited to 'synapse/storage') diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index 61215bbc7b..6a82d7fcf8 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -51,7 +51,7 @@ logger = logging.getLogger(__name__) # Remember to update this number every time a change is made to database # schema files, so the users will be informed on server restarts. -SCHEMA_VERSION = 16 +SCHEMA_VERSION = 17 dir_path = os.path.abspath(os.path.dirname(__file__)) diff --git a/synapse/storage/schema/delta/15/server_keys.sql b/synapse/storage/schema/delta/15/server_keys.sql deleted file mode 100644 index 513c30a717..0000000000 --- a/synapse/storage/schema/delta/15/server_keys.sql +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright 2015 OpenMarket Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -CREATE TABLE IF NOT EXISTS server_keys_json ( - server_name TEXT, -- Server name. - key_id TEXT, -- Requested key id. - from_server TEXT, -- Which server the keys were fetched from. - ts_added_ms INTEGER, -- When the keys were fetched - ts_valid_until_ms INTEGER, -- When this version of the keys exipires. - key_json bytea, -- JSON certificate for the remote server. - CONSTRAINT uniqueness UNIQUE (server_name, key_id, from_server) -); diff --git a/synapse/storage/schema/delta/17/server_keys.sql b/synapse/storage/schema/delta/17/server_keys.sql new file mode 100644 index 0000000000..513c30a717 --- /dev/null +++ b/synapse/storage/schema/delta/17/server_keys.sql @@ -0,0 +1,24 @@ +/* Copyright 2015 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CREATE TABLE IF NOT EXISTS server_keys_json ( + server_name TEXT, -- Server name. + key_id TEXT, -- Requested key id. + from_server TEXT, -- Which server the keys were fetched from. + ts_added_ms INTEGER, -- When the keys were fetched + ts_valid_until_ms INTEGER, -- When this version of the keys exipires. + key_json bytea, -- JSON certificate for the remote server. + CONSTRAINT uniqueness UNIQUE (server_name, key_id, from_server) +); -- cgit 1.5.1