kopia lustrzana https://github.com/jaseg/gerbolyze
deploy: add notification proxy
rodzic
40ae8e829c
commit
314d03748e
|
@ -1,2 +1,3 @@
|
|||
*_secret.txt
|
||||
*_apikey.txt
|
||||
playbook.retry
|
||||
|
|
|
@ -129,6 +129,44 @@ http {
|
|||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name automation.jaseg.de;
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
ssl_certificate "/etc/letsencrypt/live/automation.jaseg.de/fullchain.pem";
|
||||
ssl_certificate_key "/etc/letsencrypt/live/automation.jaseg.de/privkey.pem";
|
||||
ssl_dhparam "/etc/letsencrypt/ssl-dhparams.pem";
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
resolver 67.207.67.2 67.207.67.3 valid=300s;
|
||||
resolver_timeout 10s;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=86400";
|
||||
|
||||
# Load configuration files for the default server block.
|
||||
include /etc/nginx/default.d/*.conf;
|
||||
|
||||
location / {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass unix:/run/uwsgi/notification-proxy.socket;
|
||||
}
|
||||
|
||||
error_page 404 /404.html;
|
||||
location = /40x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
|
|
|
@ -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()
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
SENDGRID_APIKEY = '{{lookup('file', 'notification_proxy_sendgrid_apikey.txt')}}'
|
||||
DOMAIN = 'automation.jaseg.de'
|
||||
|
||||
SECRET_KLINGEL = '{{lookup('password', 'notification_proxy_klingel_secret.txt length=32')}}'
|
|
@ -71,3 +71,6 @@
|
|||
- name: Setup pogojig
|
||||
include_tasks: setup_pogojig.yml
|
||||
|
||||
- name: Setup notification proxy
|
||||
include_tasks: setup_notification_proxy.yml
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
- name: Create notification proxy worker user and group
|
||||
user:
|
||||
name: uwsgi-notification-proxy
|
||||
create_home: no
|
||||
group: uwsgi
|
||||
password: '!'
|
||||
shell: /sbin/nologin
|
||||
system: yes
|
||||
|
||||
- name: Create webapp dir
|
||||
file:
|
||||
path: /var/lib/notification-proxy
|
||||
state: directory
|
||||
owner: uwsgi-notification-proxy
|
||||
group: uwsgi
|
||||
mode: 0550
|
||||
|
||||
- name: Copy webapp sources
|
||||
copy:
|
||||
src: notification_proxy.py
|
||||
dest: /var/lib/notification-proxy/
|
||||
owner: uwsgi-notification-proxy
|
||||
group: uwsgi
|
||||
mode: 0440
|
||||
|
||||
- name: Template webapp config
|
||||
template:
|
||||
src: notification_proxy_config.py.j2
|
||||
dest: /var/lib/notification-proxy/config.py
|
||||
owner: uwsgi-notification-proxy
|
||||
group: root
|
||||
mode: 0660
|
||||
|
||||
- name: Copy uwsgi config
|
||||
copy:
|
||||
src: uwsgi-notification-proxy.ini
|
||||
dest: /etc/uwsgi.d/notification-proxy.ini
|
||||
owner: uwsgi-notification-proxy
|
||||
group: uwsgi
|
||||
mode: 0440
|
||||
|
||||
- name: Enable uwsgi systemd socket
|
||||
systemd:
|
||||
daemon-reload: yes
|
||||
name: uwsgi-app@notification-proxy.socket
|
||||
enabled: yes
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
- kochbuch.jaseg.net
|
||||
- tracespace.jaseg.net
|
||||
- openjscad.jaseg.net
|
||||
- automation.jaseg.de
|
||||
|
||||
- name: Copy uwsgi systemd socket config
|
||||
copy:
|
||||
|
@ -54,6 +55,7 @@
|
|||
- tracespace.jaseg.net
|
||||
- openjscad.jaseg.net
|
||||
- pogojig.jaseg.net
|
||||
- automation.jaseg.de
|
||||
|
||||
- name: Copy final nginx config
|
||||
copy:
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
[uwsgi]
|
||||
master = True
|
||||
cheap = True
|
||||
die-on-idle = False
|
||||
manage-script-name = True
|
||||
log-format = [pid: %(pid)|app: -|req: -/-] %(addr) (%(user)) {%(vars) vars in %(pktsize) bytes} [%(ctime)] %(method) [URI hidden] => generated %(rsize) bytes in %(msecs) msecs (%(proto) %(status)) %(headers) headers in %(hsize) bytes (%(switches) switches on core %(core))
|
||||
plugins = python3
|
||||
chdir = /var/lib/notification-proxy
|
||||
mount = /=notification_proxy:app
|
||||
|
Ładowanie…
Reference in New Issue