import uuid import requests from flask import Blueprint, request, g from sqlalchemy import text from handlers.base import fail, success from config import config from models.credential import Credential from utlis.database import create_engine_with_timeout from utils.logging import logging credential_bp = Blueprint("credential_bp", __name__) CREATE_USER_TPL = "CREATE USER IF NOT EXISTS '{}.{}'@'{}' IDENTIFIED BY '{}';" GRANT_TPL = "GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,ALTER,CREATE TEMPORARY TABLES,CREATE VIEW ON *.* TO '{}.{}'@'{}';" def __get_username_password(auth0_token: str, cluster_id: int): url = f"{config.ACCOUNT_ADDR}/inner/account-central/api/v1/user-jwt" params = { "cluster_id": cluster_id, "auth0_token": auth0_token, } resp = requests.get(url, params=params) resp_json = resp.json() username = resp_json["db_user"] passwd = resp_json["jwt"] logging.info("exchange auth0_token to username & password, resp %s", resp.text) return username, passwd def __get_db_host_and_port(auth0_token: str, org_id: int, project_id: int, cluster_id: int): url = f"{config.API_ADDR}/api/v1/orgs/{org_id}/projects/{project_id}/clusters" headers = {'Authorization': f'Bearer {auth0_token}'} resp = requests.get(url, headers=headers) resp_json = resp.json() logging.info("exchange auth0_token to database connection strings, resp %s", resp.text) for i in resp_json["items"]: if i["id"] == str(cluster_id): endpoint = i["endpoint"] return endpoint["address"], endpoint["port"], endpoint["token"] return None, None, None def __get_auth0_token(): authorization = request.headers.get("authorization") if not authorization: return None items = authorization.split(" ") if len(items) == 2: return items[1] return None @credential_bp.get("/credential") def get_credentials(): org_id = int(request.args["org_id"]) project_id = int(request.args["project_id"]) cluster_id = int(request.args["cluster_id"]) auth0_token = __get_auth0_token() if not auth0_token: return fail(code=401, msg="one o auth0_token or api_key is required") credential = Credential.get_by_cluster_id(g.session, cluster_id) if not credential: host, port, token = __get_db_host_and_port(auth0_token, org_id, project_id, cluster_id) username, passwd = __get_username_password(auth0_token, cluster_id) # connect to the database and create a special user for the jupyter notebook nb_user, nb_passwd = "nb_user", str(uuid.uuid4()) database_uri = "mysql+pymysql://{}:{}@{}:{}/{}?ssl_ca%2Fetc%2Fssl%2Fcerts%2Fca-certificates.crt&ssl_verify_identity=true".format( username, passwd, host, port, "test", ) logging.info("database_uri: %s", database_uri) engine = create_engine_with_timeout(database_uri) with engine.connect() as conn: sql = CREATE_USER_TPL.format(token, nb_user, "%", nb_passwd) logging.info("execute sql %s", sql) conn.execute(text(sql)) sql = GRANT_TPL.format(token, nb_user, "%") logging.info("execute sql %s", sql) conn.execute(text(sql)) credential = Credential.upsert(g.session, cluster_id, host, port, f"{token}.{nb_user}", nb_passwd) result = { "host": credential.host, "port": credential.port, "username": credential.username, "password": credential.passwd, } if credential else None return success(result=result)