#!/usr/bin/env python3 import os import kopf import prometheus_async from functools import wraps from sanic import Sanic, response from sanic import exceptions app = Sanic("users-proxy") devenv = bool(os.getenv("DEV_ENV", False)) api_key = os.environ["API_KEY"] users_lookup = {} def resource_is_deleted(event, **_): return event["type"] == "DELETED" def authorized(): def decorator(f): @wraps(f) async def decorated_function(request, *args, **kwargs): if request.token and request.token == api_key: return await f(request, *args, **kwargs) else: return response.json({"status": "not_authorized"}, 403) return decorated_function return decorator @app.route("/", methods=["GET"]) async def get_index(request): return response.text("hello") @app.route("/users", methods=["GET"]) @authorized() async def get_users(request): return response.json(list(users_lookup.values())) @app.route("/users/", methods=["GET"]) @authorized() async def get_single_user(request, username: str): user = users_lookup.get(username) if user: return response.json(user) else: raise exceptions.NotFound() @kopf.on.startup() async def configure(settings: kopf.OperatorSettings, **_): settings.scanning.disabled = True settings.posting.enabled = False settings.persistence.finalizer = "users-proxy" print("Kopf operator starting up") @kopf.on.resume('oidcgatewayusers') @kopf.on.create('oidcgatewayusers') @kopf.on.update('oidcgatewayusers') async def save_handler(body, **_): username = body['metadata']['name'] groups = [] for group in body.get("status", {}).get("groups", []): groups.append(f"{group['prefix']}:{group['name']}") user = { "username": username, "display_name": body.get("spec", {}).get("customProfile", {}).get("name", None), "slack_id": body.get("status", {}).get("slackId", None), "groups": groups } print(f"Saving {username}") users_lookup[username] = user @kopf.on.event('', 'v1', 'oidcgatewayusers', when=resource_is_deleted) async def delete_handler(body, **_): username = body['metadata']['name'] print(f"Deleting {username}") del users_lookup[username] @app.listener("before_server_start") async def do_setup(app, loop): print("Setting up") app.add_task(kopf.operator(clusterwide=True)) app.add_task(prometheus_async.aio.web.start_http_server(port=5000)) if __name__ == "__main__": app.run(host="0.0.0.0", port=3001, single_process=False, motd=False, dev=devenv)