Sunil Mohan Adapa 7f608cd570
*: Collect output for all privileged sub-processes
- Now that we have a mechanism for properly collecting, transmitting, and display
the stdout and stderr. There is no reason not to collect all of the stdin and
stderr.

- Also, the stdin/stderr=subprocess.PIPE is redundant and prevents the output
from getting collected for debugging. So, remove it.

Tests:

- Ran functional tests on backups, calibre, ejabberd, email, gitweb, ikiwiki,
infinoted, kiwix, mediawiki, mumble, nextcloud,, openvpn, samba, wireguard,
zoph. 2-3 issues were found but did not seem like new errors.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Veiko Aasa <veiko17@disroot.org>
2025-09-29 16:58:57 +03:00

71 lines
2.1 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""Generate DKIM keys for signing outgoing messages.
See: https://rspamd.com/doc/modules/dkim_signing.html
"""
import pathlib
import re
import shutil
from plinth import action_utils
from plinth.actions import privileged
from plinth.privileged import service as service_privileged
_keys_dir = pathlib.Path('/var/lib/rspamd/dkim/')
rspamd_user = '_rspamd'
DOMAIN_PART_REGEX = r'^[a-zA-Z0-9]([-a-zA-Z0-9]{,61}[a-zA-Z0-9])?$'
def _validate_domain_name(domain):
for part in domain.split('.'):
if not re.match(DOMAIN_PART_REGEX, part):
raise ValueError('Invalid domain name')
@privileged
def get_dkim_public_key(domain: str) -> str:
"""Privileged action to get the public key from DKIM key."""
_validate_domain_name(domain)
key_file = _keys_dir / f'{domain}.dkim.key'
output = action_utils.run(
['openssl', 'rsa', '-in',
str(key_file), '-pubout'], check=True).stdout
return ''.join(output.decode().splitlines()[1:-1])
@privileged
def setup_dkim(domain: str):
"""Create DKIM key for a given domain."""
_validate_domain_name(domain)
_keys_dir.mkdir(exist_ok=True)
_keys_dir.chmod(0o500)
shutil.chown(_keys_dir, rspamd_user, rspamd_user)
# Default path is /var/lib/dkim/$domain.$selector.key. Default selector is
# "dkim". Use these to simplify key management until we have a need to
# implement creating new or multiple keys.
key_file = _keys_dir / f'{domain}.dkim.key'
if key_file.exists():
return
# Ed25519 is widely *not* accepted as of 2022-01. See:
# https://serverfault.com/questions/1023674
action_utils.run([
'rspamadm', 'dkim_keygen', '-t', 'rsa', '-b', '2048', '-s', 'dkim',
'-d', domain, '-k', (str(key_file))
], check=True)
shutil.chown(key_file, rspamd_user, rspamd_user)
key_file.chmod(0o400)
service_privileged.try_restart('rspamd')
@privileged
def fix_incorrect_key_ownership():
"""Set the ownership on DKIM private keys."""
for key in _keys_dir.glob('*.dkim.key'):
shutil.chown(key, rspamd_user, rspamd_user)