stackabletech / issues

This repository is only for issues that concern multiple repositories or don't fit into any specific repository
2 stars 0 forks source link

SDP support for JupyterHub #191

Open adwk67 opened 2 years ago

adwk67 commented 2 years ago

As a machine learning engineer, I want to test/asses the viability of using JupyterHub notebooks from within a kubernetes environment. This involves the following:

The result of this story will be:

adwk67 commented 2 days ago

Proposal

These points are outlined below.

A) A suite of images

See this issue for more information. If we are to offer any formal support for JupyterHub, it is essential that we can recommend images that work across this version matrix. It would not involve any new code.

B) Authentication with Keycloak

A WIP can be found in this branch. Keycloak can be set up with a jupyterhub client/realm, much like is done in the e2e-security demo. See also https://oauthenticator.readthedocs.io/en/latest/tutorials/provider-specific-setup/providers/generic.html. The JuypterHub config should reference GenericOAuthenticator:

hub:
    config:
      GenericOAuthenticator:
        client_id: jupyterhub
        client_secret: jupyterhubjupyterhub
        # TODO: How to define this here before Jupyterhub has been deployed?
        oauth_callback_url: http://172.19.0.3:32336/hub/oauth_callback
        # TODO: template the host:port for Keycloak
        authorize_url: https://172.19.0.3:31245/realms/jupyterhub/protocol/openid-connect/auth
        token_url: https:///172.19.0.3:31245/realms/jupyterhub/protocol/openid-connect/token
        userdata_url: https://172.19.0.3:31245/realms/jupyterhub/protocol/openid-connect/userinfo
        username_claim: preferred_username
        auth_state_groups_key: "oauth_user.groups"
        manage_groups: True
        tls_verify: False
        allowed_groups:
          - "Notebook Developers"
        scope:
          - openid
      JupyterHub:
        authenticator_class: generic-oauth

C) Authorization with OPA

The docs seem to tackle both by lumping both custom Authentication and Authorization in a custom Authenticator class.

Authenticate/Authorize on login

Provide a custom Authenticator and issue a callout to the OPA server in the authenticate method.

Example ``` from jupyterhub.auth import Authenticator import requests class OPAAuthorizer: def __init__(self, opa_url): self.opa_url = opa_url def is_allowed(self, user, action, resource): payload = { "input": { "user": user, "action": action, "resource": resource } } response = requests.post(f"{self.opa_url}/v1/data/authz/allow", json=payload) # If response is successful, return the result (True/False) if response.status_code == 200: return response.json().get("result", False) return False class OPAAuthenticator(Authenticator): def __init__(self, *args, opa_url, **kwargs): super().__init__(*args, **kwargs) self.authorizer = OPAAuthorizer(opa_url) def authenticate(self, handler, data): user = data['username'] # Get user info (you can adjust this) action = 'login' # Define action (login for authentication) resource = 'jupyterhub' # Define resource (you can adjust this) if self.authorizer.is_allowed(user, action, resource): # Continue authentication process return user else: # Deny access if not authorized raise Exception("Access Denied") # Use the custom authenticator in JupyterHub config c.JupyterHub.authenticator_class = OPAAuthenticator c.OPAAuthenticator.opa_url = "http://:" ```

Authorize on spawning a notebook

Provide a custom spawner class and issue a callout to the OPA server in the start method.

adwk67 commented 2 days ago

D) JupyterHub Operator

A basic Helm install will create several objects.

Created on helm install ``` kind: NetworkPolicy - name: hub kind: NetworkPolicy - name: proxy kind: PodDisruptionBudget - name: user-placeholder kind: ServiceAccount - name: hub kind: Secret - name: hub kind: ConfigMap - name: hub kind: PersistentVolumeClaim - name: hub-db-dir kind: Role - name: hub kind: RoleBinding - name: hub kind: Service - name: hub kind: Service - name: proxy-api kind: Service - name: proxy-public kind: Deployment - name: hub kind: Deployment - name: proxy kind: StatefulSet - name: user-placeholder ```