mirror of
https://github.com/FAUSheppy/atlantis-event-dispatcher
synced 2025-12-06 06:21:36 +01:00
feat: direct token auth & webhook path auth support
This commit is contained in:
@@ -12,7 +12,7 @@ import json
|
|||||||
HTTP_NOT_FOUND = 404
|
HTTP_NOT_FOUND = 404
|
||||||
|
|
||||||
DISPATCH_SERVER = None
|
DISPATCH_SERVER = None
|
||||||
AUTH = None
|
DISPATCH_ACCESS_TOKEN = None
|
||||||
|
|
||||||
def debug_send(uuid, data, fail_it=False):
|
def debug_send(uuid, data, fail_it=False):
|
||||||
'''Dummy function to print and ack a dispatch for debugging'''
|
'''Dummy function to print and ack a dispatch for debugging'''
|
||||||
@@ -92,7 +92,7 @@ def report_failed_dispatch(uuid, error):
|
|||||||
'''Inform the server that the dispatch has failed'''
|
'''Inform the server that the dispatch has failed'''
|
||||||
|
|
||||||
payload = [{ "uuid" : uuid, "error" : error }]
|
payload = [{ "uuid" : uuid, "error" : error }]
|
||||||
response = requests.post(DISPATCH_SERVER + "/report-dispatch-failed", json=payload, auth=AUTH)
|
response = requests.post(DISPATCH_SERVER + "/report-dispatch-failed", json=payload)
|
||||||
|
|
||||||
if response.status_code not in [200, 204]:
|
if response.status_code not in [200, 204]:
|
||||||
print("Failed to report back failed dispatch for {} ({})".format(
|
print("Failed to report back failed dispatch for {} ({})".format(
|
||||||
@@ -102,7 +102,7 @@ def confirm_dispatch(uuid):
|
|||||||
'''Confirm to server that message has been dispatched and can be removed'''
|
'''Confirm to server that message has been dispatched and can be removed'''
|
||||||
|
|
||||||
payload = [{ "uuid" : uuid }]
|
payload = [{ "uuid" : uuid }]
|
||||||
response = requests.post(DISPATCH_SERVER + "/confirm-dispatch", json=payload, auth=AUTH)
|
response = requests.post(DISPATCH_SERVER + "/confirm-dispatch", json=payload)
|
||||||
|
|
||||||
if response.status_code not in [200, 204]:
|
if response.status_code not in [200, 204]:
|
||||||
print("Failed to confirm dispatch with server for {} ({})".format(
|
print("Failed to confirm dispatch with server for {} ({})".format(
|
||||||
@@ -115,8 +115,7 @@ if __name__ == "__main__":
|
|||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
|
|
||||||
parser.add_argument('--dispatch-server')
|
parser.add_argument('--dispatch-server')
|
||||||
parser.add_argument('--dispatch-user')
|
parser.add_argument('--dispatch-access-token')
|
||||||
parser.add_argument('--dispatch-password')
|
|
||||||
|
|
||||||
parser.add_argument('--ntfy-api-server')
|
parser.add_argument('--ntfy-api-server')
|
||||||
parser.add_argument('--ntfy-api-token')
|
parser.add_argument('--ntfy-api-token')
|
||||||
@@ -136,12 +135,11 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
|
|
||||||
dispatch_server = args.dispatch_server or os.environ.get("DISPATCH_SERVER")
|
dispatch_server = args.dispatch_server or os.environ.get("DISPATCH_SERVER")
|
||||||
dispatch_user = args.dispatch_user or os.environ.get("DISPATCH_USER")
|
dispatch_access_token = args.dispatch_access_token or os.environ.get("DISPATCH_ACCESS_TOKEN")
|
||||||
dispatch_password = args.dispatch_password or os.environ.get("DISPATCH_PASSWORD")
|
|
||||||
|
|
||||||
# set dispatch server & authentication global #
|
# set dispatch server & authentication global #
|
||||||
DISPATCH_SERVER = dispatch_server
|
DISPATCH_SERVER = dispatch_server
|
||||||
AUTH = (dispatch_user, dispatch_password)
|
DISPATCH_ACCESS_TOKEN = dispatch_access_token
|
||||||
|
|
||||||
ntfy_api_server = args.ntfy_api_server or os.environ.get("NTFY_API_SERVER")
|
ntfy_api_server = args.ntfy_api_server or os.environ.get("NTFY_API_SERVER")
|
||||||
ntfy_api_token = args.ntfy_api_token or os.environ.get("NTFY_API_TOKEN")
|
ntfy_api_token = args.ntfy_api_token or os.environ.get("NTFY_API_TOKEN")
|
||||||
@@ -159,7 +157,8 @@ if __name__ == "__main__":
|
|||||||
while args.loop or first_run:
|
while args.loop or first_run:
|
||||||
|
|
||||||
# request dispatches #
|
# request dispatches #
|
||||||
response = requests.get(dispatch_server + "/get-dispatch?method=all&timeout=0", auth=AUTH)
|
response = requests.get(dispatch_server +
|
||||||
|
"/get-dispatch?method=all&timeout=0&dispatch-access-token={}".format(DISPATCH_ACCESS_TOKEN))
|
||||||
|
|
||||||
# check status #
|
# check status #
|
||||||
if response.status_code == HTTP_NOT_FOUND:
|
if response.status_code == HTTP_NOT_FOUND:
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ app = flask.Flask("Signal Notification Gateway")
|
|||||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///sqlite.db"
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///sqlite.db"
|
||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
|
BAD_DISPATCH_ACCESS_TOKEN = "Invalid or missing dispatch-access-token parameter in URL"
|
||||||
|
|
||||||
|
class WebHookPaths(db.Model):
|
||||||
|
|
||||||
|
__tablename__ = "webhook_paths"
|
||||||
|
|
||||||
|
username = Column(String, primary_key=True)
|
||||||
|
path = Column(String, primary_key=True)
|
||||||
|
|
||||||
class UserSettings(db.Model):
|
class UserSettings(db.Model):
|
||||||
|
|
||||||
__tablename__ = "user_settings"
|
__tablename__ = "user_settings"
|
||||||
@@ -153,6 +162,10 @@ def get_dispatch():
|
|||||||
timeout = flask.request.args.get("timeout") or 5 # timeout in seconds
|
timeout = flask.request.args.get("timeout") or 5 # timeout in seconds
|
||||||
timeout = int(timeout)
|
timeout = int(timeout)
|
||||||
|
|
||||||
|
dispatch_acces_token = flask.request.args.get("dispatch-access-token") or ""
|
||||||
|
if dispatch_acces_token != app.config["DISPATCH_ACCESS_TOKEN"]:
|
||||||
|
return (BAD_DISPATCH_ACCESS_TOKEN, 401)
|
||||||
|
|
||||||
if not method:
|
if not method:
|
||||||
return (500, "Missing Dispatch Target (signal|email|phone|ntfy|all|any)")
|
return (500, "Missing Dispatch Target (signal|email|phone|ntfy|all|any)")
|
||||||
|
|
||||||
@@ -259,8 +272,9 @@ def confirm_dispatch():
|
|||||||
return ("", 204)
|
return ("", 204)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/smart-send/<path:path>', methods=["POST"])
|
||||||
@app.route('/smart-send', methods=["POST"])
|
@app.route('/smart-send', methods=["POST"])
|
||||||
def smart_send_to_clients():
|
def smart_send_to_clients(path=None):
|
||||||
'''Send to clients based on querying the LDAP
|
'''Send to clients based on querying the LDAP
|
||||||
requests MAY include:
|
requests MAY include:
|
||||||
- list of usernames under key "users"
|
- list of usernames under key "users"
|
||||||
@@ -280,6 +294,19 @@ def smart_send_to_clients():
|
|||||||
title = instructions.get("title")
|
title = instructions.get("title")
|
||||||
method = instructions.get("method")
|
method = instructions.get("method")
|
||||||
|
|
||||||
|
# authenticated by access token or webhook path #
|
||||||
|
dispatch_acces_token = flask.request.args.get("dispatch-access-token") or ""
|
||||||
|
print(path)
|
||||||
|
if path:
|
||||||
|
webhook_path = db.session.query(WebHookPaths).filter(WebHookPaths.path==path).first()
|
||||||
|
if webhook_path:
|
||||||
|
users = webhook_path.username
|
||||||
|
groups = None
|
||||||
|
else:
|
||||||
|
return ("Invalid Webhook path", 401)
|
||||||
|
elif dispatch_acces_token != app.config["DISPATCH_ACCESS_TOKEN"]:
|
||||||
|
return (BAD_DISPATCH_ACCESS_TOKEN, 401)
|
||||||
|
|
||||||
# allow single use string instead of array #
|
# allow single use string instead of array #
|
||||||
if type(users) == str:
|
if type(users) == str:
|
||||||
users = [users]
|
users = [users]
|
||||||
@@ -346,6 +373,7 @@ def create_app():
|
|||||||
}
|
}
|
||||||
app.config["LDAP_ARGS"] = ldap_args
|
app.config["LDAP_ARGS"] = ldap_args
|
||||||
app.config["SETTINGS_ACCESS_TOKEN"] = os.environ["SETTINGS_ACCESS_TOKEN"]
|
app.config["SETTINGS_ACCESS_TOKEN"] = os.environ["SETTINGS_ACCESS_TOKEN"]
|
||||||
|
app.config["DISPATCH_ACCESS_TOKEN"] = os.environ["DISPATCH_ACCESS_TOKEN"]
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
@@ -363,6 +391,7 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument('--ldap-manager-password')
|
parser.add_argument('--ldap-manager-password')
|
||||||
|
|
||||||
parser.add_argument('--settings-access-token')
|
parser.add_argument('--settings-access-token')
|
||||||
|
parser.add_argument('--dispatch-access-token')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -376,6 +405,7 @@ if __name__ == "__main__":
|
|||||||
app.config["LDAP_NO_READ_ENV"] = True
|
app.config["LDAP_NO_READ_ENV"] = True
|
||||||
|
|
||||||
app.config["SETTINGS_ACCESS_TOKEN"] = args.settings_access_token
|
app.config["SETTINGS_ACCESS_TOKEN"] = args.settings_access_token
|
||||||
|
app.config["DISPATCH_ACCESS_TOKEN"] = args.dispatch_access_token
|
||||||
|
|
||||||
if not any([value is None for value in ldap_args.values()]):
|
if not any([value is None for value in ldap_args.values()]):
|
||||||
app.config["LDAP_ARGS"] = ldap_args
|
app.config["LDAP_ARGS"] = ldap_args
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ if __name__ == "__main__":
|
|||||||
signal_cli_bin = args.signal_cli_bin
|
signal_cli_bin = args.signal_cli_bin
|
||||||
|
|
||||||
# request dispatches #
|
# request dispatches #
|
||||||
response = requests.get(args.target + "/get-dispatch?method={}".format(args.method),
|
response = requests.get(args.target +
|
||||||
auth=(args.user, args.password))
|
"/get-dispatch?method={}&dispatch-access-token={}".format(args.method), args.password)
|
||||||
|
|
||||||
# check status #
|
# check status #
|
||||||
if response.status_code == HTTP_NOT_FOUND:
|
if response.status_code == HTTP_NOT_FOUND:
|
||||||
|
|||||||
Reference in New Issue
Block a user