diff options
Diffstat (limited to 'src/mailman_pgp/pgp/__init__.py')
| -rw-r--r-- | src/mailman_pgp/pgp/__init__.py | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/src/mailman_pgp/pgp/__init__.py b/src/mailman_pgp/pgp/__init__.py index 52506a6..b9aad50 100644 --- a/src/mailman_pgp/pgp/__init__.py +++ b/src/mailman_pgp/pgp/__init__.py @@ -1,39 +1,78 @@ """""" -from pathlib import Path +from os import listdir, makedirs +from os.path import isfile -import gpgmime from mailman.config import config as mailman_config from mailman.utilities.string import expand +from pgpy import PGPKeyring +from pgpy.constants import PubKeyAlgorithm from public import public from mailman_pgp.config import config -GPG_CONFIG_PATHS = ['homedir', 'keyring', 'secring', 'binary'] +KEYDIR_CONFIG_PATHS = ['list_keydir', 'user_keydir', 'archive_keydir'] KEYPAIR_CONFIG_VARIABLES = ['key_type', 'key_length', 'subkey_type', 'subkey_length'] -KEYPAIR_CONFIG_DEFAULTS = { - 'key_usage': 'auth,sign,cert', - 'subkey_usage': 'enc' +KEYPAIR_KEY_TYPE_VALID = ['RSA', 'DSA', 'ECDSA'] +KEYPAIR_SUBKEY_TYPE_VALID = ['RSA', 'ECDH'] +KEYPAIR_TYPE_MAP = { + 'RSA': PubKeyAlgorithm.RSAEncryptOrSign, + 'DSA': PubKeyAlgorithm.DSA, + 'ECDSA': PubKeyAlgorithm.ECDSA, + 'ECDH': PubKeyAlgorithm.ECDH } @public -class GPG(gpgmime.GPG): +class PGP: def __init__(self): + self._load_config() + self._validate_config() + + def _load_config(self): # Get all the [keypairs] config variables. self.keypair_config = dict( (k, config.get('keypairs', k)) for k in KEYPAIR_CONFIG_VARIABLES) - self.keypair_config.update(KEYPAIR_CONFIG_DEFAULTS) # Get and expand all [gpg] config paths against Mailman's directories. - self.gpg_config = dict( - (k, expand(config.get('gpg', k), None, mailman_config.paths)) - for k in GPG_CONFIG_PATHS) + self.keydir_config = dict( + (k, expand(config.get('keydirs', k), None, mailman_config.paths)) + for k in KEYDIR_CONFIG_PATHS) + + def _validate_config(self): + # Validate keypair config + key_type = self.keypair_config['key_type'].upper() + if key_type not in KEYPAIR_KEY_TYPE_VALID: + raise ValueError('Invalid key_type. {}'.format(key_type)) + self.keypair_config['key_type'] = KEYPAIR_TYPE_MAP[key_type] + self.keypair_config['key_size'] = int(self.keypair_config['key_size']) + + subkey_type = self.keypair_config['subkey_type'].upper() + if subkey_type not in KEYPAIR_SUBKEY_TYPE_VALID: + raise ValueError('Invalid subkey_type. {}'.format(subkey_type)) + self.keypair_config['subkey_type'] = KEYPAIR_TYPE_MAP[subkey_type] + self.keypair_config['subkey_size'] = int( + self.keypair_config['subkey_size']) + + # Make sure the keydir paths are directories and exist. + for keydir in self.keydir_config.values(): + # TODO set a strict mode here + makedirs(keydir, exist_ok=True) + + def _keyring(self, keydir): + keyfiles = [f for f in listdir(self.keydir_config[keydir]) + if isfile(f)] + return PGPKeyring(*keyfiles) + + @property + def list_keyring(self): + return self._keyring('list_keydir') - # Ensure that the homedir path is a directory before passing it to GPG. - # If it's actually a file this raises FileExistsError. - homedir_path = Path(self.gpg_config['homedir']) - homedir_path.mkdir(parents=True, exist_ok=True) + @property + def user_keyring(self): + return self._keyring('user_keydir') - super().__init__(**self.gpg_config) + @property + def archive_keyring(self): + return self._keyring('archive_keydir') |
