From 473be2735dffc63b1ba759739ebfa7e471bc1495 Mon Sep 17 00:00:00 2001 From: J08nY Date: Mon, 7 Aug 2017 22:48:47 +0200 Subject: Use config transforms in PGP keydir and keypair configs. --- src/mailman_pgp/model/address.py | 2 +- src/mailman_pgp/model/list.py | 2 +- src/mailman_pgp/pgp/__init__.py | 94 +++++---------------------------------- src/mailman_pgp/testing/layers.py | 12 +++-- src/mailman_pgp/utils/config.py | 34 ++++++++++++++ 5 files changed, 51 insertions(+), 93 deletions(-) diff --git a/src/mailman_pgp/model/address.py b/src/mailman_pgp/model/address.py index 9ecfa95..81bcc4b 100644 --- a/src/mailman_pgp/model/address.py +++ b/src/mailman_pgp/model/address.py @@ -48,7 +48,7 @@ class PGPAddress(Base): @reconstructor def _init(self): self._address = None - self._key = FSKey(config.pgp.keydir_config['user_keydir'], + self._key = FSKey(config.pgp.keydirs['user_keydir'], self.email + '.asc', True) @property diff --git a/src/mailman_pgp/model/list.py b/src/mailman_pgp/model/list.py index 9c2d317..c68cb67 100644 --- a/src/mailman_pgp/model/list.py +++ b/src/mailman_pgp/model/list.py @@ -71,7 +71,7 @@ class PGPMailingList(Base): @reconstructor def _init(self): self._mlist = None - self._key = FSKey(config.pgp.keydir_config['list_keydir'], + self._key = FSKey(config.pgp.keydirs['list_keydir'], self.list_id + '.asc', True) @property diff --git a/src/mailman_pgp/pgp/__init__.py b/src/mailman_pgp/pgp/__init__.py index 6841f02..a68c66b 100644 --- a/src/mailman_pgp/pgp/__init__.py +++ b/src/mailman_pgp/pgp/__init__.py @@ -17,103 +17,29 @@ """""" -from glob import glob -from os import makedirs -from os.path import join - -from mailman.config import config as mailman_config -from mailman.utilities.string import expand from pgpy import PGPKeyring -from pgpy.constants import EllipticCurveOID, PubKeyAlgorithm from public import public from mailman_pgp.config import config - -KEYDIR_CONFIG_PATHS = ['list_keydir', 'user_keydir', 'archive_keydir'] -KEYPAIR_CONFIG_VARIABLES = ['autogenerate', 'primary_key', 'sub_key'] - -KEYPAIR_TYPE_MAP = { - 'RSA': PubKeyAlgorithm.RSAEncryptOrSign, - 'DSA': PubKeyAlgorithm.DSA, - 'ECDSA': PubKeyAlgorithm.ECDSA, - 'ECDH': PubKeyAlgorithm.ECDH -} -ECC_OID_MAP = { - 'nistp256': EllipticCurveOID.NIST_P256, - 'nistp384': EllipticCurveOID.NIST_P384, - 'nistp521': EllipticCurveOID.NIST_P521, - 'brainpoolP256r1': EllipticCurveOID.Brainpool_P256, - 'brainpoolP384r1': EllipticCurveOID.Brainpool_P384, - 'brainpoolP512r1': EllipticCurveOID.Brainpool_P512, - 'secp256k1': EllipticCurveOID.SECP256K1 -} +from mailman_pgp.utils.config import key_spec @public class PGP: def __init__(self): - self._load_config() - self._validate_config() - - def _load_config(self): - """ - Load [keypairs] and [keydirs] config sections. Expand paths in them. - """ - # Get all the [keypairs] config variables. - self._keypair_config = dict( - (k, config.get('keypairs', k)) for k in - KEYPAIR_CONFIG_VARIABLES) - - # Get and expand all [keydirs] config paths against Mailman's paths. - self.keydir_config = dict( - (k, - expand(config.get('keydirs', k), None, mailman_config.paths)) - for k in KEYDIR_CONFIG_PATHS) - - def _parse_key_directive(self, value): - key_type, key_length = value.split(':') - key_type = key_type.upper() - key_length = key_length.lower() - - if key_type not in KEYPAIR_TYPE_MAP: - raise ValueError('Invalid key type: {}.'.format(key_type)) - - out_type = KEYPAIR_TYPE_MAP[key_type] - if key_type in ('ECDSA', 'ECDH'): - if key_length not in ECC_OID_MAP: - raise ValueError('Invalid key length: {}.'.format(key_length)) - out_length = ECC_OID_MAP[key_length] - else: - out_length = int(key_length) - return (out_type, out_length) - - def _validate_config(self): - """ - Validate [keypairs] and [keydirs] config sections. And create - keydirs if necessary. - """ - # Validate keypair config. - self.primary_key_args = self._parse_key_directive( - self._keypair_config['primary_key']) - if not self.primary_key_args[0].can_sign: - raise ValueError( - 'Invalid primary key type: {}.'.format( - self.primary_key_args[0])) - - self.sub_key_args = self._parse_key_directive( - self._keypair_config['sub_key']) - if not self.sub_key_args[0].can_encrypt: - raise ValueError( - 'Invalid sub key type: {}.'.format(self.sub_key_args[0])) - + self.primary_key_args = key_spec( + config.get_value('keypairs', 'primary_key')) + self.sub_key_args = key_spec(config.get_value('keypairs', 'sub_key')) # Make sure the keydir paths are directories and exist. - for keydir in self.keydir_config.values(): + self.keydirs = {keydir_name: config.get_value('keydirs', keydir_name) + for keydir_name in config.options('keydirs')} + for keydir_path in self.keydirs.values(): # TODO set a strict mode here - makedirs(keydir, exist_ok=True) + keydir_path.mkdir(parents=True, exist_ok=True) def _keyring(self, keydir): - directory = self.keydir_config[keydir] - return PGPKeyring(*glob(join(directory, '*.asc'))) + directory = self.keydirs[keydir] + return PGPKeyring(*directory.glob('*.asc')) @property def list_keyring(self): diff --git a/src/mailman_pgp/testing/layers.py b/src/mailman_pgp/testing/layers.py index dcba526..986a388 100644 --- a/src/mailman_pgp/testing/layers.py +++ b/src/mailman_pgp/testing/layers.py @@ -15,8 +15,6 @@ # You should have received a copy of the GNU General Public License along with # this program. If not, see . import contextlib -import os -from os.path import isfile from mailman.testing.layers import (ConfigLayer, RESTLayer, SMTPLayer) from sqlalchemy.exc import SQLAlchemyError @@ -31,11 +29,11 @@ def reset_rollback(): def reset_pgp_dirs(): - for keydir in (config.pgp.keydir_config.values()): - for path in os.listdir(keydir): - full_path = os.path.join(keydir, path) - if isfile(full_path): - os.remove(full_path) + for keydir in (config.pgp.keydirs.values()): + for path in keydir.iterdir(): + full_path = keydir.joinpath(path) + if full_path.is_file(): + full_path.unlink() def reset_pgp_hard(): diff --git a/src/mailman_pgp/utils/config.py b/src/mailman_pgp/utils/config.py index 3296379..6b45d05 100644 --- a/src/mailman_pgp/utils/config.py +++ b/src/mailman_pgp/utils/config.py @@ -19,6 +19,7 @@ import pathlib from mailman.utilities.string import expand +from pgpy.constants import EllipticCurveOID, PubKeyAlgorithm from mailman_pgp.config import mm_config @@ -29,3 +30,36 @@ def expandable_str(value): def expandable_path(value): return pathlib.Path(expandable_str(value)) + + +def key_spec(value): + KEYPAIR_TYPE_MAP = { + 'RSA': PubKeyAlgorithm.RSAEncryptOrSign, + 'DSA': PubKeyAlgorithm.DSA, + 'ECDSA': PubKeyAlgorithm.ECDSA, + 'ECDH': PubKeyAlgorithm.ECDH + } + ECC_OID_MAP = { + 'nistp256': EllipticCurveOID.NIST_P256, + 'nistp384': EllipticCurveOID.NIST_P384, + 'nistp521': EllipticCurveOID.NIST_P521, + 'brainpoolP256r1': EllipticCurveOID.Brainpool_P256, + 'brainpoolP384r1': EllipticCurveOID.Brainpool_P384, + 'brainpoolP512r1': EllipticCurveOID.Brainpool_P512, + 'secp256k1': EllipticCurveOID.SECP256K1 + } + key_type, key_length = value.split(':') + key_type = key_type.upper() + key_length = key_length.lower() + + if key_type not in KEYPAIR_TYPE_MAP: + raise ValueError('Invalid key type: {}.'.format(key_type)) + + out_type = KEYPAIR_TYPE_MAP[key_type] + if key_type in ('ECDSA', 'ECDH'): + if key_length not in ECC_OID_MAP: + raise ValueError('Invalid key length: {}.'.format(key_length)) + out_length = ECC_OID_MAP[key_length] + else: + out_length = int(key_length) + return (out_type, out_length) -- cgit v1.2.3-70-g09d2