Compare commits

..

22 Commits

Author SHA1 Message Date
holger krekel
31f0e4a9ec refinements and fixes 2024-04-03 18:50:20 +02:00
holger krekel
a2be4dcc38 a bit of renaming 2024-04-03 18:31:32 +02:00
holger krekel
78ac2f5ce2 ignore and remove .tmp files in notification_dir 2024-04-03 18:31:32 +02:00
holger krekel
aee68b05b5 avoid float with time, and be safe against crashes during file writing 2024-04-03 18:31:32 +02:00
holger krekel
a3b6223039 implemented suggestion fopr using an absolute deadline instead of retrying but choose 5 hours for now because if our own notification server is down/buggy we have at least a bit of time to fix it 2024-04-03 18:31:32 +02:00
holger krekel
f01360855d address typo-level review comments 2024-04-03 18:31:32 +02:00
holger krekel
5c67effe55 finally use persistent queue items with random file names, simplifying the flows 2024-04-03 18:31:32 +02:00
holger krekel
91effb0998 proper doc string for Notifier 2024-04-03 18:31:32 +02:00
holger krekel
5b00ff193f fix failing CI (uncovering real bug) 2024-04-03 18:31:32 +02:00
holger krekel
0272fcb5f4 split metadata and notifier into separate files 2024-04-03 18:31:32 +02:00
holger krekel
50a3930c74 separate notification thread into own class, and test start_notification_threads 2024-04-03 18:31:32 +02:00
holger krekel
24f7d89bee some more renaming 2024-04-03 18:31:32 +02:00
holger krekel
6caa8ba868 fix 2024-04-03 18:31:32 +02:00
holger krekel
4f8fab9428 fix changelog 2024-04-03 18:31:31 +02:00
holger krekel
f12f659a80 better naming 2024-04-03 18:31:17 +02:00
holger krekel
07003cb69e some refinements and extending the tests 2024-04-03 18:31:17 +02:00
holger krekel
59e529aa0f extend testing 2024-04-03 18:31:17 +02:00
holger krekel
49d8d248b4 refine testing and code 2024-04-03 18:31:17 +02:00
holger krekel
8b14e7fde0 more precision 2024-04-03 18:31:17 +02:00
holger krekel
da39a2aa58 remove redundant test code for requests mocking 2024-04-03 18:31:17 +02:00
holger krekel
f8e41b04b6 snap somewhat working again 2024-04-03 18:31:17 +02:00
holger krekel
a038452ee5 better preserve notification order, using a queue again 2024-04-03 18:31:17 +02:00
11 changed files with 28 additions and 137 deletions

View File

@@ -56,7 +56,7 @@ jobs:
# restore acme & dkim state to staging.testrun.org
rsync -avz acme-restore/acme/ root@staging.testrun.org:/var/lib/acme || true
rsync -avz dkimkeys-restore/dkimkeys/ root@staging.testrun.org:/etc/dkimkeys || true
ssh -o StrictHostKeyChecking=accept-new -v root@staging.testrun.org chown root:root -R /var/lib/acme || true
ssh -o StrictHostKeyChecking=accept-new -v root@staging.testrun.org chown root:root -R /var/lib/acme
- name: run formatting checks
run: cmdeploy fmt -v

View File

@@ -1,17 +1,6 @@
# Changelog for chatmail deployment
## untagged
- Accept Let's Encrypt's new Terms of Services
([#275](https://github.com/deltachat/chatmail/pull/276))
- Reload Dovecot and Postfix when TLS certificate updates
([#271](https://github.com/deltachat/chatmail/pull/271))
- Use forked version of dovecot without hardcoded delays
([#270](https://github.com/deltachat/chatmail/pull/270))
## 1.2.0 - 2024-04-04
## untagged
- Install dig on the server to resolve DNS records
([#267](https://github.com/deltachat/chatmail/pull/267))

View File

@@ -159,27 +159,4 @@ While this file is present, account creation will be blocked.
Delta Chat apps will, however, discover all ports and configurations
automatically by reading the [autoconfig XML file](https://www.ietf.org/archive/id/draft-bucksch-autoconfig-00.html) from the chatmail service.
## Email authentication
chatmail servers rely on [DKIM](https://www.rfc-editor.org/rfc/rfc6376)
to authenticate incoming emails.
Incoming emails must have a valid DKIM signature with
Signing Domain Identifier (SDID, `d=` parameter in the DKIM-Signature header)
equal to the `From:` header domain.
This property is checked by OpenDKIM screen policy script
before validating the signatures.
This correpsonds to strict [DMARC](https://www.rfc-editor.org/rfc/rfc7489) alignment (`adkim=s`),
but chatmail does not rely on DMARC and does not consult the sender policy published in DMARC records.
Other legacy authentication mechanisms such as [iprev](https://www.rfc-editor.org/rfc/rfc8601#section-2.7.3)
and [SPF](https://www.rfc-editor.org/rfc/rfc7208) are also not taken into account.
If there is no valid DKIM signature on the incoming email,
the sender receives a "5.7.1 No valid DKIM signature found" error.
Outgoing emails must be sent over authenticated connection
with envelope MAIL FROM (return path) corresponding to the login.
This is ensured by Postfix which maps login username
to MAIL FROM with
[`smtpd_sender_login_maps`](https://www.postfix.org/postconf.5.html#smtpd_sender_login_maps)
and rejects incorrectly authenticated emails with [`reject_sender_login_mismatch`](reject_sender_login_mismatch) policy.
`From:` header must correspond to envelope MAIL FROM,
this is ensured by `filtermail` proxy.

View File

@@ -4,7 +4,6 @@ import time
import sys
import json
import crypt
from pathlib import Path
from socketserver import (
UnixStreamServer,
StreamRequestHandler,
@@ -46,32 +45,23 @@ def is_allowed_to_create(config: Config, user, cleartext_password) -> bool:
return False
localpart, domain = parts
if localpart == "echo":
# echobot account should not be created in the database
return False
if (
len(localpart) > config.username_max_length
or len(localpart) < config.username_min_length
):
logging.warning(
"localpart %s has to be between %s and %s chars long",
localpart,
config.username_min_length,
config.username_max_length,
)
if localpart != "echo":
logging.warning(
"localpart %s has to be between %s and %s chars long",
localpart,
config.username_min_length,
config.username_max_length,
)
return False
return True
def get_user_data(db, config: Config, user):
if user == f"echo@{config.mail_domain}":
return dict(
home=f"/home/vmail/mail/{config.mail_domain}/echo@{config.mail_domain}",
uid="vmail",
gid="vmail",
)
with db.read_connection() as conn:
result = conn.get_user(user)
if result:
@@ -86,21 +76,6 @@ def lookup_userdb(db, config: Config, user):
def lookup_passdb(db, config: Config, user, cleartext_password):
if user == f"echo@{config.mail_domain}":
# Echobot writes password it wants to log in with into /run/echobot/password
try:
password = Path("/run/echobot/password").read_text()
except Exception:
logging.exception("Exception when trying to read /run/echobot/password")
return None
return dict(
home=f"/home/vmail/mail/{config.mail_domain}/echo@{config.mail_domain}",
uid="vmail",
gid="vmail",
password=encrypt_password(password),
)
with db.write_transaction() as conn:
userdata = conn.get_user(user)
if userdata:

View File

@@ -3,17 +3,14 @@
it will echo back any message that has non-empty text and also supports the /help command.
"""
import logging
import os
import sys
import subprocess
from deltachat_rpc_client import Bot, DeltaChat, EventType, Rpc, events
from pathlib import Path
from chatmaild.config import read_config
from chatmaild.newemail import create_newemail_dict
from chatmaild.config import read_config
hooks = events.HookCollection()
@@ -78,23 +75,9 @@ def main():
account = accounts[0] if accounts else deltachat.add_account()
bot = Bot(account, hooks)
config = read_config(sys.argv[1])
# Create password file
if bot.is_configured():
password = bot.account.get_config("mail_pw")
else:
password = create_newemail_dict(config)["password"]
Path("/run/echobot/password").write_text(password)
# Give the user which doveauth runs as access to the password file.
subprocess.run(
["/usr/bin/setfacl", "-m", "user:vmail:r", "/run/echobot/password"],
check=True,
)
if not bot.is_configured():
config = read_config(sys.argv[1])
password = create_newemail_dict(config).get("password")
email = "echo@" + config.mail_domain
bot.configure(email, password)
bot.run_forever()

View File

@@ -477,30 +477,12 @@ def deploy_chatmail(config_path: Path) -> None:
groups=["opendkim"],
system=True,
)
server.user(name="Create echobot user", user="echobot", system=True)
server.shell(
name="Fix file owner in /home/vmail",
commands=["test -d /home/vmail && chown -R vmail:vmail /home/vmail"],
)
# Add our OBS repository for dovecot_no_delay
files.put(
name = "Add Deltachat OBS GPG key to apt keyring",
src = importlib.resources.files(__package__).joinpath("obs-home-deltachat.gpg"),
dest = "/etc/apt/keyrings/obs-home-deltachat.gpg",
user="root",
group="root",
mode="644",
)
files.line(
name = "Add DeltaChat OBS home repository to sources.list",
path = "/etc/apt/sources.list",
line = "deb [signed-by=/etc/apt/keyrings/obs-home-deltachat.gpg] https://download.opensuse.org/repositories/home:/deltachat/Debian_12/ ./",
ensure_newline = True,
)
apt.update(name="apt update", cache_time=24 * 3600)
apt.packages(
@@ -531,6 +513,7 @@ def deploy_chatmail(config_path: Path) -> None:
# Deploy acmetool to have TLS certificates.
deploy_acmetool(
nginx_hook=True,
domains=[mail_domain, f"mta-sts.{mail_domain}", f"www.{mail_domain}"],
)

View File

@@ -5,7 +5,7 @@ from pyinfra import host
from pyinfra.facts.systemd import SystemdStatus
def deploy_acmetool(email="", domains=[]):
def deploy_acmetool(nginx_hook=False, email="", domains=[]):
"""Deploy acmetool."""
apt.packages(
name="Install acmetool",
@@ -20,13 +20,16 @@ def deploy_acmetool(email="", domains=[]):
mode="644",
)
files.put(
src=importlib.resources.files(__package__).joinpath("acmetool.hook").open("rb"),
dest="/usr/lib/acme/hooks/nginx",
user="root",
group="root",
mode="744",
)
if nginx_hook:
files.put(
src=importlib.resources.files(__package__)
.joinpath("acmetool.hook")
.open("rb"),
dest="/usr/lib/acme/hooks/nginx",
user="root",
group="root",
mode="744",
)
files.template(
src=importlib.resources.files(__package__).joinpath("response-file.yaml.j2"),
@@ -71,5 +74,5 @@ def deploy_acmetool(email="", domains=[]):
server.shell(
name=f"Request certificate for: { ', '.join(domains) }",
commands=[f"acmetool want --xlog.severity=debug { ' '.join(domains)}"],
commands=[f"acmetool want { ' '.join(domains)}"],
)

View File

@@ -3,5 +3,3 @@ set -e
EVENT_NAME="$1"
[ "$EVENT_NAME" = "live-updated" ] || exit 42
systemctl restart nginx.service
systemctl reload dovecot.service
systemctl reload postfix.service

View File

@@ -1,2 +1,2 @@
"acme-enter-email": "{{ email }}"
"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf": true
"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf": true

View File

@@ -7,20 +7,6 @@ Environment="PATH={remote_venv_dir}:$PATH"
Restart=always
RestartSec=30
User=echobot
Group=echobot
# Create /var/lib/echobot
StateDirectory=echobot
# Create /run/echobot
#
# echobot stores /run/echobot/password
# with a password there, which doveauth then reads.
RuntimeDirectory=echobot
WorkingDirectory=/var/lib/echobot
# Apply security restrictions suggested by
# systemd-analyze security echobot.service
CapabilityBoundingSet=
@@ -30,10 +16,7 @@ NoNewPrivileges=true
PrivateDevices=true
PrivateMounts=true
PrivateTmp=true
# We need to know about doveauth user to give it access to /run/echobot/password
PrivateUsers=false
PrivateUsers=true
ProtectClock=true
ProtectControlGroups=true
ProtectHostname=true