From 8cc1136a90071e3cb8eb1e733f2e3e6a3802b535 Mon Sep 17 00:00:00 2001 From: "Piotr F. Mieszkowski" Date: Sun, 10 Dec 2023 21:27:05 +0100 Subject: [PATCH 1/3] =?UTF-8?q?lacre.daemon:=20When=20keys=20can't=C2=A0be?= =?UTF-8?q?=20loaded,=20fail=20gracefully?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduce '[daemon]bounce_on_keys_missing' option to let the admin decide if they want Lacre to deliver cleartext message when identity database is unreachable or throws exceptions. It defaults to 'no'. - In IdentityRepository, use option mentioned above to decide what to do when an exception is caught. --- gpg-mailgate.conf.sample | 5 +++++ lacre/daemon.py | 2 -- lacre/repositories.py | 15 ++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/gpg-mailgate.conf.sample b/gpg-mailgate.conf.sample index 01a1d9c..42dd7bc 100644 --- a/gpg-mailgate.conf.sample +++ b/gpg-mailgate.conf.sample @@ -68,6 +68,11 @@ max_data_bytes = 33554432 # This should never be PII, but information like encoding, content types, etc. log_headers = no +# Sometimes we might fail to load keys and need to choose between delivering +# in cleartext or not delivering. The default is to deliver cleartext, but +# administrators can make this decision on their own. +bounce_on_keys_missing = no + [relay] # the relay settings to use for Postfix # gpg-mailgate will submit email to this relay after it is done processing diff --git a/lacre/daemon.py b/lacre/daemon.py index b704609..59d3ac0 100644 --- a/lacre/daemon.py +++ b/lacre/daemon.py @@ -37,9 +37,7 @@ class MailEncryptionProxy: with time_logger('Message delivery', LOG): try: keys = self._keyring.freeze_identities() - LOG.debug('Parsing message: %s', self._beginning(envelope)) message = email.message_from_bytes(envelope.original_content, policy=SMTPUTF8) - LOG.debug('Parsed into %s: %s', type(message), repr(message)) if message.defects: LOG.warning("Issues found: %d; %s", len(message.defects), repr(message.defects)) diff --git a/lacre/repositories.py b/lacre/repositories.py index b6b54ad..b95eb75 100644 --- a/lacre/repositories.py +++ b/lacre/repositories.py @@ -13,6 +13,7 @@ LOG = logging.getLogger(__name__) # Internal state _engine = None + def connect(url): global _engine @@ -78,13 +79,21 @@ class IdentityRepository(KeyRing): self._conn.execute(delq) def freeze_identities(self) -> KeyCache: - """Return a static, async-safe copy of the identity map.""" + """Return a static, async-safe copy of the identity map. + + Depending on the value of [daemon]bounce_on_keys_missing value, + if we get a database exception, this method will either return + empty collection or let the exception be propagated. + """ self._ensure_connected() try: return self._load_identities() except OperationalError: - LOG.exception('Cannot retrieve identities') - return None + if conf.flag_enabled('daemon', 'bounce_on_keys_missing'): + raise + else: + LOG.exception('Failed to load keys, returning empty collection') + return KeyCache({}) def _load_identities(self) -> KeyCache: all_identities = select(self._identities.c.fingerprint, self._identities.c.email) -- 2.30.2 From 23a05c11acffe193abb565687849189c6b0a1e0e Mon Sep 17 00:00:00 2001 From: "Piotr F. Mieszkowski" Date: Sun, 10 Dec 2023 21:35:35 +0100 Subject: [PATCH 2/3] Remove EncryptionException formatting test --- test/modules/test_gnupg.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/modules/test_gnupg.py b/test/modules/test_gnupg.py index f3d0eba..f71eff3 100644 --- a/test/modules/test_gnupg.py +++ b/test/modules/test_gnupg.py @@ -65,10 +65,6 @@ class GnuPGUtilitiesTest(unittest.TestCase): uid = GnuPG._parse_uid_line(sample_in) self.assertEqual(uid, 'alice@disposlab') - def test_exception_formatting(self): - e = GnuPG.EncryptionException('alice@disposlab', 'key expired', None, b'DEADBEEF') - self.assertEqual(str(e), 'To: alice@disposlab; Issue: key expired; Key: DEADBEEF') - def test_parse_statusfd_key_expired(self): key_expired = b""" [GNUPG:] KEYEXPIRED 1668272263 -- 2.30.2 From e8d0d248b3fbdfc28e732a8344f9014bd04e493b Mon Sep 17 00:00:00 2001 From: "Piotr F. Mieszkowski" Date: Sun, 10 Dec 2023 21:39:59 +0100 Subject: [PATCH 3/3] lacre.repositories: Add missing import --- lacre/repositories.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lacre/repositories.py b/lacre/repositories.py index b95eb75..b4c3ad0 100644 --- a/lacre/repositories.py +++ b/lacre/repositories.py @@ -4,6 +4,7 @@ from sqlalchemy import create_engine, select, delete, and_, func from sqlalchemy.exc import OperationalError import logging +from lacre.config import flag_enabled from lacre._keyringcommon import KeyRing, KeyCache import lacre.dbschema as db @@ -89,7 +90,7 @@ class IdentityRepository(KeyRing): try: return self._load_identities() except OperationalError: - if conf.flag_enabled('daemon', 'bounce_on_keys_missing'): + if flag_enabled('daemon', 'bounce_on_keys_missing'): raise else: LOG.exception('Failed to load keys, returning empty collection') -- 2.30.2