From 79e0614dcb00d236fa3f14fd1bf32a80dab10136 Mon Sep 17 00:00:00 2001 From: Emmanuel Nyachoke Date: Mon, 5 Feb 2024 09:09:02 +0300 Subject: [PATCH] Initial commit --- .github/workflows/ci.yml | 26 +++++++++ Dockerfile | 12 +++++ requirements.txt | 3 ++ security.py | 58 ++++++++++++++++++++ superset-init.sh | 49 +++++++++++++++++ superset_config.py | 112 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 260 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 Dockerfile create mode 100644 requirements.txt create mode 100644 security.py create mode 100755 superset-init.sh create mode 100644 superset_config.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..36c1f75 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + release: + types: [published] + +jobs: + docker-pre-release: + uses: mekomsolutions/shared-github-workflow/.github/workflows/docker-build-publish.yml@main + with: + image-name: "superset-ozonepro" + secrets: + DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_REGISTRY_USERNAME }} + DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_REGISTRY_PASSWORD }} + + docker-release: + uses: mekomsolutions/shared-github-workflow/.github/workflows/docker-build-publish.yml@main + with: + image-name: "superset-ozonepro" + secrets: + DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_REGISTRY_USERNAME }} + DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_REGISTRY_PASSWORD }} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e4df1da --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM amancevice/superset:3.1.0 +# Switching to root to install the required packages +USER root + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +# Switching back to using the `superset` user +USER superset +COPY ./superset-init.sh /etc/superset +COPY ./superset_config.py /etc/superset +COPY ./security.py /etc/superset diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7457945 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +flask-oidc==1.3.0 +flask_openid +itsdangerous==2.0.1 diff --git a/security.py b/security.py new file mode 100644 index 0000000..8a9a9a7 --- /dev/null +++ b/security.py @@ -0,0 +1,58 @@ +from flask import redirect, request +from flask_appbuilder.security.manager import AUTH_OID +from superset.security import SupersetSecurityManager +from flask_oidc import OpenIDConnect +from flask_appbuilder.security.views import AuthOIDView +from flask_login import login_user +from urllib.parse import quote +from flask_appbuilder.views import ModelView, SimpleFormView, expose +import logging +logger = logging.getLogger(__name__) + +class AuthOIDCView(AuthOIDView): + def add_role_if_missing(self, sm, user_id, role_name): + found_role = sm.find_role(role_name) + session = sm.get_session + user = session.query(sm.user_model).get(user_id) + if found_role and found_role not in user.roles: + user.roles += [found_role] + session.commit() + + @expose('/login/', methods=['GET', 'POST']) + def login(self, flag=True): + sm = self.appbuilder.sm + oidc = sm.oid + + + @self.appbuilder.sm.oid.require_login + def handle_login(): + user = sm.auth_user_oid(oidc.user_getfield('email')) + if user is None: + info = oidc.user_getinfo(['preferred_username', 'given_name', 'family_name', 'email','roles']) + user = sm.add_user(info.get('preferred_username'), info.get('given_name'), info.get('family_name'), info.get('email'), sm.find_role('Gamma')) + role_info = oidc.user_getinfo(['roles']) + if role_info is not None: + for role in role_info['roles']: + self.add_role_if_missing(sm, user.id, role) + login_user(user, remember=False) + return redirect(self.appbuilder.get_url_for_index) + + return handle_login() + + @expose('/logout/', methods=['GET', 'POST']) + def logout(self): + + oidc = self.appbuilder.sm.oid + + oidc.logout() + super(AuthOIDCView, self).logout() + redirect_url = request.url_root.strip('/') + self.appbuilder.get_url_for_login + + return redirect(oidc.client_secrets.get('issuer') + '/protocol/openid-connect/logout?redirect_uri=' + quote(redirect_url)) + +class OIDCSecurityManager(SupersetSecurityManager): + authoidview = AuthOIDCView + def __init__(self,appbuilder): + super(OIDCSecurityManager, self).__init__(appbuilder) + if self.auth_type == AUTH_OID: + self.oid = OpenIDConnect(self.appbuilder.get_app) \ No newline at end of file diff --git a/superset-init.sh b/superset-init.sh new file mode 100755 index 0000000..a94b3df --- /dev/null +++ b/superset-init.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +STEP_CNT=6 + +echo_step() { +cat <