diff options
| -rw-r--r-- | src/mailman_pgp/commands/eml_key.py | 20 | ||||
| -rw-r--r-- | src/mailman_pgp/commands/tests/test_key.py | 16 | ||||
| -rw-r--r-- | src/mailman_pgp/config/mailman_pgp.cfg | 24 | ||||
| -rw-r--r-- | src/mailman_pgp/config/tests/test_config.py | 2 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/base.py | 3 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/test_keygen.py | 3 | ||||
| -rw-r--r-- | src/mailman_pgp/testing/layers.py | 6 | ||||
| -rw-r--r-- | src/mailman_pgp/testing/mailman_pgp.cfg | 24 | ||||
| -rw-r--r-- | src/mailman_pgp/workflows/key_change.py | 5 |
9 files changed, 74 insertions, 29 deletions
diff --git a/src/mailman_pgp/commands/eml_key.py b/src/mailman_pgp/commands/eml_key.py index 0437430..e792fa4 100644 --- a/src/mailman_pgp/commands/eml_key.py +++ b/src/mailman_pgp/commands/eml_key.py @@ -183,6 +183,16 @@ def _cmd_change(pgp_list, mlist, msg, msgdata, arguments, results): file=results) return ContinueProcessing.no + email = get_email(msg) + if not email: + print('No email to change key of.', file=results) + return ContinueProcessing.no + + pgp_address = PGPAddress.for_email(email) + if pgp_address is None: + print('A pgp enabled address not found.', file=results) + return ContinueProcessing.no + wrapped = PGPWrapper(msg) if wrapped.is_encrypted(): decrypted = wrapped.decrypt(pgp_list.key) @@ -197,16 +207,6 @@ def _cmd_change(pgp_list, mlist, msg, msgdata, arguments, results): print('More than one key! Send only one key.', file=results) return ContinueProcessing.no - email = get_email(msg) - if not email: - print('No email to change key of.', file=results) - return ContinueProcessing.no - - pgp_address = PGPAddress.for_email(email) - if pgp_address is None: - print('A pgp enabled address not found.', file=results) - return ContinueProcessing.no - workflow = KeyChangeWorkflow(mlist, pgp_address, keys.pop()) list(workflow) print('Key change request received.', file=results) diff --git a/src/mailman_pgp/commands/tests/test_key.py b/src/mailman_pgp/commands/tests/test_key.py index 0125888..8920e44 100644 --- a/src/mailman_pgp/commands/tests/test_key.py +++ b/src/mailman_pgp/commands/tests/test_key.py @@ -686,6 +686,14 @@ class TestAfterSubscription(unittest.TestCase): results_msg.get_payload()) def test_change_no_key(self): + bart = getUtility(IUserManager).create_address('bart@example.com', + 'Bart Person') + with transaction() as t: + pgp_address = PGPAddress(bart) + pgp_address.key = self.bart_key.pubkey + pgp_address.key_confirmed = True + t.add(pgp_address) + message = _create_plain('bart@example.com', 'test@example.com', 'key change', '') @@ -699,6 +707,14 @@ class TestAfterSubscription(unittest.TestCase): results_msg.get_payload()) def test_change_multiple_keys(self): + bart = getUtility(IUserManager).create_address('bart@example.com', + 'Bart Person') + with transaction() as t: + pgp_address = PGPAddress(bart) + pgp_address.key = self.bart_key.pubkey + pgp_address.key_confirmed = True + t.add(pgp_address) + set_message = _create_mixed('bart@example.com', 'test@example.com', 'key change') diff --git a/src/mailman_pgp/config/mailman_pgp.cfg b/src/mailman_pgp/config/mailman_pgp.cfg index 1f0999a..e975836 100644 --- a/src/mailman_pgp/config/mailman_pgp.cfg +++ b/src/mailman_pgp/config/mailman_pgp.cfg @@ -19,23 +19,23 @@ [db] # db path the PGP plugin will use to store list/user configuration (not keys!). -url = sqlite:////$DATA_DIR/pgp.db +url: sqlite:////$DATA_DIR/pgp.db [keydirs] # Key directory used to store user public keys. -user_keydir = $DATA_DIR/pgp/user_keydir/ +user_keydir: $DATA_DIR/pgp/user_keydir/ # Key directory used to store list keypairs. -list_keydir = $DATA_DIR/pgp/list_keydir/ +list_keydir: $DATA_DIR/pgp/list_keydir/ # Key directory used to store archive public keys. -archive_keydir = $DATA_DIR/pgp/archive_keydir/ +archive_keydir: $DATA_DIR/pgp/archive_keydir/ [keypairs] # Whether to autogenerate the list key on list creation. -autogenerate = yes +autogenerate: yes # Type of primary list key and its size. # Format: type:size @@ -44,7 +44,7 @@ autogenerate = yes # size is the key size or curve name for ECDSA, which can be one of: # nistp256, nistp384, nistp521, brainpoolP256r1, brainpoolP384r1, # brainpoolP512r1, secp256k1 -primary_key = RSA:4096 +primary_key: RSA:4096 # Type of list encryption subkey and its size. # Format: type:size @@ -53,9 +53,17 @@ primary_key = RSA:4096 # size is the key size or curve name for ECDH, which can be one of: # nistp256, nistp384, nistp521, brainpoolP256r1, brainpoolP384r1, # brainpoolP512r1, secp256k1 -sub_key = RSA:4096 +sub_key: RSA:4096 + +# Shred keys on list deletion? +shred: yes [queues] # The queue to which processed incoming messages are passed. -in = in_default
\ No newline at end of file +in: in_default + + +[misc] +# The lifetime for `key change` request confirmation. +change_request_lifetime: 1d diff --git a/src/mailman_pgp/config/tests/test_config.py b/src/mailman_pgp/config/tests/test_config.py index 0c2bfe7..3ad4ca2 100644 --- a/src/mailman_pgp/config/tests/test_config.py +++ b/src/mailman_pgp/config/tests/test_config.py @@ -30,7 +30,7 @@ class TestConfig(TestCase): self.assertEqual(config.name, 'pgp') def test_sections(self): - sections = sorted(['db', 'keydirs', 'keypairs', 'queues']) + sections = sorted(['db', 'keydirs', 'keypairs', 'queues', 'misc']) self.assertListEqual(sorted(config.sections()), sections) def test_db(self): diff --git a/src/mailman_pgp/pgp/tests/base.py b/src/mailman_pgp/pgp/tests/base.py index 52e5ec4..47d333c 100644 --- a/src/mailman_pgp/pgp/tests/base.py +++ b/src/mailman_pgp/pgp/tests/base.py @@ -25,6 +25,8 @@ from mailman.email.message import Message from pgpy import PGPKey from pkg_resources import resource_string +from mailman_pgp.testing.layers import PGPLayer + def load_message(path): data = resource_string('mailman_pgp.pgp.tests', @@ -40,6 +42,7 @@ def load_key(path): class WrapperTestCase(TestCase): + layer = PGPLayer wrapper = None def wrap(self, message): diff --git a/src/mailman_pgp/pgp/tests/test_keygen.py b/src/mailman_pgp/pgp/tests/test_keygen.py index f2f72a7..a3a5499 100644 --- a/src/mailman_pgp/pgp/tests/test_keygen.py +++ b/src/mailman_pgp/pgp/tests/test_keygen.py @@ -25,9 +25,12 @@ from pgpy import PGPKey from pgpy.constants import EllipticCurveOID, PubKeyAlgorithm from mailman_pgp.pgp.keygen import ListKeyGenerator +from mailman_pgp.testing.layers import PGPLayer class TestKeygen(TestCase): + layer = PGPLayer + def setUp(self): self.display_name = 'Display Name' self.posting_address = 'posting@address.com' diff --git a/src/mailman_pgp/testing/layers.py b/src/mailman_pgp/testing/layers.py index 07eb386..34f6b1a 100644 --- a/src/mailman_pgp/testing/layers.py +++ b/src/mailman_pgp/testing/layers.py @@ -18,7 +18,8 @@ import contextlib import os from os.path import isfile -from mailman.testing.layers import (ConfigLayer, RESTLayer, SMTPLayer) +from mailman.testing.layers import (ConfigLayer, RESTLayer, SMTPLayer, + MockAndMonkeyLayer) from sqlalchemy.exc import SQLAlchemyError from mailman_pgp.config import config @@ -59,6 +60,9 @@ def reset_pgp_soft(): trans.commit() +class PGPLayer: + pass + # It's weird that ws have to do this, but for some reason nose2 test layers # don't work when ws create a mixin class with the two classmethods # and subclass both it and the respective Mailman Core test layer. diff --git a/src/mailman_pgp/testing/mailman_pgp.cfg b/src/mailman_pgp/testing/mailman_pgp.cfg index 871f429..c85d38a 100644 --- a/src/mailman_pgp/testing/mailman_pgp.cfg +++ b/src/mailman_pgp/testing/mailman_pgp.cfg @@ -19,23 +19,23 @@ [db] # db path the PGP plugin will use to store list/user configuration (not keys!). -url = sqlite:////$DATA_DIR/pgp.db +url: sqlite:////$DATA_DIR/pgp.db [keydirs] # Key directory used to store user public keys. -user_keydir = $DATA_DIR/pgp/user_keydir/ +user_keydir: $DATA_DIR/pgp/user_keydir/ # Key directory used to store list keypairs. -list_keydir = $DATA_DIR/pgp/list_keydir/ +list_keydir: $DATA_DIR/pgp/list_keydir/ # Key directory used to store archive public keys. -archive_keydir = $DATA_DIR/pgp/archive_keydir/ +archive_keydir: $DATA_DIR/pgp/archive_keydir/ [keypairs] # Whether to autogenerate the list key on list creation. -autogenerate = no +autogenerate: no # Type of primary list key and its size. # Format: type:size @@ -44,7 +44,7 @@ autogenerate = no # size is the key size or curve name for ECDSA, which can be one of: # nistp256, nistp384, nistp521, brainpoolP256r1, brainpoolP384r1, # brainpoolP512r1, secp256k1 -primary_key = ECDSA:secp256k1 +primary_key: ECDSA:secp256k1 # Type of list encryption subkey and its size. # Format: type:size @@ -53,9 +53,17 @@ primary_key = ECDSA:secp256k1 # size is the key size or curve name for ECDH, which can be one of: # nistp256, nistp384, nistp521, brainpoolP256r1, brainpoolP384r1, # brainpoolP512r1, secp256k1 -sub_key = ECDH:secp256k1 +sub_key: ECDH:secp256k1 + +# Shred keys on list deletion? +shred: yes [queues] # The queue to which processed incoming messages are passed. -in = in_default
\ No newline at end of file +in: in_default + + +[misc] +# The lifetime for `key change` request confirmation. +change_request_lifetime: 1d diff --git a/src/mailman_pgp/workflows/key_change.py b/src/mailman_pgp/workflows/key_change.py index 01693f5..61acf95 100644 --- a/src/mailman_pgp/workflows/key_change.py +++ b/src/mailman_pgp/workflows/key_change.py @@ -16,6 +16,7 @@ # this program. If not, see <http://www.gnu.org/licenses/>. """""" +from lazr.config import as_timedelta from mailman.email.message import UserNotification from mailman.interfaces.pending import IPendable, IPendings from mailman.interfaces.subscriptions import TokenOwner @@ -26,6 +27,7 @@ from public import public from zope.component import getUtility from zope.interface import implementer +from mailman_pgp.config import config from mailman_pgp.database import transaction from mailman_pgp.model.address import PGPAddress from mailman_pgp.model.list import PGPMailingList @@ -93,7 +95,8 @@ class KeyChangeWorkflow(Workflow): pubkey=str(self.pubkey), fingerprint=self.pubkey.fingerprint ) - self.token = pendings.add(pendable) + lifetime = as_timedelta(config.get('misc', 'change_request_lifetime')) + self.token = pendings.add(pendable, lifetime=lifetime) self.token_owner = TokenOwner.subscriber self.push('receive_confirmation') |
