Add error reporting over email and improve logging

This commit is contained in:
Timotej Lazar 2023-07-03 15:55:49 +02:00
parent b55ae4d305
commit 5e65755ec0
2 changed files with 47 additions and 25 deletions

View file

@ -1,4 +1,5 @@
import os
import syslog
import secrets
import flask
@ -7,6 +8,7 @@ import flask_login
def create_app(test_config=None):
app = flask.Flask(__name__)
syslog.openlog('friwall')
# Ensure all required keys exist.
settings = {
@ -19,6 +21,7 @@ def create_app(test_config=None):
'ldap_base_dn': '',
'ldap_user_dn': '',
'ldap_login_attr': 'userPrincipalName',
'admin_mail': '',
'wg_endpoint': '',
'wg_port': '51820',
'wg_key': '',

View file

@ -1,11 +1,16 @@
#!/usr/bin/python3
import collections
import email.message
import getpass
import multiprocessing
import os
import pathlib
import shutil
import smtplib
import socket
import subprocess
import sys
import syslog
import click
@ -15,6 +20,15 @@ import ldap3
from . import db
def mail(rcpt, subject, body):
msg = email.message.EmailMessage()
msg['Subject'] = f'friwall: {subject}'
msg['From'] = f'{getpass.getuser()}@{socket.getfqdn()}'
msg['To'] = rcpt
msg.set_content(body)
with smtplib.SMTP('localhost') as server:
server.send_message(msg)
def init_app(app):
app.cli.add_command(generate)
app.cli.add_command(push)
@ -147,11 +161,15 @@ AllowedIPs = {ip}
return True
except Exception as e:
syslog.syslog(f'exception while generating config: {e}')
import traceback
with open('/tmp/wtflog', 'a+') as f:
traceback.print_exc(file=f)
e.add_note(f'exception while generating config: {e}')
msg = traceback.format_exc()
if rcpt := settings.get('admin_mail'):
mail(rcpt, 'error generating config', msg)
# TODO this doesn’t seem to work
#syslog.syslog(msg)
return False
finally:
# Remove temporary directory.
if output:
@ -174,30 +192,31 @@ def push(version=None):
nodes = db.read('nodes')
tar_file = pathlib.Path.home() / 'config' / f'{version}.tar.gz'
done = True
errors = []
for node, node_version in nodes.items():
if node_version != version:
if not os.path.exists(tar_file):
syslog.syslog(f'wanted to push version {version} but {version}.tar.gz doesn’t exist')
return
try:
# Push config tarfile to node. There sshd runs a forced command that
# reads in a tarball, copies files to /etc and reloads services.
syslog.syslog(f'updating config for {node} from v{node_version} to v{version}')
result = subprocess.run([f'ssh -T -o ConnectTimeout=10 root@{node}'],
stdin=open(tar_file), shell=True, capture_output=True)
result = subprocess.run(['/usr/bin/ssh', '-T', '-o', 'ConnectTimeout=10', f'root@{node}'],
stdin=open(tar_file), capture_output=True, text=True)
if result.returncode == 0:
nodes[node] = version
db.write('nodes', nodes)
syslog.syslog(f'successfully updated config for {node} to v{version}')
else:
done = False
syslog.syslog(f'error updating config for node {node} to v{version}: {result.stderr}')
# TODO notify by mail
return done
raise RuntimeError(f'error updating config to v{version}: {result.stderr}')
except (FileNotFoundError, RuntimeError) as e:
e.add_note(f'error while updating node {node}')
errors.append(e)
if errors:
raise ExceptionGroup('errors while updating nodes', errors)
except Exception as e:
import traceback
with open('/tmp/wtflog', 'a+') as f:
traceback.print_exc(file=f)
return False
msg = traceback.format_exc()
if rcpt := db.load('settings').get('admin_mail'):
mail(rcpt, 'error updating nodes', msg)
syslog.syslog(msg)