From f92cfcdfc943cfc01d1dca255cecd70723c4b1f1 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Tue, 30 Aug 2016 11:49:39 -0300 Subject: [bug] don't remove combined_bundle file on destructor After PR #116, it's possible to inject an existing combined_ca_bundle to the keymanager initialisation. However, it won't work for multiple users because the file is removed when the keymanager is destroyed. Considering there's no sensitive data on the file and it's created as a temp file, we don't need to handle its deletion. --- src/leap/keymanager/__init__.py | 13 ------------- tests/test_keymanager.py | 4 ---- 2 files changed, 17 deletions(-) diff --git a/src/leap/keymanager/__init__.py b/src/leap/keymanager/__init__.py index ac9f8eb..2a5bac4 100644 --- a/src/leap/keymanager/__init__.py +++ b/src/leap/keymanager/__init__.py @@ -130,19 +130,6 @@ class KeyManager(object): self._nicknym = Nicknym(self._nickserver_uri, self._ca_cert_path, self._token) self.refresher = None - # - # destructor - # - - def __del__(self): - try: - created_tmp_combined_ca_bundle = self._combined_ca_bundle not in \ - [ca_bundle.where(), self._ca_cert_path] - if created_tmp_combined_ca_bundle: - os.remove(self._combined_ca_bundle) - except OSError: - pass - # # utilities # diff --git a/tests/test_keymanager.py b/tests/test_keymanager.py index 118cd8c..ae06372 100644 --- a/tests/test_keymanager.py +++ b/tests/test_keymanager.py @@ -20,7 +20,6 @@ Tests for the Key Manager. """ -from os import path import json import urllib from datetime import datetime @@ -496,9 +495,6 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase): expected = self._slurp_file(ca_bundle.where()) + ca_content self.assertEqual(expected, self._slurp_file(tmp_output.name)) - del km # force km out of scope - self.assertFalse(path.exists(tmp_output.name)) - def _dump_to_file(self, filename, content): with open(filename, 'w') as out: out.write(content) -- cgit v1.2.3 From 2d9bec78f3f8c46f00f585cadae652d6e3aec904 Mon Sep 17 00:00:00 2001 From: drebs Date: Fri, 12 Aug 2016 08:34:31 -0300 Subject: [test] add speed tests for gpg/wrapper init/enc/dec --- Makefile | 37 +++++++ tests/TODO | 1 + tests/common.py | 43 ++++++++ tests/conftest.py | 51 +++++++++ tests/test_gpg_speed.py | 286 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/test_openpgp.py | 7 +- tox.ini | 8 ++ 7 files changed, 428 insertions(+), 5 deletions(-) create mode 100644 Makefile create mode 100644 tests/TODO create mode 100644 tests/conftest.py create mode 100644 tests/test_gpg_speed.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0a3db77 --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +# This makefile is currently intended to make it easy to generate the +# benchmarking graphs. + +RESULTS_FILE = tests/results.json +GRAPH_PREFIX = benchmark + +GRAPH_FILE = $(GRAPH_PREFIX)-test_gpg_init.svg + +all: $(GRAPH_FILE) + +# +# rules for generating one graph with the results of all speed tests +# + +$(RESULTS_FILE): + tox -v test_gpg_speed.py -- -v --pdb -s \ + --benchmark-max-time=2.0 \ + --benchmark-json=$(subst tests/,,$@) + +$(GRAPH_FILE): $(RESULTS_FILE) + py.test-benchmark compare $< --histogram $(GRAPH_PREFIX) + + +# +# rule for generating one graph for each graph +# + +test: + tox -v test_gpg_speed.py -- -v --pdb -s \ + --benchmark-histogram=gpg_speed \ + --benchmark-storage=./graphs/ \ + --benchmark-save=keymanager_gpg_speed \ + +clean: + rm -f $(RESULTS_FILE) $(GRAPH_PREFIX)*.svg + +.PHONY: all test graph diff --git a/tests/TODO b/tests/TODO new file mode 100644 index 0000000..9f596a1 --- /dev/null +++ b/tests/TODO @@ -0,0 +1 @@ +- tune test params (max time, number of iterations, etc) diff --git a/tests/common.py b/tests/common.py index 8eb5d4e..9d16991 100644 --- a/tests/common.py +++ b/tests/common.py @@ -265,8 +265,51 @@ RZXoH+FTg9UAW87eqU610npOkT6cRaBxaMK/mDtGNdc= =JTFu -----END PGP PRIVATE KEY BLOCK----- """ +CIPHERTEXT = """ +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1 + +hQIMAyj9aG/xtZOwAQ/+OtgYlCULNaCqSnzDIAIO5Swsg7fLFIErSWF/4ngkNxPk +GqL3/2/HvlLY6blsmn5RU2AK4vo5Dc5s2lQU3PwqsaVKNoqkn1G9bMqsoIQhP4vW +M6c+KdxtA8cQggENpx0kF8FXdvV+GclChfK38TDJUrJLnksfo+UP9rI2BsIpHpiS +sfikVLuUc83+2hTozuTOVARNG7x58hhnR7wPtbgm/6AwVNvU0SQDEDJXi43MFRbP +9VboUHIRZLbeIwlxFHj3umh4f8rca4jSwiWxDna2YRAFBZrFiyiGAnISZQc9Nh4d +jLqa7rMeLSfTigkOXVYdVjEgx/wsbsDjgJ2f6TUrfP6RWen3/4223ctfeL2x4r2V +6ej2cbbR61qQx2FR4HV4XRaSg3tV+Ytz0dklrvcL0PQVdSsJhDmRV4pNgLSt0/bA +E6F2hk/S3sjnXZRMvXNb3SRQk2R0Svn4j/8ft/8VC+h5jkHO2G5K3DbAHkS2MPJm +bLwx4LMPohZstS75OFKZv63nzdOYIz5gPSy9A4IC1VHqM4d3T99cqY8XOJOqRkr5 +TCYOxOHF4z6N2nRkzVXoDoTfC6+qx9bWuvGhoj5WjFG1I19e+L1IVVvpYKo6LAOa +7Dn+IXe3XnCGGHn3AusJgyeqt/3Z5HgzsSPMKIh2WfUKERZZ+vrxTXIf4Ko+2tbS +aQEpuiQUr9zE4z8eT+brGJNl5mx9c1qYCSPjGIGUCt8fTOKruMEkWBQHMln05qpF +nFMYk7JXtYaArGrC1QPRVHOvgUTB6Vx7KVHikzsEXGLF6ywBnZYzeh8ah/FtxHG9 +o+vTTcScQkxVcw== +=qYFS +-----END PGP MESSAGE----- +""" +SIGNEDTEXT = """ +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1 + +owHtwYszEwAcAOBtbMxrxOWRhp2aIq/Ligubt2Ynbh45c6Sb6mZbmeFY18qi7lY4 +VHMlXENey2M9PCKvW5FHpesKXSycavNcxOr/6H7fV2Ssg0Ah3YKTnBwnxLPIJqLd +GSyXlXKe7crL5sU1I6j2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAf+AGylYXgUQh +MGhUXDOCijDAmroFJzk5TohnsZm4v7GUm3nKlmm81iD29kxTiej+o721Di7tHisO +RQNzteoFD7aa5r8tfnUnptG7YHjV10I7mKLYnuDFCJJxrPxmUo7v0haOsKS4GqYe +snts8+eyUaU/rjVh/Z5ygNnEovajBQGWeYnTpLcc6fsF7a7TmNzQndW3FjKnUitb +P0lGTGQ1kfV0RdakLsOYpNAU8qNWZTYSVcimX9kHhlliY8WQXUMEVn9/GMEkXPV5 +5GLQiuVAYXqQ9YPXmJ64UYOds8Nzxpe62vu2enMwSLQ3Odo8p1CJiBqjOAtSnegs +2sM1T1odsnqFk3zUiO2bwRfqdS40qNjX5vkbZBceiXM9mRedWaXRHE6L9PMpDnhK +iTY5Hag99XXq25v1Y0gmt2aPWnXrOyNUKuo9UrrzrlhhvxyJo3Xhmi70SbKJ83KZ +F+rkogA/nM/8GKWT4VkQLw/16KKmM8q8pjpGB3UtDsV3L1df6UnlL5LN+lOFL0QO +AZQDXE3aL8fy8B9aeri4CJmLrxvElwhH3Ad2Kp6XykVZnc8wT1q39OTFS8tfXsb8 +lKyZcmy47m2x5TKf+LpAqxKNraHf+CS+xiS7Et0gvbtrNSNN26ffprRdtWZFdByX +H0SiTbvNExzL8zhEXo/QldiyWT+e6GwpOadPGL9xIpe8Uc0k/A6uonvy8f8A +=wZ2N +-----END PGP MESSAGE----- +""" # key 7FEE575A: public key "anotheruser " +KEY_FINGERPRINT_2 = "F6E2B572ADB84EA58BD2E9A57F9DFA687FEE575A" PUBLIC_KEY_2 = """ -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..0c428a0 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,51 @@ +import pytest + +from leap.keymanager.keys import build_key_from_dict +from common import ADDRESS +from common import KEY_FINGERPRINT +from common import PUBLIC_KEY +from common import PRIVATE_KEY +from common import ADDRESS_2 +from common import KEY_FINGERPRINT_2 +from common import PUBLIC_KEY_2 +from common import PRIVATE_KEY_2 +from leap.keymanager.wrapper import TempGPGWrapper + + +@pytest.fixture +def wrapper(keys=None): + return TempGPGWrapper(keys=keys) + + +def _get_key(address, key_fingerprint, key_data, private): + kdict = { + 'uids': [address], + 'fingerprint': key_fingerprint, + 'key_data': key_data, + 'private': private, + 'length': 4096, + 'expiry_date': 0, + 'refreshed_at': 1311239602, + } + key = build_key_from_dict(kdict) + return key + + +@pytest.fixture +def public_key(): + return _get_key(ADDRESS, KEY_FINGERPRINT, PUBLIC_KEY, False) + + +@pytest.fixture +def public_key_2(): + return _get_key(ADDRESS_2, KEY_FINGERPRINT_2, PUBLIC_KEY_2, False) + + +@pytest.fixture +def openpgp_keys(): + return [ + _get_key(ADDRESS, KEY_FINGERPRINT, PUBLIC_KEY, False), + _get_key(ADDRESS_2, KEY_FINGERPRINT_2, PUBLIC_KEY_2, False), + _get_key(ADDRESS, KEY_FINGERPRINT, PRIVATE_KEY, True), + _get_key(ADDRESS_2, KEY_FINGERPRINT_2, PRIVATE_KEY_2, True), + ] diff --git a/tests/test_gpg_speed.py b/tests/test_gpg_speed.py new file mode 100644 index 0000000..e028cae --- /dev/null +++ b/tests/test_gpg_speed.py @@ -0,0 +1,286 @@ +import commands +import pytest + +from functools import partial +from gnupg import GPG +from leap.keymanager.wrapper import TempGPGWrapper + +from common import CIPHERTEXT +from common import SIGNEDTEXT + + +GROUP_INIT = 'initialization only' +GROUP_CRYPTO = 'crypto only' +GROUP_INIT_AND_CRYPTO = 'initialization and crypto' + + +# the gnupg module gets the binary version each time the GPG object is +# initialized. In some platforms this takes hundreds of milliseconds, and +# sometimes more than a second. This is currently a known bug. For making it +# evident, we provide a way to bypass the version check by monkeypatching the +# actual function that does the job. + +def get_gpg_version(): + output = commands.getoutput( + 'gpg --list-config --with-colons | grep version') + version = output.split(':').pop() + return version + + +GPG_VERSION = get_gpg_version() + + +def mock_gpg_get_version(monkeypatch): + def _setver(self): + self.binary_version = GPG_VERSION + monkeypatch.setattr( + GPG, '_check_sane_and_get_gpg_version', _setver) + + +# +# generic speed test creator +# + +def create_test(fun, num_keys=0, mock_get_version=True, init=None, group=None): + + @pytest.mark.benchmark(group=group) + def test(tmpdir, benchmark, openpgp_keys, monkeypatch): + + if mock_get_version: + mock_gpg_get_version(monkeypatch) + + if init: + res = init(tmpdir, benchmark, openpgp_keys, monkeypatch, num_keys) + benchmark(fun, res) + else: + benchmark( + fun, tmpdir, benchmark, openpgp_keys, monkeypatch, num_keys) + + return test + + +# +# gpg initializarion: 0, 1 and 2 keys +# + +def gpg_init_only(tmpdir, benchmark, openpgp_keys, monkeypatch, num_keys): + keys = openpgp_keys[0:num_keys] + gpg = GPG(homedir=tmpdir.dirname) + for key in keys: + gpg.import_keys(key.key_data) + + +test_gpg_init_nokey_slow = create_test( + gpg_init_only, num_keys=0, + mock_get_version=False, + group=GROUP_INIT) +test_gpg_init_1key_slow = create_test( + gpg_init_only, num_keys=1, + mock_get_version=False, + group=GROUP_INIT) +test_gpg_init_2keys_slow = create_test( + gpg_init_only, num_keys=2, + mock_get_version=False, + group=GROUP_INIT) + +test_gpg_init_nokey = create_test( + gpg_init_only, num_keys=0, + group=GROUP_INIT) +test_gpg_init_1key = create_test( + gpg_init_only, num_keys=1, + group=GROUP_INIT) +test_gpg_init_2keys = create_test( + gpg_init_only, num_keys=2, + group=GROUP_INIT) + + +# +# wrapper initialization: 0, 1 and 2 keys +# + +def wrapper_init_only(tmpdir, benchmark, openpgp_keys, monkeypatch, num_keys): + keys = openpgp_keys[0:num_keys] + wrapper = TempGPGWrapper(keys=keys) + with wrapper as gpg: + assert GPG == type(gpg) + + +test_wrapper_init_nokey_slow = create_test( + wrapper_init_only, num_keys=0, + mock_get_version=False, + group=GROUP_INIT) +test_wrapper_init_1key_slow = create_test( + wrapper_init_only, num_keys=1, + mock_get_version=False, + group=GROUP_INIT) +test_wrapper_init_2keys_slow = create_test( + wrapper_init_only, num_keys=2, + mock_get_version=False, + group=GROUP_INIT) + +test_wrapper_init_nokey = create_test( + wrapper_init_only, num_keys=0, + group=GROUP_INIT) +test_wrapper_init_1key = create_test( + wrapper_init_only, num_keys=1, + group=GROUP_INIT) +test_wrapper_init_2keys = create_test( + wrapper_init_only, num_keys=2, + group=GROUP_INIT) + + +# +# initialization + encryption +# + +PLAINTEXT = ' ' * 10000 # 10 KB + + +def gpg_init_exec(fun, tmpdir, benchmark, openpgp_keys, monkeypatch, _): + pubkey = openpgp_keys[0] + privkey = openpgp_keys[2] # this is PRIVATE_KEY + gpg = GPG(homedir=tmpdir.dirname) + gpg.import_keys(pubkey.key_data) + gpg.import_keys(privkey.key_data) + fun((gpg, pubkey, privkey)) + + +def wrapper_init_exec(fun, tmpdir, benchmark, openpgp_keys, monkeypatch, _): + pubkey = openpgp_keys[0] + privkey = openpgp_keys[2] + wrapper = TempGPGWrapper(keys=[pubkey, privkey]) + wrapper._build_keyring() + fun((wrapper._gpg, pubkey, privkey)) + + +def gpg_enc(res): + gpg, pubkey, _ = res + ciphertext = gpg.encrypt(PLAINTEXT, pubkey.fingerprint) + assert ciphertext.ok + assert len(ciphertext.data) + + +test_gpg_init_enc = create_test( + partial(gpg_init_exec, gpg_enc), + group=GROUP_INIT_AND_CRYPTO) +test_wrapper_init_enc = create_test( + partial(wrapper_init_exec, gpg_enc), + group=GROUP_INIT_AND_CRYPTO) + + +# +# initialization + decryption +# + +def gpg_dec(res): + gpg, _, _ = res + plaintext = gpg.decrypt(CIPHERTEXT) + assert plaintext.ok + assert len(plaintext.data) + + +test_gpg_init_dec = create_test( + partial(gpg_init_exec, gpg_dec), + group=GROUP_INIT_AND_CRYPTO) +test_wrapper_init_dec = create_test( + partial(wrapper_init_exec, gpg_dec), + group=GROUP_INIT_AND_CRYPTO) + + +# +# initialization + sign +# + +def gpg_sign(res): + gpg, _, privkey = res + gpg.import_keys(privkey.key_data) + signed = gpg.sign(PLAINTEXT, default_key=privkey.fingerprint) + assert signed.status == 'begin signing' + assert len(signed.data) > len(PLAINTEXT) + assert '-----BEGIN PGP SIGNATURE-----' in signed.data + assert '-----END PGP SIGNATURE-----' in signed.data + + +test_gpg_init_sign = create_test( + partial(gpg_init_exec, gpg_sign), + group=GROUP_INIT_AND_CRYPTO) +test_wrapper_init_sign = create_test( + partial(wrapper_init_exec, gpg_sign), + group=GROUP_INIT_AND_CRYPTO) + + +# +# initialization + verify +# + +def gpg_verify(res): + gpg, _, privkey = res + signed = gpg.verify(SIGNEDTEXT) + assert signed.valid + + +test_gpg_init_verify = create_test( + partial(gpg_init_exec, gpg_verify), + group=GROUP_INIT_AND_CRYPTO) +test_wrapper_init_verify = create_test( + partial(wrapper_init_exec, gpg_verify), + group=GROUP_INIT_AND_CRYPTO) + + +# +# encryption only +# + +def gpg_init(tmpdir, benchmark, openpgp_keys, monkeypatch, _): + pubkey = openpgp_keys[0] + privkey = openpgp_keys[2] # this is PRIVATE_KEY + gpg = GPG(homedir=tmpdir.dirname) + gpg.import_keys(pubkey.key_data) + gpg.import_keys(privkey.key_data) + return gpg, pubkey, privkey + + +def wrapper_init(tmpdir, benchmark, openpgp_keys, monkeypatch, _): + pubkey = openpgp_keys[0] + privkey = openpgp_keys[2] + wrapper = TempGPGWrapper(keys=[pubkey, privkey]) + wrapper._build_keyring() + return wrapper._gpg, pubkey, privkey + + +test_gpg_enc = create_test( + gpg_enc, init=gpg_init, group=GROUP_CRYPTO) +test_wrapper_enc = create_test( + gpg_enc, init=wrapper_init, group=GROUP_CRYPTO) + + +# +# decryption only +# + +test_gpg_dec = create_test( + gpg_dec, + init=gpg_init, group=GROUP_CRYPTO) +test_wrapper_dec = create_test( + gpg_dec, + init=wrapper_init, group=GROUP_CRYPTO) + + +# +# sign only +# + +test_gpg_sign = create_test( + gpg_sign, init=gpg_init, group=GROUP_CRYPTO) +test_wrapper_sign = create_test( + gpg_sign, init=wrapper_init, group=GROUP_CRYPTO) + + +# +# verify only +# + +test_gpg_verify = create_test( + gpg_verify, init=gpg_init, group=GROUP_CRYPTO) +test_wrapper_verify = create_test( + gpg_verify, init=wrapper_init, group=GROUP_CRYPTO) diff --git a/tests/test_openpgp.py b/tests/test_openpgp.py index 1f78ad4..60d2319 100644 --- a/tests/test_openpgp.py +++ b/tests/test_openpgp.py @@ -23,16 +23,13 @@ Tests for the OpenPGP support on Key Manager. from datetime import datetime from mock import Mock -from twisted.internet.defer import inlineCallbacks, gatherResults, succeed +from twisted.internet.defer import inlineCallbacks, succeed from leap.keymanager import ( KeyNotFound, openpgp, ) -from leap.keymanager.documents import ( - TYPE_FINGERPRINT_PRIVATE_INDEX, - TYPE_ADDRESS_PRIVATE_INDEX, -) +from leap.keymanager.documents import TYPE_FINGERPRINT_PRIVATE_INDEX from leap.keymanager.keys import OpenPGPKey from common import ( diff --git a/tox.ini b/tox.ini index 7667788..af67f56 100644 --- a/tox.ini +++ b/tox.ini @@ -3,8 +3,15 @@ envlist = py27 [testenv] commands = py.test {posargs} +changedir = tests deps = pytest + pytest-benchmark +# need the next 2 for graphs, but new version changed api a bit and is +# incompatible with pytest-benchmark, so we pin version <2.1 +# (https://github.com/ionelmc/pytest-benchmark/issues/50). + pygal<2.1 + pygaljs pdbpp mock setuptools-trial @@ -12,3 +19,4 @@ deps = leap.soledad.client setenv = HOME=/tmp + TERM=xterm -- cgit v1.2.3