aboutsummaryrefslogtreecommitdiff
path: root/notification_proxy.py
diff options
context:
space:
mode:
authorjaseg <code@jaseg.net>2020-01-17 11:11:52 +0100
committerjaseg <code@jaseg.net>2020-01-22 15:57:23 +0100
commita747ed293ec4449ca15271f9476903905dbbfaf5 (patch)
treefdbd089df1d9052ba7c886cbc3e235ea8c1faab9 /notification_proxy.py
parent6408f5a15c8dd3967b073e8a2d160b5f490f534a (diff)
downloadinfra-a747ed293ec4449ca15271f9476903905dbbfaf5.tar.gz
infra-a747ed293ec4449ca15271f9476903905dbbfaf5.tar.bz2
infra-a747ed293ec4449ca15271f9476903905dbbfaf5.zip
deploy: add notification proxy
Diffstat (limited to 'notification_proxy.py')
-rw-r--r--notification_proxy.py89
1 files changed, 89 insertions, 0 deletions
diff --git a/notification_proxy.py b/notification_proxy.py
new file mode 100644
index 0000000..ae4d73e
--- /dev/null
+++ b/notification_proxy.py
@@ -0,0 +1,89 @@
+import smtplib
+import ssl
+import email.utils
+import hmac
+from email.mime.text import MIMEText
+from datetime import datetime
+import functools
+import json
+import binascii
+
+from flask import Flask, request, abort
+
+app = Flask(__name__)
+app.config.from_pyfile('config.py')
+
+smtp_server = "smtp.sendgrid.net"
+port = 465
+
+mail_routes = {}
+def mail_route(name, receiver, subject):
+ def wrap(func):
+ global routes
+ mail_routes[name] = (receiver, subject, func)
+ return func
+ return wrap
+
+
+def authenticate(secret):
+ def wrap(func):
+ func.last_seqnum = 0
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ if not request.is_json:
+ abort(400)
+
+ if not 'auth' in request.json and 'payload' in request.json:
+ abort(400)
+
+ if not isinstance(request.json['auth'], str):
+ abort(400)
+ their_digest = binascii.unhexlify(request.json['auth'])
+
+ our_digest = hmac.digest(secret.encode('utf-8'), request.json['payload'].encode('utf-8'), 'sha256')
+ if not hmac.compare_digest(their_digest, our_digest):
+ abort(403)
+
+ try:
+ payload = json.loads(request.json['payload'])
+ except:
+ abort(400)
+
+ if not isinstance(payload['seq'], int) or payload['seq'] <= func.last_seqnum:
+ abort(400)
+
+ func.last_seqnum = payload['seq']
+ del payload['seq']
+ return func(payload)
+ return wrapper
+ return wrap
+
+@mail_route('klingel', 'computerstuff@jaseg.de', 'It rang!')
+@authenticate(app.config['SECRET_KLINGEL'])
+def klingel(_):
+ return f'Date: {datetime.utcnow().isoformat()}'
+
+
+@app.route('/notify/<route_name>', methods=['POST'])
+def notify(route_name):
+ try:
+ context = ssl.create_default_context()
+ smtp = smtplib.SMTP_SSL(smtp_server, port)
+ smtp.login('apikey', app.config['SENDGRID_APIKEY'])
+
+ sender = f'{route_name}@{app.config["DOMAIN"]}'
+
+ receiver, subject, func = mail_routes[route_name]
+
+ msg = MIMEText(func() or subject)
+ msg['Subject'] = subject
+ msg['From'] = sender
+ msg['To'] = receiver
+ msg['Date'] = email.utils.formatdate()
+ smtp.sendmail(sender, receiver, msg.as_string())
+ finally:
+ smtp.quit()
+ return 'success'
+
+if __name__ == '__main__':
+ app.run()