From 81232da09286f7f1812f6d3d182cd57665feaa1f Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Fri, 18 Dec 2015 19:37:44 +0100 Subject: [feat] Migrate soledad documents by adding versioning field - Resolves: #7713 --- src/leap/keymanager/migrator.py | 171 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 src/leap/keymanager/migrator.py (limited to 'src/leap/keymanager/migrator.py') diff --git a/src/leap/keymanager/migrator.py b/src/leap/keymanager/migrator.py new file mode 100644 index 0000000..b59647a --- /dev/null +++ b/src/leap/keymanager/migrator.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- +# migrator.py +# Copyright (C) 2015 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Document migrator +""" +# XXX: versioning has being added 12/2015 when keymanager was not +# much in use in the wild. We can probably drop support for +# keys without version at some point. + + +from collections import namedtuple +from twisted.internet.defer import gatherResults, succeed + +from leap.keymanager.keys import ( + TAGS_PRIVATE_INDEX, + KEYMANAGER_KEY_TAG, + KEYMANAGER_ACTIVE_TAG, + + KEYMANAGER_DOC_VERSION, + KEY_VERSION_KEY, + KEY_ID_KEY, + KEY_VALIDATION_KEY, + KEY_LAST_AUDITED_AT_KEY, + KEY_ENCR_USED_KEY, + KEY_SIGN_USED_KEY, +) +from leap.keymanager.validation import ValidationLevels + + +KeyDocs = namedtuple("KeyDocs", ['key', 'active']) + + +class KeyDocumentsMigrator(object): + """ + Migrate old KeyManager Soledad Documents to the newest schema + """ + + def __init__(self, soledad): + self._soledad = soledad + + def migrate(self): + deferred_public = self._get_docs(private=False) + deferred_public.addCallback(self._migrate_docs) + + deferred_private = self._get_docs(private=True) + deferred_private.addCallback(self._migrate_docs) + + return gatherResults([deferred_public, deferred_private]) + + def _get_docs(self, private=False): + private_value = '1' if private else '0' + + deferred_keys = self._soledad.get_from_index( + TAGS_PRIVATE_INDEX, + KEYMANAGER_KEY_TAG, + private_value) + deferred_active = self._soledad.get_from_index( + TAGS_PRIVATE_INDEX, + KEYMANAGER_ACTIVE_TAG, + private_value) + return gatherResults([deferred_keys, deferred_active]) + + def _migrate_docs(self, (key_docs, active_docs)): + def update_keys(keys): + deferreds = [] + for key_id in keys: + key = keys[key_id].key + actives = keys[key_id].active + + d = self._migrate_actives(key, actives) + deferreds.append(d) + + d = self._migrate_key(key) + deferreds.append(d) + return gatherResults(deferreds) + + d = self._buildKeyDict(key_docs, active_docs) + d.addCallback(lambda keydict: self._filter_outdated(keydict)) + d.addCallback(update_keys) + + def _buildKeyDict(self, keys, actives): + keydict = { + fp2id(key.content[KEY_FINGERPRINT_KEY]): KeyDocs(key, []) + for key in keys} + + deferreds = [] + for active in actives: + if KEY_ID_KEY in active.content: + key_id = active.content[KEY_ID_KEY] + if key_id not in keydict: + d = self._soledad.delete_doc(active) + deferreds.append(d) + continue + keydict[key_id].active.append(active) + + d = gatherResults(deferreds) + d.addCallback(lambda _: keydict) + return d + + def _filter_outdated(self, keydict): + outdated = {} + for key_id, docs in keydict.items(): + if ((docs.key and KEY_VERSION_KEY not in docs.key.content) or + docs.active): + outdated[key_id] = docs + return outdated + + def _migrate_actives(self, key, actives): + if not key: + deferreds = [] + for active in actives: + d = self._soledad.delete_doc(active) + deferreds.append(d) + return gatherResults(deferreds) + + validation = str(ValidationLevels.Weak_Chain) + last_audited = 0 + encr_used = False + sign_used = False + if len(actives) == 1 and KEY_VERSION_KEY not in key.content: + # we can preserve the validation of the key if there is only one + # active address for the key + validation = key.content[KEY_VALIDATION_KEY] + last_audited = key.content[KEY_LAST_AUDITED_AT_KEY] + encr_used = key.content[KEY_ENCR_USED_KEY] + sign_used = key.content[KEY_SIGN_USED_KEY] + + deferreds = [] + for active in actives: + if KEY_VERSION_KEY in active.content: + continue + + active.content[KEY_VERSION_KEY] = KEYMANAGER_DOC_VERSION + active.content[KEY_VALIDATION_KEY] = validation + active.content[KEY_LAST_AUDITED_AT_KEY] = last_audited + active.content[KEY_ENCR_USED_KEY] = encr_used + active.content[KEY_SIGN_USED_KEY] = sign_used + d = self._soledad.put_doc(active) + deferreds.append(d) + return gatherResults(deferreds) + + def _migrate_key(self, key): + if not key or KEY_VERSION_KEY in key.content: + return succeed(None) + + key.content[KEY_VERSION_KEY] = KEYMANAGER_DOC_VERSION + del key.content[KEY_VALIDATION_KEY] + del key.content[KEY_LAST_AUDITED_AT_KEY] + del key.content[KEY_ENCR_USED_KEY] + del key.content[KEY_SIGN_USED_KEY] + return self._soledad.put_doc(key) + + +def fp2id(fingerprint): + KEY_ID_LENGTH = 16 + return fingerprint[-KEY_ID_LENGTH:] -- cgit v1.2.3 From 3d544f4a85930c5d1611d193500744fc97f0aee1 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Fri, 18 Dec 2015 20:31:18 +0100 Subject: [feat] Use fingerprints instead of key ids - Resolves: #7500 --- src/leap/keymanager/migrator.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/leap/keymanager/migrator.py') diff --git a/src/leap/keymanager/migrator.py b/src/leap/keymanager/migrator.py index b59647a..11cf243 100644 --- a/src/leap/keymanager/migrator.py +++ b/src/leap/keymanager/migrator.py @@ -33,7 +33,7 @@ from leap.keymanager.keys import ( KEYMANAGER_DOC_VERSION, KEY_VERSION_KEY, - KEY_ID_KEY, + KEY_FINGERPRINT_KEY, KEY_VALIDATION_KEY, KEY_LAST_AUDITED_AT_KEY, KEY_ENCR_USED_KEY, @@ -42,6 +42,8 @@ from leap.keymanager.keys import ( from leap.keymanager.validation import ValidationLevels +KEY_ID_KEY = 'key_id' + KeyDocs = namedtuple("KeyDocs", ['key', 'active']) @@ -132,6 +134,7 @@ class KeyDocumentsMigrator(object): last_audited = 0 encr_used = False sign_used = False + fingerprint = key.content[KEY_FINGERPRINT_KEY] if len(actives) == 1 and KEY_VERSION_KEY not in key.content: # we can preserve the validation of the key if there is only one # active address for the key @@ -146,10 +149,12 @@ class KeyDocumentsMigrator(object): continue active.content[KEY_VERSION_KEY] = KEYMANAGER_DOC_VERSION + active.content[KEY_FINGERPRINT_KEY] = fingerprint active.content[KEY_VALIDATION_KEY] = validation active.content[KEY_LAST_AUDITED_AT_KEY] = last_audited active.content[KEY_ENCR_USED_KEY] = encr_used active.content[KEY_SIGN_USED_KEY] = sign_used + del active.content[KEY_ID_KEY] d = self._soledad.put_doc(active) deferreds.append(d) return gatherResults(deferreds) @@ -159,6 +164,7 @@ class KeyDocumentsMigrator(object): return succeed(None) key.content[KEY_VERSION_KEY] = KEYMANAGER_DOC_VERSION + del key.content[KEY_ID_KEY] del key.content[KEY_VALIDATION_KEY] del key.content[KEY_LAST_AUDITED_AT_KEY] del key.content[KEY_ENCR_USED_KEY] -- cgit v1.2.3 From fdb6e285a97d5af21c7b3bdc02cba6fc21382f74 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Mon, 21 Dec 2015 19:26:55 +0100 Subject: [feat] Make EncryptionKey aware of the active address --- src/leap/keymanager/migrator.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/leap/keymanager/migrator.py') diff --git a/src/leap/keymanager/migrator.py b/src/leap/keymanager/migrator.py index 11cf243..9e4ae77 100644 --- a/src/leap/keymanager/migrator.py +++ b/src/leap/keymanager/migrator.py @@ -32,6 +32,8 @@ from leap.keymanager.keys import ( KEYMANAGER_ACTIVE_TAG, KEYMANAGER_DOC_VERSION, + KEY_ADDRESS_KEY, + KEY_UIDS_KEY, KEY_VERSION_KEY, KEY_FINGERPRINT_KEY, KEY_VALIDATION_KEY, @@ -164,6 +166,8 @@ class KeyDocumentsMigrator(object): return succeed(None) key.content[KEY_VERSION_KEY] = KEYMANAGER_DOC_VERSION + key.content[KEY_UIDS_KEY] = key.content[KEY_ADDRESS_KEY] + del key.content[KEY_ADDRESS_KEY] del key.content[KEY_ID_KEY] del key.content[KEY_VALIDATION_KEY] del key.content[KEY_LAST_AUDITED_AT_KEY] -- cgit v1.2.3