Merge pull request 'Rename GPG-Mailgate to Lacre' (#138) from 81_rename-to-lacre into main

Reviewed-on: #138
This commit is contained in:
pfm 2024-02-23 07:35:21 +00:00
commit d75ded751e
29 changed files with 382 additions and 272 deletions

4
.gitignore vendored
View File

@ -29,10 +29,10 @@ pip-log.txt
.tox
nosetests.xml
# GPG-Mailgate test files
# Lacre test files
test/logs
test/tmp
test/gpg-mailgate.conf
test/lacre.conf
test/keyhome/random_seed
# Emacs files

View File

@ -1,20 +1,20 @@
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
"""GnuPG wrapper module."""

View File

@ -3,19 +3,19 @@
## Content
- General information
- Install GPG-Mailgate
- Install GPG-Mailgate-Web
- Install Lacre
- Install [Lacre-Webgate](https://git.disroot.org/Lacre/lacre-webgate)
- Install Register-handler
## General information
GPG-Mailgate is divided in 3 main parts: GPG-Mailgate itself, GPG-Mailgate-Web and Register-handler. Some parts of the GPG-Mailgate project depend on other parts of the project. You will find information about these dependencies at the beginning of every installation part.
Lacre is divided in 3 main parts: Lacre itself, Lacre-Webgate and Register-handler. Some parts of the Lacre project depend on other parts of the project. You will find information about these dependencies at the beginning of every installation part.
These instructions show you how to set up GPG-Mailgate in an easy way. If you are a more advanced user, feel free to experiment with the settings. For these instructions a home directory for the user `nobody` is set. Sadly this is an odd workaround but no better solution was found.
These instructions show you how to set up Lacre in an easy way. If you are a more advanced user, feel free to experiment with the settings. For these instructions a home directory for the user `nobody` is set. Sadly this is an odd workaround but no better solution was found.
These instructions are based on an installation on an Ubuntu 14.04 LTS virtual machine. For other Linux distributions and other versions these instructions might need to be adapted to your distribution (e.g. installation of packages and used directories).
## Install GPG-Mailgate
## Install Lacre
### Requirements
@ -41,29 +41,26 @@ usermod -d /var/gpgmailgate nobody
3. Create dedicated directories for storing PGP keys and S/MIME certificates and make the user `nobody` owner of these:
```
mkdir -p /var/gpgmailgate/.gnupg
mkdir -p /var/gpgmailgate/smime
chown -R nobody:nogroup /var/gpgmailgate/
install -u nobody -g nobody -d /var/gpgmailgate/ /var/gpgmailgate/.gnupg /var/gpgmailgate/smime
```
4. Place the `gpg-mailgate.py` in `/usr/local/bin/`, make the user `nobody` owner of the file and make it executable:
4. Place the `lacre.py` in `/usr/local/bin/`, make the user `nobody` owner of the file and make it executable:
```
chown nobody:nogroup /usr/local/bin/gpg-mailgate.py
chmod u+x /usr/local/bin/gpg-mailgate.py
install -u nobody -g nobody -mode u=rx lacre.py /usr/local/bin/
```
5. Place the `GnuPG` directory in `/usr/local/lib/python3.x/dist-packages` (replace 3.x with your Python version)
5. Place `GnuPG` and `lacre` directories in `/usr/local/lib/python3.x/dist-packages` (replace 3.x with your Python version). Make sure they're available for Python `import`s by executing `python -m lacre.admin -h` command.
6. Configure `/etc/gpg-mailgate.conf` based on the provided `gpg-mailgate.conf.sample`. Change the settings according to your configuration. If you follow this guide and have a standard configuration for postfix, you don't need to change much.
6. Configure `/etc/lacre.conf` based on the provided `lacre.conf.sample`. Change the settings according to your configuration. If you follow this guide and have a standard configuration for postfix, you don't need to change much.
7. Configure logging by copying `gpg-lacre-logging.conf.sample` to `/etc/gpg-lacre-logging.conf` and editing it according to your needs. The path to this file is included in `[logging]` section of `gpg-mailgate.conf` file, so if you place it somewhere else, make sure to update the path too. See also: [Configuration file format](https://docs.python.org/3/library/logging.config.html#configuration-file-format).
7. Configure logging by copying `lacre-logging.conf.sample` to `/etc/lacre-logging.conf` and editing it according to your needs. The path to this file is included in `[logging]` section of `lacre.conf` file, so if you place it somewhere else, make sure to update the path too. See also: Python logging package's [Configuration file format](https://docs.python.org/3/library/logging.config.html#configuration-file-format).
8. Add the following to the end of `/etc/postfix/master.cf`
```
gpg-mailgate unix - n n - - pipe
flags= user=nobody argv=/usr/local/bin/gpg-mailgate.py ${recipient}
lacre unix - n n - - pipe
flags= user=nobody argv=/usr/local/bin/lacre.py ${recipient}
127. 0. 0. 1:10028 inet n - n - 10 smtpd
-o content_filter=
@ -76,12 +73,12 @@ gpg-mailgate unix - n n - - pipe
-o smtpd_authorized_xforward_hosts=127. 0. 0. 0/8
```
If you use Postfix versions from 2.5 onwards, it is recommended to change `${recipient}` to `${original_recipient}` in line two of the lines above.
If you use Postfix versions from 2.5 onwards, it is recommended to change `${recipient}` to `${original_recipient}` in second line of the snippet above.
9. Add the following line to `/etc/postfix/main.cf`
```
content_filter = gpg-mailgate
content_filter = lacre
```
10. Optional: GPG can automatically download new public keys for automatic signature verification. To enable automatic create the file `/var/gpgmailgate/.gnupg/gpg.conf`. Add the following line to the file:
@ -98,22 +95,23 @@ You are now ready to go. To add a public key for encryption just use the followi
sudo -u nobody /usr/bin/gpg --homedir=/var/gpgmailgate/.gnupg --import /some/public.key
```
- Replace `/some/public.key` with the location of a public key
- `/some/public.key` can be deleted after importation
- Replace `/some/public.key` with the location of a public key (`/some/public.key` can be deleted after the import).
- Confirm that it's working: `sudo -u nobody /usr/bin/gpg --list-keys --homedir=/var/gpgmailgate/.gnupg`
If you already have a keyring you would like to import into Lacre, you can use `lacre.admin` command-line utility. Read more in [Lacre administration](doc/admin.md).
Please also test your installation before using it.
GPG-Mailgate is also able to handle S/MIME certificates for encrypting mails. However, it is best to use it in combination with Register-Handler described later to add new certificates. If you try to add them manually it might fail. The certificates are stored in `/var/gpgmailgate/smime` in PKCS7 format and are named like `User@example.com` (the user part is case sensitive, the domain part should be in lower case).
Lacre is also able to handle S/MIME certificates for encrypting mails. However, it is best to use it in combination with Register-Handler described later to add new certificates. If you try to add them manually it might fail. The certificates are stored in `/var/gpgmailgate/smime` in PKCS7 format and are named like `User@example.com` (the user part is case sensitive, the domain part should be in lower case).
#### Additional settings
Most mail servers do not handle mail addresses case sensitive. If you know that all your recipient mail servers do not care about case sensitivity then you can set `mail_case_insensitive` in the settings to `yes` so looking up PGP keys or S/MIME certificates does also happen case insensitive.
If your recipients have problems to decrypt mails encrypted by GPG-Mailgate they might use a piece of software that does not support PGP/MIME encrypted mails. You can tell GPG-Mailgate to use the legacy PGP/INLINE format by adding the recipient to the `pgp_style` map in the following format:
If your recipients have problems to decrypt mails encrypted by Lacre they might use a piece of software that does not support PGP/MIME encrypted mails. You can tell Lacre to use the legacy PGP/INLINE format by adding the recipient to the `pgp_style` map in the following format:
`User@example.com=inline`
## Install GPG-Mailgate-Web
## Install Lacre-Webgate
### Requirements
@ -134,13 +132,13 @@ repository.
apt-get install python-mysqldb python-markdown
```
2. Create a new database for GPG-Mailgate-Web.
2. Create a new database for Lacre-Webgate.
3. Import the schema file `schema.sql` into the newly created database.
4. Edit the config file located at `/etc/gpg-mailgate.conf`. Set `enabled = yes` in `[database]` and fill in the necessary settings for the database connection.
4. Edit the config file located at `/etc/lacre.conf`. Set `enabled = yes` in `[database]` and fill in the necessary settings for the database connection.
5. Copy the files located in the [public_html](gpg-mailgate-web/public_html) directory onto your webserver. They can also be placed in a subdirectory on your webserver.
5. Copy the files located in the [public_html](https://git.disroot.org/Lacre/lacre-webgate/src/branch/main/public_html) directory onto your webserver. They can also be placed in a subdirectory on your webserver.
6. On your webserver move the `config.sample.php` file to `config.php` and edit the configuration file.
@ -156,28 +154,27 @@ mkdir -p /var/gpgmailgate/cron_templates
chown -R nobody:nogroup /var/gpgmailgate/cron_templates
```
9. Copy `cron.py` to `/usr/local/bin/gpgmw-cron.py`. Make it executable and and transfer ownership to `nobody`:
9. Copy `cron.py` to `/usr/local/bin/cron.py`. Make it executable and and transfer ownership to `nobody`:
```
chown nobody:nogroup /usr/local/bin/gpgmw-cron.py
chmod u+x /usr/local/bin/gpgmw-cron.py
install -u nobody -g nobody -m u+x cron.py /usr/local/bin/lacre-cron.py
```
10. Create `/etc/cron.d/gpgmw` with contents:
`*/3 * * * * nobody /usr/bin/python /usr/local/bin/gpgmw-cron.py > /dev/null`
10. Create `/etc/cron.d/lacre-cron` with contents:
`*/3 * * * * nobody /usr/bin/python /usr/local/bin/lacre-cron.py > /dev/null`
for executing the cron job automatically.
11. Test your installation.
### GPG-Mailgate-Web as keyserver
### Lacre-Webgate as keyserver
GPG-Mailgate-Web can also be used as a keyserver. For more information have a look at GPG-Mailgate-Web's [readme](gpg-mailgate-web/README).
Lacre-Webgate can also be used as a keyserver. For more information have a look at Lacre-Webgate's [README](https://git.disroot.org/Lacre/lacre-webgate/src/branch/main/README.md).
## Install Register-handler
### Requirements
- Already set up and working GPG-Mailgate-Web. It should be reachable from the machine that will run register-handler
- Already set up and working Lacre-Webgate. It should be reachable from the machine that will run register-handler
- Postfix is already installed and configured. It is recommended that you have already tested your configuration so we can exclude this as a main cause of problems. Your Postfix configuration should also support aliases
### Installation
@ -203,11 +200,10 @@ chown -R nobody:nogroup /var/gpgmailgate/register_templates
4. Copy `register-handler.py` to `/usr/local/bin/register-handler.py`. Make it executable and own it to `nobody`:
```
chown nobody:nogroup /usr/local/bin/register-handler.py
chmod a+x /usr/local/bin/register-handler.py
install -u nobody -g nogroup -m a+x register-handler.py /usr/local/bin/
```
5. Edit the config file located at `/etc/gpg-mailgate.conf`. Set the parameter `webpanel_url` in `[mailregister]` to the url of your GPG-Mailgate-Web panel (the URL should be the same as the one you use to access the panel with your web browser). Also set the parameter `register_email` to the email address you want the user to see when receiving mails from the register-handler (it does not have to be an existing address but it is recommended). Register-handler will send users mails when they are registering S/MIME certificates or when neither a S/MIME certificate nor a PGP key was found in a mail sent to the register-handler.
5. Edit the config file located at `/etc/lacre.conf`. Set the parameter `webpanel_url` in `[mailregister]` to the url of your Lacre-Webgate panel (the URL should be the same as the one you use to access the panel with your web browser). Also set the parameter `register_email` to the email address you want the user to see when receiving mails from the register-handler (it does not have to be an existing address but it is recommended). Register-handler will send users mails when they are registering S/MIME certificates or when neither a S/MIME certificate nor a PGP key was found in a mail sent to the register-handler.
6. Add `register: |/usr/local/bin/register-handler.py` to `/etc/aliases`

View File

@ -28,9 +28,9 @@ test: e2etest daemontest unittest crontest
#
# Run a set of end-to-end tests.
#
# Test scenarios are described and configured by the test/e2e.ini
# file. Basically this is just a script that feeds GPG Mailgate with
# known input and checks whether output meets expectations.
# Test scenarios are described and configured by the test/e2e.ini file.
# Basically this is just a script that feeds Lacre with known input and checks
# whether output meets expectations.
#
e2etest: test/tmp test/logs pre-clean restore-keyhome
$(PYTHON) test/e2e_test.py
@ -39,11 +39,11 @@ e2etest: test/tmp test/logs pre-clean restore-keyhome
# Run a basic cron-job test.
#
# We use PYTHONPATH to make sure that cron.py can import GnuPG
# package. We also set GPG_MAILGATE_CONFIG env. variable to make sure
# package. We also set LACRE_CONFIG env. variable to make sure
# it slurps the right config.
#
crontest: clean-db $(TEST_DB)
GPG_MAILGATE_CONFIG=test/gpg-mailgate-cron-test.conf PYTHONPATH=`pwd` \
LACRE_CONFIG=test/lacre-daemon.conf PYTHONPATH=`pwd` \
$(PYTHON) webgate-cron.py
$(TEST_DB):
@ -64,10 +64,10 @@ clean-db:
# Run unit tests
#
unittest:
GPG_MAILGATE_CONFIG=test/gpg-mailgate.conf $(PYTHON) -m unittest discover -s test/modules
LACRE_CONFIG=test/lacre.conf $(PYTHON) -m unittest discover -s test/modules
pre-clean:
rm -fv test/gpg-mailgate.conf
rm -fv test/lacre.conf
rm -f test/logs/*.log
restore-keyhome:

View File

@ -11,6 +11,20 @@ python -m lacre.admin -h
Of course `-h` displays some help.
**Note:** Help output includes information about the configuration file being
in use, which may be useful at times.
## Initialising database schema
If you want to initialise Lacre's database (which is also used by the
frontend), run:
```sh
python -m lacre.admin database -i
```
## Inspecting key confirmation queue
To find out how many keys are waiting to be confirmed, run:
@ -19,6 +33,19 @@ To find out how many keys are waiting to be confirmed, run:
python -m lacre.admin queue
```
To see identities (emails) waiting for confirmation, use `--list` (or `-l`)
option:
```sh
python -m lacre.admin queue -l
```
To delete one of these emails, use `--delete` (or `-d`) option:
```sh
python -m lacre.admin queue -d malory@example.org
```
## Inspecting identities registered
To list all identities, run:
@ -35,12 +62,12 @@ python -m lacre.admin identities -e alice@example.com
## Importing identities from existing GnuPG keyring
If you already have a GnuPG keyring with your users' public keys or for some
If you already have a GnuPG keyring with your users' public keys or for some
reason Lacre's identity database needs to be re-populated with identities,
there's a command to do that:
there's a command to do that:
```sh
python -m lacre.admin import -d /path/to/gnupg/directory
python -m lacre.admin import -d /path/to/gnupg/directory
```
If you want to just re-populate the database, Lacre can remove all identities

View File

@ -33,13 +33,13 @@ setting port to `10026`.
Command to spawn a Lacre daemon process is:
```
GPG_MAILGATE_CONFIG=/etc/gpg-mailgate.conf PYTHONPATH=... python -m lacre.daemon
LACRE_CONFIG=/etc/lacre.conf PYTHONPATH=... python -m lacre.daemon
```
Two environment variables used here are:
* `GPG_MAILGATE_CONFIG` (not mandatory) -- path to Lacre configuration,
unless it's kept in default location (`/etc/gpg-maillgate.conf`).
* `LACRE_CONFIG` (not mandatory) -- path to Lacre configuration,
unless it's kept in default location (`/etc/lacre.conf`).
* `PYTHONPATH` (not mandatory) -- location of Lacre modules. You can place
them below your Python's `site-packages` to be reachable by any other
Python software.

View File

@ -1,71 +0,0 @@
#!/usr/bin/python
#
# gpg-mailgate
#
# This file is part of the gpg-mailgate source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
#
import email
from email.policy import SMTPUTF8
import sys
import time
import logging
import lacre
import lacre.config as conf
start = time.process_time()
conf.load_config()
lacre.init_logging(conf.get_item('logging', 'config'))
# This has to be executed *after* logging initialisation.
import lacre.core as core
LOG = logging.getLogger('gpg-mailgate.py')
missing_params = conf.validate_config(additional=conf.SCRIPT_REQUIRED)
config_file = conf.config_source()
if missing_params:
LOG.error(f"Aborting delivery! Following mandatory config parameters are missing in {config_file!r}: {missing_params}")
sys.exit(lacre.EX_CONFIG)
delivered = False
try:
# Read e-mail from stdin, parse it
raw = sys.stdin.read()
raw_message = email.message_from_string(raw, policy=SMTPUTF8)
from_addr = raw_message['From']
# Read recipients from the command-line
to_addrs = sys.argv[1:]
# Let's start
core.deliver_message(raw_message, from_addr, to_addrs)
process_t = (time.process_time() - start) * 1000
LOG.info("Message delivered in {process:.2f} ms".format(process=process_t))
delivered = True
except:
LOG.exception('Could not handle message')
if not delivered:
# It seems we weren't able to deliver the message. In case it was some
# silly message-encoding issue that shouldn't bounce the message, we just
# try recoding the message body and delivering it.
try:
core.failover_delivery(raw_message, to_addrs, from_addr)
except:
LOG.exception('Failover delivery failed too')

View File

@ -1,11 +1,11 @@
[default]
# Whether gpg-mailgate should add a header after it has processed an email
# Whether lacre should add a header after it has processed an email
# This may be useful for debugging purposes
add_header = yes
# Whether we should only encrypt emails if they are explicitly defined in
# the key mappings below ([enc_keymap] section)
# This means gpg-mailgate won't automatically detect PGP recipients for encrypting
# This means lacre won't automatically detect PGP recipients for encrypting
enc_keymap_only = no
# Convert encrypted text/plain email to MIME-attached encrypt style.
@ -20,36 +20,36 @@ mime_conversion = yes
mail_case_insensitive = no
[gpg]
# the directory where gpg-mailgate public keys are stored
# the directory where lacre public keys are stored
# (see INSTALL for details)
#
# Note that this directory should be accessible only for the Lacre user,
# i.e. have mode 700.
keyhome = /var/gpgmailgate/.gnupg
keyhome = /var/lacre/.gnupg
[smime]
# the directory for the S/MIME certificate files
cert_path = /var/gpgmailgate/smime
cert_path = /var/lacre/smime
[mailregister]
# settings for the register-handler
register_email = register@yourdomain.tld
mail_templates = /var/gpgmailgate/register_templates
mail_templates = /var/lacre/register_templates
# URL to webpanel. Upon receiving an email with a key, register-handler
# uploads it to the web panel.
webpanel_url = http://yourdomain.tld
[cron]
# settings for the gpgmw cron job
# settings for the cron job
send_email = yes
notification_email = gpg-mailgate@yourdomain.tld
mail_templates = /var/gpgmailgate/cron_templates
notification_email = lacre@yourdomain.tld
mail_templates = /var/lacre/cron_templates
[logging]
# path to the logging configuration; see documentation for details:
# https://docs.python.org/3/library/logging.config.html#logging-config-fileformat
config = /etc/gpg-lacre-logging.conf
config = /etc/lacre-logging.conf
[daemon]
# Advanced Content Filter section.
@ -75,12 +75,12 @@ 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
# lacre will submit email to this relay after it is done processing
# unless you alter the default Postfix configuration, you won't have to modify this
host = 127.0.0.1
port = 10028
# This is the default port of postfix. It is used to send some
# mails through the GPG-Mailgate so they are encrypted
# mails through the Lacre so they are encrypted
enc_port = 25
# Set this option to yes to use TLS for SMTP Servers which require TLS.
@ -89,7 +89,7 @@ starttls = no
[smtp]
# Options when smtp auth is required to send out emails
enabled = false
username = gpg-mailgate
username = lacre
password = changeme
host = yourdomain.tld
port = 587
@ -97,7 +97,7 @@ starttls = true
[database]
# edit the settings below if you want to read keys from a
# gpg-mailgate-web database other than SQLite
# lacre-webgate database other than SQLite
enabled = yes
url = sqlite:///test.db
@ -112,10 +112,10 @@ url = sqlite:///test.db
#
pooling_mode = optimistic
# For a MySQL database "gpgmw", user "gpgmw" and password "password",
# For a MySQL database "lacre", user "lacre" and password "password",
# use the following URL:
#
#url = mysql://gpgmw:password@localhost/gpgmw
#url = mysql://lacre:password@localhost/lacre
#
# For other RDBMS backends, see:
# https://docs.sqlalchemy.org/en/14/core/engines.html#database-urls

73
lacre.py Executable file
View File

@ -0,0 +1,73 @@
#!/usr/bin/python
#
# lacre
#
# This file is part of the lacre source code.
#
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
import email
from email.policy import SMTPUTF8
import sys
import logging
import lacre
import lacre.config as conf
from lacre.stats import time_logger
conf.load_config()
lacre.init_logging(conf.get_item('logging', 'config'))
# This has to be executed *after* logging initialisation.
import lacre.core as core
LOG = logging.getLogger('lacre.py')
def main():
with time_logger('Message delivery', LOG):
missing_params = conf.validate_config()
config_file = conf.config_source()
if missing_params:
LOG.error(f"Aborting delivery! Following mandatory config parameters are missing in {config_file!r}: {missing_params}")
sys.exit(lacre.EX_CONFIG)
delivered = False
try:
# Read e-mail from stdin, parse it
raw = sys.stdin.read()
raw_message = email.message_from_string(raw, policy=SMTPUTF8)
from_addr = raw_message['From']
# Read recipients from the command-line
to_addrs = sys.argv[1:]
# Let's start
core.deliver_message(raw_message, from_addr, to_addrs)
delivered = True
except:
LOG.exception('Could not handle message')
if not delivered:
# It seems we weren't able to deliver the message. In case it was
# some silly message-encoding issue that shouldn't bounce the
# message, we just try recoding the message body and delivering it.
try:
core.failover_delivery(raw_message, to_addrs, from_addr)
except:
LOG.exception('Failover delivery failed too')
if __name__ == '__main__':
main()

View File

@ -18,12 +18,26 @@ lacre.init_logging(conf.get_item('logging', 'config'))
import lacre.repositories as repo
import lacre.dbschema as db
LOG = logging.getLogger(__name__)
if __name__ == '__main__':
LOG = logging.getLogger('lacre.admin')
else:
LOG = logging.getLogger(__name__)
def _no_database():
print('Database unavailable or not configured properly')
exit(lacre.EX_CONFIG)
sys.exit(lacre.EX_CONFIG)
def sub_db(args):
"""Sub-command to manipulate database."""
LOG.debug('Database operations ahead')
if args.init:
eng = repo.init_engine(conf.get_item('database', 'url'))
LOG.warning('Initialising database schema with engine: %s', eng)
print('Creating database tables')
db.create_tables(eng)
def sub_queue(args):
@ -35,6 +49,12 @@ def sub_queue(args):
if args.delete:
queue.delete_key_by_email(args.delete)
elif args.list:
for k in queue.fetch_keys():
print(f'- {k.id}: {k.email}')
elif args.to_delete:
for k in queue.fetch_keys_to_delete():
print(f'- {k.id}: {k.email}')
else:
cnt = queue.count_keys()
if cnt is None:
@ -86,7 +106,10 @@ def sub_import(args):
def main():
conf.validate_config(additional=conf.SCRIPT_REQUIRED)
missing = conf.validate_config()
if missing:
LOG.error('Missing configuration parameters: %s', missing)
sys.exit(lacre.EX_CONFIG)
general_conf = conf.config_source()
log_conf = conf.get_item('logging', 'config')
@ -99,6 +122,14 @@ def main():
sub_commands = parser.add_subparsers(help='Sub-commands', required=True)
cmd_db = sub_commands.add_parser('database',
help='',
aliases=['db']
)
cmd_db.add_argument('-i', '--init', action='store_true',
help='Initialise database schema')
cmd_db.set_defaults(operation=sub_db)
cmd_import = sub_commands.add_parser('import',
help='Load identities from GnuPG directory to Lacre database'
)
@ -114,6 +145,10 @@ def main():
)
cmd_queue.add_argument('-D', '--delete',
help='delete specified email from the queue')
cmd_queue.add_argument('-l', '--list', action='store_true',
help='list keys in the queue')
cmd_queue.add_argument('-d', '--to-delete', action='store_true',
help='list keys to be deleted')
cmd_queue.set_defaults(operation=sub_queue)
cmd_identities = sub_commands.add_parser('identities',

View File

@ -11,9 +11,9 @@ import os
# Environment variable name we read to retrieve configuration path. This is to
# enable non-root users to set up and run GPG Mailgate and to make the software
# enable non-root users to set up and run Lacre and to make the software
# testable.
CONFIG_PATH_ENV = "GPG_MAILGATE_CONFIG"
CONFIG_PATH_ENV = "LACRE_CONFIG"
# List of mandatory configuration parameters. Each item on this list should be
# a pair: a section name and a parameter name.
@ -21,16 +21,12 @@ MANDATORY_CONFIG_ITEMS = [("relay", "host"),
("relay", "port"),
("daemon", "host"),
("daemon", "port"),
("gpg", "keyhome")]
("gpg", "keyhome"),
('database', 'enabled'),
('database', 'url'),
('database', 'pooling_mode')]
SCRIPT_REQUIRED = [('database', 'enabled'),
('database', 'url'),
('database', 'pooling_mode')]
CRON_REQUIRED = [('database', 'enabled'),
('database', 'url'),
('database', 'pooling_mode'),
('cron', 'mail_templates')]
CRON_REQUIRED = [('cron', 'mail_templates')]
# Global dict to keep configuration parameters. It's hidden behind several
# utility functions to make it easy to replace it with ConfigParser object in
@ -44,7 +40,7 @@ def load_config() -> dict:
If environment variable identified by CONFIG_PATH_ENV
variable is set, its value is taken as a configuration file
path. Otherwise, the default is taken
('/etc/gpg-mailgate.conf').
('/etc/lacre.conf').
"""
config_file = config_source()
@ -61,9 +57,9 @@ def load_config() -> dict:
def config_source() -> str:
"""Return path of configuration file.
Taken from GPG_MAILGATE_CONFIG environment variable, and if it's not
set, defaults to /etc/gpg-mailgate.conf."""
return os.getenv(CONFIG_PATH_ENV, '/etc/gpg-mailgate.conf')
Taken from LACRE_CONFIG environment variable, and if it's not
set, defaults to /etc/lacre.conf."""
return os.getenv(CONFIG_PATH_ENV, '/etc/lacre.conf')
def _read_config(fileName) -> RawConfigParser:

View File

@ -1,20 +1,20 @@
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
"""Lacre's actual mail-delivery module.
@ -142,7 +142,7 @@ def _gpg_encrypt_and_deliver(message: EmailMessage, keys, recipients, encrypt_f)
def _customise_headers(message: EmailMessage):
if conf.flag_enabled('default', 'add_header'):
message['X-GPG-Mailgate'] = 'Encrypted by GPG Mailgate'
message['X-Lacre'] = 'Encrypted by Lacre'
def _encrypt_all_payloads_inline(message: EmailMessage, gpg_to_cmdline):

View File

@ -13,7 +13,7 @@ import email
from email.policy import SMTPUTF8
# Load configuration and init logging, in this order. Only then can we load
# the last Lacre module, i.e. lacre.mailgate.
# the last Lacre module, i.e. lacre.core.
conf.load_config()
lacre.init_logging(conf.get_item("logging", "config"))
LOG = logging.getLogger('lacre.daemon')

View File

@ -7,32 +7,58 @@ This definition includes:
- 'lacre_identities' -- identity catalogue, used by encryption logic to match
emails with corresponding keys.
- 'lacre_locks' -- used only by the frontend.
"""
import sqlalchemy
# Values for lacre_keys.status column:
# - ST_DEFAULT: initial state;
# - ST_IMPORTED: key has been successfully processed by cron job;
# - ST_TO_BE_DELETED: key can be deleted.
ST_DEFAULT, ST_IMPORTED, ST_TO_BE_DELETED = range(3)
# lacre_keys.confirmed is set to an empty string when a key is confirmed by the user.
CO_CONFIRMED = ''
_meta = sqlalchemy.MetaData()
LACRE_KEYS = sqlalchemy.Table('lacre_keys', _meta,
sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
sqlalchemy.Column('email', sqlalchemy.String(256)),
sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True, autoincrement='auto'),
sqlalchemy.Column('email', sqlalchemy.String(256), index=True),
# ASCII-armored key
sqlalchemy.Column('publickey', sqlalchemy.Text),
# Empty string means this key has been confirmed.
sqlalchemy.Column('confirm', sqlalchemy.String(32)),
# Status: see ST_* constants at the top of the file.
sqlalchemy.Column('status', sqlalchemy.Integer),
sqlalchemy.Column('status', sqlalchemy.Integer, nullable=False),
sqlalchemy.Column('time', sqlalchemy.DateTime))
LACRE_LOCKS = sqlalchemy.Table('lacre_locks', _meta,
sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True, nullable=False, autoincrement='auto'),
sqlalchemy.Column('ip', sqlalchemy.String(16)),
sqlalchemy.Column('time', sqlalchemy.Integer),
sqlalchemy.Column('action', sqlalchemy.String(16)),
sqlalchemy.Column('num', sqlalchemy.Integer),
)
LACRE_IDENTITIES = sqlalchemy.Table('lacre_identities', _meta,
sqlalchemy.Column('email', sqlalchemy.String(256), index=True),
sqlalchemy.Column('email', sqlalchemy.String(256), index=True, nullable=False),
# Key fingerprint
sqlalchemy.Column('fingerprint', sqlalchemy.String(64), index=True))
sqlalchemy.Column('fingerprint', sqlalchemy.String(64), index=True, nullable=False))
def init_identities_table() -> sqlalchemy.Table:
return LACRE_IDENTITIES
def init_locks_table() -> sqlalchemy.Table:
return LACRE_LOCKS
def init_keys_table() -> sqlalchemy.Table:
return LACRE_KEYS
def create_tables(engine):
_meta.create_all(engine)
def table_metadata():
return _meta

View File

@ -1,20 +1,20 @@
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
"""Recipient processing package.

View File

@ -17,17 +17,17 @@ _HOUR_IN_SECONDS = 3600
_engine = None
def init_engine(url):
def init_engine(url, db_debug=False):
global _engine
if not _engine:
config = _conn_config()
config = _conn_config(db_debug)
_engine = create_engine(url, **config)
return _engine
def _conn_config():
def _conn_config(db_debug):
config = dict()
mode = PoolingMode.from_config('database', 'pooling_mode', required=True)
@ -45,6 +45,10 @@ def _conn_config():
if config_item_set('database', 'max_overflow'):
config['max_overflow'] = int(get_item('database', 'max_overflow'))
if db_debug:
config['echo'] = 'debug'
config['echo_pool'] = 'debug'
LOG.debug('Database engine configuration: %s', config)
return config
@ -71,7 +75,7 @@ class IdentityRepository(KeyRing):
def _insert(self, email, fprint):
insq = self._identities.insert().values(email=email, fingerprint=fprint)
LOG.debug('Registering identity %s: %s', email, insq)
LOG.debug('Registering identity: %s -- %s', insq, insq.compile().params)
with self._engine.connect() as conn:
conn.execute(insq)
@ -80,13 +84,13 @@ class IdentityRepository(KeyRing):
.values(fingerprint=fprint) \
.where(self._identities.c.email == email)
LOG.debug('Updating identity %s: %s', email, upq)
LOG.debug('Updating identity: %s -- %s', upq, upq.compile().params)
with self._engine.connect() as conn:
conn.execute(upq)
def delete(self, email):
delq = delete(self._identities).where(self._identities.c.email == email)
LOG.debug('Deleting keys assigned to %s', email)
LOG.debug('Deleting assigned keys: %s -- %s', delq, delq.compile().params)
with self._engine.connect() as conn:
conn.execute(delq)
@ -118,7 +122,7 @@ class IdentityRepository(KeyRing):
all_identities = select(self._identities.c.fingerprint, self._identities.c.email)
with self._engine.connect() as conn:
result = conn.execute(all_identities)
LOG.debug('Retrieving all keys')
LOG.debug('Retrieving all keys: %s', all_identities)
return KeyCache({key_id: email for key_id, email in result})
@ -135,33 +139,37 @@ class KeyConfirmationQueue:
def fetch_keys(self, /, max_keys=None):
"""Runs a query to retrieve at most `keys_read_max` keys and returns db result."""
max_keys = max_keys or self.keys_read_max
LOG.debug('Row limit: %d', max_keys)
selq = select(self._keys.c.publickey, self._keys.c.id, self._keys.c.email) \
.where(and_(self._keys.c.status == db.ST_DEFAULT, self._keys.c.confirm == "")) \
.where(and_(self._keys.c.status == db.ST_DEFAULT, self._keys.c.confirm == db.CO_CONFIRMED)) \
.limit(max_keys)
LOG.debug('Retrieving keys to be processed: %s', selq)
LOG.debug('Retrieving keys to be processed: %s -- %s', selq, selq.compile().params)
with self._engine.connect() as conn:
return conn.execute(selq)
return [e for e in conn.execute(selq)]
def count_keys(self):
selq = select(func.count(self._keys.c.id))
selq = select(func.count(self._keys.c.id)) \
.where(and_(self._keys.c.status == db.ST_DEFAULT, self._keys.c.confirm == db.CO_CONFIRMED))
LOG.debug('Counting all keys: %s', selq)
LOG.debug('Counting all keys: %s -- %s', selq, selq.compile().params)
try:
with self._engine.connect() as conn:
c = [cnt for cnt in conn.execute(selq)]
# Result is an iterable of tuples:
return c[0][0]
res = conn.execute(selq)
# This is a 1-element tuple.
return res.one_or_none()[0]
except OperationalError:
LOG.exception('Cannot count keys')
return None
def fetch_keys_to_delete(self):
seldel = select(self._keys.c.email, self._keys.c.id).where(self._keys.c.status == db.ST_TO_BE_DELETED).limit(self.keys_read_max)
seldel = select(self._keys.c.email, self._keys.c.id) \
.where(self._keys.c.status == db.ST_TO_BE_DELETED) \
.limit(self.keys_read_max)
with self._engine.connect() as conn:
return conn.execute(seldel)
return [e for e in conn.execute(seldel)]
def delete_keys(self, row_id, /, email=None):
"""Remove key from the database."""
@ -174,7 +182,7 @@ class KeyConfirmationQueue:
with self._engine.connect() as conn:
LOG.debug('Deleting public keys associated with confirmed email: %s', delq)
return conn.execute(delq)
conn.execute(delq)
def delete_key_by_email(self, email):
"""Remove keys linked to the given email from the database."""

View File

@ -1,20 +1,20 @@
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
"""S/MIME handling module."""
@ -75,7 +75,7 @@ def encrypt(raw_message, recipients, from_addr):
out.write('Subject: ' + raw_message['Subject'] + text.EOL_S)
if conf.config_item_equals('default', 'add_header', 'yes'):
out.write('X-GPG-Mailgate: Encrypted by GPG Mailgate' + text.EOL_S)
out.write('X-Lacre: Encrypted by Lacre' + text.EOL_S)
s.write(out, p7)

View File

@ -1,20 +1,20 @@
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
import configparser
@ -30,7 +30,7 @@ def _spawn(cmd):
"PATH": os.getenv("PATH"),
"PYTHONPATH": os.getcwd(),
"LANG": 'en_US.UTF-8',
"GPG_MAILGATE_CONFIG": "test/gpg-mailgate-daemon-test.conf"
"LACRE_CONFIG": "test/lacre-daemon.conf"
}
logging.debug(f"Spawning command: {cmd} with environment: {env_dict!r}")
return subprocess.Popen(cmd,

View File

@ -32,8 +32,8 @@ certs: test/certs
e2e_log: test/logs/e2e.log
e2e_log_format: %(asctime)s %(pathname)s:%(lineno)d %(levelname)s [%(funcName)s] %(message)s
e2e_log_datefmt: %Y-%m-%d %H:%M:%S
lacre_log: test/logs/gpg-mailgate.log
log_config: test/gpg-lacre-log.ini
lacre_log: test/logs/lacre-simple.log
log_config: test/lacre-logging.conf
# TEST IDENTITIES AND SETTINGS:
#

View File

@ -1,20 +1,20 @@
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
import os
@ -27,7 +27,7 @@ import unittest
RELAY_SCRIPT = "test/utils/relay.py"
CONFIG_FILE = "test/gpg-mailgate.conf"
CONFIG_FILE = "test/lacre.conf"
def _build_config(config):
@ -129,7 +129,7 @@ class SimpleMailFilterE2ETest(unittest.TestCase):
following properties: 'descr', 'to', 'in' and 'out'.
"""
gpglacre_cmd = self._python_command(
'gpg-mailgate.py',
'lacre.py',
self._e2e_config.get(case_name, 'to'))
relay_cmd = self._python_command(
@ -147,7 +147,7 @@ class SimpleMailFilterE2ETest(unittest.TestCase):
gpglacre_proc = subprocess.run(gpglacre_cmd,
input=_load_file(self._e2e_config.get(case_name, "in")),
capture_output=True,
env={"GPG_MAILGATE_CONFIG": self._e2e_config_path,
env={"LACRE_CONFIG": self._e2e_config_path,
"PATH": os.getenv("PATH")})
# Let the relay process the data.

Binary file not shown.

View File

@ -1,5 +1,5 @@
[logging]
config = test/gpg-lacre-log.ini
config = test/lacre-logging.conf
file = test/logs/gpg-mailgate.log
format = %(asctime)s %(module)s[%(process)d]: %(message)s
date_format = ISO
@ -17,6 +17,8 @@ port = not_used
[database]
enabled = yes
url = sqlite:///test/lacre.db
pooling_mode = optimistic
max_connection_age = 3600
[relay]
host = localhost

View File

@ -1,5 +1,5 @@
[logging]
config = test/gpg-lacre-log.ini
config = test/lacre-logging.conf
file = test/logs/gpg-mailgate.log
format = %(asctime)s %(module)s[%(process)d]: %(message)s
date_format = ISO
@ -26,6 +26,7 @@ log_headers = yes
[cron]
send_email = no
mail_templates = not_used
[pgp_style]
# this recipient has PGP/MIME enabled, because the default approach is to use

View File

@ -1,20 +1,20 @@
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
"""Unit-tests as contracts for external dependencies.

View File

@ -1,7 +1,7 @@
#!/usr/local/bin/python2
#
# This quick-and-dirty script supports only the happy case of SMTP session,
# i.e. what gpg-mailgate/gpg-lacre needs to deliver encrypted email.
# i.e. what lacre needs to deliver encrypted email.
#
# It listens on the port given as the only command-line argument and consumes a
# message, then prints it to standard output. The goal is to be able to

View File

@ -90,8 +90,8 @@ AQgHiHgEGBYIACAWIQQZz0tH7MnEevqE1L2W85/aDjG7ZwUCYdTF4AIbDAAKCRCW\n\
OjjB6xRD0Q2FN+alsNGCtdutAs18AZ5l33RMzws=\n\
=wWoq\n\
-----END PGP PUBLIC KEY BLOCK-----\
", "status": 0, "confirm": "", "time": None},
{"id": 3, "email": "cecil@lacre.io", "publickey": "RUBBISH", "status": 0, "confirm": "", "time": None}
", "status": 1, "confirm": "", "time": None},
{"id": 3, "email": "cecil@lacre.io", "publickey": "RUBBISH", "status": 2, "confirm": "", "time": None}
])
conn.execute(identities.insert(), [

View File

@ -1,22 +1,22 @@
#!/usr/bin/python
#
# gpg-mailgate
# lacre
#
# This file is part of the gpg-mailgate source code.
# This file is part of the lacre source code.
#
# gpg-mailgate is free software: you can redistribute it and/or modify
# lacre is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gpg-mailgate source code is distributed in the hope that it will be useful,
# lacre source code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
# along with lacre source code. If not, see <http://www.gnu.org/licenses/>.
#
import sys
@ -25,7 +25,7 @@ import lacre
import lacre.config as conf
from lacre.notify import notify
# Read configuration from /etc/gpg-mailgate.conf
# Read configuration from /etc/lacre.conf
conf.load_config()
lacre.init_logging(conf.get_item('logging', 'config'))
@ -42,6 +42,49 @@ def _validate_config():
exit(lacre.EX_CONFIG)
def import_key(key_dir, armored_key, key_id, email, key_queue, identities):
# import the key to gpg
(fingerprint, _) = GnuPG.add_key(key_dir, armored_key)
key_queue.mark_accepted(key_id)
identities.register_or_update(email, fingerprint)
LOG.info('Imported key from: %s', email)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key registration successful", "registrationSuccess.md", email)
def import_failed(key_id, email, key_queue):
key_queue.delete_keys(key_id)
LOG.warning('Import confirmation failed: %s', email)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key registration failed", "registrationError.md", email)
def delete_key(key_id, email, key_queue):
# delete key so we don't continue processing it
LOG.debug('Empty key received, just deleting')
key_queue.delete_keys(row_id)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key deleted", "keyDeleted.md", email)
def cleanup(key_dir, key_queue):
"""Delete keys and queue entries."""
LOG.info('Cleaning up after a round of key confirmation')
for email, row_id in key_queue.fetch_keys_to_delete():
LOG.debug('Removing key from keyring: %s', email)
GnuPG.delete_key(key_dir, email)
LOG.debug('Removing key from identity store: %s', row_id)
key_queue.delete_keys(row_id)
LOG.info('Deleted key for: %s', email)
_validate_config()
if not (conf.flag_enabled('database', 'enabled') and conf.config_item_set('database', 'url')):
@ -59,49 +102,23 @@ try:
key_dir = conf.get_item('gpg', 'keyhome')
LOG.debug('Using GnuPG with home directory in %s', key_dir)
result_set = key_queue.fetch_keys()
for armored_key, row_id, email in result_set:
for armored_key, row_id, email in key_queue.fetch_keys():
# delete any other public keys associated with this confirmed email address
key_queue.delete_keys(row_id, email=email)
identities.delete(email)
GnuPG.delete_key(key_dir, email)
LOG.info('Deleted key for <%s> via import request', email)
LOG.info('Deleted key via import request for: %s', email)
if armored_key.strip(): # we have this so that user can submit blank key to remove any encryption
if GnuPG.confirm_key(armored_key, email):
# import the key to gpg
(fingerprint, _) = GnuPG.add_key(key_dir, armored_key)
key_queue.mark_accepted(row_id)
identities.register_or_update(email, fingerprint)
LOG.info('Imported key from <%s>', email)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key registration successful", "registrationSuccess.md", email)
else:
key_queue.delete_keys(row_id)
LOG.warning('Import confirmation failed for <%s>', email)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key registration failed", "registrationError.md", email)
else:
if not armored_key.strip(): # we have this so that user can submit blank key to remove any encryption
# delete key so we don't continue processing it
LOG.debug('Empty key received, just deleting')
delete_key(row_id, email, key_queue)
continue
key_queue.delete_keys(row_id)
if conf.flag_enabled('cron', 'send_email'):
notify("PGP key deleted", "keyDeleted.md", email)
if GnuPG.confirm_key(armored_key, email):
import_key(key_dir, armored_key, row_id, email, key_queue, identities)
else:
import_failed(row_id, email, key_queue)
LOG.info('Cleaning up after a round of key confirmation')
stat2_result_set = key_queue.fetch_keys_to_delete()
for email, row_id in stat2_result_set:
LOG.debug('Removing key from keyring: %s', email)
GnuPG.delete_key(key_dir, email)
LOG.debug('Removing key from identity store: %s', row_id)
key_queue.delete_keys(row_id)
LOG.info('Deleted key for <%s>', email)
cleanup(key_dir, key_queue)
except:
LOG.exception('Unexpected issue during key confirmation')