From b8ef98066cbbdd7e1901dfcde1f55cbeda2bc603 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Thu, 23 Feb 2023 16:35:03 +0200 Subject: [PATCH 01/33] Remove anything auth0 --- deployer/auth.py | 175 ------------------------------ deployer/cluster.schema.yaml | 57 ---------- deployer/config_validation.py | 12 +- deployer/deployer.py | 14 +-- deployer/hub.py | 34 +----- dev-requirements.txt | 3 - extra_scripts/count-auth0-apps.py | 152 -------------------------- requirements.txt | 4 - 8 files changed, 6 insertions(+), 445 deletions(-) delete mode 100644 deployer/auth.py delete mode 100644 extra_scripts/count-auth0-apps.py diff --git a/deployer/auth.py b/deployer/auth.py deleted file mode 100644 index 4a768a6c2b..0000000000 --- a/deployer/auth.py +++ /dev/null @@ -1,175 +0,0 @@ -import re - -from auth0.v3.authentication import GetToken -from auth0.v3.management import Auth0 -from yarl import URL - -# What key in the authenticated user's profile to use as hub username -# This shouldn't be changeable by the user! -USERNAME_KEYS = { - "github": "nickname", - "google-oauth2": "email", - "password": "email", - "CILogon": "email", -} - - -class KeyProvider: - def __init__(self, domain, client_id, client_secret): - self.client_id = client_id - self.client_secret = client_secret - self.domain = domain - - @property - def auth0(self): - """ - Return an authenticated Auth0 instance - """ - if not hasattr(self, "_auth0"): - gt = GetToken(self.domain) - creds = gt.client_credentials( - self.client_id, self.client_secret, f"https://{self.domain}/api/v2/" - ) - self._auth0 = Auth0(self.domain, creds["access_token"]) - return self._auth0 - - def _get_clients(self): - return { - client["name"]: client - # Our account is limited to 100 clients, and we want it all in one go - for client in self.auth0.clients.all(per_page=100) - } - - def _get_connections(self): - return { - connection["name"]: connection - for connection in self.auth0.connections.all() - } - - def create_client(self, name, callback_url, logout_url): - client = { - "name": name, - "app_type": "regular_web", - "callbacks": [callback_url], - "allowed_logout_urls": [logout_url], - } - created_client = self.auth0.clients.create(client) - return created_client - - def _ensure_client_callback(self, client, callback_url): - """ - Ensure client has correct callback URL - """ - if "callbacks" not in client or client["callbacks"] != [callback_url]: - self.auth0.clients.update( - client["client_id"], - { - # Overwrite any other callback URL specified - # Only one hub should use any one auth0 application, and it - # should only have one callback url. Additional URLs can be - # a security risk, since people who control those URLs could - # potentially steal user credentials (if they have client_id and secret). - # Fully managing list of callback URLs in code keeps everything - # simpler - "callbacks": [callback_url] - }, - ) - - def _ensure_client_logout_url(self, client, logout_url): - if "allowed_logout_urls" not in client or client["allowed_logout_urls"] != [ - logout_url - ]: - self.auth0.clients.update( - client["client_id"], - { - # Overwrite any other logout URL - users should only land on - # the hub home page after logging out. - "allowed_logout_urls": [logout_url] - }, - ) - - def ensure_client( - self, - name, - callback_url, - logout_url, - connection_name, - connection_config, - ): - current_clients = self._get_clients() - if name not in current_clients: - # Create the client, all good - client = self.create_client(name, callback_url, logout_url) - else: - client = current_clients[name] - self._ensure_client_callback(client, callback_url) - self._ensure_client_logout_url(client, logout_url) - - current_connections = self._get_connections() - - if connection_name == "password": - # Users should not be shared between hubs - each hub - # should have its own username / password database. - # So we create a new 'database connection' per hub, - # instead of sharing one across hubs. - db_connection_name = connection_config.get("database_name", name) - - if db_connection_name not in current_connections: - # connection doesn't exist yet, create it - connection = self.auth0.connections.create( - { - "name": db_connection_name, - "display_name": name, - "strategy": "auth0", - } - ) - current_connections[db_connection_name] = connection - selected_connection_name = db_connection_name - else: - selected_connection_name = connection_name - - for connection in current_connections.values(): - # The chosen connection! - enabled_clients = connection["enabled_clients"].copy() - needs_update = False - client_id = client["client_id"] - if connection["name"] == selected_connection_name: - if client_id not in enabled_clients: - enabled_clients.append(client_id) - needs_update = True - else: - if client_id in enabled_clients: - enabled_clients.remove(client_id) - needs_update = True - - if needs_update: - self.auth0.connections.update( - connection["id"], {"enabled_clients": enabled_clients} - ) - - return client - - def get_client_creds(self, client, connection_name): - """ - Return z2jh config for auth0 authentication for this JupyterHub - """ - logout_redirect_params = { - "client_id": client["client_id"], - "returnTo": client["allowed_logout_urls"][0], - } - - auth = { - "auth0_subdomain": re.sub(r"\.auth0.com$", "", self.domain), - "userdata_url": f"https://{self.domain}/userinfo", - "username_key": USERNAME_KEYS[connection_name], - "client_id": client["client_id"], - "client_secret": client["client_secret"], - "scope": ["openid", "name", "profile", "email"], - "logout_redirect_url": str( - URL(f"https://{self.domain}/v2/logout").with_query( - logout_redirect_params - ) - ), - } - - return auth diff --git a/deployer/cluster.schema.yaml b/deployer/cluster.schema.yaml index e574dea7e6..609487f47a 100644 --- a/deployer/cluster.schema.yaml +++ b/deployer/cluster.schema.yaml @@ -159,7 +159,6 @@ properties: required: - name - domain - - auth0 - helm_chart - helm_chart_values_files properties: @@ -205,62 +204,6 @@ properties: enum: - basehub - daskhub - auth0: - additionalProperties: false - type: object - description: | - Most hubs use Auth0 for authentication, and we dynamically fetch the credentials - needed for each hub - client_id, client_secret, callback_url - on deploy. This - block contains configuration on how auth0 should be configured for this hub. - properties: - enabled: - type: boolean - default: true - description: | - Whether or not to enable Auth0 authentication for this hub. - This should almost always be true. It should only be false if - authenticating against GitHub Orgs or Teams using the - JupyterHub OAuthenticator. Defaults to true. - connection: - type: string - enum: - - google-oauth2 - - github - - password - - CILogon - description: | - Authentication method users of the hub can use to log in to the hub. - We support a subset of the [connectors](https://auth0.com/docs/identityproviders) - that auth0 supports - application_name: - type: string - description: | - We make use of an OAuth2 applications in Auth0 and this is the - name of that application. Defaults to - "-". - - See https://manage.auth0.com/dashboard/us/2i2c/applications. - password: - type: object - description: | - Configuration specific to a connection of type password. - properties: - database_name: - type: string - description: | - Username and password authentication requires a Auth0 - database to store the username and passwords in. This is - the name of that Auth0 database. Defaults to - "-". - - See https://manage.auth0.com/dashboard/us/2i2c/connections/database. - if: - properties: - enabled: - const: true - then: - required: - - connection helm_chart_values_files: type: array description: | diff --git a/deployer/config_validation.py b/deployer/config_validation.py index 297ca859e5..8684ede3c7 100644 --- a/deployer/config_validation.py +++ b/deployer/config_validation.py @@ -160,9 +160,6 @@ def validate_support_config(cluster_name): def validate_authenticator_config(cluster_name, hub_name): """ For each hub of a specific cluster: - - It asserts that only a single auth method is enabled. - An error is raised when an authenticator other than Auth0 - is enabled and `auth0` is not explicitly disabled. - It asserts that when the JupyterHub GitHubOAuthenticator is used, then `Authenticator.allowed_users` is not set. An error is raised otherwise. @@ -184,7 +181,7 @@ def validate_authenticator_config(cluster_name, hub_name): f"{i+1} / {len(hubs)}: Validating authenticator config for {hub.spec['name']}..." ) - authenticator_class = "auth0" + authenticator_class = "" allowed_users = [] for values_file_name in hub.spec["helm_chart_values_files"]: if "secret" not in os.path.basename(values_file_name): @@ -210,13 +207,6 @@ def validate_authenticator_config(cluster_name, hub_name): except KeyError: pass - # If the authenticator class is other than auth0, then raise an error - # if auth0 is not explicitly disabled from the cluster config - if authenticator_class != "auth0" and hub.spec["auth0"].get("enabled", True): - raise ValueError( - f"Please disable auth0 for {hub.spec['name']} hub before using another authenticator class!" - ) - # If the authenticator class is github, then raise an error # if `Authenticator.allowed_users` is set if authenticator_class == "github" and allowed_users and org_based_github_auth: diff --git a/deployer/deployer.py b/deployer/deployer.py index d5eaa85816..404bdd998a 100644 --- a/deployer/deployer.py +++ b/deployer/deployer.py @@ -14,7 +14,6 @@ import typer from ruamel.yaml import YAML -from .auth import KeyProvider from .cli_app import app from .cluster import Cluster from .config_validation import ( @@ -163,15 +162,6 @@ def deploy( with open(decrypted_file_path) as f: config = yaml.load(f) - # Most of our hubs use Auth0 for Authentication. This lets us programmatically - # determine what auth provider each hub uses - GitHub, Google, etc. Without - # this, we'd have to manually generate credentials for each hub - and we - # don't want to do that. Auth0 domains are tied to a account, and - # this is our auth0 domain for the paid account that 2i2c has. - auth0 = config["auth0"] - - k = KeyProvider(auth0["domain"], auth0["client_id"], auth0["client_secret"]) - config_file_path = find_absolute_path_to_cluster_file(cluster_name) with open(config_file_path) as f: cluster = Cluster(yaml.load(f), config_file_path.parent) @@ -181,13 +171,13 @@ def deploy( if hub_name: hub = next((hub for hub in hubs if hub.spec["name"] == hub_name), None) print_colour(f"Deploying hub {hub.spec['name']}...") - hub.deploy(k, dask_gateway_version) + hub.deploy(dask_gateway_version) else: for i, hub in enumerate(hubs): print_colour( f"{i+1} / {len(hubs)}: Deploying hub {hub.spec['name']}..." ) - hub.deploy(k, dask_gateway_version) + hub.deploy(dask_gateway_version) @app.command() diff --git a/deployer/hub.py b/deployer/hub.py index 703616fe33..dadcfa19e9 100644 --- a/deployer/hub.py +++ b/deployer/hub.py @@ -6,7 +6,6 @@ from ruamel.yaml import YAML -from .auth import KeyProvider from .file_acquisition import get_decrypted_file, get_decrypted_files from .utils import print_colour @@ -24,7 +23,7 @@ def __init__(self, cluster, spec): self.cluster = cluster self.spec = spec - def get_generated_config(self, auth_provider: KeyProvider): + def get_generated_config(self): """ Generate config automatically for each hub @@ -135,33 +134,6 @@ def get_generated_config(self, auth_provider: KeyProvider): }, }, } - # - # Allow explicilty ignoring auth0 setup - if self.spec["auth0"].get("enabled", True): - # Auth0 sends users back to this URL after they authenticate - callback_url = f"https://{self.spec['domain']}/hub/oauth_callback" - # Users are redirected to this URL after they log out - logout_url = f"https://{self.spec['domain']}" - client = auth_provider.ensure_client( - name=self.spec["auth0"].get( - "application_name", - f"{self.cluster.spec['name']}-{self.spec['name']}", - ), - callback_url=callback_url, - logout_url=logout_url, - connection_name=self.spec["auth0"]["connection"], - connection_config=self.spec["auth0"].get( - self.spec["auth0"]["connection"], {} - ), - ) - # NOTE: Some dictionary merging might make these lines prettier/more readable. - # Since Auth0 is enabled, we set the authenticator_class to the Auth0OAuthenticator class - generated_config["jupyterhub"]["hub"]["config"]["JupyterHub"] = { - "authenticator_class": "oauthenticator.auth0.Auth0OAuthenticator" - } - generated_config["jupyterhub"]["hub"]["config"][ - "Auth0OAuthenticator" - ] = auth_provider.get_client_creds(client, self.spec["auth0"]["connection"]) # Due to nesting of charts on top of the basehub, our generated basehub # config may need to be nested as well. @@ -170,7 +142,7 @@ def get_generated_config(self, auth_provider: KeyProvider): return generated_config - def deploy(self, auth_provider, dask_gateway_version): + def deploy(self, dask_gateway_version): """ Deploy this hub """ @@ -196,7 +168,7 @@ def deploy(self, auth_provider, dask_gateway_version): self.spec["domain"] = domain_override_config["domain"] - generated_values = self.get_generated_config(auth_provider) + generated_values = self.get_generated_config() if self.spec["helm_chart"] == "daskhub": # Install CRDs for daskhub before deployment diff --git a/dev-requirements.txt b/dev-requirements.txt index d43b4b854d..a7e881aa4b 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -8,6 +8,3 @@ chartpress==2.* # requests is used by extra_scripts/rsync-active-users.py requests==2.* - -# rich is used by extra_scripts/count-auth0-apps.py -rich==13.* diff --git a/extra_scripts/count-auth0-apps.py b/extra_scripts/count-auth0-apps.py deleted file mode 100644 index cb00860384..0000000000 --- a/extra_scripts/count-auth0-apps.py +++ /dev/null @@ -1,152 +0,0 @@ -""" -### Summary - -This is a helper script that will tell us how many duplicated auth apps we -currently have on Auth0 - -### Requirements - -All requirements are already listed in `requirements.txt` with the exception of -rich, which is listed in `dev-requirements.txt`. - -### Running the script - -Execute the script from the root of the repository: - -- python extra_scripts/count-auth0-apps.py - -This will output to the console a list of app names that have more than one -client id (i.e. they have duplicates) - -Adding the purge flag will delete apps on Auth0 until each app name only has one -client id associated with it - -- python extra_scripts/count-auth0-apps.py --purge -""" - -import json -import os -import subprocess -import tempfile -from collections import defaultdict -from contextlib import contextmanager -from pathlib import Path - -from auth0.v3.authentication import GetToken -from auth0.v3.management import Auth0 -from rich import print -from ruamel.yaml import YAML -from ruamel.yaml.scanner import ScannerError - -yaml = YAML(typ="safe", pure=True) - - -@contextmanager -def decrypt_file(encrypted_path): - """ - Provide secure temporary decrypted contents of a given file - - If file isn't a sops encrypted file, we assume no encryption is used - and return the current path. - """ - # We must first determine if the file is using sops - # sops files are JSON/YAML with a `sops` key. So we first check - # if the file is valid JSON/YAML, and then if it has a `sops` key - with open(encrypted_path) as f: - _, ext = os.path.splitext(encrypted_path) - # Support the (clearly wrong) people who use .yml instead of .yaml - if ext == ".yaml" or ext == ".yml": - try: - encrypted_data = yaml.load(f) - except ScannerError: - yield encrypted_path - return - elif ext == ".json": - try: - encrypted_data = json.load(f) - except json.JSONDecodeError: - yield encrypted_path - return - - if "sops" not in encrypted_data: - yield encrypted_path - return - - # If file has a `sops` key, we assume it's sops encrypted - with tempfile.NamedTemporaryFile() as f: - subprocess.check_call(["sops", "--output", f.name, "--decrypt", encrypted_path]) - yield f.name - - -def get_auth0_inst(domain, client_id, client_secret): - """ - Return an authenticated Auth0 instance - """ - gt = GetToken(domain) - creds = gt.client_credentials(client_id, client_secret, f"https://{domain}/api/v2/") - auth0_inst = Auth0(domain, creds["access_token"]) - return auth0_inst - - -# Read in the auth0 client id and secret from a file -root_dir = Path(__file__).parent.parent -auth0_secret_path = os.path.join(root_dir, "config", "secrets.yaml") -with decrypt_file(auth0_secret_path) as decrypted_file_path: - with open(decrypted_file_path) as f: - auth0_config = yaml.load(f) - -# Create an authenticated auth0 instance using above creds -auth0_inst = get_auth0_inst( - auth0_config["auth0"]["domain"], - auth0_config["auth0"]["client_id"], - auth0_config["auth0"]["client_secret"], -) - -# Get a dictionary of all apps currently active on Auth0. Where there is more -# than one app with the same name, append the client_id to a list -clients = defaultdict(list) -for client in auth0_inst.clients.all(per_page=100): - clients[client["name"]].append(client["client_id"]) - -# Filter the dictionary so we only have entries where len(value) > 1 -filtered_clients = {k: v for k, v in clients.items() if len(v) > 1} - -if len(filtered_clients) > 0: - # Print the names of the apps that have duplicates and total number of apps - print("[bold blue]Clients with duplicated Auth0 apps:[/bold blue]") - for k, v in sorted(filtered_clients.items()): - print(f"\t{k}: {len(v)}") - -else: - print("[bold green]There are no duplicated Auth0 apps![/bold green] :tada:") - -# === -# This section of the script currently does not work as intended as the -# auth0 client available in config/secrets.yaml is not configured with the -# clients.delete scope. -# === -# if "--purge" in sys.argv[1:]: -# print( -# "[bold red]YOU HAVE OPTED TO PURGE THE DUPLICATED APPS. THIS ACTION CANNOT BE UNDONE. ARE YOU SURE YOU WANT TO PROCEED?[/bold red]" -# ) -# resp = input("Only 'yes' will be accepted > ") - -# if resp == "yes": -# for app_name in filtered_clients.keys(): -# while len(filtered_clients[app_name]) > 1: -# print( -# f":fire: [bold red]Purging[/bold red] {app_name}:{filtered_clients[app_name][-1]}" -# ) -# auth0_inst.clients.delete(filtered_clients[app_name][-1]) -# del filtered_clients[app_name][-1] - -# print("[blue]Duplicated apps deleted![/blue] :tada:") -# print( -# "[bold green]You should now redeploy all hubs to ensure they have the correct Auth0 tokens![/bold green]" -# ) - -# else: -# import sys -# -# print("[blue]Exiting without purging[/blue]") -# sys.exit() diff --git a/requirements.txt b/requirements.txt index 5338ab45a3..6e6aabfad2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,10 +5,6 @@ # ruamel.yaml is used to read and write .yaml files. ruamel.yaml==0.17.* -# auth0 is used to communicate with Auth0's REST API that we integrate with in -# various ways. -auth0-python==3.* - # jsonschema is used for validating cluster.yaml configurations jsonschema==4.* From 12876f03e07b81f1b308177d17e11fcf24f2b787 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Thu, 23 Feb 2023 16:47:47 +0200 Subject: [PATCH 02/33] Disabled by default --- config/clusters/2i2c-aws-us/cluster.yaml | 4 --- config/clusters/2i2c-uk/cluster.yaml | 2 -- config/clusters/2i2c/cluster.yaml | 16 ------------ config/clusters/awi-ciroh/cluster.yaml | 4 --- config/clusters/callysto/cluster.yaml | 4 --- config/clusters/cloudbank/cluster.yaml | 30 ---------------------- config/clusters/gridsst/cluster.yaml | 8 ------ config/clusters/leap/cluster.yaml | 4 --- config/clusters/linked-earth/cluster.yaml | 8 ------ config/clusters/m2lines/cluster.yaml | 4 --- config/clusters/meom-ige/cluster.yaml | 2 -- config/clusters/nasa-cryo/cluster.yaml | 8 ------ config/clusters/nasa-veda/cluster.yaml | 4 --- config/clusters/pangeo-hubs/cluster.yaml | 4 --- config/clusters/templates/gcp/cluster.yaml | 2 -- config/clusters/ubc-eoas/cluster.yaml | 4 --- config/clusters/utoronto/cluster.yaml | 8 ------ config/clusters/victor/cluster.yaml | 8 ------ 18 files changed, 124 deletions(-) diff --git a/config/clusters/2i2c-aws-us/cluster.yaml b/config/clusters/2i2c-aws-us/cluster.yaml index 8c0e066422..42bc8d7e39 100644 --- a/config/clusters/2i2c-aws-us/cluster.yaml +++ b/config/clusters/2i2c-aws-us/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: "2i2c AWS staging" domain: staging.aws.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - staging.values.yaml - enc-staging.secret.values.yaml @@ -23,8 +21,6 @@ hubs: display_name: "2i2c AWS dask-staging" domain: dask-staging.aws.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - dask-staging.values.yaml diff --git a/config/clusters/2i2c-uk/cluster.yaml b/config/clusters/2i2c-uk/cluster.yaml index fb531c03db..24803b63e0 100644 --- a/config/clusters/2i2c-uk/cluster.yaml +++ b/config/clusters/2i2c-uk/cluster.yaml @@ -22,8 +22,6 @@ hubs: display_name: "London Interdisciplinary School" domain: ds.lis.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - lis.values.yaml - enc-lis.secret.values.yaml diff --git a/config/clusters/2i2c/cluster.yaml b/config/clusters/2i2c/cluster.yaml index 89d2cf3795..18a3fd290e 100644 --- a/config/clusters/2i2c/cluster.yaml +++ b/config/clusters/2i2c/cluster.yaml @@ -23,10 +23,6 @@ hubs: display_name: "2i2c dask staging" domain: dask-staging.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -37,10 +33,6 @@ hubs: display_name: "2i2c binder staging" domain: binder-staging.2i2c.cloud helm_chart: binderhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: - binder-staging.values.yaml - enc-binder-staging.secret.values.yaml @@ -48,8 +40,6 @@ hubs: display_name: "2i2c demo" domain: demo.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -60,8 +50,6 @@ hubs: display_name: "Ocean Hack Week" domain: oceanhackweek.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -150,8 +138,6 @@ hubs: display_name: "Temple University" domain: temple.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - temple.values.yaml - enc-temple.secret.values.yaml @@ -159,8 +145,6 @@ hubs: display_name: "UC Merced" domain: ucmerced.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - ucmerced.values.yaml - enc-ucmerced.secret.values.yaml diff --git a/config/clusters/awi-ciroh/cluster.yaml b/config/clusters/awi-ciroh/cluster.yaml index 5d78c511fc..7299709150 100644 --- a/config/clusters/awi-ciroh/cluster.yaml +++ b/config/clusters/awi-ciroh/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: "Alabama Water Institute: CIROH (staging)" domain: staging.ciroh.awi.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - staging.values.yaml @@ -24,8 +22,6 @@ hubs: display_name: "Alabama Water Institute: CIROH (prod)" domain: ciroh.awi.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - prod.values.yaml diff --git a/config/clusters/callysto/cluster.yaml b/config/clusters/callysto/cluster.yaml index 2e5c36c6e0..f88df987fd 100644 --- a/config/clusters/callysto/cluster.yaml +++ b/config/clusters/callysto/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: "Callysto Staging" domain: staging.callysto.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - staging.values.yaml @@ -24,8 +22,6 @@ hubs: display_name: "Callysto Prod" domain: 2i2c.callysto.ca helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - prod.values.yaml diff --git a/config/clusters/cloudbank/cluster.yaml b/config/clusters/cloudbank/cluster.yaml index faeb07e852..506b7dc185 100644 --- a/config/clusters/cloudbank/cluster.yaml +++ b/config/clusters/cloudbank/cluster.yaml @@ -40,10 +40,6 @@ hubs: display_name: "College of San Mateo" domain: csm.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -67,10 +63,6 @@ hubs: display_name: "Glendale Community College" domain: glendale.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -94,10 +86,6 @@ hubs: display_name: "MiraCosta College" domain: miracosta.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -121,8 +109,6 @@ hubs: display_name: "Cloudbank demo" domain: demo.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -133,10 +119,6 @@ hubs: display_name: "Fresno City College" domain: fresno.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -212,10 +194,6 @@ hubs: display_name: "Pasadena City College" domain: pasadena.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -226,10 +204,6 @@ hubs: display_name: "San Jose Community College" domain: sjcc.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -266,10 +240,6 @@ hubs: display_name: "California State University" domain: csu.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check diff --git a/config/clusters/gridsst/cluster.yaml b/config/clusters/gridsst/cluster.yaml index 91a5e6abd9..887b7006b4 100644 --- a/config/clusters/gridsst/cluster.yaml +++ b/config/clusters/gridsst/cluster.yaml @@ -14,10 +14,6 @@ hubs: display_name: "gridSST Hack-A-Thon(staging)" domain: staging.gridsst.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -29,10 +25,6 @@ hubs: display_name: "gridSST Hack-A-Thon (prod)" domain: gridsst.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check diff --git a/config/clusters/leap/cluster.yaml b/config/clusters/leap/cluster.yaml index 9f5590f6bb..ad1596ff87 100644 --- a/config/clusters/leap/cluster.yaml +++ b/config/clusters/leap/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: "LEAP Staging" domain: staging.leap.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - staging.values.yaml @@ -24,8 +22,6 @@ hubs: display_name: "LEAP Prod" domain: leap.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - prod.values.yaml diff --git a/config/clusters/linked-earth/cluster.yaml b/config/clusters/linked-earth/cluster.yaml index 55657ba1af..4d0d90a66f 100644 --- a/config/clusters/linked-earth/cluster.yaml +++ b/config/clusters/linked-earth/cluster.yaml @@ -19,10 +19,6 @@ hubs: display_name: "LinkedEarth (staging)" domain: staging.linkedearth.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -34,10 +30,6 @@ hubs: display_name: "LinkedEarth (prod)" domain: linkedearth.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check diff --git a/config/clusters/m2lines/cluster.yaml b/config/clusters/m2lines/cluster.yaml index 364bf35834..568bd29454 100644 --- a/config/clusters/m2lines/cluster.yaml +++ b/config/clusters/m2lines/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: "M2LInES (staging)" domain: staging.m2lines.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - staging.values.yaml @@ -24,8 +22,6 @@ hubs: display_name: "M2LInES (prod)" domain: m2lines.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - prod.values.yaml diff --git a/config/clusters/meom-ige/cluster.yaml b/config/clusters/meom-ige/cluster.yaml index e6234ddee5..8dd4b510ae 100644 --- a/config/clusters/meom-ige/cluster.yaml +++ b/config/clusters/meom-ige/cluster.yaml @@ -42,8 +42,6 @@ hubs: display_name: "2023 DRAKKAR Ocean Modelling Workshop" domain: drakkar-demo.meom-ige.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - drakkar-demo.values.yaml - enc-drakkar-demo.secret.values.yaml diff --git a/config/clusters/nasa-cryo/cluster.yaml b/config/clusters/nasa-cryo/cluster.yaml index 90f67d37b5..c8369609b6 100644 --- a/config/clusters/nasa-cryo/cluster.yaml +++ b/config/clusters/nasa-cryo/cluster.yaml @@ -14,10 +14,6 @@ hubs: display_name: "NASA Cryo in the Cloud (staging)" domain: staging.hub.cryointhecloud.com helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -29,10 +25,6 @@ hubs: display_name: "NASA Cryo in the Cloud (prod)" domain: hub.cryointhecloud.com helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check diff --git a/config/clusters/nasa-veda/cluster.yaml b/config/clusters/nasa-veda/cluster.yaml index 3cc0f18c2a..7b2b5de0a6 100644 --- a/config/clusters/nasa-veda/cluster.yaml +++ b/config/clusters/nasa-veda/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: "NASA VEDA (staging)" domain: staging.nasa-veda.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -27,8 +25,6 @@ hubs: display_name: "NASA VEDA (prod)" domain: nasa-veda.2i2c.cloud helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check diff --git a/config/clusters/pangeo-hubs/cluster.yaml b/config/clusters/pangeo-hubs/cluster.yaml index 3a5a11a181..db52db3d5a 100644 --- a/config/clusters/pangeo-hubs/cluster.yaml +++ b/config/clusters/pangeo-hubs/cluster.yaml @@ -15,8 +15,6 @@ hubs: display_name: "Pangeo (staging)" domain: staging.us-central1-b.gcp.pangeo.io helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -28,8 +26,6 @@ hubs: display_name: "Pangeo (prod)" domain: us-central1-b.gcp.pangeo.io helm_chart: daskhub - auth0: - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check diff --git a/config/clusters/templates/gcp/cluster.yaml b/config/clusters/templates/gcp/cluster.yaml index 8c51636f46..b134a9de9f 100644 --- a/config/clusters/templates/gcp/cluster.yaml +++ b/config/clusters/templates/gcp/cluster.yaml @@ -16,8 +16,6 @@ hubs: display_name: "{{ cluster_name }} - {{ hub_name }}" domain: {{ hub_name }}.{{ cluster_name }}.2i2c.cloud helm_chart: {{ hub_type }} - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - {{ hub_name }}.values.yaml diff --git a/config/clusters/ubc-eoas/cluster.yaml b/config/clusters/ubc-eoas/cluster.yaml index e92cad540e..7073a0700b 100644 --- a/config/clusters/ubc-eoas/cluster.yaml +++ b/config/clusters/ubc-eoas/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: UBC EOAS (staging) domain: staging.ubc-eoas.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - staging.values.yaml @@ -24,8 +22,6 @@ hubs: display_name: UBC EOAS domain: ubc-eoas.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - prod.values.yaml diff --git a/config/clusters/utoronto/cluster.yaml b/config/clusters/utoronto/cluster.yaml index 89631bfec2..d4e1516630 100644 --- a/config/clusters/utoronto/cluster.yaml +++ b/config/clusters/utoronto/cluster.yaml @@ -12,8 +12,6 @@ hubs: display_name: "University of Toronto (staging)" domain: staging.utoronto.2i2c.cloud helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - default-common.values.yaml @@ -23,8 +21,6 @@ hubs: display_name: "University of Toronto (prod)" domain: jupyter.utoronto.ca helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - default-common.values.yaml @@ -34,8 +30,6 @@ hubs: display_name: "University of Toronto (r-staging)" domain: r-staging.datatools.utoronto.ca helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - r-common.values.yaml @@ -45,8 +39,6 @@ hubs: display_name: "University of Toronto (R)" domain: r.datatools.utoronto.ca helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - r-common.values.yaml diff --git a/config/clusters/victor/cluster.yaml b/config/clusters/victor/cluster.yaml index e40e4b0693..823031a6ab 100644 --- a/config/clusters/victor/cluster.yaml +++ b/config/clusters/victor/cluster.yaml @@ -14,10 +14,6 @@ hubs: display_name: "Victor (staging)" domain: staging.victor.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -29,10 +25,6 @@ hubs: display_name: "Victor" domain: victor.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - enabled: false helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check From 966bcda57c54ae0512a458af93c3c1d5d08da057 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Fri, 24 Feb 2023 18:49:44 +0200 Subject: [PATCH 03/33] Smarter remove --- deployer/cilogon_app.py | 100 ++++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 19 deletions(-) diff --git a/deployer/cilogon_app.py b/deployer/cilogon_app.py index 67e3512baf..7fd6333088 100644 --- a/deployer/cilogon_app.py +++ b/deployer/cilogon_app.py @@ -206,7 +206,19 @@ def _build_config_filename(self, cluster_name, hub_name): return cluster_config_dir_path.joinpath(f"enc-{hub_name}.secret.values.yaml") - def _persist_client_credentials(self, client, hub_type, config_filename): + def _config_file_exists(self, config_filename): + if not Path(config_filename).is_file(): + print_colour( + "Oops! A CILogon client for this hub doesn't exist.", + "yellow", + ) + return False + + return True + + def _persist_client_credentials_in_config_file( + self, client, hub_type, config_filename + ): auth_config = {} jupyterhub_config = { "jupyterhub": { @@ -226,53 +238,101 @@ def _persist_client_credentials(self, client, hub_type, config_filename): else: auth_config = jupyterhub_config - with open(config_filename, "w+") as f: + with open(config_filename, "a+") as f: yaml.dump(auth_config, f) subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) def _load_client_id(self, config_filename): - try: - with get_decrypted_file(config_filename) as decrypted_path: - with open(decrypted_path) as f: - auth_config = yaml.load(f) + if not self._config_file_exists(config_filename): + return + with get_decrypted_file(config_filename) as decrypted_path: + with open(decrypted_path) as f: + auth_config = yaml.load(f) - basehub = auth_config.get("basehub", None) + basehub = auth_config.get("basehub", None) + try: if basehub: return auth_config["basehub"]["jupyterhub"]["hub"]["config"][ "CILogonOAuthenticator" ]["client_id"] + return auth_config["jupyterhub"]["hub"]["config"]["CILogonOAuthenticator"][ "client_id" ] - except FileNotFoundError: + # The config_file might contain other config too, not just CILogon credentials + except KeyError: print_colour( "Oops! The CILogon client you requested to doesn't exist! Please create it first.", "yellow", ) return + def _remove_client_credentials_from_config_file(self, config_filename): + if not self._config_file_exists(config_filename): + return + with get_decrypted_file(config_filename) as decrypted_path: + with open(decrypted_path) as f: + auth_config = yaml.load(f) + + basehub = auth_config.get("basehub", None) + if basehub: + auth_config["basehub"]["jupyterhub"]["hub"]["config"].pop( + "CILogonOAuthenticator", None + ) + else: + auth_config["jupyterhub"]["hub"]["config"].pop( + "CILogonOAuthenticator", None + ) + + def clean_empty_nested_dicts(d): + if isinstance(d, dict): + return { + key: value + for key, value in ( + (key, clean_empty_nested_dicts(value)) + for key, value in d.items() + ) + if value + } + return d + + remaining_config = clean_empty_nested_dicts(auth_config) + if remaining_config: + with open(config_filename, "w+") as f: + yaml.dump(auth_config, f) + subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) + return + # If the file only contained the CILogon creds, then we can safely delete it + Path(config_filename).unlink() + def create_client(self, cluster_name, hub_name, hub_type, callback_url): client_details = self._build_client_details( cluster_name, hub_name, callback_url ) config_filename = self._build_config_filename(cluster_name, hub_name) - if Path(config_filename).is_file(): + # Check if a client id already exists for this hub + client_id = self._load_client_id(config_filename) + if client_id: print_colour( - f""" + """ Oops! A CILogon client already exists for this hub! - Use the update subcommand to update it or delete {config_filename} if you want to generate a new one. + Use the update subcommand to update it or the delete on first, if you want to generate a new one. """, "yellow", ) return # Ask CILogon to create the client - print(f"Creating client with details {client_details}...") + print( + f"No existing client has been found. Creating a new one with details {client_details}..." + ) client = self.admin_client.create(client_details) # Persist and encrypt the client credentials - self._persist_client_credentials(client, hub_type, config_filename) + self._persist_client_credentials_in_config_file( + client, hub_type, config_filename + ) print(f"Client credentials encrypted and stored to {config_filename}.") def update_client(self, cluster_name, hub_name, callback_url): @@ -315,15 +375,17 @@ def delete_client(self, cluster_name, hub_name, client_id=None): ) return - config_filename = self._build_config_filename(cluster_name, hub_name) - client_id = self._load_client_id(config_filename) + config_filename = self._build_config_filename(cluster_name, hub_name) + client_id = self._load_client_id(config_filename) - # No client has been found - if not client_id: - return + # No client has been found + if not client_id: + return print(f"Deleting the CILogon client details for {client_id}...") - return self.admin_client.delete(client_id) + self.admin_client.delete(client_id) + # Delete client credentials from file also + self._remove_client_credentials_from_config_file(config_filename) def get_all_clients(self): print("Getting all existing OAauth client applications...") From 23de0d6722140c8bb094d8ed1cd4371983fa082b Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Tue, 28 Feb 2023 18:06:23 +0200 Subject: [PATCH 04/33] No more classes --- .../2i2c/enc-staging.secret.values.yaml | 12 +- deployer/cilogon_app.py | 635 +++++++++--------- 2 files changed, 314 insertions(+), 333 deletions(-) diff --git a/config/clusters/2i2c/enc-staging.secret.values.yaml b/config/clusters/2i2c/enc-staging.secret.values.yaml index 8c4bd6a76b..9a4c41caa3 100644 --- a/config/clusters/2i2c/enc-staging.secret.values.yaml +++ b/config/clusters/2i2c/enc-staging.secret.values.yaml @@ -1,19 +1,19 @@ staticWebsite: githubAuth: githubApp: - id: ENC[AES256_GCM,data:EDJXakop,iv:BPu3qh9zpMVJWVNxPIfScoaeA+avSsacqxA6adriU98=,tag:wHxbuCOLrjvyu8/m0bj3rg==,type:int] - privateKey: ENC[AES256_GCM,data:9kGfIIw3C42l41ewl3rAJqxLL7Onj4WPPSy+VgU/qRgBcaGVUIjFs7S3CTmtY2lnFS3VFsmVgNN6js2FrmUXGOqOpwFDjk2otHCCW1tikivnUzzJ93gsB4kEadxg88LsWMcnsfuJRXYxMlgo3pxt76VX2FO+rkrOB058dHlc/FqdkRmMheGMh+7j8HwOkQT1xOK4e2fpX3jGkDJZ/CuzPd4CmGzcVEDQ1sijPdYZosG22CstXgOmK6tZLWXOD7+Ia+Fl59R2+fYlqQYKRDABt7HjV0H6yybTrP/Uz5Q4iFLOYDOZrc3ZCbGRTdfwq1zM/kCDq795WiMC5MybU3C4jGmwXocXPJpfoIcxlHOfKMagZ5bWkwO1uok+9jFk9IV1OCCWj+BBs1gPS6vgOgRq8nhmVIxy0oEVlPg/lDy0VgD9cYtShulg+BwnCLOMBA75S857xmMCkbREkGax/6DZKYfXl9Fs7UR9JokwZuTyspR8Tk1xQTKEVZJ06KxID2YnJWvPsgoEF9bTkOcYWYFjm+Vo6a5kGHfetTNmguKYJpnlxAYOrBC4VuiItboXbTTSM9Hn9BnDgQjbUchfjnzS2BdmWDW52YC8iFpiTWLr7QslZJQuKnAn3+aqud9Gp5uDJumPAch3Q1U41Sj+YiyV2Rhxdvshc2wiEe4PrvLiaR5jlh8BnLkqRaLm5kFN7poiqLNrI8XsHoerjufxJGwVtIfPUmvDmmRS8ya03Wkxze/MzYv0hnIlOWYm8/L9xfXpoduhVdluC/1iRFNA7jyQN4YEBNHIznPZNBRdMm+2DDdEPu2m+Xh6eT5tgTKAyvQTh1eECTZUOL19L6kVzOGBRzTKTNw7sBrGFQh0QeyzX+0qqrf/KcsP65rs0zGezrxbGPdtPGT75vywhw7nYM6GijpxYZOujZJsvUlleGZDUe5f7lgIQB7BAcm5Z6QZXSsJbSz93UDZKSVRPDB4twnUOhMM/ruNJ5WpsA6PgK9wwxCYHllCTr3IqoTXAqz11s42KMfKCiX5zBzcM406Gn1+37HZ8YXLo4CZ3n294EQupTB66gHE77ziP5uCUmtY3iDiNXmH6aUKs+rZpSZ20UVY2q6HzvkK1chkLib3v0INjDqrmoYBjdJ0h2Zxaokzp9ug18Ut5DWh9QTVOXI1qiICxgJoF7UtZMVc7VWZDLJzspZGNbZCVskNUEL+XqNjgsWyuQcSUpGmy5sw1zF0VxSJQqWVlBrJ8lLgeBrHsywcJ+b1PB1Wo4ir9jEo2+goMWwFNjmRtbjhyDgzxUS2oX9Ej4rIhWxF4E91uF1y/rMV2w0C7mqHgUoRFzbRP/aqmiTqfWdpYW+IqOg3eYIkWZ3eXRRPB44tH63mBA1yNkKdql3MUJFxluGhSrVLZWLDc+wDnQJEQGvuG0gCvjn1KYv71nWhAKPkhnqo1OlcFrLRL6nyLlXNoPXKL5EeIDtGOExxR3bqGVajfKmaQsmEf6G7FeTxokSMcQPS+EF2NJ44/Cut16whG2CcWwi6mlSHzk1vvTdQiVSb1K81mtRimfuAq+gXbivzGS7jbFHZO8yuNVFpjkTHtHKmJwI8rd9ehMWH+TbJhblRgLjb96B9G0A/b0veYRWRpmfv4x/RNoCUFaQXLHaEAY/w4WBzSMiych4vGqyF2XILin6xMU8MeVhyh33FyiWZzLKhTF3E0rcYYVYr62722M+jbm0jjafrIDMMBj0ceIf50g3zlfRVW8G1xbllB7Yc8DwxcuZtatffMKsyu1u1/Q91F7jzJfz9RljRyJzs0nVsJc1R2hA0arlqmT8GWD1LI56lKQsYI0FYGc0C9h83rbZlNrV4Moxhayg7qSxXOQ/LI2t+2ds208RDsK8dieiCmJlGtel1eKKVqBobKQGH+0yKTBiWHcEMY5rqsyglYBG4MnLLwnqeOc9juX1Rp+QNyP9lmo3/H7E3HAgBUickW/AwZxAWOG+P1HKB85cd148OnVnPCg5uaCpMnhZGBWoVRXtAzALBkMCkI7zJduegIm8JtfYyoWpr6/HcsCslAUADERzzB141id0BlsCoJE4xsUFM5NkPiaVk56VvdRrFJ5rEL226AQCbmC6mx+wpFlgNv/ympuP3HvABJI9Z0G1UKZ9TZWbNUY38VHCPxREWaxc+r8mt1QoSH6sHfKbJ5SnLPhpqC4OvRks/JLTN3Bc96npcmVAyFxMKAJf3nDHW6EZKFu/OlA==,iv:iu/nD/1zYDo9OY4q+j0sd+E5ODjLHZ3Otbkd0qte8WM=,tag:wD9S4cOGUeCVZIh9mRrI/w==,type:str] + id: ENC[AES256_GCM,data:224IYaJZ,iv:1/0hYPG44TtPxSHLik+CtjoHlD5qPfGDIJyqYj59ogQ=,tag:hGpWZi0FpUkVJfDmFAY/Sg==,type:int] + privateKey: ENC[AES256_GCM,data:5eIRyyzYnd+HipGXYnGHTIH9wDBW2M+ne7diuTP5aZTc9CG1syu0TxjM0xWor3eEWjDPymXokWCZQzWnoIeMlfzHgLm+Znn8Fk7UqWY+RmzJsGrpL1UctK2unQ9sNWV6+P2Y1mFZ7WMmT4PggiehO5U4higQoWAcyfNEJmkPS3kF695Hk/ALAahGbYm4gvRyxBx6QvWwURd2yFE7uqDSUQBeUi/O48hrOs+9rLdVnjEX61hSTzCvHEgvKvLY04Om0YvO9O57kX2vM9kVaUIsdPNsAuEgvjXQpE28pBjbC31yV7bjdtif5sCUAgSbkE0GpTjTFDq5pvwNHEJmQAp+IXV2eiJT8d5zriy0y0bUHrWuyhOj4Em9kdjurffOsdwdcPM2tjWQeJlKCGlXGgp/FwbZkVuy7sI6sTGUEhUp32b3Mm249IQuMXSERUtVYTbFEj6ZSU0mPFimgYyXodxetG0E7ydRvW+FxR4kMYN7ksH254ueKnb+Nv/qkXf1c9ZY0C6SwAXzqy0hpXHjZMLbCZM6b67stVdlvq1S8QlbG+v6B804jFKT17VE68hwIeIdC08wJtF4HaiHdYBCk5aLtu0iuPDXG1qi8Vppa9p+67CINhD1Sf8vlhDdolq9/g7V5D/dAEMB51V7nquYw+/0mfqjbbAZFIURmo3zf6VCYS8u1pgowgTG/zPr4Kd6apf6AeRyqPaxLjnx7wtZjqCewtq/ARAik5kz93ghH4vckXnvaMD7qcoDzJqyTpfl6b3MqWakqd4c2cuyBjt7GP9be4pv4zANbfUkihGOfKVSoYzb2ftUo8yr7a+Ei7yHKwqZW9uHjpiAnl33rWm32sso9SfLjjDMRmV+f+yGUPK7MadunInYcg1zUGZDNkbRJqFI/yfbG5jav7O39NQhxjxsPn66aZ7Bpd/pevuuFRnRSeIR0gLkPb1X9Ol20k0CqwG152gweTEFkoHhfhDX3cdRj65IQvB1w8UvDrqV8BX4Mw1DfW68Fw15iKi2BgYsp2boN92CcoZsKqDWIEw2bygRmb57tRImOzhtGScff7usN07v7HIRRYtD/yZCBiImUBcWkbh9xl6KHcjO6dWo2xeuOTmaHylYY2vLyvCTsfOAFTStXDdYzujJCmIAoFcV2vY9mh3eLPthThszuNxvc8F6W9R0HoBYEWe1Hj81SwGsnBWEnsCjHUiVy+NqC8kW3PTtrzKOVsP0UrbjiPqcygkd/Q1DdKrKyL3gbbOIPizN3RbJQGPEi89Q/YavU7+JZ6qb3ylGtFgF9goajxcrIgNXUdALpeSUeuE9czpwbIWMYodnE9QycJXW2dXk1svg7JqZLJaD39cwc0qeEbdWaoG0NHmRnQIN6frQmqL+FBwIRDYif4nsNVJt9eWdhNyMHt6NA7qLsUvZnQu96kfFO/n38f4SYq7FnPtvwku6VsnKUp5EMvgx2V8B3h+r7hMGt8ONWH695ZmFOpxidDiG6y7ds9eaWAzqstVPJBuIGNsIVLTEqNoBi6kLNEuYNxJijxQc2ukQECYdOVqdbDlOm2VyaId4ghO4FeKT3bv64iyUcwijpuAwHw6rbvuj1mhp7Jl2HAQUR9ZI3Cgbnn6CoYEFMKwwbnCUypHYG4mPojLcqgqKJWH/wsdII/ZV7kQHOXKVrbXM8hl/tBqbhZ3pidqyn09JumWOUgZvsTNEOWKXFUvIvz5GGXKHuqzsH2g8gxwMXTH1mSeduvjOPPUcivLvX3CIu1TBPyODFhsi90zmVhbLP/idgP3hYs++vxj61JVrVDoVwysYcHy1i7LI9tDpqoYXfeeg3IZe6C4WCybZde8frVSDTCnl85WQA7z0Dxrmr9rc/2WQ0OewW7Oc17jsVtnSjQHByeyJGk8Zodo/+OZ3rdvqFUXO/T0ZIg7zMTTc1ocBnB6/o0ekyEKpDqBEfhlvzYGwfR9F+7ViKZSBurUb2Qnjpu4Y2rz0mlul93QcOxNTL8my6kvA5t0ZjAl+F63/yMzSt4GAuN468zZWC7OW6uzQHLbbgW6B9iAwH1ia788/VHldwzHnJ9+N+IeOrBHElIvtlM8FxZwSp2RwXBhpTZwwJKNuwlIekVIbMz4CbcuTb8/WKkYriNo0rQxAB0nQXlK7wj/kdeiB+xDz8vyjCB3mOzXst88wqccU23qV5T0NV+T6A3slb/xT0uPf0QLR0VqF0yu88hRU8Z9DCiumDhjpdSv3cSMB0A==,iv:TZ28VsoUDCPlSSNO1Wfag9YwCHKcNCVzjk2mLDsWgu8=,tag:foGF/cCGeGDoUoAdo1iS3w==,type:str] sops: kms: [] gcp_kms: - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs - created_at: "2022-03-21T10:38:36Z" - enc: CiQA4OM7eJn+A9b0ulwu64MnqKfDM1EwtoKzj7Utg4iXOccLCroSSQDm5XgWCwOR2/FDqBIOrVVltPV7nASpq8h+fiHw5dYTSaPUyAMYwQ62iytA2kwTGQcOMmtxZVhn4dpGt2b0VlEvdiHP02Cgzvo= + created_at: "2023-02-28T13:10:41Z" + enc: CiUA4OM7eCB9SOfo/rCHz/lklfVShY5ZHQ8bHC0FACv70STH3NeqEkkALQgViE3J8T6I97G7a4CWUXJJ7X1OZJjffS6sdWZMmL44KazE0fWroPKDGRCi+xFCPQ4k1XOGu9l6yXSeHHKONzV9nxaDEpas azure_kv: [] hc_vault: [] age: [] - lastmodified: "2023-02-13T15:05:08Z" - mac: ENC[AES256_GCM,data:i+sWcuOK5SH+xkK+P8dwxlV8mNAOg2PAcg8dJ6FGJG/2J+CGLWYFoH/faeLq6ZFxt58/8hC0OvTyANxuYrTf/eB3YxiIp2bx5+xTvRZF26I/9bf4ijXhJ9LOMU4nDL+QfsdO9xS9gQtZAIX1dE33f+IGXAByqFXjh5LeWTddiGU=,iv:TQo92Q7EpjDi7L6OurGnqb17wlUGaoNpO5yIpre8y8A=,tag:bfylC1sivpFrGMhM/nY3MA==,type:str] + lastmodified: "2023-02-28T13:10:42Z" + mac: ENC[AES256_GCM,data:iO2Gm9mqtl2qh7geGXpVOS5tWDNzeofD6BT77tweIyT0lmb44ctpvtzQW0EJoYyuhb49h6v8DkFrZZ93Ns+NJYlxuhXcVVH8VZkb35qR8KUPrjVxdjF6tCW1NLt8BWMDv2OeNPstMsTjyNgFwiIfPr/DHE1zjd5ypU1CRu8mMsM=,iv:NLJ9h6a+XI4dILvlvDp/ThjxhyNRPHvJEwK+VBZxNaU=,tag:d6xJng8zfj2pu/dW8SMxPg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.7.3 diff --git a/deployer/cilogon_app.py b/deployer/cilogon_app.py index 7fd6333088..96c0400261 100644 --- a/deployer/cilogon_app.py +++ b/deployer/cilogon_app.py @@ -16,6 +16,7 @@ """ import base64 +import json import subprocess from pathlib import Path @@ -31,386 +32,366 @@ yaml = YAML(typ="safe") -class CILogonAdmin: - timeout = 5.0 +def build_request_headers(admin_id, admin_secret): + token_string = f"{admin_id}:{admin_secret}" + bearer_token = base64.urlsafe_b64encode(token_string.encode("utf-8")).decode( + "ascii" + ) - def __init__(self, admin_id, admin_secret): - self.admin_id = admin_id - self.admin_secret = admin_secret + return { + "Authorization": f"Bearer {bearer_token}", + "Content-Type": "application/json; charset=UTF-8", + } - token_string = f"{self.admin_id}:{self.admin_secret}" - bearer_token = base64.urlsafe_b64encode(token_string.encode("utf-8")).decode( - "ascii" - ) - self.base_headers = { - "Authorization": f"Bearer {bearer_token}", - "Content-Type": "application/json; charset=UTF-8", - } +def build_request_url(id=None): + url = "https://cilogon.org/oauth2/oidc-cm" - def _url(self, id=None): - url = "https://cilogon.org/oauth2/oidc-cm" + if id is None: + return url - if id is None: - return url + return str(URL(url).with_query({"client_id": id})) - return str(URL(url).with_query({"client_id": id})) - def create(self, body): - """Creates a new client +def build_client_details(cluster_name, hub_name, callback_url): + return { + "client_name": f"{cluster_name}-{hub_name}", + "app_type": "web", + "redirect_uris": [callback_url], + "scope": "openid email org.cilogon.userinfo", + } - Args: - body (dict): Attributes for the new client - Returns a dict containing the client details - or None if the `create` request returned a status code not in the range 200-299. +def build_config_filename(cluster_name, hub_name): + cluster_config_dir_path = find_absolute_path_to_cluster_file(cluster_name).parent + return cluster_config_dir_path.joinpath(f"enc-{hub_name}.secret.values.yaml") - See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-post.sh - """ - headers = self.base_headers.copy() - response = requests.post( - self._url(), json=body, headers=headers, timeout=self.timeout +def config_file_exists(config_filename): + if not Path(config_filename).is_file(): + return False + return True + + +def persist_client_credentials_in_config_file(client, hub_type, config_filename): + auth_config = {} + jupyterhub_config = { + "jupyterhub": { + "hub": { + "config": { + "CILogonOAuthenticator": { + "client_id": client["client_id"], + "client_secret": client["client_secret"], + } + } + } + } + } + + if hub_type != "basehub": + auth_config["basehub"] = jupyterhub_config + else: + auth_config = jupyterhub_config + + if config_file_exists(config_filename): + subprocess.check_call(["sops", "--decrypt", "--in-place", config_filename]) + with open(config_filename, "r+") as f: + config = yaml.load(f) + config.update(auth_config) + f.seek(0) + yaml.dump(config, f) + f.truncate() + subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) + print_colour( + f"Successfully updated the {config_filename} file with the encrypted CILogon OAuth client app credentials." ) + return - client_name = body["client_name"] + with open(config_filename, "a+") as f: + yaml.dump(auth_config, f) + subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) + print_colour( + "Successfully persisted the encrypted CILogon OAuth client app credentials to file {config_filename}" + ) - if not response.ok: - print_colour( - f"Creating the {id} client returned a {response.status_code} status code.", - "red", - ) - print_colour(f"{response.text}", "yellow") - return - print_colour(f"Successfully created a new CILogon client for {client_name}!") - return response.json() +def load_client_id_from_file(config_filename): + if not config_file_exists(config_filename): + return - def get(self, id=None): - """Retrieves a client by its id. + with get_decrypted_file(config_filename) as decrypted_path: + with open(decrypted_path) as f: + auth_config = yaml.load(f) - Args: - id (str): Id of the client to get + basehub = auth_config.get("basehub", None) + try: + if basehub: + return auth_config["basehub"]["jupyterhub"]["hub"]["config"][ + "CILogonOAuthenticator" + ]["client_id"] - Returns a dict containing the client details - or None if the `get` request returned a status code not in the range 200-299. + return auth_config["jupyterhub"]["hub"]["config"]["CILogonOAuthenticator"][ + "client_id" + ] + # Event if it exists, the config_file might contain other config too, not just CILogon credentials + except KeyError: + return - See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-get.sh - """ - headers = self.base_headers.copy() - response = requests.get( - self._url(id), params=None, headers=headers, timeout=self.timeout - ) +def remove_client_credentials_from_config_file(config_filename): + if not config_file_exists(config_filename): + return - if not response.ok: - print_colour( - f"Getting the details of {id} client returned a {response.status_code} status code.", - "red", - ) - print_colour(f"{response.text}", "yellow") - return + with get_decrypted_file(config_filename) as decrypted_path: + with open(decrypted_path) as f: + config = yaml.load(f) - if id: - print_colour(f"Successfully got the details for {id} client!") + basehub = config.get("basehub", None) + try: + if basehub: + config["basehub"]["jupyterhub"]["hub"]["config"].pop( + "CILogonOAuthenticator" + ) + else: + config["jupyterhub"]["hub"]["config"].pop("CILogonOAuthenticator") + except KeyError: + print_colour("No CILogon OAuth client app to delete from {config_filename}") + return + + def clean_empty_nested_dicts(d): + if isinstance(d, dict): + return { + key: value + for key, value in ( + (key, clean_empty_nested_dicts(value)) for key, value in d.items() + ) + if value + } + return d - return response.json() + remaining_config = clean_empty_nested_dicts(config) - def update(self, id, body): - """Modifies a client by its id. + if remaining_config: + with open(config_filename, "w") as f: + yaml.dump(remaining_config, f) + f.truncate() - The `client_secret` attribute cannot be updated. + subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) + print_colour(f"CILogon OAuth client app removed from {config_filename}") + return - Note that any missing attribute values will be deleted from the client's stored information! - Args: - id (str): Id of the client to modify - body (dict): Attributes to modify. + # If the file only contained the CILogon credentials, then we can safely delete it + print_colour( + f"Deleted empty {config_filename} file after CILogon OAuth client app was removed." + ) + Path(config_filename).unlink() - Returns status code if response.ok - or None if the `update` request returned a status code not in the range 200-299. - See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-put.sh - """ - headers = self.base_headers.copy() - response = requests.put( - self._url(id), json=body, headers=headers, timeout=self.timeout +def stored_client_id_same_with_cilogon_records(cluster_name, hub_name, client_id): + stored_client_id = get_client(cluster_name, hub_name)["client_id"] + if stored_client_id is not client_id: + print_colour( + "CILogon records are different than the OAuth client app stored in the configuration file. Consider updating the file.", + "red", ) + return False + return True - if not response.ok: - print_colour( - f"Updating the details of {id} client returned a {response.status_code} status code.", - "red", - ) - print_colour(f"{response.text}", "yellow") - return - print_colour("Client updated successfully!") - return response.status_code +def print_not_ok_request_message(response): + print_colour( + f"The request to CILogon API returned a {response.status_code} status code.", + "red", + ) + print_colour(f"{response.text}", "yellow") - def delete(self, id): - """Deletes the client associated with the id. - Args: - id (str): Id of the client to delete +def create_client( + admin_id, admin_secret, cluster_name, hub_name, hub_type, callback_url +): + """Creates a new client - Returns status code if response.ok - or None if the `delete` request returned a status code not in the range 200-299. + Args: + body (dict): Attributes for the new client - See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-delete.sh - """ + Returns a dict containing the client details + or None if the `create` request returned a status code not in the range 200-299. - headers = self.base_headers.copy() - response = requests.delete(self._url(id), headers=headers, timeout=self.timeout) + See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-post.sh + """ + client_details = build_client_details(cluster_name, hub_name, callback_url) + config_filename = build_config_filename(cluster_name, hub_name) - if not response.ok: - print_colour( - f"Deleting the {id} client returned a {response.status_code} status code.", - "red", - ) - print_colour(f"{response.text}", "yellow") - return + # Check if there's a client id already stored in the config file for this hub + client_id = load_client_id_from_file(config_filename) + if client_id: + print_colour( + "Found existing CILogon OAuth client app in {config_filename}.", "yellow" + ) + # Also check if what's in the file matches CILogon records in case the file was not updated accordingly + # Exit anyway since manual intervention is required if different + return stored_client_id_same_with_cilogon_records( + cluster_name, hub_name, client_id + ) - print_colour(f"Successfully deleted the {id} client!") - return response.status_code + # Ask CILogon to create the client + print(f"Creating a new CILogon OAuth client app with details {client_details}...") + headers = build_request_headers(admin_id, admin_secret) + response = requests.post( + build_request_url(), json=client_details, headers=headers, timeout=5 + ) + if not response.ok: + print_not_ok_request_message(response) + return -class CILogonClientManager: - def __init__(self, admin_id, admin_secret): - self.admin_id = admin_id - self.admin_secret = admin_secret + client = response.json() + print_colour("Done! Successfully created a new CILogon OAuth client app.") - @property - def admin_client(self): - """ - Return a CILogonAdmin instance - """ - if not hasattr(self, "_cilogon_admin"): - self._cilogon_admin = CILogonAdmin(self.admin_id, self.admin_secret) + # Persist and encrypt the client credentials + return persist_client_credentials_in_config_file(client, hub_type, config_filename) - return self._cilogon_admin - def _build_client_details(self, cluster_name, hub_name, callback_url): - client_details = { - "client_name": f"{cluster_name}-{hub_name}", - "app_type": "web", - "redirect_uris": [callback_url], - "scope": "openid email org.cilogon.userinfo", - } +def update_client(admin_id, admin_secret, cluster_name, hub_name, callback_url): + """Modifies a client by its id. - return client_details + ! The `client_secret` attribute cannot be updated. - def _build_config_filename(self, cluster_name, hub_name): - cluster_config_dir_path = find_absolute_path_to_cluster_file( - cluster_name - ).parent + Note that any missing attribute values will be deleted from the client's stored information! + Args: + id (str): Id of the client to modify + body (dict): Attributes to modify. - return cluster_config_dir_path.joinpath(f"enc-{hub_name}.secret.values.yaml") + Returns status code if response.ok + or None if the `update` request returned a status code not in the range 200-299. - def _config_file_exists(self, config_filename): - if not Path(config_filename).is_file(): - print_colour( - "Oops! A CILogon client for this hub doesn't exist.", - "yellow", - ) - return False - - return True - - def _persist_client_credentials_in_config_file( - self, client, hub_type, config_filename - ): - auth_config = {} - jupyterhub_config = { - "jupyterhub": { - "hub": { - "config": { - "CILogonOAuthenticator": { - "client_id": client["client_id"], - "client_secret": client["client_secret"], - } - } - } - } - } + See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-put.sh + """ + client_details = build_client_details(cluster_name, hub_name, callback_url) + config_filename = build_config_filename(cluster_name, hub_name) + client_id = load_client_id_from_file(config_filename) - if hub_type != "basehub": - auth_config["basehub"] = jupyterhub_config - else: - auth_config = jupyterhub_config + if not client_id: + print_colour("Can't update a client that doesn't exist", "red") + return - with open(config_filename, "a+") as f: - yaml.dump(auth_config, f) - subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) + headers = build_request_headers(admin_id, admin_secret) + response = requests.put( + build_request_url(client_id), json=client_details, headers=headers, timeout=5 + ) - def _load_client_id(self, config_filename): - if not self._config_file_exists(config_filename): - return - with get_decrypted_file(config_filename) as decrypted_path: - with open(decrypted_path) as f: - auth_config = yaml.load(f) - - basehub = auth_config.get("basehub", None) - try: - if basehub: - return auth_config["basehub"]["jupyterhub"]["hub"]["config"][ - "CILogonOAuthenticator" - ]["client_id"] - - return auth_config["jupyterhub"]["hub"]["config"]["CILogonOAuthenticator"][ - "client_id" - ] - # The config_file might contain other config too, not just CILogon credentials - except KeyError: - print_colour( - "Oops! The CILogon client you requested to doesn't exist! Please create it first.", - "yellow", - ) - return + if not response.ok: + print_not_ok_request_message(response) + return - def _remove_client_credentials_from_config_file(self, config_filename): - if not self._config_file_exists(config_filename): - return - with get_decrypted_file(config_filename) as decrypted_path: - with open(decrypted_path) as f: - auth_config = yaml.load(f) + print_colour("Done! Client updated successfully") - basehub = auth_config.get("basehub", None) - if basehub: - auth_config["basehub"]["jupyterhub"]["hub"]["config"].pop( - "CILogonOAuthenticator", None - ) - else: - auth_config["jupyterhub"]["hub"]["config"].pop( - "CILogonOAuthenticator", None - ) - def clean_empty_nested_dicts(d): - if isinstance(d, dict): - return { - key: value - for key, value in ( - (key, clean_empty_nested_dicts(value)) - for key, value in d.items() - ) - if value - } - return d +def get_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None): + """Retrieves a client by its id. - remaining_config = clean_empty_nested_dicts(auth_config) - if remaining_config: - with open(config_filename, "w+") as f: - yaml.dump(auth_config, f) - subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) - return - # If the file only contained the CILogon creds, then we can safely delete it - Path(config_filename).unlink() + Args: + id (str): Id of the client to get - def create_client(self, cluster_name, hub_name, hub_type, callback_url): - client_details = self._build_client_details( - cluster_name, hub_name, callback_url - ) - config_filename = self._build_config_filename(cluster_name, hub_name) - - # Check if a client id already exists for this hub - client_id = self._load_client_id(config_filename) - if client_id: - print_colour( - """ - Oops! A CILogon client already exists for this hub! - Use the update subcommand to update it or the delete on first, if you want to generate a new one. - """, - "yellow", - ) - return + Returns a dict containing the client details + or None if the `get` request returned a status code not in the range 200-299. - # Ask CILogon to create the client - print( - f"No existing client has been found. Creating a new one with details {client_details}..." - ) - client = self.admin_client.create(client_details) + See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-get.sh + """ + config_filename = build_config_filename(cluster_name, hub_name) - # Persist and encrypt the client credentials - self._persist_client_credentials_in_config_file( - client, hub_type, config_filename - ) - print(f"Client credentials encrypted and stored to {config_filename}.") + if client_id: + if not stored_client_id_same_with_cilogon_records( + cluster_name, hub_name, client_id + ): + return + else: + client_id = load_client_id_from_file(config_filename) + # No client has been found + if not client_id: + return + headers = build_request_headers(admin_id, admin_secret) + response = requests.get( + build_request_url(client_id), params=None, headers=headers, timeout=5 + ) - def update_client(self, cluster_name, hub_name, callback_url): - client_details = self._build_client_details( - cluster_name, hub_name, callback_url - ) - config_filename = self._build_config_filename(cluster_name, hub_name) + if not response.ok: + print_not_ok_request_message(response) + return - client_id = self._load_client_id(config_filename) + client_details = response.json() + print(json.dumps(client_details, sort_keys=True, indent=4)) + return client_details - # No client has been found for this hub - if not client_id: - return - print(f"Updating the existing CILogon client for {cluster_name}-{hub_name}...") - return self.admin_client.update(client_id, client_details) +def delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None): + """Deletes the client associated with the id. - def get_client(self, cluster_name, hub_name): - config_filename = self._build_config_filename(cluster_name, hub_name) + Args: + id (str): Id of the client to delete - client_id = self._load_client_id(config_filename) + Returns status code if response.ok + or None if the `delete` request returned a status code not in the range 200-299. - # No client has been found + See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-delete.sh + """ + config_filename = build_config_filename(cluster_name, hub_name) + + if client_id: + if not stored_client_id_same_with_cilogon_records( + cluster_name, hub_name, client_id + ): + return + else: + client_id = load_client_id_from_file(config_filename) + # Nothing to do if no client has been found if not client_id: return - print( - f"Getting the stored CILogon client details for {cluster_name}-{hub_name}..." - ) - client_details = self.admin_client.get(client_id) - if client_details: - print(client_details) + print(f"Deleting the CILogon client details for {client_id}...") + headers = build_request_headers(admin_id, admin_secret) + response = requests.delete(build_request_url(client_id), headers=headers, timeout=5) + if not response.ok: + print_not_ok_request_message(response) + return - def delete_client(self, cluster_name, hub_name, client_id=None): - if not client_id: - if not cluster_name or not hub_name: - print_colour( - "Please provide either the client id to delete or the cluster and hub name.", - "red", - ) - return + print_colour("Done!") - config_filename = self._build_config_filename(cluster_name, hub_name) - client_id = self._load_client_id(config_filename) + # Delete client credentials from file also + remove_client_credentials_from_config_file(config_filename) - # No client has been found - if not client_id: - return - print(f"Deleting the CILogon client details for {client_id}...") - self.admin_client.delete(client_id) - # Delete client credentials from file also - self._remove_client_credentials_from_config_file(config_filename) - - def get_all_clients(self): - print("Getting all existing OAauth client applications...") - clients = self.admin_client.get() - for c in clients["clients"]: - print(c) - - @staticmethod - def get_2i2c_cilogon_client_provider(): - """ - Create an instance of a `CILogonClientManager` using the 2i2c administrative client credentials - stored in `shared/deployer/enc-auth-providers-credentials.secret.yaml`. - """ - # This filepath is relative to the PROJECT ROOT - general_auth_config = ( - "shared/deployer/enc-auth-providers-credentials.secret.yaml" - ) - with get_decrypted_file(general_auth_config) as decrypted_file_path: - with open(decrypted_file_path) as f: - config = yaml.load(f) +def get_all_clients(admin_id, admin_secret): + print("Getting all existing OAauth client applications...") + headers = build_request_headers(admin_id, admin_secret) + response = requests.get( + build_request_url(), params=None, headers=headers, timeout=5 + ) - return CILogonClientManager( - config["cilogon_admin"]["client_id"], - config["cilogon_admin"]["client_secret"], - ) + if not response.ok: + print_not_ok_request_message(response) + return + + clients = response.json() + for c in clients["clients"]: + print(c) + + +def get_2i2c_cilogon_admin_credentials(): + """ + Retrieve the 2i2c administrative client credentials + stored in `shared/deployer/enc-auth-providers-credentials.secret.yaml`. + """ + # This filepath is relative to the PROJECT ROOT + general_auth_config = "shared/deployer/enc-auth-providers-credentials.secret.yaml" + with get_decrypted_file(general_auth_config) as decrypted_file_path: + with open(decrypted_file_path) as f: + config = yaml.load(f) + + return ( + config["cilogon_admin"]["client_id"], + config["cilogon_admin"]["client_secret"], + ) @app.command() @@ -428,8 +409,9 @@ def cilogon_client_create( ), ): """Create a CILogon OAuth client for a hub.""" - CILogonClientManager.get_2i2c_cilogon_client_provider().create_client( - cluster_name, hub_name, hub_type, callback_url + admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() + create_client( + admin_id, admin_secret, cluster_name, hub_name, hub_type, callback_url ) @@ -445,9 +427,8 @@ def cilogon_client_update( ), ): """Update the CILogon OAuth client of a hub.""" - CILogonClientManager.get_2i2c_cilogon_client_provider().update_client( - cluster_name, hub_name, callback_url - ) + admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() + update_client(admin_id, admin_secret, cluster_name, hub_name, callback_url) @app.command() @@ -458,32 +439,32 @@ def cilogon_client_get( ), ): """Retrieve details about an existing CILogon client.""" - CILogonClientManager.get_2i2c_cilogon_client_provider().get_client( - cluster_name, hub_name - ) + admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() + get_client(admin_id, admin_secret, cluster_name, hub_name) @app.command() def cilogon_client_get_all(): """Retrieve details about all existing 2i2c CILogon OAuth clients.""" - CILogonClientManager.get_2i2c_cilogon_client_provider().get_all_clients() + admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() + get_all_clients(admin_id, admin_secret) @app.command() def cilogon_client_delete( - cluster_name: str = typer.Argument( - "", help="Name of cluster to operate or none if --client_id is passed" - ), + cluster_name: str = typer.Argument(..., help="Name of cluster to operate"), hub_name: str = typer.Argument( - "", - help="Name of the hub for which we'll delete the CILogon client details or none if --client_id is passed", + ..., + help="Name of the hub for which we'll delete the CILogon client details", ), client_id: str = typer.Option( "", - help="Id of the CILogon OAuth client to delete of the form cilogon:/client_id/", + help="""(Optional) Id of the CILogon OAuth client to delete of the form `cilogon:/client_id/`. + If the id is not passed, it will be retrieved from the configuration file + """, ), ): - """Delete an existing CILogon client.""" - CILogonClientManager.get_2i2c_cilogon_client_provider().delete_client( - cluster_name, hub_name, client_id - ) + """Delete an existing CILogon client. This deletes both the CILogon OAuth application, + and the client credentials from the configuration file.""" + admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() + delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id) From 1be26954c312ec23fffa191fb6ad0ff6395b7b03 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Fri, 3 Mar 2023 12:22:39 +0200 Subject: [PATCH 05/33] requests is now a deployer dep --- requirements.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements.txt b/requirements.txt index 6e6aabfad2..15259f7e84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,3 +24,6 @@ jinja2==3.* # Used for the debug CLI typer==0.7.* escapism==1.* + +# requests is used by deployer/cilogon_app.py +requests==2.* From 23fa11db2168c9f4902021110a844c502aac6fa0 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Thu, 9 Mar 2023 12:57:16 +0200 Subject: [PATCH 06/33] Add profile to the list of scopes. This is needed for GitHub --- deployer/cilogon_app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployer/cilogon_app.py b/deployer/cilogon_app.py index 96c0400261..538427d9fe 100644 --- a/deployer/cilogon_app.py +++ b/deployer/cilogon_app.py @@ -58,7 +58,7 @@ def build_client_details(cluster_name, hub_name, callback_url): "client_name": f"{cluster_name}-{hub_name}", "app_type": "web", "redirect_uris": [callback_url], - "scope": "openid email org.cilogon.userinfo", + "scope": "openid email org.cilogon.userinfo profile", } @@ -111,7 +111,7 @@ def persist_client_credentials_in_config_file(client, hub_type, config_filename) yaml.dump(auth_config, f) subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) print_colour( - "Successfully persisted the encrypted CILogon OAuth client app credentials to file {config_filename}" + f"Successfully persisted the encrypted CILogon OAuth client app credentials to file {config_filename}" ) From def89fb360ce2267b2e46f038860bc0ac6c49c7d Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Thu, 9 Mar 2023 13:12:22 +0200 Subject: [PATCH 07/33] Add GitHub login option to dask-staging and update the OAuth app creds --- config/clusters/2i2c/dask-staging.values.yaml | 9 ++++++++- .../2i2c/enc-dask-staging.secret.values.yaml | 17 +++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/config/clusters/2i2c/dask-staging.values.yaml b/config/clusters/2i2c/dask-staging.values.yaml index d463fe28f8..6bce2c95bb 100644 --- a/config/clusters/2i2c/dask-staging.values.yaml +++ b/config/clusters/2i2c/dask-staging.values.yaml @@ -37,13 +37,20 @@ basehub: JupyterHub: authenticator_class: cilogon CILogonOAuthenticator: + scope: + - "email" + - "profile" oauth_callback_url: "https://dask-staging.2i2c.cloud/hub/oauth_callback" # Only show the option to login with Google shown_idps: - - https://accounts.google.com/o/oauth2/auth + - http://accounts.google.com/o/oauth2/auth + - http://github.com/login/oauth/authorize allowed_idps: http://google.com/accounts/o8/id: username_derivation: username_claim: "email" allowed_domains: - "2i2c.org" + http://github.com/login/oauth/authorize: + username_derivation: + username_claim: "preferred_username" diff --git a/config/clusters/2i2c/enc-dask-staging.secret.values.yaml b/config/clusters/2i2c/enc-dask-staging.secret.values.yaml index 1b7298c168..e158d26234 100644 --- a/config/clusters/2i2c/enc-dask-staging.secret.values.yaml +++ b/config/clusters/2i2c/enc-dask-staging.secret.values.yaml @@ -3,18 +3,19 @@ basehub: hub: config: CILogonOAuthenticator: - client_id: ENC[AES256_GCM,data:U2tPwhzJNuPaVhZh2+l/x06yu2qIgBPBaQQ+DAIHbTmKoRDGWMtrNWQddmbwKEootGiz,iv:sX1r0qjT6B8qCCEjHA31xwHpQdOJdLyAy8wdig+5CBk=,tag:Ns276qpjnejuv9Ui8yNgSQ==,type:str] - client_secret: ENC[AES256_GCM,data:pMoD+NYq1IEjnl7TZkkJRYVmsAuz0NIbEkbANUTFFtt1FWXxjs2993AnRzNBanL9G7G48udurnpZsRt3Nze2bJIBUulB0AA4pnmKQz1fpERbk2Gi2Yo=,iv:tg5ZUw+N9mxvqw/E8SMyTONjWA8MtBcytKvoOj1ByDg=,tag:/kPamEhUtYUamzk8YrMPTQ==,type:str] + client_id: ENC[AES256_GCM,data:1dsOFXtp3iPR8g4XW3XJu7WjfQ3ma165dBrKtOKbrEgGND/iBeBEicMOecoIZAD7hSI=,iv:MOiqHBDjnqFWzkZGKFIZzUGvqBGkgtIijD/7kiO+Oyw=,tag:Cwz9HRYlnWa2ZpgN2TSNUQ==,type:str] + client_secret: ENC[AES256_GCM,data:sfsFpalWm++43Lo4TIGbrMmV4ezk5Vip5KquwSLgmaS6UpE9Y9pvQHf0TKWVc1qQ1/jWJQAs2o2C4KKkVEf4+kMr4DLlzqyZA+34cHQS6vCC3Ox9SJY=,iv:C1/Ixu4wsLPBZ5y1gCk6qotZ/79uvN96j2qkSWLF74c=,tag:9L96bfiLzwnrSB0/etOWYw==,type:str] sops: kms: [] gcp_kms: - - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs - created_at: '2022-03-21T13:32:55Z' - enc: CiQA4OM7eILHin2dVwbBCzUPzS05fF4t5RZBAE0JfP6atdLuO38SSQDm5XgWkZe3tUEj+YR1BIfS+/loNOIei+7DK1t/wzTd3306YjyW44g7pZdxKgQqw9V26HGR4jpUf/Xnj9fnslwR2yCkt2KPUjs= + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-09T10:24:58Z" + enc: CiUA4OM7eHa8jsW67SXJL/YgvkEKzAjkwLcXtAbYOZC5+0HX/wejEkkALQgViGKJ6oZGPw2tw0FIPXjKFsnjfg2VHIE7dzQPxOworJz3vyTCFxVVpwLal6xMI/QRtScMLt3MrvFHPaM1g3wOzVFp6SnC azure_kv: [] hc_vault: [] - lastmodified: '2022-03-21T13:32:56Z' - mac: ENC[AES256_GCM,data:2TB3w10yWfkFC0rIwDnHkDhEZJtC7FClfEQzjFsHnFS6cNcIPZf+mAOMgfipq/PosGNAdGOaTMH95cNXJt4z5sMAoRzFINu5seef3llpax6HtbJ2D4AAcCx7QNq4RGVD1fH2abqZ6P9TxG9VEsHZb0NsaYEA/mhI5kXxrA1fB5s=,iv:4mebKvZWxV1vRW/7f+xRPAU092pb94+0vTfehoNGytw=,tag:nEPCTLbJLPD2D9xGuyW+vQ==,type:str] + age: [] + lastmodified: "2023-03-09T10:24:59Z" + mac: ENC[AES256_GCM,data:/KHJaPyXRbNARb7LLyVeBspzu0KT4FPaM12/DADqXcBvhBXFq1sG8ZwnYdBiHlwCaTMWm19gVVnx96KIdfUVROMLky0/77ZU1q9Tl3K0rn3iqxtdTYzHz8nZXl51oiQo3LnQrJCY+Hp6Jhx6eTNLfdrEigx75l9Jlq3UZMrVN5Q=,iv:BVNkHdrNY8crOCk0/ghILgY/powC9oYssqvcdoVDEBw=,tag:FK/tMoVqO35irj1T4SC5CA==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.6.1 + version: 3.7.3 From ed7601d594f40aa5382626b88574f48d4593148f Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Thu, 9 Mar 2023 13:13:01 +0200 Subject: [PATCH 08/33] Move 2i2c-staging to cilogon authentication --- config/clusters/2i2c/cluster.yaml | 2 -- .../2i2c/enc-staging.secret.values.yaml | 18 ++++++++++++------ config/clusters/2i2c/staging.values.yaml | 14 +++++++++----- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/config/clusters/2i2c/cluster.yaml b/config/clusters/2i2c/cluster.yaml index 18a3fd290e..a7006b42da 100644 --- a/config/clusters/2i2c/cluster.yaml +++ b/config/clusters/2i2c/cluster.yaml @@ -14,8 +14,6 @@ hubs: display_name: "2i2c staging" domain: staging.2i2c.cloud helm_chart: basehub - auth0: - connection: google-oauth2 helm_chart_values_files: - staging.values.yaml - enc-staging.secret.values.yaml diff --git a/config/clusters/2i2c/enc-staging.secret.values.yaml b/config/clusters/2i2c/enc-staging.secret.values.yaml index 9a4c41caa3..2655a2f614 100644 --- a/config/clusters/2i2c/enc-staging.secret.values.yaml +++ b/config/clusters/2i2c/enc-staging.secret.values.yaml @@ -1,19 +1,25 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:ut+eICzfH7Ss+xDE78mfxi1BQyNvVCT15muWDj2DWjQBVKEALK/JimUwGrIOUcvp/RIg,iv:e9kc3i33M4W5H3Otb7Ligc15PY5z4IEj+oSQp8N6BZc=,tag:qMJSmn7haIlqRH7S4AQZ8Q==,type:str] + client_secret: ENC[AES256_GCM,data:PiRAC4I3IhRMLYNLLJPBzu3K19AFGyScnxIILUnt/T3Ba1G1yqEi8agJ1je6YGRmubPPUrqQ65IE1cxeCbZn/pWkbBXZsHFWmjJy+eiQRMBnliZAhbg=,iv:tyVoI2Ef08lL+J/ws7CKCFCy2EtVvRfhTWwD2cTCCP8=,tag:rbMjb8bjAzmV/4c0Se/c8Q==,type:str] staticWebsite: githubAuth: githubApp: - id: ENC[AES256_GCM,data:224IYaJZ,iv:1/0hYPG44TtPxSHLik+CtjoHlD5qPfGDIJyqYj59ogQ=,tag:hGpWZi0FpUkVJfDmFAY/Sg==,type:int] - privateKey: ENC[AES256_GCM,data:5eIRyyzYnd+HipGXYnGHTIH9wDBW2M+ne7diuTP5aZTc9CG1syu0TxjM0xWor3eEWjDPymXokWCZQzWnoIeMlfzHgLm+Znn8Fk7UqWY+RmzJsGrpL1UctK2unQ9sNWV6+P2Y1mFZ7WMmT4PggiehO5U4higQoWAcyfNEJmkPS3kF695Hk/ALAahGbYm4gvRyxBx6QvWwURd2yFE7uqDSUQBeUi/O48hrOs+9rLdVnjEX61hSTzCvHEgvKvLY04Om0YvO9O57kX2vM9kVaUIsdPNsAuEgvjXQpE28pBjbC31yV7bjdtif5sCUAgSbkE0GpTjTFDq5pvwNHEJmQAp+IXV2eiJT8d5zriy0y0bUHrWuyhOj4Em9kdjurffOsdwdcPM2tjWQeJlKCGlXGgp/FwbZkVuy7sI6sTGUEhUp32b3Mm249IQuMXSERUtVYTbFEj6ZSU0mPFimgYyXodxetG0E7ydRvW+FxR4kMYN7ksH254ueKnb+Nv/qkXf1c9ZY0C6SwAXzqy0hpXHjZMLbCZM6b67stVdlvq1S8QlbG+v6B804jFKT17VE68hwIeIdC08wJtF4HaiHdYBCk5aLtu0iuPDXG1qi8Vppa9p+67CINhD1Sf8vlhDdolq9/g7V5D/dAEMB51V7nquYw+/0mfqjbbAZFIURmo3zf6VCYS8u1pgowgTG/zPr4Kd6apf6AeRyqPaxLjnx7wtZjqCewtq/ARAik5kz93ghH4vckXnvaMD7qcoDzJqyTpfl6b3MqWakqd4c2cuyBjt7GP9be4pv4zANbfUkihGOfKVSoYzb2ftUo8yr7a+Ei7yHKwqZW9uHjpiAnl33rWm32sso9SfLjjDMRmV+f+yGUPK7MadunInYcg1zUGZDNkbRJqFI/yfbG5jav7O39NQhxjxsPn66aZ7Bpd/pevuuFRnRSeIR0gLkPb1X9Ol20k0CqwG152gweTEFkoHhfhDX3cdRj65IQvB1w8UvDrqV8BX4Mw1DfW68Fw15iKi2BgYsp2boN92CcoZsKqDWIEw2bygRmb57tRImOzhtGScff7usN07v7HIRRYtD/yZCBiImUBcWkbh9xl6KHcjO6dWo2xeuOTmaHylYY2vLyvCTsfOAFTStXDdYzujJCmIAoFcV2vY9mh3eLPthThszuNxvc8F6W9R0HoBYEWe1Hj81SwGsnBWEnsCjHUiVy+NqC8kW3PTtrzKOVsP0UrbjiPqcygkd/Q1DdKrKyL3gbbOIPizN3RbJQGPEi89Q/YavU7+JZ6qb3ylGtFgF9goajxcrIgNXUdALpeSUeuE9czpwbIWMYodnE9QycJXW2dXk1svg7JqZLJaD39cwc0qeEbdWaoG0NHmRnQIN6frQmqL+FBwIRDYif4nsNVJt9eWdhNyMHt6NA7qLsUvZnQu96kfFO/n38f4SYq7FnPtvwku6VsnKUp5EMvgx2V8B3h+r7hMGt8ONWH695ZmFOpxidDiG6y7ds9eaWAzqstVPJBuIGNsIVLTEqNoBi6kLNEuYNxJijxQc2ukQECYdOVqdbDlOm2VyaId4ghO4FeKT3bv64iyUcwijpuAwHw6rbvuj1mhp7Jl2HAQUR9ZI3Cgbnn6CoYEFMKwwbnCUypHYG4mPojLcqgqKJWH/wsdII/ZV7kQHOXKVrbXM8hl/tBqbhZ3pidqyn09JumWOUgZvsTNEOWKXFUvIvz5GGXKHuqzsH2g8gxwMXTH1mSeduvjOPPUcivLvX3CIu1TBPyODFhsi90zmVhbLP/idgP3hYs++vxj61JVrVDoVwysYcHy1i7LI9tDpqoYXfeeg3IZe6C4WCybZde8frVSDTCnl85WQA7z0Dxrmr9rc/2WQ0OewW7Oc17jsVtnSjQHByeyJGk8Zodo/+OZ3rdvqFUXO/T0ZIg7zMTTc1ocBnB6/o0ekyEKpDqBEfhlvzYGwfR9F+7ViKZSBurUb2Qnjpu4Y2rz0mlul93QcOxNTL8my6kvA5t0ZjAl+F63/yMzSt4GAuN468zZWC7OW6uzQHLbbgW6B9iAwH1ia788/VHldwzHnJ9+N+IeOrBHElIvtlM8FxZwSp2RwXBhpTZwwJKNuwlIekVIbMz4CbcuTb8/WKkYriNo0rQxAB0nQXlK7wj/kdeiB+xDz8vyjCB3mOzXst88wqccU23qV5T0NV+T6A3slb/xT0uPf0QLR0VqF0yu88hRU8Z9DCiumDhjpdSv3cSMB0A==,iv:TZ28VsoUDCPlSSNO1Wfag9YwCHKcNCVzjk2mLDsWgu8=,tag:foGF/cCGeGDoUoAdo1iS3w==,type:str] + id: ENC[AES256_GCM,data:WpL4Y/Q5,iv:q/Y+T8UAwjIRpVHfjglBYS12Nx0oh8K/r3vm8PdYGL8=,tag:z3AnnYKwc/tbvmfv+dDPnw==,type:int] + privateKey: ENC[AES256_GCM,data:3/t4E45bKdGVFYMyvJcIsi28sGEyizvsH+GXxmxlUJr8/2yvVpYcl5t/Cy1Ymht6idPsAGKdVhUWvXrrlAo2kohMo1t2jWUvuHILoNiyw1WmXNP2XKwdX/eMeyAZoBqTZOQ/sBGVE1a/oXZonNiovFs0ASI0th4zSuRqZuiYtshq/RZOnPhBEo76b0yjPORD6WrksmlJeOTYaGkc6sihf8jYmRBxpq4Ne5Ew6HJUZRMo0MBg6vCvQtAjVfo/S7waZVkdI19G1cVMtoYDV2WUz5LkUwk0TTr4PFCq5VfXuNo1/PW7Y08TAOxb6EBDQAEU/lrk7vOqnJrkDCOlv91N2nVLcBkwD6yq2vgG5LCDVK/4ugyicsQau4ZGpYiAP68ZJ+CynvjfNHsoh+W4os5wU5ZsuVuTGGlb+lgo2E9uLQiLCNBJX+NIhLXh08fiCSajFC/rZJJcr0ZrTMB2/sJA/V74oHC68ZlrMqoo/7GjVWNSWSqaEDIXWCulR+LcvExXe5xQ2Lm5YHpl6fRNi1iNygD7NhjfUs7G09xIC14wIl6GJNAnpSG0p+rstPXKQycHX1uF9SU5YvcLf7Lcsbpq/ZTVc8EBeh+g8k5sWmXJEnPHD56CPAsJ9GFb6b3O32ctoAH+F8QAdzYLDASyn5NBrjCQOwjs652X24zB/f9yl5muutXJJoHQ0LQd7rnWE81CpryMEK3XDcMhDW86rJDTrOaRDAYqjKPxKqDrtFRCwMAezVSrg2aiwzBjaBGSPRE7JL+EQFCn3UUDSf60jNtuX0EZMOLJxWxXnTx2bW0pfL53Iwc70Alc3S/yy3EF+LgR0MqHh+AKu5HgnR4W+epWWiI06OcAfvPVWZz0/9w7VWc/rYKXdlzRekez4yx1+YscdxbgCSTpEfe75kJHZMiNZA/mofe/jx8sUH/ZAq9hndEeYIHuHIzZbCWEDZ91Rbg5NP0xyiDFOsZ3LNexw+XsEX+VUBBzKX417LR4vRPMGMj23yAA0I8hWGhm2dLkZ5obHJ2u0HBTuCiIXlThe4/vOHaomJfjooae/aT2zSiWVKwdRyzmDn3cc3VFPreAk/Fs0TMa/JF70rja8g5KlhsTlAns0d3cKJARmvtb1F1AO5yINKBwjPCsB0tuzItIORuaj2MvyHjXEjiPs/ZcM0cRf4tXwsQYv5CS4xt/cKGrOMoTspkUP5esqbdQd4q0K4fSZQdAbTZwFPkQww0bNx1qjGJuBoBTOP1LNc1ZX9XXNLlb/Cfko8GyLX117verli4lnDxShTXEeU7Z+byB4pkxv+fHP5xGqs2tkwoh8nKbRtV34I8NDyh2GWxJzWZhKjNoIIVNbrj7DvsWUVilWht2DYF5nVRGpXa8yj6a9Arjz7Rxa0Wlw2fPnk4r5NwWU1Yv5y39dj4dT4h1nQC4hcW0ueRCgrxUGF2DrAb/y1MtzbLalvUg8XluJTozFmP5j0oupZFHm43I0JetlIFuipI+LhMqSGxEi+pYTssG0yJSAB0w8z9Y9Q6HIE2hPfFzFdTh1dujyzZq3k28007MSRxNRMTYCWmfbilwwSUmVG4SQ49AjW87hLNGDqYLdu+AkTJKnB90h2sNi6vruNiPL+ahZ2XAeOpQyu587HWD33sBfWS/9uKOeUWXKusYA54uprpVU3f7tXkmm+8UlPQ2UWKez5ytuhO2hlkHQMOinVxLC/SnoHnTiDgR9YjDpTOTzcAvoh7l+sO2Dr5xrXvV2gWUDgt2u/Gd6uqwDCaZvwOz15VtlFYzPlSEMo7bIyZ23u54y3qjhr85gcbe9mmkCwNo3/iE6gcjgYNFpfpM3LGucLOlVSJ2z7AV44UHMEcZeKUxgrmRWv9bhRKZy/mKWI0WrH5LmRqk9/ixVsdzZQN+fz2zB6tpEjdqEadz9c2fhNz5X+9J0WhYc/t9me+hwil4nPMipeWE8TQIL4dfSYZcZRcYfqFMKb0GseQEGQnBBcwMr4YzcJHjoyJG99hGhChoDFFl3TLByk5lI9Ygb21aBfB2X8vJdBZh7giKas97STp/PGpC6BWeOX7jh/rUnvLOiwe4nuEntNg6C7naCvGj8WgStIaxLNpoKuqubiB0yAX0xGfbzLbLusEn1ukeQD5sEruoqUTjrnOYQUqPewFmijqFFLHCb3HuacTCfTPVMokxJ9meIs/7j4zhQZq+sll0h0Rfh366+1s+OJByULxaN2Oq9quiaPTe9wQqVQ==,iv:sv02xzuA+rDx+RUmgyfyBZknuID1cDPdWdtdBOBGfm0=,tag:5Vf+gPpKAsWEItTwB2NUiw==,type:str] sops: kms: [] gcp_kms: - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs - created_at: "2023-02-28T13:10:41Z" - enc: CiUA4OM7eCB9SOfo/rCHz/lklfVShY5ZHQ8bHC0FACv70STH3NeqEkkALQgViE3J8T6I97G7a4CWUXJJ7X1OZJjffS6sdWZMmL44KazE0fWroPKDGRCi+xFCPQ4k1XOGu9l6yXSeHHKONzV9nxaDEpas + created_at: "2023-03-09T10:59:05Z" + enc: CiUA4OM7eJjO0R6F1YN6dsk3txhtXwdeiDiOASocvMm4ygYeOpE5EkkALQgViNvsT02c2G7cn1u9pXUjBEtByBRByd3v/0sLQ+ZRJ18WfzEVrgmqTAcsuiUb0WVDHNOWGXySuxUUTL9y4k8JbOQcR/wu azure_kv: [] hc_vault: [] age: [] - lastmodified: "2023-02-28T13:10:42Z" - mac: ENC[AES256_GCM,data:iO2Gm9mqtl2qh7geGXpVOS5tWDNzeofD6BT77tweIyT0lmb44ctpvtzQW0EJoYyuhb49h6v8DkFrZZ93Ns+NJYlxuhXcVVH8VZkb35qR8KUPrjVxdjF6tCW1NLt8BWMDv2OeNPstMsTjyNgFwiIfPr/DHE1zjd5ypU1CRu8mMsM=,iv:NLJ9h6a+XI4dILvlvDp/ThjxhyNRPHvJEwK+VBZxNaU=,tag:d6xJng8zfj2pu/dW8SMxPg==,type:str] + lastmodified: "2023-03-09T10:59:06Z" + mac: ENC[AES256_GCM,data:RLYpW3qeNkUfreFfwbW3an7k/weE2p/Fu1DXBGd0/GgEyPsy9jQj34w66fT5DFWJFcIpSEvAty3hzB8S4Y0NEATooahD5T6cvvi3GD/d9b+V1pXjeFNpigQ+SRkwUghfajy2LcAVdXTDeorR0V8zlSj8lLUuu51PSeB0UkC5L00=,iv:7blbojnWaAE46D6JgZiXpLEbXWHeup8o7Sh1pehedOs=,tag:ZFXAd9Rw61Bgybla23g1yg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.7.3 diff --git a/config/clusters/2i2c/staging.values.yaml b/config/clusters/2i2c/staging.values.yaml index 8be25a11ca..3c18f37a72 100644 --- a/config/clusters/2i2c/staging.values.yaml +++ b/config/clusters/2i2c/staging.values.yaml @@ -12,7 +12,7 @@ staticWebsite: host: staging.2i2c.cloud path: /textbook githubAuth: - enabled: true + enabled: false jupyterhub: custom: @@ -45,7 +45,11 @@ jupyterhub: url: http://dex:9000 display: false config: - Authenticator: - allowed_users: &staging_users - - colliand@gmail.com - admin_users: *staging_users + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://staging.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id From 4566856863bc6681a74bd7102119c1a3bcf230bb Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Thu, 9 Mar 2023 13:40:00 +0200 Subject: [PATCH 09/33] Update function signature --- deployer/cilogon_app.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/deployer/cilogon_app.py b/deployer/cilogon_app.py index 538427d9fe..3f87b2a0d5 100644 --- a/deployer/cilogon_app.py +++ b/deployer/cilogon_app.py @@ -187,9 +187,13 @@ def clean_empty_nested_dicts(d): Path(config_filename).unlink() -def stored_client_id_same_with_cilogon_records(cluster_name, hub_name, client_id): - stored_client_id = get_client(cluster_name, hub_name)["client_id"] - if stored_client_id is not client_id: +def stored_client_id_same_with_cilogon_records( + admin_id, admin_secret, cluster_name, hub_name, client_id +): + stored_client_id = get_client(admin_id, admin_secret, cluster_name, hub_name)[ + "client_id" + ] + if stored_client_id != client_id: print_colour( "CILogon records are different than the OAuth client app stored in the configuration file. Consider updating the file.", "red", @@ -226,12 +230,12 @@ def create_client( client_id = load_client_id_from_file(config_filename) if client_id: print_colour( - "Found existing CILogon OAuth client app in {config_filename}.", "yellow" + f"Found existing CILogon OAuth client app in {config_filename}.", "yellow" ) # Also check if what's in the file matches CILogon records in case the file was not updated accordingly # Exit anyway since manual intervention is required if different return stored_client_id_same_with_cilogon_records( - cluster_name, hub_name, client_id + admin_id, admin_secret, cluster_name, hub_name, client_id ) # Ask CILogon to create the client @@ -302,7 +306,7 @@ def get_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None): if client_id: if not stored_client_id_same_with_cilogon_records( - cluster_name, hub_name, client_id + admin_id, admin_secret, cluster_name, hub_name, client_id ): return else: @@ -339,7 +343,13 @@ def delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None if client_id: if not stored_client_id_same_with_cilogon_records( - cluster_name, hub_name, client_id + admin_id, + admin_secret, + admin_id, + admin_secret, + cluster_name, + hub_name, + client_id, ): return else: From a33d2035291aeb81e776d046536c4b8703955171 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Thu, 9 Mar 2023 14:00:04 +0200 Subject: [PATCH 10/33] Move all prior auth0 hubs to their cilogon counterparts --- config/clusters/2i2c/aup.values.yaml | 10 +++++++ .../2i2c/catalyst-cooperative.values.yaml | 8 +++++ config/clusters/2i2c/cluster.yaml | 30 ++++--------------- config/clusters/2i2c/earthlab.values.yaml | 10 +++++++ .../clusters/2i2c/enc-aup.secret.values.yaml | 20 +++++++++++++ ...nc-catalyst-cooperative.secret.values.yaml | 21 +++++++++++++ .../2i2c/enc-earthlab.secret.values.yaml | 20 +++++++++++++ .../2i2c/enc-paleohack2021.secret.values.yaml | 20 +++++++++++++ .../2i2c/enc-peddie.secret.values.yaml | 20 +++++++++++++ .../clusters/2i2c/enc-pfw.secret.values.yaml | 20 +++++++++++++ .../clusters/2i2c/paleohack2021.values.yaml | 10 +++++++ config/clusters/2i2c/peddie.values.yaml | 8 +++++ config/clusters/2i2c/pfw.values.yaml | 10 +++++++ 13 files changed, 183 insertions(+), 24 deletions(-) create mode 100644 config/clusters/2i2c/enc-aup.secret.values.yaml create mode 100644 config/clusters/2i2c/enc-catalyst-cooperative.secret.values.yaml create mode 100644 config/clusters/2i2c/enc-earthlab.secret.values.yaml create mode 100644 config/clusters/2i2c/enc-paleohack2021.secret.values.yaml create mode 100644 config/clusters/2i2c/enc-peddie.secret.values.yaml create mode 100644 config/clusters/2i2c/enc-pfw.secret.values.yaml diff --git a/config/clusters/2i2c/aup.values.yaml b/config/clusters/2i2c/aup.values.yaml index b4235dc6fe..ba1f02e29f 100644 --- a/config/clusters/2i2c/aup.values.yaml +++ b/config/clusters/2i2c/aup.values.yaml @@ -24,6 +24,16 @@ jupyterhub: guarantee: 6G hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://aup.pilot.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize Authenticator: allowed_users: &aup_users - swalker diff --git a/config/clusters/2i2c/catalyst-cooperative.values.yaml b/config/clusters/2i2c/catalyst-cooperative.values.yaml index 11c452817d..f5145c7c6c 100644 --- a/config/clusters/2i2c/catalyst-cooperative.values.yaml +++ b/config/clusters/2i2c/catalyst-cooperative.values.yaml @@ -38,6 +38,14 @@ basehub: url: https://2i2c.org hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://catalyst-cooperative.pilot.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &catalyst_users - zane.selvans@catalyst.coop diff --git a/config/clusters/2i2c/cluster.yaml b/config/clusters/2i2c/cluster.yaml index a7006b42da..df67dd1332 100644 --- a/config/clusters/2i2c/cluster.yaml +++ b/config/clusters/2i2c/cluster.yaml @@ -58,80 +58,62 @@ hubs: display_name: "Purdue Fort Wayne" domain: pfw.pilot.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - pfw.values.yaml + - enc-pfw.secret.values.yaml - name: peddie display_name: "Peddie Academy" domain: peddie.pilot.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - peddie.values.yaml + - enc-peddie.secret.values.yaml - name: catalyst-cooperative display_name: "Catalyst Cooperative" domain: catalyst-cooperative.pilot.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - catalyst-cooperative.values.yaml + - enc-catalyst-cooperative.secret.values.yaml - name: earthlab display_name: "EarthLab" domain: earthlab.pilot.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - earthlab.values.yaml + - enc-earthlab.secret.values.yaml - name: paleohack2021 display_name: "PaleoHack" domain: paleohack2021.hackathon.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - paleohack2021.values.yaml + - enc-paleohack2021.secret.values.yaml - name: aup display_name: "The American University of Paris" domain: aup.pilot.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - aup.values.yaml + - enc-aup.secret.values.yaml - name: temple display_name: "Temple University" domain: temple.2i2c.cloud diff --git a/config/clusters/2i2c/earthlab.values.yaml b/config/clusters/2i2c/earthlab.values.yaml index 3c52faed85..599e948455 100644 --- a/config/clusters/2i2c/earthlab.values.yaml +++ b/config/clusters/2i2c/earthlab.values.yaml @@ -20,6 +20,16 @@ jupyterhub: url: https://investinopen.org/blog/jrost-rapid-response-fund-awardees hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://earthlab.pilot.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize Authenticator: allowed_users: &earthlab_users - lwasser diff --git a/config/clusters/2i2c/enc-aup.secret.values.yaml b/config/clusters/2i2c/enc-aup.secret.values.yaml new file mode 100644 index 0000000000..528b329505 --- /dev/null +++ b/config/clusters/2i2c/enc-aup.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:skz582BMzIdoaU1ND/NrJQkkjwQVu84GjqkjLI3AR/9lwdXfC2V+Negbtlbg773rb1Wc,iv:yPgRHqrNW+wuNIPM/CCYJwiSTU4/elV9EUzsFi9SKB0=,tag:gKJyaIyeb0r5+KFMQbZTHw==,type:str] + client_secret: ENC[AES256_GCM,data:m6TikJ95O3HLF91G8Fs8SGiJsO2CRr0MD3vWKUvbMFeQYhkwQ/ImpN9gZ5fqvFhLIvMsdK0laOGo3DqyBmva99MVx/Rw19NuZtL+mVa7SOjjWRsnSHs=,iv:nSdTaoV2lNnNC6wHYwjWAZTQ2HiHPVNrR86EIcGwU2I=,tag:NkJxOB/OHu7faDID7/R+EA==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-09T11:44:08Z" + enc: CiUA4OM7eD9t5d2xJBjb7r71D2P6hJTJIWhxorOrRcXzzFFC8ZvKEkkALQgViKJNq8Eo+B/YY2JmbqCemM2QeDWoqCdsZzUKiFzGkT1h2fpW912Fk34TwmqFIzbUw6oHqi80dAu/0gOkgFfiu32R+gGG + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-09T11:44:08Z" + mac: ENC[AES256_GCM,data:1JJQvYQfzqY8JrBDbsXH2LMrehbWx+5RgZ6jIY5bh16bieot4+hCzKTSa8kqXKGmDZTT2s7X28e4V4yx9EzKterG6RYWZ1se6j8C23XeBti02ZLLPYESTTg6d7XhaiPm1UPXJNP+VoO3bIFqNqjlNkwNbdCu1zmhqPcgJ9k8BEM=,iv:H/61a0/E9hD2KPHU85LZF1gsVRkgExwCMiqJT6qHUdU=,tag:84pYDjFDQyyiywzUUA+QCQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c/enc-catalyst-cooperative.secret.values.yaml b/config/clusters/2i2c/enc-catalyst-cooperative.secret.values.yaml new file mode 100644 index 0000000000..6dbf5e8b1a --- /dev/null +++ b/config/clusters/2i2c/enc-catalyst-cooperative.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:Qlu4OJtBmg82qD1OTj0FVQDA5K8RRlpdUevtFBgchB6LAHj5CnepwMQz+hueJAZhNdZS,iv:i/cnfNw8PQmnrOt7oUt3KXxTkFGyqfXwMwrezQmMVyQ=,tag:YvMEbRdSeN6lJGffole6cA==,type:str] + client_secret: ENC[AES256_GCM,data:zcvVGpmoAe+DO7GIWX51S5xrdVVUAI2fZS9hLQVWmI0IzCOlMeOROT3m5gV000h7B2uaRNRICS+za6IhhwluLS3n6XTvjr1VNVl55EOeLbnA8LxgLhs=,iv:V4c0t42mU7I3GaGvcbT68BRdF4WlN8p7lLstuCzhH3I=,tag:RdesI/NlBvgGUv+KJMg0NA==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-09T11:28:16Z" + enc: CiUA4OM7eCrxQztzKJoFZfwlURj4g7zQWfVZmhEeOpoTMN+9YazfEkkALQgViPNv8VbN9gACA/5sGTKwpQHwi4svh9nL4C4oLlL6MDYx7h/nFBUWZxprv5aHJJVoS8vxyGa/s0N9OHKaOIkC3AtNb+Zc + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-09T11:28:17Z" + mac: ENC[AES256_GCM,data:KrlJ5uzMawcdH/r4M5QAHyINq3t04vHumrJFw/rRO5OSi5Hi3ZcrV++hJ4G+w9JmiX/qdkU5XkjQb6n3UNDPbS+V4pYSlcOpHDRWax2mH6zxszYNjgAwBOrXRLrfxW8x63LZhGkEu7Wx3rSkmdU9hPtPWm18p9cqmIcEN2QPbUE=,iv:G7qBVms1J5+N5jv8i6aGbI06pVVAtJOyI+xh9YKcL/Y=,tag:h5wWEZ1UvGODq1YWvjQv+w==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c/enc-earthlab.secret.values.yaml b/config/clusters/2i2c/enc-earthlab.secret.values.yaml new file mode 100644 index 0000000000..de06258e73 --- /dev/null +++ b/config/clusters/2i2c/enc-earthlab.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:3/WW8s2VlTTKnJyaxkRN1Yrk5RPjXfRJomW825kHIBgKTFZpK+4SGMu/PaFQtyIsP95/,iv:Bl8MU6rnkMsd2kUmkYL8IizsUUILPa8g2puZD0W6UIA=,tag:zR6eSdKD+WaTcQmeX+XCYQ==,type:str] + client_secret: ENC[AES256_GCM,data:8x/DKwk/hvfaWwL6wPd+QGJGmxEdqk08oYy0XQ9GnX5xGD3k6y8HBBTp5cBra0DqfqY5i+RjrXwUK3DWijtY2swFxJCqMZI+kwfVeepJiCCCax8wy08=,iv:kWVBaRxRZ0oi2YFCjNGh4eQ1D+GEUal/nkUoFrjtFuw=,tag:neV7YMR92W0qwk6LVf+lpQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-09T11:30:53Z" + enc: CiUA4OM7eJl4YgWBqTqA7ggpXZJlw1HbVzD0UZ5ybNFW1phFfn1BEkkALQgViGi77vVOktsKjyNLt7jmo5lvx4N1kDwsY3m9aCBn37HZHeMp/QclWyjB+22gDKd3h9Kzu2dm41kVjeBKVtX8S2Y9WtoW + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-09T11:30:53Z" + mac: ENC[AES256_GCM,data:t/6TB+xxxoIB5JN17h2V0fVTjIG5iaKqFAqJ8YGT5VlCkO9arMM0qgOkxolHY2OTthppA6TxJaUvAg5Htk1CfRxqk9bGbC19ibWGElLKRqEAfRfpjxqqNYYAXoxmO6tvCH5Le+q2C0uSGB9Xgf8AaBkBZPDqwWdzA56EFfrMiwM=,iv:O4Vf6jy/JZu99dYyOptlU3edSAshlUvSkSgC1nSvNXU=,tag:Pqy9h/r0mHPGK+/tCSxpgA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c/enc-paleohack2021.secret.values.yaml b/config/clusters/2i2c/enc-paleohack2021.secret.values.yaml new file mode 100644 index 0000000000..cc2ee7aa4d --- /dev/null +++ b/config/clusters/2i2c/enc-paleohack2021.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:tdBdkhm+8h0accu0gu930Y4224KUK8qRjQcEeYkYaWYPQT61qHjsIwzMmBCYDVvAXr7N,iv:KSpi6+OFiUYKHHN5PglEOMkXE6PtgpIm3zld/GOJipU=,tag:JxesDUscaNFEjF4L7FZhfw==,type:str] + client_secret: ENC[AES256_GCM,data:SEHHeF4wQORHVQpyKc+3FiFLsnvS/B4vLFOt2o/+GjujYyaQXGC1itUjwQbxUQu77D+qenJd6j8HCvaxUYrwNPplHE+CWzSu9vcndcf55oZYFsmK5dw=,iv:h4e5y3kBcjSsOVSZ4EkxycjSq5mKoYm7nSv4y+zg30E=,tag:T+3vSKHyweZ2+bep0dYDMQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-09T11:42:18Z" + enc: CiUA4OM7eJ+qGiJlGqyjGOvsLMNR0Te18trL06QAXrZAQ35S6LhvEkkALQgViBn8HJnnKdodELCgUHmuGWY+h4gmny2r2RRPcwkggKwzy/hYEHXVGqIePVaQPQygCtySk5HMGebZUTiUwhjYxnR8R4Jc + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-09T11:42:19Z" + mac: ENC[AES256_GCM,data:xfUpI9EiJs9fSD8KQsD3ufkhq7IVNm0CAQGhqPiHa7ZeeNa7kC2mu7p89WVa7jB0vorcuAtx+Q7D+x88E74sFjx283uslNK11nS2RQqpyJObP+fAHm3QHSz37bfk0j6zOlmuDib/TlkHdE4MAckAZJeLeoMvBY64cof3HS4n+5k=,iv:thkN1Kb2SD/sYkoMHjr5kAbMq+FIVRbbmYGqm2fFIQU=,tag:KZuY5GZAioRCkIScBCowlw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c/enc-peddie.secret.values.yaml b/config/clusters/2i2c/enc-peddie.secret.values.yaml new file mode 100644 index 0000000000..adb6bae48e --- /dev/null +++ b/config/clusters/2i2c/enc-peddie.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:bHSpEgTmUndOoJqzuQ+I3EpuU+S5FO/ctTnpPynd/OszZfYaw25OTDDCJW9gOJqxgFwz,iv:0s1VN8eWejq8v315zf/zIZcnNu1u/1iPK0iMRqv4U/Y=,tag:iWpX29FUtusHC34BEYmDXw==,type:str] + client_secret: ENC[AES256_GCM,data:riGTTau9qdpLLPshexdBKpAn5wCUbWl4B8MapjbsawDnmp0JB6zEnH1LqlWA/IQcIbdVs7zcc1iCw4xzJzIeYewS0gETFZsD4k9fGz0WHI4Sru7gYDE=,iv:ECx/1glC9SbEQHT10IDq3izfZ0w6zDhNhN78OjRjv1U=,tag:e3yHGrxci9SjTgw9dsRIgQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-09T11:26:18Z" + enc: CiUA4OM7eCsDSLt6InApBvcg24KJolYS9WLcu4rwIGe6FqMNexLsEkkALQgViC47iAPmkKjCADJEUFvfH+htD+mjyTTsYMOexSrMGvYxRNNVZO3SDA6OfFiIivBK7kdVVk5dRYfX/Zettpx0+hdCCeOA + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-09T11:26:18Z" + mac: ENC[AES256_GCM,data:d+sd+igriHtObkVcMz43d1ruk6h7pDcTrNzkyGCXnVpphFtyWJBZkPC6QTsZy2ca+6dmB9VK33eqwvgBG+Ppb5DN9xhYxPzVjijgv84/+7ombES+3c+bAKxKIwONtyclJ2ZVCCKdgBiHJlgwKwrvmDs1Q0hxxO948KcRVaEtW7Y=,iv:KvlB95xE8ADhFRnRLsrtqHStdddzdno7iObdPApUHK0=,tag:XnTJ8PZlU+XcAEgqxO3E9w==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c/enc-pfw.secret.values.yaml b/config/clusters/2i2c/enc-pfw.secret.values.yaml new file mode 100644 index 0000000000..805f6e1159 --- /dev/null +++ b/config/clusters/2i2c/enc-pfw.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:4FSmYZ6OiQP1B+43wHlzO9VHMfJPKxfKxH6W/GBuAleyp7BFn91151dS6+YN/cSivwgC,iv:1KGdpRM47DUsGdrV8ZkUQuRV82oFXxiAV0UZijYJKXA=,tag:oj/lYmWMHOt7NpLCP6PN1g==,type:str] + client_secret: ENC[AES256_GCM,data:E3JiAxfB/8L1GXzvZxEK1PoX2ft67eDShKPSyqNQdbrUmUrzebuHaCObFP0Dfr8tFXBWPlvN3X7RXXt9VMeFxCV0q3MECmdKGLwlML1hWSlZKemDLNE=,iv:h9kkTzPExnn88UJS0sKsGfYikY/YqkR7CyixBVJtcr4=,tag:cfspCQuGmlRIRdkRCQfdbA==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-09T11:21:27Z" + enc: CiUA4OM7eBjOaqEY18nDzOArcUN3ot6bWO6eRt6z/WMN+9dAcm45EkkALQgViD9hreey1Ktl+EPN5zr/WWA+P+BKx3LlQFT+kcqiIeAjFxYumbkgTtaQx659L22n0pMrtLRTptgK6pvasMM1lsVvduIt + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-09T11:21:27Z" + mac: ENC[AES256_GCM,data:BPV9gmeCF/YZ5nUOgFEQrlBIPdSTgZ5UZF5ivBvTVF+8QjTfgkCf+CK+UnuHn7yKvUcTXulfnnLbt3AVbV1tPPPuLxDYJCLc4qql8lmChZSz6YUZ26dxo84Psl3S3VuzKohdsLW+6oXHeHVe4W1E5JEgvPHmRaaCUkvxojrSMfM=,iv:+2Wc7J9HiJijwNVpzsritSyPU7VoxafPj+8H+vUyQLQ=,tag:FDj64UXxSMBtlaABw8FoLg==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c/paleohack2021.values.yaml b/config/clusters/2i2c/paleohack2021.values.yaml index 344933eb21..94e4738b67 100644 --- a/config/clusters/2i2c/paleohack2021.values.yaml +++ b/config/clusters/2i2c/paleohack2021.values.yaml @@ -33,6 +33,16 @@ jupyterhub: tag: "9d557294938e" hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://paleohack2021.hackathon.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize Authenticator: allowed_users: &paleohack_users - CommonClimate diff --git a/config/clusters/2i2c/peddie.values.yaml b/config/clusters/2i2c/peddie.values.yaml index 9cc9975766..61625b536f 100644 --- a/config/clusters/2i2c/peddie.values.yaml +++ b/config/clusters/2i2c/peddie.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: https://investinopen.org/blog/jrost-rapid-response-fund-awardees hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://peddie.pilot.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &peddie_users - rbennett@peddie.org diff --git a/config/clusters/2i2c/pfw.values.yaml b/config/clusters/2i2c/pfw.values.yaml index 3c3997bc62..6769a3df53 100644 --- a/config/clusters/2i2c/pfw.values.yaml +++ b/config/clusters/2i2c/pfw.values.yaml @@ -20,6 +20,16 @@ jupyterhub: url: https://investinopen.org/blog/jrost-rapid-response-fund-awardees hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://pfw.pilot.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize Authenticator: allowed_users: &pfw_users - colliand From dbe267a83d5c1caf2de5ecda8634b63a6cc970ce Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Fri, 10 Mar 2023 15:31:02 +0200 Subject: [PATCH 11/33] Move 2i2c-uk hubs from auth0 to cilogon --- config/clusters/2i2c-uk/cluster.yaml | 3 +-- .../2i2c-uk/enc-staging.secret.values.yaml | 20 +++++++++++++++++++ config/clusters/2i2c-uk/staging.values.yaml | 12 +++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 config/clusters/2i2c-uk/enc-staging.secret.values.yaml diff --git a/config/clusters/2i2c-uk/cluster.yaml b/config/clusters/2i2c-uk/cluster.yaml index 24803b63e0..504a0c6c14 100644 --- a/config/clusters/2i2c-uk/cluster.yaml +++ b/config/clusters/2i2c-uk/cluster.yaml @@ -14,10 +14,9 @@ hubs: display_name: "2i2c-uk Staging" domain: staging.uk.2i2c.cloud helm_chart: basehub - auth0: - connection: github helm_chart_values_files: - staging.values.yaml + - enc-staging.secret.values.yaml - name: lis display_name: "London Interdisciplinary School" domain: ds.lis.2i2c.cloud diff --git a/config/clusters/2i2c-uk/enc-staging.secret.values.yaml b/config/clusters/2i2c-uk/enc-staging.secret.values.yaml new file mode 100644 index 0000000000..5b1f06fe27 --- /dev/null +++ b/config/clusters/2i2c-uk/enc-staging.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:OulkQLtbaZZUvZFQfR1fiuWkoQdvZaJAh+Wphg3S9YxSXZOnRNy23hN3Ui2hnazX8wLL,iv:TZOmXllGA4GvE2azJd7IwhypwC/D6CLJg3CweX3R7wE=,tag:DnCyr5eat32g9B4AlCVxRg==,type:str] + client_secret: ENC[AES256_GCM,data:SLM8V8HIBv+nMozwdpOhO4NlRvYae+fhVO4IhpHnnhZ8BGnsCot0uad+tklFGwyoR68vddX9yun0qHwjfTzlaOHENkkwXkD52J+TIeRVEJOdrwQPvJs=,iv:ApMDFnSLqB4KHknvpJcCSevmptKa9tZyAnjMBqkr9Is=,tag:bQN0EYyHMTaIwZyzWP5ZOg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:29:59Z" + enc: CiUA4OM7eBQfi4RYcpwuLJXamh/i6kVx2K/y87f+PgIjWXE1dngFEkkALQgViKjrMGaTl3ZxlgCkKZW6xi6GHF5taiqSLl3IuWSIivslyCbld75Em6NhFiBaoNQrj+LLxGs7DIfUT6S+RSnJ2QyGbSrd + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:29:59Z" + mac: ENC[AES256_GCM,data:kuFGqPRbS7PUZLos+29gXZklEz6RXfNBDQP2Kp8yYHLObvNxp/ZM3PPp5wQNCVbZjFN6QJIl3QnsYcrZR9uRplD1G9xVUG1+ZIpieZp4oQ6iprCJ7K0tMbA1yrb1kcpSNWFILzUt65XgqcCWyV7aGIuevkTq071zyfDqNR8GR74=,iv:U/B/KPQxkDLAkxgFMGiiCflVqe6q3rfG7KG32mliAVQ=,tag:efK5tPKMlebap6dQ5/GgfA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c-uk/staging.values.yaml b/config/clusters/2i2c-uk/staging.values.yaml index 6e7ae00c94..2dd7586b4a 100644 --- a/config/clusters/2i2c-uk/staging.values.yaml +++ b/config/clusters/2i2c-uk/staging.values.yaml @@ -28,3 +28,15 @@ jupyterhub: funded_by: name: 2i2c url: https://2i2c.org + hub: + config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://staging.uk.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize From 6aaf39f5ba22b10fe36010083562a7e2ff66acc9 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Fri, 10 Mar 2023 15:57:29 +0200 Subject: [PATCH 12/33] Move cloudbank hubs from auth0 to cilogon --- config/clusters/cloudbank/avc.values.yaml | 11 ++++ config/clusters/cloudbank/ccsf.values.yaml | 8 +++ config/clusters/cloudbank/cluster.yaml | 60 ++++--------------- .../clusters/cloudbank/elcamino.values.yaml | 8 +++ .../cloudbank/enc-avc.secret.values.yaml | 20 +++++++ .../cloudbank/enc-ccsf.secret.values.yaml | 20 +++++++ .../cloudbank/enc-elcamino.secret.values.yaml | 20 +++++++ .../cloudbank/enc-howard.secret.values.yaml | 20 +++++++ .../cloudbank/enc-lacc.secret.values.yaml | 20 +++++++ .../cloudbank/enc-lassen.secret.values.yaml | 20 +++++++ .../cloudbank/enc-mills.secret.values.yaml | 20 +++++++ .../cloudbank/enc-palomar.secret.values.yaml | 20 +++++++ .../cloudbank/enc-sbcc.secret.values.yaml | 20 +++++++ .../cloudbank/enc-skyline.secret.values.yaml | 20 +++++++ .../cloudbank/enc-staging.secret.values.yaml | 20 +++++++ .../cloudbank/enc-tuskegee.secret.values.yaml | 20 +++++++ config/clusters/cloudbank/howard.values.yaml | 8 +++ config/clusters/cloudbank/lacc.values.yaml | 8 +++ config/clusters/cloudbank/lassen.values.yaml | 8 +++ config/clusters/cloudbank/mills.values.yaml | 8 +++ config/clusters/cloudbank/palomar.values.yaml | 8 +++ config/clusters/cloudbank/sbcc.values.yaml | 8 +++ config/clusters/cloudbank/skyline.values.yaml | 8 +++ config/clusters/cloudbank/staging.values.yaml | 8 +++ .../clusters/cloudbank/tuskegee.values.yaml | 8 +++ 25 files changed, 351 insertions(+), 48 deletions(-) create mode 100644 config/clusters/cloudbank/enc-avc.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-ccsf.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-elcamino.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-howard.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-lacc.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-lassen.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-mills.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-palomar.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-sbcc.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-skyline.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-staging.secret.values.yaml create mode 100644 config/clusters/cloudbank/enc-tuskegee.secret.values.yaml diff --git a/config/clusters/cloudbank/avc.values.yaml b/config/clusters/cloudbank/avc.values.yaml index e02399fefa..a58cbc5bc1 100644 --- a/config/clusters/cloudbank/avc.values.yaml +++ b/config/clusters/cloudbank/avc.values.yaml @@ -32,6 +32,7 @@ jupyterhub: scopes: [read:users!group=section1, servers!group=section2] users: [sean.smorris@gmail.com] config: +<<<<<<< HEAD loadGroups: section1: - sean.smorris@gmail.com @@ -41,6 +42,16 @@ jupyterhub: - smorris@ausdk12.org - kae@gmail.com - ciara@gmail.com +======= + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://avc.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id +>>>>>>> 1bf0e48c (Move cloudbank hubs from auth0 to cilogon) Authenticator: allowed_users: &avc_users - aculich@berkeley.edu diff --git a/config/clusters/cloudbank/ccsf.values.yaml b/config/clusters/cloudbank/ccsf.values.yaml index 958e147cae..7315d26953 100644 --- a/config/clusters/cloudbank/ccsf.values.yaml +++ b/config/clusters/cloudbank/ccsf.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://ccsf.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &ccsf_users - ericvd@gmail.com diff --git a/config/clusters/cloudbank/cluster.yaml b/config/clusters/cloudbank/cluster.yaml index 506b7dc185..34aabecf26 100644 --- a/config/clusters/cloudbank/cluster.yaml +++ b/config/clusters/cloudbank/cluster.yaml @@ -14,28 +14,22 @@ hubs: display_name: "Cloudbank Staging" domain: staging.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - staging.values.yaml + - enc-staging.secret.values.yaml - name: ccsf display_name: "City College SF" domain: ccsf.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - ccsf.values.yaml + - enc-ccsf.values.yaml - name: csm display_name: "College of San Mateo" domain: csm.cloudbank.2i2c.cloud @@ -50,15 +44,12 @@ hubs: display_name: "El Camino College" domain: elcamino.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - elcamino.values.yaml + - enc-elcamino.values.yaml - name: glendale display_name: "Glendale Community College" domain: glendale.cloudbank.2i2c.cloud @@ -73,15 +64,12 @@ hubs: display_name: "Howard University" domain: howard.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - howard.values.yaml + - enc-howard.values.yaml - name: miracosta display_name: "MiraCosta College" domain: miracosta.cloudbank.2i2c.cloud @@ -96,15 +84,12 @@ hubs: display_name: "Skyline College" domain: skyline.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - skyline.values.yaml + - enc-skyline.values.yaml - name: demo display_name: "Cloudbank demo" domain: demo.cloudbank.2i2c.cloud @@ -129,67 +114,52 @@ hubs: display_name: "Lassen College" domain: lassen.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - lassen.values.yaml + - enc-lassen.values.yaml - name: sbcc display_name: "Santa Barbara City College" domain: sbcc.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - sbcc.values.yaml + - enc-sbcc.values.yaml - name: lacc display_name: "Los Angeles City College" domain: lacc.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - lacc.values.yaml + - enc-lacc.values.yaml - name: mills display_name: "Mills College" domain: datahub.mills.edu helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - mills.values.yaml + - enc-mills.values.yaml - name: palomar display_name: "Palomar Community College" domain: palomar.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - palomar.values.yaml + - enc-palomar.values.yaml - name: pasadena display_name: "Pasadena City College" domain: pasadena.cloudbank.2i2c.cloud @@ -214,28 +184,22 @@ hubs: display_name: "Tuskegee University" domain: tuskegee.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - tuskegee.values.yaml + - enc-tuskegee.values.yaml - name: avc display_name: "Antelope Valley College" domain: avc.cloudbank.2i2c.cloud helm_chart: basehub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: google-oauth2 helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - avc.values.yaml + - enc-avc.values.yaml - name: csu display_name: "California State University" domain: csu.cloudbank.2i2c.cloud diff --git a/config/clusters/cloudbank/elcamino.values.yaml b/config/clusters/cloudbank/elcamino.values.yaml index 306b4a9012..4a2e24628b 100644 --- a/config/clusters/cloudbank/elcamino.values.yaml +++ b/config/clusters/cloudbank/elcamino.values.yaml @@ -25,6 +25,14 @@ jupyterhub: guarantee: 2G hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://elcamino.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &elcamino_users - ericvd@gmail.com diff --git a/config/clusters/cloudbank/enc-avc.secret.values.yaml b/config/clusters/cloudbank/enc-avc.secret.values.yaml new file mode 100644 index 0000000000..72ad5001a1 --- /dev/null +++ b/config/clusters/cloudbank/enc-avc.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:CEhT4qAMF6wgjpKKYgC+8xKihU9TXdtDQ0FVYXCRQ5oQpLS/2+qQWVEbu7hr/U7pB1gH,iv:3yffO1+QsWyGIumZLqy5LFU+R8FAHPcpXNCidQoQm7k=,tag:gd353pGTrk7q12SBbj6Q9w==,type:str] + client_secret: ENC[AES256_GCM,data:+MdMqUzst56KLwQae3/khShRPw/rGj1VRwFAXiQTgI8ciP7bv5mGCWB6h/JZG3x0cUFxRELjvjzSAqG+4p1hFnJYdocT/PW3Bbu1NR7uLujSeeBb6aw=,iv:DT3bApTO3Cwx6eMAXQB8IKgcrVCOhBZtKSeBBD9z1rY=,tag:qBVUbXEdT3OeqIjziDU8EQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:49:34Z" + enc: CiUA4OM7eMxRVksfqzh2TdJzwJN66JQkRKZQqx9CY2yejzf2im47EkkALQgViIfo+f++sm3WPResRYXcZ9ED3CL3JdwgLRNmvgknfTZWNde8hLJC523qwd1c1Ca0m22N6UWW0ws6QRNebvTCtKJDWFRv + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:49:35Z" + mac: ENC[AES256_GCM,data:nfoChvhb8XNgsUcG3gFV4dA7eMXZu0uIO8jbaPIRURijXSc3m3vmCr6h6meMOkRrpyS6thJtFPZXEeALJ3crulIlL9/H6hrmSPQvtEDsDvxgwv2tWjMoDwdKNNm+x58YzEskBOORUeU4+ba3cIjZJeET88HpnciV93rL7ZqQeAA=,iv:6552s1r4D3SomxdzYQUedmBgnH9Cryf1BxhyTpppHzw=,tag:pzYXR0b3NjZ6S9LQx3rviQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-ccsf.secret.values.yaml b/config/clusters/cloudbank/enc-ccsf.secret.values.yaml new file mode 100644 index 0000000000..b86850dc08 --- /dev/null +++ b/config/clusters/cloudbank/enc-ccsf.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:JoB0S4qKxtOcvkDHDmyVLDMFuzOBiyDvUzCmUkSWwHyEjSKLlIEkgyjS7lF/DWomF5iJ,iv:qT3NFIpFDlRKGlL8SSxZ2WIg4FX5Gcb08T2YZoj1stg=,tag:2P2jYWF4YrpZdJD4SvVJjQ==,type:str] + client_secret: ENC[AES256_GCM,data:fnLFTBBuOpgSRmNl6mxDK1zMv6fTBwOyg5QFRhjZmbfXLbbjv//mGLRPxuQ87viwGPPc9pCuGWrWfD4MRJ7+Rsgrjv9kqgJA3LnKc7E34jBcRHNJ690=,iv:KMzEhnmEztaNVCc6HEd3hPE2ghR3whaRph5rYOB5PMY=,tag:sCG/iKeSeCwis5gEHLO2Jw==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:37:00Z" + enc: CiUA4OM7eENb3LFyS0KZEpd4qfxU/eGKgG3rR9BFgpnL4uWBpac6EkkALQgViEoEQf3cbZwDGC62RNOPNr9hlpScMVAJxXvAr1o2SylMxWeSMXHXk45ONpxZmUL80SHo0Yiakny5qFp2zfMxOotB7td6 + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:37:01Z" + mac: ENC[AES256_GCM,data:IWTxVp55KRYOuiMJz9oi3RsFSbkXazfTkOvlLY1dw/iHSJq/cQEVHnhdQwNsIazAbDjOs7LJo6Ffna2QSSVHfyIPcqaWnLU/GR02IPZ+/QOjyYi6QY3oltONPNhpSKXSgV2uEEi3TfKX/HhrBEC931ztqfgyv9DS5sQkwfgoKgA=,iv:De5bvzP5tpe+8ZW3O2viOWHVkECQddu6tcqm8UWfmh4=,tag:q7bp5yaT1SV8QQ5soPV0FQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-elcamino.secret.values.yaml b/config/clusters/cloudbank/enc-elcamino.secret.values.yaml new file mode 100644 index 0000000000..cfa43aa327 --- /dev/null +++ b/config/clusters/cloudbank/enc-elcamino.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:mhtNzhpv8Wo9dWrELvuiceuwRDjdW6zeVR3T3LlP/pFgXMf726IK2FIWtsS6KlwSWvw+,iv:ShNdhGivQkRqHRUBLau+/D/IyMZarcwaPOsXcL20T0U=,tag:+vFxLLWVSM6KzADZmp17oQ==,type:str] + client_secret: ENC[AES256_GCM,data:GCtevet+pbL5X1MvjWtAYMenatZUl9BJNbmYV4GYT6ZkXRnHGoIriY6GwNOUIaTtsb7SzQFbBrThgFC70Kut6EBvZ8rpEMIBkyMf4xyeNV8rm7+hzh0=,iv:wjFe3WXnXXzzxvyNoKEwtUmHRnHXn6mj/WdePhC9W/E=,tag:srYg9GsGe35qQTVnRfp7Bg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:38:30Z" + enc: CiUA4OM7eG0PUZWZ5PhjBXmqzFMVUxFss3Qa/pk9AzIgXd5XCVO1EkkALQgViJobxsfWsojroy42sJeXvZUtlZMi9qPzXE0vUO9JWFVWtjPHXeMCf7x8gQdH9QMjCKMZ5BlwYtXD7WFEpBINu0HGCdhV + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:38:31Z" + mac: ENC[AES256_GCM,data:PgWrkixpNr3hdzS+zI9G3L91vNVJz6wSG5FIhbIarA62OeGeM1YXmeQ5vcG4ELmRxNRpLekI+TLGbZt4gqh07BVpamoKlK+4WXelILsZ97N2dXrTGxTWG+upiSJjRx3QZmlbVaoW9/IyLZdHAZGDSEv3z+zUFre/naZSHrs0q0g=,iv:crvsUIYSoEULbW+dWPYFiiz7jiRJLCzM6BJQOrsOUn4=,tag:T20oZxGAXWzX+vg1Z3ONLw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-howard.secret.values.yaml b/config/clusters/cloudbank/enc-howard.secret.values.yaml new file mode 100644 index 0000000000..e6f06a227f --- /dev/null +++ b/config/clusters/cloudbank/enc-howard.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:cZONUUumhmXLv+i6aY3TVLQzqlwmvdDSD8h0WiCvd2S2+FWDyJnIjEmP+zhqd1NtuSgM,iv:oX44Wz/lgOV7URIwCGMtycv/hnP2/BgukICm9fLIB7g=,tag:fYeEVuTMXJUiPS9SDp0vrA==,type:str] + client_secret: ENC[AES256_GCM,data:IAd0AOQfguoOuzYvcPNWhnIVr6GJWWzcXfb3ebK1bdkHxu6Nb2RxXQbh9p3uCYOBrcnVx9B5h1GtDbBCJq7tmrDWWWtUgcHNOphVtV7t/0zdRARiyls=,iv:sIK7IWV/p/8k6F3ueY2hYuoNOegn45bcYepwL+Qv7No=,tag:ew+RhxWvtDj68JO8ETAPdg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:40:04Z" + enc: CiUA4OM7eMcqBCnZ5DfMuBk8qy2yfn+2XeNISme5NSQggstW5gOPEkkALQgViMP4NYSmWaN98idFR+sZIYPy/d74u2nfn0sbOp1SC55MqD+62t6qA0lij5iMjp1JD8UdZQsJpTBeUkaU1Fh0DDmlAln0 + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:40:04Z" + mac: ENC[AES256_GCM,data:X5hQcL2WpMwintQAkIhOKqbAL5KzI7BQ3h1C3Q97djdpdZOtsi+nTJwsWaWKwwduDEu9zYAIOPTpESOps2STq2FEMZv7M54Bi+2f1kGbCebdYLwtL5Tig3jfyVQL5FiomfyFhOY9opt9rzfgWNGM3QuSi6gOqTvZOLR1dXTD9n8=,iv:1LkyHDjFWn3ztiOLon4vjHXQeITVCkZwdLjFu8whkfk=,tag:7IUaT1jvHr/fkL+ddNjh0w==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-lacc.secret.values.yaml b/config/clusters/cloudbank/enc-lacc.secret.values.yaml new file mode 100644 index 0000000000..3759baf27e --- /dev/null +++ b/config/clusters/cloudbank/enc-lacc.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:llZ3GJJ4M3Y/TSUrjVmiojDJmmvdGyvc06cONP82B/wCPZmp9XlcdnDzD272lJ/TN2xt,iv:/Tq9UMGSfgM2ldihhFIcGuufC9PqDCIvwnPiBMpe5Ec=,tag:O2B6vvEHWrq6sNGyZdPJ0g==,type:str] + client_secret: ENC[AES256_GCM,data:UIvoIoOSVdVtlImiunfbs9Bp/uRFr1wen1N41ZfhI32Xd6JclhQ3iRC4/q5U4dJgENCCR/5bA74BGOjF4CR7GjjGrvPn5K9RBApRV7trkW7cPKmYAZ0=,iv:SlPgs3WCSIQFkNIV0u/eVAH9g7ndBsFrZSa6Uszt68I=,tag:fFbTUrqedQL0YFbFisPYlA==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:54:15Z" + enc: CiUA4OM7eOcvzwYL4sZmciC3rC5oVZVOn9yFg3T7FKkm8ctBxOutEkkALQgViI6gQP44hbX+j8zQdUxd55552CIS9pz6swxwc5dLoIKnTjjQpbD9DBlhZITtjy659EUPmJBMULMAfA5TxbVzo6mZ0NBX + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:54:16Z" + mac: ENC[AES256_GCM,data:x2wFpjECISD3zXpR+vecQIeyQmWf+vYThjss96a/hdJ7J/cuB6fRc3mg+BnmStJEHjrvJ2+OFCNT01w/k7XOvRh6qXXVzc24RrWN+kiGVnYowA50wA1JoDk/Nda9jm+YiBAoq+EfBheOKm2Ls+KSAeCIoflcH+sMYgPGgd1gZ+8=,iv:nw4f2LNNP5fw6eRa9g6fTb4WxVXewRlGOC09R2ckDxI=,tag:tKl1qjwxKooZK1Y2ZJWxbg==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-lassen.secret.values.yaml b/config/clusters/cloudbank/enc-lassen.secret.values.yaml new file mode 100644 index 0000000000..043820b145 --- /dev/null +++ b/config/clusters/cloudbank/enc-lassen.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:WQkpVeWrCBf8axpsO2UcDpVnBJz9YVw7gZypivhWUf8hJOQg1ChZppVlWiig8xxSEmg=,iv:T4jzBI4YorW62njLGYOo4uxmzNNc7UVpG+ouTJRaMBo=,tag:Tjn+7LzF3ie05wPEnhXIgQ==,type:str] + client_secret: ENC[AES256_GCM,data:MpPCl+hmPU8X9QXVa2mpqUobipegOQaIrdU7oVIYIgLH+3kfT2V51DK7ZjRAhou23UM+Rb7z/TT5mb9qLXvz2rp9p0WVAccW7A4m+bWcwVfZH6ELIgI=,iv:e2a3wqBrF3HwlfJ7X4UFi/So+upXq2gaACeaPslK0E4=,tag:Ea4qoW+9LbPxPz+kmBIysg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:56:19Z" + enc: CiUA4OM7eHs1Ioue/IwgTGXa6oyUunjQ0S2tiDpYV6KpA6aEt63NEkkALQgViHU3fTuuf0rMA65kYDRY8sgnsNxdqDHxkv1PRul69xARUzP66JvzcgrBbZ+8B1JaRBOJICcpnKcoRJIPbiDIeCTqCKA1 + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:56:19Z" + mac: ENC[AES256_GCM,data:HVXEov5mRmFEsR5qMv6/fPmECu2V3bm1sivYiD9FUwjLH1GIDdB+JmBpTrrJzkBBm3Ev1uBUgj45PbGNtGpNaYDe6SWiPg4Wu4w93Zm63YTOuxlmZESrF6rxpOfz48N5Tl2sEGdGpWvG2CXsYrrgWkgAPDNToBdpi9nVoe+aqBI=,iv:7lZi//dEGIA6U22JpSSbvj4znEA072J+Ihwh4uAGCTg=,tag:TMJb/yVGURnulrmCcnFbKw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-mills.secret.values.yaml b/config/clusters/cloudbank/enc-mills.secret.values.yaml new file mode 100644 index 0000000000..0420fdb1cc --- /dev/null +++ b/config/clusters/cloudbank/enc-mills.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:7OGjugoiRyepvfRYbGSYa6+4HHAtLh+ZUUXaP1Ir0vaoPBS4uYmnWWGJxPEAt7+G0RSv,iv:St1ZHRXWNNmxqwwLFt6KkFj3hTPqZmUtmE02ZOs7tuM=,tag:QYXJjOjkh1/7FoGkTMiFyQ==,type:str] + client_secret: ENC[AES256_GCM,data:uYKy56h0mTerlJn4b40W3UeNKihDqBjprZYN+xRtEPM4h4L178SUL63ZzirxyqJqLDCiL1Y27gKJTQIYQrjiOzJDP707S+spK35xIW4FaEe8glvpnNY=,iv:XRzmYWdfUFKs8TkRu1reBph55fRlru5plb7KWBMgJtU=,tag:qaWgluL/N7wpjgzT2ufz9Q==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:53:13Z" + enc: CiUA4OM7eE5chuOlh9xXCHyZpMuz4AAsOwe9Anei0E4Jn+06L1KLEkkALQgViEHZyJKn/MUUyDRWfTIo1pps9Y/PRQOgq1HDSMXIli0ZfnCfSscmDyCWVhcTcgpvNVFg/BCJtb0Nc7FiFCXMCdOUtQnI + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:53:14Z" + mac: ENC[AES256_GCM,data:H0LDrHt8SjwvISxGCmoXhjn1rb/3zYZC9woJPrcc1EMAF/TtEXJDTyBrjNURnG0+U8eyK6l5/rYEyY+DBVFYW69QENTFHm/ZO+PmCNjRzWCYCDN8RBkN+EG1k72lokCuFvjo9wIHeVilqEcxD3PtBO4ErglRkOid13btimEeHyc=,iv:Rbv3kBZv8XRIlGVwtaxz1vKqc7OXP4QlK6WNBvKPXGM=,tag:q3v2IyOoaWI9MMzNqosftw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-palomar.secret.values.yaml b/config/clusters/cloudbank/enc-palomar.secret.values.yaml new file mode 100644 index 0000000000..74a5a39199 --- /dev/null +++ b/config/clusters/cloudbank/enc-palomar.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:vP1OiD0XQTCyclmbLELgf0lu+E+byLMHDAXX5QyWobCBG+6BYjdToouLvkHIlzXbEq2r,iv:uch5gwkOty3zauXBpfFFu2n2KqYmOT9d6m6yXQCMNMo=,tag:RbZmpO3QcEucrmhDIbnf3g==,type:str] + client_secret: ENC[AES256_GCM,data:Anw2LKLPaYMhADhA0r2zlPIE5Zte1N7Oqg1cMlbpF89XoGIeOPa4iThWD7W82HXFVIaDXi2anqlNP1yqVZU3/cn3hGKiUlXqlXFB+Znv+EVw+Uj/nko=,iv:CbFIEeNKDw6pTfYspnJ37E1S+X+6ClxaQbIs5+sSXOI=,tag:N7kZlNpn/CdAUCO8PLUrgg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:52:02Z" + enc: CiUA4OM7eDZe3TpdZxcCE6BvLcW6wEX4Imt5lTapdACvir6YHseTEkkALQgViL+wpWR7FRV3OyNkr5g8hrVSanpdDB1CPSqevac8d+lCytst4O5MiQj3vHt5K6hq0QMHKe83LCxulAz+3JIfpYoX2JIh + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:52:03Z" + mac: ENC[AES256_GCM,data:5GXX/i1i5dnBgu9u3BVaJ3D6VHbatgNn8oGFdtSpQoQcfTkG0exAvT6mXDh/E9Ux0MzMJZPN7OmwHNafISq/iwhPeahFikZGPYJI8PFeFKH9vWfUQwlMleYGqLgD3C9ig5JQIS/bxrT8wmIYc0bdhmLW6YJ7WCvZwywtPj5tk48=,iv:FunnWPMkubTOeBCo96iubBdKUJfUdA3ZKcP/wIhcRDI=,tag:5lZ3BjpKam0VbBVSOxabIA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-sbcc.secret.values.yaml b/config/clusters/cloudbank/enc-sbcc.secret.values.yaml new file mode 100644 index 0000000000..2159dc4016 --- /dev/null +++ b/config/clusters/cloudbank/enc-sbcc.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:I/tk2BCD9vIH6Nl68203LXZ3Pol/HmP4+vcTkXQJ5vDr1zfD16Pnpx7ssRAPThA5saER,iv:SXbf2qbqlE+JxQ7nm7ZBOqBvwnJmizKtnD/7j3cXd+Y=,tag:rSCaqzkEha5KCj6OKZJgPg==,type:str] + client_secret: ENC[AES256_GCM,data:AdK+mNLtMZUD382xRRDxc8Zh5g4eaFTMxN0uLCFN0oDcBjlQLnOYyTkKeo8EWQJAZiNe/4ODDHkhc8KAF3CrMDsU9kfBb0zME4yg/+j54DvoheQgTGU=,iv:RMwk/vD+DSZmlYFpqm9YIyJAzXQqORAEJ+e9zb91CCM=,tag:eWOzUXbUj4XnMzUpibLZGg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:55:15Z" + enc: CiUA4OM7eN0pYO4+jSk/uhx/Ci17uaSOxcyeOdxNFh4VOIiSj4ikEkkALQgViPwbrmVgS8k/yz3CiFqTNRsClBRTM5l/sQ9dGi09PKPq9aIg2eZClK5mDhVMxPoNjHWj/G4JjikpYrjABUMRgcJpfYWG + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:55:16Z" + mac: ENC[AES256_GCM,data:ldntPecmMkytYZKyldzsOqaxt7NNOE8aeDqF9Td58Iv6poQl2tmOQiwt7fpoKMg+dYRVS0IW09UJ8evDErxeauLXvyc/QEzdKUZvKRjrhFbV3om2vNQd8sK+7gQ1vRd1pGucyrlrAVDmMJe02I4xTLZSOkHQAuVHtoJ9d9eaNoY=,iv:tyfi2G1egQigimq7h4aUVVr40A0YJg6x4fq2Cqm8/MI=,tag:6aRzAb1TPoml4fyvfwGzcA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-skyline.secret.values.yaml b/config/clusters/cloudbank/enc-skyline.secret.values.yaml new file mode 100644 index 0000000000..c4e14b24ad --- /dev/null +++ b/config/clusters/cloudbank/enc-skyline.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:N1eQH8M/wdCODIp5GyHtccc3If1STyWm4kVmsRQvSNj090iLgHaWskbpF3liNyJrC7Z3,iv:Mna2Q8kNUdojulXoUwuIV4E8Ad4H8rae4/vL2KFPbhk=,tag:DiUzQrM4/c7iy613LRagrg==,type:str] + client_secret: ENC[AES256_GCM,data:m70L4vY2OKVjp1+nyx84HJpsYCSq0LAQUlWAc3g4/U8Ju83xdOI3YkLK2yKGdDGJM6c0wJBPf3O9Mjlk+tfZenCI6KUPSkgFYnuQ16TOd+o3JN+9HdI=,iv:MA2ODGeAk6WnoZuy5Jo0VFy8dHsOrz2PI1y+ZSDFO9w=,tag:Ywg/PlLIWY7LeWOa5Xn2fw==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:45:38Z" + enc: CiUA4OM7eDUHozGolT+xsDGCnh6bjdPgEqIvVe8D05NyZmuBP7dOEkkALQgViGlDZU30CQlNLV67b7YXIKp3Qe2sLM0b7V66GM/1bkbsMrnOXda39vpY7WPfSw+HZExo1jy3TBgKB2s85X5aCWs8e8EJ + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:45:38Z" + mac: ENC[AES256_GCM,data:X7DcK5kxwgtybl21FS9NsOIMgRnKGnj3ydoRqU7YQID0twiNMRRcRrw4KsMsV6t7ez/qTXP2R9lIMBf059lrwL+hsezTZzc6u5MN5e68fE2hymZgpy2frq4kyMa4ZVJFrJjFZeZJWQPJ1UC58y1oT16Rf85xY9UZx+1KEqEMhpA=,iv:drWC+MXA7I4UkSTzR2/YQv1xQ/TCQWfC80B3CsWKjo8=,tag:qwcSG3n6AdPRDyUu49TnmA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-staging.secret.values.yaml b/config/clusters/cloudbank/enc-staging.secret.values.yaml new file mode 100644 index 0000000000..87a44ce7e7 --- /dev/null +++ b/config/clusters/cloudbank/enc-staging.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:F6gexQRnLnmeqcG8zyZis/Dmbbmlu1XS9k+D7NlfGxYG7qKwQVamG50xKHx4cSrvu9ct,iv:l5G2hFNHsZZSCo/vdfyftwX8IiWDxIHkCM/hHgWPOXQ=,tag:YoLucbYLN5vNX/xjXijKsw==,type:str] + client_secret: ENC[AES256_GCM,data:ngXQRt20RhfHznMcRkevgClMr/I9hz/4tibGghfqvxAx5yvoFGg/0KgeU6lEO+sypErku4SJnqDC1VkGMDFUj/HZUQYLrvfk8dj+PwleepSDJLkThuo=,iv:wjNA41JFvs232b2DsB4QCKPLljK5iPWG+NTl7BXBekc=,tag:BCQR0q2l2SPSAK1vXzUrng==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:33:55Z" + enc: CiUA4OM7eE3tFD0J5epXMzmyytVw31vEgZPd620AQgfKeIoYyYGVEkkALQgViFTYOC7qIc5HUGop2uhjbLhuF2b9G5oDJ7NOJkg5L0bVS8JJ2saq2S0BjgBCsUBZP+lH1FNSmYN7Ozy+XoLeeQEi3+7c + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:33:56Z" + mac: ENC[AES256_GCM,data:+VgPemqp825ODzGtEirzO89YlwOldojxa81mk1GmKj40J4MgxQm5vHNSi081KJaoS+do1Ul603rS6EhZPp5KqrEyK87dR79+s9htPPqhKFTX82WyM31yB1Q/uUY9wT79yreRUmZYwitx0IGjWispjHNPprks/LKgaItERmx8WBA=,iv:OoH+da9eU6T5VcuzXQx0ACgeGGkqadn/UqhJaB8iC7s=,tag:UzCMHQPuXfw3tdN+RuquMA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/enc-tuskegee.secret.values.yaml b/config/clusters/cloudbank/enc-tuskegee.secret.values.yaml new file mode 100644 index 0000000000..359551d71d --- /dev/null +++ b/config/clusters/cloudbank/enc-tuskegee.secret.values.yaml @@ -0,0 +1,20 @@ +jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:ks6gGT32/DnjnMgVkrWh1nVY9Lvk80mvK6M//5uL/6AWYhxW3FHYkvMSmixRMfYqcRiF,iv:WSFYUm4ltEh9vj62adxOb/emDy62m4QYerbuIDN6cfk=,tag:UO3sKDB5GXX/oM163P31lQ==,type:str] + client_secret: ENC[AES256_GCM,data:R775NB/a3joyf9A/w3hbpIvE0bxag05egVCHSayCdvxuqOCcRQ6Hms1+1uSYwF12VAMpKXVp6Idy85lBZA8suTRSivsTENpFgBwBccbNXsdPr5qc7Ow=,iv:/4r4qcOP5e2svftTS9jpk7AGkOs84Lh4r96nWJ355io=,tag:4iBjL7CsY9Di7EcMZ9SdDw==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T13:50:43Z" + enc: CiUA4OM7eHEOrOekx/0qLP0xvvuWwl5t/9vmlpzec0P4cvEA5uWgEkkALQgViL4/5Ji3v+RHapPIcCJmSigcZI86E888/zAM1qHbnk979I+9GjSzEWrty4xtd1jGsRu4v7AakWr+F3cm11NP2Bj9/Q9f + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T13:50:43Z" + mac: ENC[AES256_GCM,data:Un7C60hO2h41QDHeMa7ayqmeRwOUjGfPgjwj8dpaZzAZ1DDAbh66YzRFfjN9hppKM0tCRr49ao8NHCLL/uxa5Nwn/ffduRPchP4nbGsO7g1ZsA6CnnbM5Bca7bKXsvzGVTqvKSGdpUxmgBD9MtkZ8VCjl6lecgA5y/W5CiXAK7Q=,iv:xD2xcCTvKdjgHXycIggV5L8o42ZucLG5ZoUj8QjTRQU=,tag:nuVWQV5NBYw4Kea4HtIJtA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/cloudbank/howard.values.yaml b/config/clusters/cloudbank/howard.values.yaml index 67e45d330c..c23276e621 100644 --- a/config/clusters/cloudbank/howard.values.yaml +++ b/config/clusters/cloudbank/howard.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://howard.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &howard_users - ericvd@berkeley.edu diff --git a/config/clusters/cloudbank/lacc.values.yaml b/config/clusters/cloudbank/lacc.values.yaml index 7484e7a40e..d016f34562 100644 --- a/config/clusters/cloudbank/lacc.values.yaml +++ b/config/clusters/cloudbank/lacc.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://lacc.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &lacc_users - PINEDAEM@laccd.edu diff --git a/config/clusters/cloudbank/lassen.values.yaml b/config/clusters/cloudbank/lassen.values.yaml index 381ea62200..9be3fbdc7c 100644 --- a/config/clusters/cloudbank/lassen.values.yaml +++ b/config/clusters/cloudbank/lassen.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://lassen.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &lassen_users - ericvd@gmail.com diff --git a/config/clusters/cloudbank/mills.values.yaml b/config/clusters/cloudbank/mills.values.yaml index febb67353d..ff3b2cd34f 100644 --- a/config/clusters/cloudbank/mills.values.yaml +++ b/config/clusters/cloudbank/mills.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://datahub.mills.edu/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: admin_users: &mills_admins - aculich@berkeley.edu diff --git a/config/clusters/cloudbank/palomar.values.yaml b/config/clusters/cloudbank/palomar.values.yaml index d349ee1c0a..1a384c74ef 100644 --- a/config/clusters/cloudbank/palomar.values.yaml +++ b/config/clusters/cloudbank/palomar.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://palomar.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &palomar_users - aculich@berkeley.edu diff --git a/config/clusters/cloudbank/sbcc.values.yaml b/config/clusters/cloudbank/sbcc.values.yaml index 2c6dfcc303..787a3a10a4 100644 --- a/config/clusters/cloudbank/sbcc.values.yaml +++ b/config/clusters/cloudbank/sbcc.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://sbcc.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &sbcc_users - ericvd@gmail.com diff --git a/config/clusters/cloudbank/skyline.values.yaml b/config/clusters/cloudbank/skyline.values.yaml index be4aa6390a..584f55bf18 100644 --- a/config/clusters/cloudbank/skyline.values.yaml +++ b/config/clusters/cloudbank/skyline.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://skyline.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &skyline_users - ericvd@gmail.com diff --git a/config/clusters/cloudbank/staging.values.yaml b/config/clusters/cloudbank/staging.values.yaml index 5d93ea1628..ae70d8b34f 100644 --- a/config/clusters/cloudbank/staging.values.yaml +++ b/config/clusters/cloudbank/staging.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: https://2i2c.org hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://staging.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &staging_users - colliand@gmail.com diff --git a/config/clusters/cloudbank/tuskegee.values.yaml b/config/clusters/cloudbank/tuskegee.values.yaml index 1523a6078a..20d5e6fd85 100644 --- a/config/clusters/cloudbank/tuskegee.values.yaml +++ b/config/clusters/cloudbank/tuskegee.values.yaml @@ -20,6 +20,14 @@ jupyterhub: url: http://cloudbank.org/ hub: config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + oauth_callback_url: "https://tuskegee.cloudbank.2i2c.cloud/hub/oauth_callback" + username_claim: "email" + # Only show the option to login with Google + shown_idps: + - http://google.com/accounts/o8/id Authenticator: allowed_users: &tuskegee_users - yasmeen.rawajfih@gmail.com From cdd9143a1706ad0079dbec2eb8d0e3b778740d03 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Fri, 10 Mar 2023 16:15:38 +0200 Subject: [PATCH 13/33] Move carbonplan hubs from auth0 to cilogon --- config/clusters/carbonplan/cluster.yaml | 12 ++++------- config/clusters/carbonplan/common.values.yaml | 5 ----- .../carbonplan/enc-prod.secret.values.yaml | 21 +++++++++++++++++++ .../carbonplan/enc-staging.secret.values.yaml | 21 +++++++++++++++++++ config/clusters/carbonplan/prod.values.yaml | 18 ++++++++++++++++ .../clusters/carbonplan/staging.values.yaml | 18 ++++++++++++++++ config/clusters/qcl/cluster.yaml | 2 -- 7 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 config/clusters/carbonplan/enc-prod.secret.values.yaml create mode 100644 config/clusters/carbonplan/enc-staging.secret.values.yaml create mode 100644 config/clusters/carbonplan/prod.values.yaml create mode 100644 config/clusters/carbonplan/staging.values.yaml diff --git a/config/clusters/carbonplan/cluster.yaml b/config/clusters/carbonplan/cluster.yaml index fcbf72354a..af1dcc7a47 100644 --- a/config/clusters/carbonplan/cluster.yaml +++ b/config/clusters/carbonplan/cluster.yaml @@ -15,25 +15,21 @@ hubs: display_name: "Carbon Plan (AWS, staging)" domain: staging.carbonplan.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - common.values.yaml + - staging.values.yaml + - enc-staging.values.yaml - name: prod display_name: "Carbon Plan (AWS, prod)" domain: carbonplan.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - common.values.yaml + - prod.values.yaml + - enc-prod.values.yaml diff --git a/config/clusters/carbonplan/common.values.yaml b/config/clusters/carbonplan/common.values.yaml index 6896e96485..b716b9efd3 100644 --- a/config/clusters/carbonplan/common.values.yaml +++ b/config/clusters/carbonplan/common.values.yaml @@ -151,11 +151,6 @@ basehub: readinessProbe: enabled: false nodeSelector: {} - config: - Authenticator: - allowed_users: &users - - jhamman - admin_users: *users dask-gateway: traefik: diff --git a/config/clusters/carbonplan/enc-prod.secret.values.yaml b/config/clusters/carbonplan/enc-prod.secret.values.yaml new file mode 100644 index 0000000000..52111e99f1 --- /dev/null +++ b/config/clusters/carbonplan/enc-prod.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:/4HJhFT25M7ndaNmZxsLS0yiUk9NcK3nf/ssu955tl0Zv5P3byfvv6O8yZZFiiGC2iDs,iv:6SOLvSpzaVtWnLnevTFqxAvbGo72ltdSf2w0fjXWYfs=,tag:vuCGGSxb7cvycCds2cbPOQ==,type:str] + client_secret: ENC[AES256_GCM,data:vWWpb9s3IlfFc4knSxKZf3mKv6e+7T7UBV5Hvfgv8l0wRAi5K4gNdvqii36KnXKZGbWnpiteyJLM5YQG0/jb4+IVTNwP9Z7xPgLnYFIYfdN5X8korW8=,iv:fG0I2Ml/t4SXeWTFIBCK3Qr/KNmD1oyw1H/OJ/Yr0h4=,tag:PolCnlCTjbWUSCLHWM9XrQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T14:14:44Z" + enc: CiUA4OM7eD4iOZT4U7dV7NF3Qz+HFISftGGIJZe/pjwxdAVjKwB9EkkALQgViLUlYBZm/1bByIkZRr8hJuququgDwHgT2RdjuY+rZ8bp0sUMiMhKZZsSksndfUdvLxTNqaNoytb0mG8aX6dIC2OkIvLY + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T14:14:44Z" + mac: ENC[AES256_GCM,data:NgmHdg0us7qAkwUDvHuVguESVDEbypia8EurIjnYwJQl+LNeB94Mh9e5bozKm8Q0kNG+BehfVdHAMD7zp4EHQNK5pLern+cMSqFbYQHo5mmtEfSLwGuS6UT9fBqyz6u8QBOeT9DXmLzSpkM4jBVd2usGocJfCWB+XbVifufIB6s=,iv:/84ExBaYTMC+MQgjjTjROCJ4d7o2Tr1Il7aERq57Sbg=,tag:istl5p8nT/78L0zle5FA8Q==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/carbonplan/enc-staging.secret.values.yaml b/config/clusters/carbonplan/enc-staging.secret.values.yaml new file mode 100644 index 0000000000..7295a07941 --- /dev/null +++ b/config/clusters/carbonplan/enc-staging.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:RhYGqIFvGPOq4aHJSRz2pGDH8YLOQzg+NFuObc9eazFGpM+C9SRI4TEZWfks/39PD88=,iv:VVd35loojo3vQIF/92EHonFae+x85xNYKjUucsbckkI=,tag:Tqag3Y0n0z7nGXwMmVYEFQ==,type:str] + client_secret: ENC[AES256_GCM,data:l+y8jLy9EoR1uzlWJJqgYh7GAtfHnn4NqdsyK9X2a/MrSNa86hZwMgt9XvK/JZDF/dzDgSsaJENjxmes4zX4iJKIC8yt/Qe0fEQf1zwfDQyXorWeNGA=,iv:irTeXTMsp6kfdPa1tuTQiSDUfWidhwHc8JoualdMux4=,tag:/WH5e9tZef4/CrPkJgpm5Q==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-10T14:04:09Z" + enc: CiUA4OM7eHEt0MqxHR+EYGCDUMJKPZgV74ZOx02eHJVOjAISjn7oEkkALQgViEwwaN2limZaQCEwfo6f7apJ/qpQCxMuoaGdyDzsFT7VSDW9jAMUdLbDOQ21FQox5SHqk50U20POOLbh/2jV+or22NKK + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-10T14:04:10Z" + mac: ENC[AES256_GCM,data:qsusV0yGD696dwiquL2KbkvzI+y7X4w6hHUVw/Wt16r3AcsUfoF8Yup95CP0k1hy+bUgs1yBZDTlv37M8PoATyMxPz5i8FDN9c+6an+DMro6jSAW9YuyQWbjIHvk2dfnlwTwVno9HgkMY0fsfezcTSEgyQEHGTnOXMHBMcVpVTY=,iv:7l30DOvO3zSym2VbwBAljVtqFX9ClJikV2N9vbmk6IY=,tag:+ON9dRxz9Sf9KENkV7DLbQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/carbonplan/prod.values.yaml b/config/clusters/carbonplan/prod.values.yaml new file mode 100644 index 0000000000..ebd869d4c3 --- /dev/null +++ b/config/clusters/carbonplan/prod.values.yaml @@ -0,0 +1,18 @@ +basehub: + jupyterhub: + hub: + config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://carbonplan.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize + Authenticator: + allowed_users: &users + - jhamman + admin_users: *users diff --git a/config/clusters/carbonplan/staging.values.yaml b/config/clusters/carbonplan/staging.values.yaml new file mode 100644 index 0000000000..b7f1552c37 --- /dev/null +++ b/config/clusters/carbonplan/staging.values.yaml @@ -0,0 +1,18 @@ +basehub: + jupyterhub: + hub: + config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://staging.carbonplan.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize + Authenticator: + allowed_users: &users + - jhamman + admin_users: *users diff --git a/config/clusters/qcl/cluster.yaml b/config/clusters/qcl/cluster.yaml index 2fe4be64e7..b46812433e 100644 --- a/config/clusters/qcl/cluster.yaml +++ b/config/clusters/qcl/cluster.yaml @@ -15,8 +15,6 @@ hubs: display_name: "QuantifiedCarbon (QCL) - staging" domain: staging.quantifiedcarbon.com helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - staging.values.yaml From 57ef12457a3a8a9eaf633fbd2d98126da9b4c4be Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Fri, 10 Mar 2023 16:22:25 +0200 Subject: [PATCH 14/33] Fix enc file namings --- config/clusters/carbonplan/cluster.yaml | 4 ++-- config/clusters/cloudbank/cluster.yaml | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/config/clusters/carbonplan/cluster.yaml b/config/clusters/carbonplan/cluster.yaml index af1dcc7a47..cdfd40b9a1 100644 --- a/config/clusters/carbonplan/cluster.yaml +++ b/config/clusters/carbonplan/cluster.yaml @@ -21,7 +21,7 @@ hubs: # that you intend for these files to be applied in this order. - common.values.yaml - staging.values.yaml - - enc-staging.values.yaml + - enc-staging.secret.values.yaml - name: prod display_name: "Carbon Plan (AWS, prod)" domain: carbonplan.2i2c.cloud @@ -32,4 +32,4 @@ hubs: # that you intend for these files to be applied in this order. - common.values.yaml - prod.values.yaml - - enc-prod.values.yaml + - enc-prod.secret.values.yaml diff --git a/config/clusters/cloudbank/cluster.yaml b/config/clusters/cloudbank/cluster.yaml index 34aabecf26..ff78f811ce 100644 --- a/config/clusters/cloudbank/cluster.yaml +++ b/config/clusters/cloudbank/cluster.yaml @@ -119,7 +119,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - lassen.values.yaml - - enc-lassen.values.yaml + - enc-lassen.secret.values.yaml - name: sbcc display_name: "Santa Barbara City College" domain: sbcc.cloudbank.2i2c.cloud @@ -129,7 +129,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - sbcc.values.yaml - - enc-sbcc.values.yaml + - enc-sbcc.secret.values.yaml - name: lacc display_name: "Los Angeles City College" domain: lacc.cloudbank.2i2c.cloud @@ -139,7 +139,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - lacc.values.yaml - - enc-lacc.values.yaml + - enc-lacc.secret.values.yaml - name: mills display_name: "Mills College" domain: datahub.mills.edu @@ -149,7 +149,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - mills.values.yaml - - enc-mills.values.yaml + - enc-mills.secret.values.yaml - name: palomar display_name: "Palomar Community College" domain: palomar.cloudbank.2i2c.cloud @@ -159,7 +159,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - palomar.values.yaml - - enc-palomar.values.yaml + - enc-palomar.secret.values.yaml - name: pasadena display_name: "Pasadena City College" domain: pasadena.cloudbank.2i2c.cloud @@ -169,7 +169,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - enc-pasadena.secret.values.yaml - - pasadena.values.yaml + - pasadena.secret.values.yaml - name: sjcc display_name: "San Jose Community College" domain: sjcc.cloudbank.2i2c.cloud @@ -189,7 +189,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - tuskegee.values.yaml - - enc-tuskegee.values.yaml + - enc-tuskegee.secret.values.yaml - name: avc display_name: "Antelope Valley College" domain: avc.cloudbank.2i2c.cloud @@ -199,7 +199,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - avc.values.yaml - - enc-avc.values.yaml + - enc-avc.secret.values.yaml - name: csu display_name: "California State University" domain: csu.cloudbank.2i2c.cloud From 5c6239d85116149138db0c74def499f5e414a93f Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 12:04:52 +0200 Subject: [PATCH 15/33] Move openscapes hubs from auth0 to cilogon --- config/clusters/openscapes/cluster.yaml | 12 ++++------ config/clusters/openscapes/common.values.yaml | 9 -------- .../openscapes/enc-prod.secret.values.yaml | 21 ++++++++++++++++++ .../openscapes/enc-staging.secret.values.yaml | 21 ++++++++++++++++++ config/clusters/openscapes/prod.values.yaml | 22 +++++++++++++++++++ .../clusters/openscapes/staging.values.yaml | 22 +++++++++++++++++++ 6 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 config/clusters/openscapes/enc-prod.secret.values.yaml create mode 100644 config/clusters/openscapes/enc-staging.secret.values.yaml create mode 100644 config/clusters/openscapes/prod.values.yaml create mode 100644 config/clusters/openscapes/staging.values.yaml diff --git a/config/clusters/openscapes/cluster.yaml b/config/clusters/openscapes/cluster.yaml index 0842fcad5f..6ba7cd23ae 100644 --- a/config/clusters/openscapes/cluster.yaml +++ b/config/clusters/openscapes/cluster.yaml @@ -15,25 +15,21 @@ hubs: display_name: "Openscapes (staging)" domain: staging.openscapes.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - common.values.yaml + - staging.values.yaml + - enc-staging.secret.values.yaml - name: prod display_name: "Openscapes (prod)" domain: openscapes.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - common.values.yaml + - prod.values.yaml + - enc-prod.secret.values.yaml diff --git a/config/clusters/openscapes/common.values.yaml b/config/clusters/openscapes/common.values.yaml index 720b986b4b..6d3593df50 100644 --- a/config/clusters/openscapes/common.values.yaml +++ b/config/clusters/openscapes/common.values.yaml @@ -248,15 +248,6 @@ basehub: enabled: false readinessProbe: enabled: false - config: - Authenticator: - admin_users: &users - - amfriesz - - jules32 - - erinmr - - betolink - # Without this, any GitHub user can authenticate - allowed_users: *users dask-gateway: gateway: extraConfig: diff --git a/config/clusters/openscapes/enc-prod.secret.values.yaml b/config/clusters/openscapes/enc-prod.secret.values.yaml new file mode 100644 index 0000000000..3393c9589e --- /dev/null +++ b/config/clusters/openscapes/enc-prod.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:PCbeuaL7ldU54DbnmVNW+q2a3wTP5qd6S3dQej1An2sLwVGj4i7bxEQQAWDNs84KNxsT,iv:Hd/mRDZDHPDVJ3tjy0Td+KZWeegEL0iFqrqaWLyotK0=,tag:D6olXkt8OIt2ZdOVomZxDA==,type:str] + client_secret: ENC[AES256_GCM,data:SI36RxfT1vtePE0pkQorVeNhkGTt6GpSEkIMjbKwlGyIPFezKqMRFPYJxAeV5tz0JgdGd59h1XQb9Jk0K0K8XlxTKfWZ/M19dMqWpjDlgM4Ur3mHoCQ=,iv:W4NoN8hMqioTK1WOQnQJH7IZvtHyHXvLyrGg3bjJqhE=,tag:kGmt3v+2GOZ77nUO3AiUIg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-13T10:03:40Z" + enc: CiUA4OM7eDczGhJwK7l0yxNNnKtIKPlKlhXLMgqaWowE7s72qJtGEkkALQgViAhzuHyTXLxoaNNjJ3HGNjksd3cst0i9hxSJO47Sxs4riFpxiTDadAYLUIhgWJXIUZRm6BBaFRBmUoTc4yUwUMFtau5u + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-13T10:03:40Z" + mac: ENC[AES256_GCM,data:ZpYHsxfzFLW2ua+A40no5U4kUKSv5Fo/qf9Ys2LEMZS2ASZ0V3J1fJH2Dz6xbveavwgxDBWU0N4+KdT+WUzlx6V1Z/REVdmzLYEADSe7vnZX2W6tDfuB/Rf8rReB8Ajb45mn2LLEgLBv+jB97QXf0ijcxi5q4Vie6qH3sZOOG/0=,iv:YQN4OTU4zYmV8uI8bmy5bXLvzyurYneO9n9hTWa7JAA=,tag:UKahoDg8DSvkq9+V7rWW8g==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/openscapes/enc-staging.secret.values.yaml b/config/clusters/openscapes/enc-staging.secret.values.yaml new file mode 100644 index 0000000000..b312b6842f --- /dev/null +++ b/config/clusters/openscapes/enc-staging.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:EBaAMzaTvfRUNK6U4k+6TMCnIreSQo2BotapMjad9nS4YgD48XXmM/vx+3IOglx9HotA,iv:/a6xsdxpI+nDSSk2nPkAFGA6TKja7c8dHF4yXsFt0sY=,tag:sYoFNPe8b3KI/5BJ8MqusA==,type:str] + client_secret: ENC[AES256_GCM,data:hzatCTFx/dQNsedELDFYjug6g+Yfs1H8Q5JAJth9xLx/2Y9XcUAu0SzsDcL4M4CbeiN5wRYpvsyKz+6ygGsNtoo8n7MG427JxJPjz7uwm3IvQrauVJE=,iv:t5hn2DttsSpeU+bbF6OF3XLxekzj92eg2+fiwGWS/Kc=,tag:CcZnc+81ea+iQkHKrp7kVQ==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-13T10:04:09Z" + enc: CiUA4OM7eHFctsBpi0BcbIY6qnw8gNoG915B2+AtJxRexq2O5SBSEkkALQgViG8aSvK5HFex4XJnFYN9+fTzWh3cWVTmY8R3GUaExQ0DdDeIyLdbpgyTFFuVEgkhOTHeALuFiE7M8OVOc0QHPm7ioj+2 + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-13T10:04:10Z" + mac: ENC[AES256_GCM,data:gNugXyk8VLkVL5+sRISipvrMD3dDP3O16Hr/PROtNp1DJjcYAmK6j1OQo/MtMho00zzycQIjI9NkYa+j99d/+cXgXJa0RRDhERBkW5OWT95cFFznJlR2vIK0sbD6UIBktVirUU6Mit3LfcB5CTzTky3ixFuoLwoG5Suqb7YfLug=,iv:S51lDAOUpTHmKa4B6WuludJTQurhqZCxHfNPj+D/M2g=,tag:aZkrbG7ZOvZft4ggZl87fA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/openscapes/prod.values.yaml b/config/clusters/openscapes/prod.values.yaml new file mode 100644 index 0000000000..d302fd8309 --- /dev/null +++ b/config/clusters/openscapes/prod.values.yaml @@ -0,0 +1,22 @@ +basehub: + jupyterhub: + hub: + config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://openscapes.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize + Authenticator: + admin_users: &users + - amfriesz + - jules32 + - erinmr + - betolink + # Without this, any GitHub user can authenticate + allowed_users: *users diff --git a/config/clusters/openscapes/staging.values.yaml b/config/clusters/openscapes/staging.values.yaml new file mode 100644 index 0000000000..676eb0bf39 --- /dev/null +++ b/config/clusters/openscapes/staging.values.yaml @@ -0,0 +1,22 @@ +basehub: + jupyterhub: + hub: + config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://staging.openscapes.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize + Authenticator: + admin_users: &users + - amfriesz + - jules32 + - erinmr + - betolink + # Without this, any GitHub user can authenticate + allowed_users: *users From 10324e9942179d54aaaa0764b240d2480a928b70 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 12:20:45 +0200 Subject: [PATCH 16/33] Move meom-ige hubs from auth0 to cilogon --- config/clusters/meom-ige/cluster.yaml | 8 ------- .../meom-ige/enc-prod.secret.values.yaml | 21 +++++++++++++++++++ .../meom-ige/enc-staging.secret.values.yaml | 21 +++++++++++++++++++ config/clusters/meom-ige/prod.values.yaml | 21 +++++++++++++++++++ config/clusters/meom-ige/staging.values.yaml | 21 +++++++++++++++++++ 5 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 config/clusters/meom-ige/enc-prod.secret.values.yaml create mode 100644 config/clusters/meom-ige/enc-staging.secret.values.yaml diff --git a/config/clusters/meom-ige/cluster.yaml b/config/clusters/meom-ige/cluster.yaml index 8dd4b510ae..58d9690640 100644 --- a/config/clusters/meom-ige/cluster.yaml +++ b/config/clusters/meom-ige/cluster.yaml @@ -14,10 +14,6 @@ hubs: display_name: "SWOT Ocean Pangeo Team (staging)" domain: staging.meom-ige.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check @@ -28,10 +24,6 @@ hubs: display_name: "SWOT Ocean Pangeo Team (prod)" domain: meom-ige.2i2c.cloud helm_chart: daskhub - auth0: - # connection update? Also ensure the basehub Helm chart is provided a - # matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type! - connection: github helm_chart_values_files: # The order in which you list files here is the order the will be passed # to the helm upgrade command in, and that has meaning. Please check diff --git a/config/clusters/meom-ige/enc-prod.secret.values.yaml b/config/clusters/meom-ige/enc-prod.secret.values.yaml new file mode 100644 index 0000000000..549006b331 --- /dev/null +++ b/config/clusters/meom-ige/enc-prod.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:xIMwdp4OmWwc1w0H9Grbhv6g+CpATbn3rScgJlShpcte1LzDqeVgLvBHiLrUMo/Xi70Q,iv:5f5lrIHUrtbN2M74b9OPefH4WRCmlm36yToX8Wsziss=,tag:WUCXxLH38iWWHnW/1RM6cQ==,type:str] + client_secret: ENC[AES256_GCM,data:tWeX8fYjm/xCXcRGNiHqby0D1b1HKGZ6j+wkF1F8TMR3JuzGEhXLI6j2HI/TgenX6/Ai0v/y16OxG1Ae62KaWJLa0YRtIhONN/XDOKFZppApKm+P2A4=,iv:Mqs9fuH3rzoFUipiocz3irGTHS65ymQOjigdlhOBmFs=,tag:9dCcnlMlH3+WHDZlVSzcNg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-13T10:17:08Z" + enc: CiUA4OM7eHFCKHxkiMcLd9tjDU87r2QU7yauBdKAOwl0UVOV6ECGEkkALQgViIyOLYwyQIt3YzOd+DIEm5bghYgGp7wCT1vtGkRPxM++xzevRt1f7D2acqLFlAocvl/tgXiAAwYTUUmwWb+lLTfhxa+R + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-13T10:17:09Z" + mac: ENC[AES256_GCM,data:h7iNgvpiwxTARQxz8/MGI/xOf0vC7BK3xZ/CBJF4nYofIdKltVAwqHRX/ztLCpzCMRZ6BdyFUIIHVAWxIIQTVFT0l/Cp9f/cxvoddHKzx4cerA9WC9Zv8lmdgCIL2irFshyNFm/7BQmTTpjLDGmt9OW0/wZflyJCAC7uWNaiMRQ=,iv:l84Ikdxm9pv0/tihz03sAVIfMiUPzj56ayefwolJ7JQ=,tag:DBaGopzzB8FWce4VZFchfQ==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/meom-ige/enc-staging.secret.values.yaml b/config/clusters/meom-ige/enc-staging.secret.values.yaml new file mode 100644 index 0000000000..432042469f --- /dev/null +++ b/config/clusters/meom-ige/enc-staging.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:yx2uzwGKf+WEoG+pyGKzkA0NvoayyW1PXJ+dtXwf0sHnohOUkGsQmWt7mLBm2d6sXzc0,iv:axmz1xSTtAgNgEXnFuQ1Af0ftDqxu13KABtZIixmboc=,tag:dZA//khE2//4d4+3pT+F+Q==,type:str] + client_secret: ENC[AES256_GCM,data:MAjP8OZLLJlL0moBRR13xc+2dWcVkFMi6O0U/6m+pcZeCD8HNw2Jo9mX0cHzHciGD6a5Q63iFHiMKR/i9Nnj7kddBW3mnp1ZCO+qpFvoR4JFE3VJ2/M=,iv:zNMIhEL8/RbKk3Ss0UljkzHntRXPzvrdOTZTciH51FU=,tag:mDCSDz671bJ291nPccD6zw==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-13T10:15:46Z" + enc: CiUA4OM7eHgYzj8BLwkArOmEtjvrc4OOOnE0VZLsLKdFp6aYfM+5EkkALQgViPcHhqvp7tpQXCpfpYZVy/7bGDfDgsqbMftrGH493iGtKn+Rp+JW2x65WugoLHxYR/lLWf3SIgK9VQfRkP2z/gHijmcz + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-13T10:15:46Z" + mac: ENC[AES256_GCM,data:YTpTnlBaZaya4DY1D1/z3SjHrjtAZ/JJmgwa8urrNz7CgQOu/nreWbO6+xalfEKJS7F8jl/rntPOJC/B5V38/gu77sTH31snGtoqMHcJg2yrP+LuEBB40OjukpVi/6cBdM4HmduXCt/ksjGsuo3rvZ9qqmCEoRv/nGg/WK3L3qM=,iv:Ph+2pjyyko4k5tWwT2OWf/pOcpFvuviSj8P5EnaNVQk=,tag:2hGU/xdfyX/C8QicHiLeYw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/meom-ige/prod.values.yaml b/config/clusters/meom-ige/prod.values.yaml index f1e0bc13ea..26e349f6ca 100644 --- a/config/clusters/meom-ige/prod.values.yaml +++ b/config/clusters/meom-ige/prod.values.yaml @@ -2,3 +2,24 @@ basehub: userServiceAccount: annotations: iam.gke.io/gcp-service-account: meom-ige-prod@meom-ige-cnrs.iam.gserviceaccount.com + jupyterhub: + hub: + config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://meom-ige.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize + Authenticator: + admin_users: &users + - amfriesz + - jules32 + - erinmr + - betolink + # Without this, any GitHub user can authenticate + allowed_users: *users diff --git a/config/clusters/meom-ige/staging.values.yaml b/config/clusters/meom-ige/staging.values.yaml index 6d80ac0bb1..f02991eac0 100644 --- a/config/clusters/meom-ige/staging.values.yaml +++ b/config/clusters/meom-ige/staging.values.yaml @@ -2,3 +2,24 @@ basehub: userServiceAccount: annotations: iam.gke.io/gcp-service-account: meom-ige-staging-workload-sa@meom-ige-cnrs.iam.gserviceaccount.com + jupyterhub: + hub: + config: + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://staging.meom-ige.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize + Authenticator: + admin_users: &users + - amfriesz + - jules32 + - erinmr + - betolink + # Without this, any GitHub user can authenticate + allowed_users: *users From 01ea6cb197444b474c3c2c1c027c942df5c67972 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 12:28:07 +0200 Subject: [PATCH 17/33] Move 2i2c-aws-us hubs from auth0 to cilogon --- config/clusters/2i2c-aws-us/cluster.yaml | 3 +-- .../enc-researchdelight.secret.values.yaml | 21 +++++++++++++++++++ .../2i2c-aws-us/researchdelight.values.yaml | 14 +++++++++---- 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 config/clusters/2i2c-aws-us/enc-researchdelight.secret.values.yaml diff --git a/config/clusters/2i2c-aws-us/cluster.yaml b/config/clusters/2i2c-aws-us/cluster.yaml index 42bc8d7e39..b1d4c57ae3 100644 --- a/config/clusters/2i2c-aws-us/cluster.yaml +++ b/config/clusters/2i2c-aws-us/cluster.yaml @@ -29,8 +29,7 @@ hubs: display_name: "2i2c Research Delight" domain: researchdelight.2i2c.cloud helm_chart: daskhub - auth0: - connection: github helm_chart_values_files: - common.values.yaml - researchdelight.values.yaml + - enc-researchdelight.secret.values.yaml diff --git a/config/clusters/2i2c-aws-us/enc-researchdelight.secret.values.yaml b/config/clusters/2i2c-aws-us/enc-researchdelight.secret.values.yaml new file mode 100644 index 0000000000..3d2d84bd48 --- /dev/null +++ b/config/clusters/2i2c-aws-us/enc-researchdelight.secret.values.yaml @@ -0,0 +1,21 @@ +basehub: + jupyterhub: + hub: + config: + CILogonOAuthenticator: + client_id: ENC[AES256_GCM,data:do6oRsCHVlEaopw/SGKnudX6QMwTRo/Vco2sBCXkHNJ8aASBToFUlHqG8U8stmAe1eYJ,iv:FgtBzUzC8kap+BASyDY/sqnv1kvItTOX0a1j+mwYsy4=,tag:BhpZ5fAaYzSSIF9/RzLsXg==,type:str] + client_secret: ENC[AES256_GCM,data:1aIn9R5loffBYMuLuzn5+I+QkmX5qE7kYuqEKy0dvKJQZg/LK0yzVKoHiLOIYYJqTToVUMCc+aC+ZYTlNmCvGg3GwYPTkjVChRVYJRUZvl1ELP7YcV0=,iv:YORVpCcx9w4hgyKlomZKyAzEvnm+OFZbPu3tw3DvQAo=,tag:hUeV48uiv5PtjSp96o5n+w==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs + created_at: "2023-03-13T10:27:13Z" + enc: CiUA4OM7eCdS0zudoyhLRbKlG+r1jUBQwFNAczMpasSH5X06+IWHEkkALQgViIkNihiV+Z+ZUwjJcCpuOprNMklD4AJ6UBeHxurj/VMPpCUBgveo7MwK/8+YMYofFpleS4b5rsLJ717oWDJjjM8cA8+W + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-03-13T10:27:13Z" + mac: ENC[AES256_GCM,data:Bw1VoDnPAN1CvIOruB4SBVJf0gKXFbtOBHAy8gGSbA7s9PdiVN8FNmRSlutC8xKNqSVQ7vmtYhonJ+AHS6+PXa1aAceKMmQAmeMtwqE0HHSwR9Ujcw3F0bkjwHUMHIGgCOm0FawbHtMFBvAYXb8rgtCnZjGirJGmJ4TJ153IpXg=,iv:SsFQArAjuip3KyOvM45TsqHrNO0SQ+sTReuzZ5Yq8GU=,tag:TbqHDResuHQkapqPd9nSBA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/config/clusters/2i2c-aws-us/researchdelight.values.yaml b/config/clusters/2i2c-aws-us/researchdelight.values.yaml index 11acfa87d8..cbb6eaaa59 100644 --- a/config/clusters/2i2c-aws-us/researchdelight.values.yaml +++ b/config/clusters/2i2c-aws-us/researchdelight.values.yaml @@ -44,7 +44,13 @@ basehub: NVIDIA_DRIVER_CAPABILITIES: compute,utility hub: config: - Authenticator: - allowed_users: &allowed_users - - jmunroe - admin_users: *allowed_users + JupyterHub: + authenticator_class: cilogon + CILogonOAuthenticator: + scope: + - "profile" + username_claim: "preferred_username" + oauth_callback_url: "https://researchdelight.2i2c.cloud/hub/oauth_callback" + # Only show the option to login with GitHub + shown_idps: + - http://github.com/login/oauth/authorize From 99269fb050dd9ae65148ed1ddc36d3c37bdb54b1 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 12:29:26 +0200 Subject: [PATCH 18/33] Add missing meom-ige config --- config/clusters/meom-ige/cluster.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/clusters/meom-ige/cluster.yaml b/config/clusters/meom-ige/cluster.yaml index 58d9690640..83e7c77f36 100644 --- a/config/clusters/meom-ige/cluster.yaml +++ b/config/clusters/meom-ige/cluster.yaml @@ -20,6 +20,7 @@ hubs: # that you intend for these files to be applied in this order. - common.values.yaml - staging.values.yaml + - enc-staging.secret.values.yaml - name: prod display_name: "SWOT Ocean Pangeo Team (prod)" domain: meom-ige.2i2c.cloud @@ -30,6 +31,7 @@ hubs: # that you intend for these files to be applied in this order. - common.values.yaml - prod.values.yaml + - enc-prod.secret.values.yaml - name: drakkar-demo display_name: "2023 DRAKKAR Ocean Modelling Workshop" domain: drakkar-demo.meom-ige.2i2c.cloud From a95e14fa03cbfa5d4147b049331af05e7e6092a7 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 12:35:23 +0200 Subject: [PATCH 19/33] Correct the enc config names --- config/clusters/cloudbank/cluster.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/clusters/cloudbank/cluster.yaml b/config/clusters/cloudbank/cluster.yaml index ff78f811ce..df8a583d5d 100644 --- a/config/clusters/cloudbank/cluster.yaml +++ b/config/clusters/cloudbank/cluster.yaml @@ -29,7 +29,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - ccsf.values.yaml - - enc-ccsf.values.yaml + - enc-ccsf.secret.values.yaml - name: csm display_name: "College of San Mateo" domain: csm.cloudbank.2i2c.cloud @@ -49,7 +49,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - elcamino.values.yaml - - enc-elcamino.values.yaml + - enc-elcamino.secret.values.yaml - name: glendale display_name: "Glendale Community College" domain: glendale.cloudbank.2i2c.cloud @@ -69,7 +69,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - howard.values.yaml - - enc-howard.values.yaml + - enc-howard.secret.values.yaml - name: miracosta display_name: "MiraCosta College" domain: miracosta.cloudbank.2i2c.cloud @@ -89,7 +89,7 @@ hubs: # to the helm upgrade command in, and that has meaning. Please check # that you intend for these files to be applied in this order. - skyline.values.yaml - - enc-skyline.values.yaml + - enc-skyline.secret.values.yaml - name: demo display_name: "Cloudbank demo" domain: demo.cloudbank.2i2c.cloud From e747bf0066801f689818432d940a9cdd9877a12e Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 12:41:34 +0200 Subject: [PATCH 20/33] James is now an admin in all hub by default --- config/clusters/2i2c/catalyst-cooperative.values.yaml | 1 - config/clusters/2i2c/pfw.values.yaml | 1 - config/clusters/cloudbank/staging.values.yaml | 1 - 3 files changed, 3 deletions(-) diff --git a/config/clusters/2i2c/catalyst-cooperative.values.yaml b/config/clusters/2i2c/catalyst-cooperative.values.yaml index f5145c7c6c..67ad7039a7 100644 --- a/config/clusters/2i2c/catalyst-cooperative.values.yaml +++ b/config/clusters/2i2c/catalyst-cooperative.values.yaml @@ -50,5 +50,4 @@ basehub: allowed_users: &catalyst_users - zane.selvans@catalyst.coop - cgosnell@catalyst.coop - - colliand@gmail.com admin_users: *catalyst_users diff --git a/config/clusters/2i2c/pfw.values.yaml b/config/clusters/2i2c/pfw.values.yaml index 6769a3df53..67c016ea2d 100644 --- a/config/clusters/2i2c/pfw.values.yaml +++ b/config/clusters/2i2c/pfw.values.yaml @@ -32,7 +32,6 @@ jupyterhub: - http://github.com/login/oauth/authorize Authenticator: allowed_users: &pfw_users - - colliand - alessandromariaselvitella - fosterk86 admin_users: *pfw_users diff --git a/config/clusters/cloudbank/staging.values.yaml b/config/clusters/cloudbank/staging.values.yaml index ae70d8b34f..c133290cea 100644 --- a/config/clusters/cloudbank/staging.values.yaml +++ b/config/clusters/cloudbank/staging.values.yaml @@ -30,6 +30,5 @@ jupyterhub: - http://google.com/accounts/o8/id Authenticator: allowed_users: &staging_users - - colliand@gmail.com - sean.smorris@berkeley.edu admin_users: *staging_users From bdd5187410365f3e37abf2afa979cde4f2be30c3 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 16:15:32 +0200 Subject: [PATCH 21/33] Turn auth0 into a deployer subcmd --- deployer/__main__.py | 1 + deployer/auth0_app.py | 258 ++++++++++++++++++++++++++++++++++++++++ deployer/cilogon_app.py | 11 +- extra_scripts/README.md | 1 - 4 files changed, 266 insertions(+), 5 deletions(-) create mode 100644 deployer/auth0_app.py diff --git a/deployer/__main__.py b/deployer/__main__.py index 3e6a9510c3..5db4070635 100644 --- a/deployer/__main__.py +++ b/deployer/__main__.py @@ -1,5 +1,6 @@ # Import the various subcommands here, they will be automatically # registered into the app +import deployer.auth0_app # noqa: F401 import deployer.cilogon_app # noqa: F401 import deployer.debug # noqa: F401 import deployer.deployer # noqa: F401 diff --git a/deployer/auth0_app.py b/deployer/auth0_app.py new file mode 100644 index 0000000000..79cc95b4aa --- /dev/null +++ b/deployer/auth0_app.py @@ -0,0 +1,258 @@ +import json +import re + +import typer +from auth0.v3.authentication import GetToken +from auth0.v3.management import Auth0 +from ruamel.yaml import YAML +from yarl import URL + +from .cli_app import app +from .file_acquisition import get_decrypted_file + +yaml = YAML(typ="safe") + + +# What key in the authenticated user's profile to use as hub username +# This shouldn't be changeable by the user! +USERNAME_KEYS = { + "github": "nickname", + "google-oauth2": "email", + "password": "email", + "CILogon": "email", +} + + +class KeyProvider: + def __init__(self, domain, client_id, client_secret): + self.client_id = client_id + self.client_secret = client_secret + self.domain = domain + + @property + def auth0(self): + """ + Return an authenticated Auth0 instance + """ + if not hasattr(self, "_auth0"): + gt = GetToken(self.domain) + creds = gt.client_credentials( + self.client_id, self.client_secret, f"https://{self.domain}/api/v2/" + ) + self._auth0 = Auth0(self.domain, creds["access_token"]) + return self._auth0 + + def _get_clients(self): + return { + client["name"]: client + # Our account is limited to 100 clients, and we want it all in one go + for client in self.auth0.clients.all(per_page=100) + } + + def _get_connections(self): + return { + connection["name"]: connection + for connection in self.auth0.connections.all() + } + + def create_client(self, name, callback_url, logout_url): + client = { + "name": name, + "app_type": "regular_web", + "callbacks": [callback_url], + "allowed_logout_urls": [logout_url], + } + created_client = self.auth0.clients.create(client) + return created_client + + def _ensure_client_callback(self, client, callback_url): + """ + Ensure client has correct callback URL + """ + if "callbacks" not in client or client["callbacks"] != [callback_url]: + self.auth0.clients.update( + client["client_id"], + { + # Overwrite any other callback URL specified + # Only one hub should use any one auth0 application, and it + # should only have one callback url. Additional URLs can be + # a security risk, since people who control those URLs could + # potentially steal user credentials (if they have client_id and secret). + # Fully managing list of callback URLs in code keeps everything + # simpler + "callbacks": [callback_url] + }, + ) + + def _ensure_client_logout_url(self, client, logout_url): + if "allowed_logout_urls" not in client or client["allowed_logout_urls"] != [ + logout_url + ]: + self.auth0.clients.update( + client["client_id"], + { + # Overwrite any other logout URL - users should only land on + # the hub home page after logging out. + "allowed_logout_urls": [logout_url] + }, + ) + + def ensure_client( + self, + name, + callback_url, + logout_url, + connection_name, + ): + current_clients = self._get_clients() + if name not in current_clients: + # Create the client, all good + client = self.create_client(name, callback_url, logout_url) + else: + client = current_clients[name] + self._ensure_client_callback(client, callback_url) + self._ensure_client_logout_url(client, logout_url) + + current_connections = self._get_connections() + + if connection_name == "password": + # Users should not be shared between hubs - each hub + # should have its own username / password database. + # So we create a new 'database connection' per hub, + # instead of sharing one across hubs. + db_connection_name = name + + if db_connection_name not in current_connections: + # connection doesn't exist yet, create it + connection = self.auth0.connections.create( + { + "name": db_connection_name, + "display_name": name, + "strategy": "auth0", + } + ) + current_connections[db_connection_name] = connection + selected_connection_name = db_connection_name + else: + selected_connection_name = connection_name + + for connection in current_connections.values(): + # The chosen connection! + enabled_clients = connection["enabled_clients"].copy() + needs_update = False + client_id = client["client_id"] + if connection["name"] == selected_connection_name: + if client_id not in enabled_clients: + enabled_clients.append(client_id) + needs_update = True + else: + if client_id in enabled_clients: + enabled_clients.remove(client_id) + needs_update = True + + if needs_update: + self.auth0.connections.update( + connection["id"], {"enabled_clients": enabled_clients} + ) + + return client + + def get_client_creds(self, client, connection_name): + """ + Return z2jh config for auth0 authentication for this JupyterHub + """ + logout_redirect_params = { + "client_id": client["client_id"], + "returnTo": client["allowed_logout_urls"][0], + } + + auth = { + "auth0_subdomain": re.sub(r"\.auth0.com$", "", self.domain), + "userdata_url": f"https://{self.domain}/userinfo", + "username_key": USERNAME_KEYS[connection_name], + "client_id": client["client_id"], + "client_secret": client["client_secret"], + "scope": ["openid", "name", "profile", "email"], + "logout_redirect_url": str( + URL(f"https://{self.domain}/v2/logout").with_query( + logout_redirect_params + ) + ), + } + + return auth + + +def get_2i2c_auth0_admin_credentials(): + """ + Retrieve the 2i2c Auth0 administrative client credentials + stored in `shared/deployer/enc-auth-providers-credentials.secret.yaml`. + """ + # This filepath is relative to the PROJECT ROOT + general_auth_config = "shared/deployer/enc-auth-providers-credentials.secret.yaml" + with get_decrypted_file(general_auth_config) as decrypted_file_path: + with open(decrypted_file_path) as f: + config = yaml.load(f) + + return ( + config["auth0"]["domain"], + config["auth0"]["client_id"], + config["auth0"]["client_secret"], + ) + + +@app.command() +def auth0_client_create( + cluster_name: str = typer.Argument(..., help="Name of cluster to operate"), + hub_name: str = typer.Argument( + ..., + help="Name of the hub for which a new Auth0 client will be created", + ), + hub_domain: str = typer.Argument( + ..., + help="The hub domain, as specified in `cluster.yaml` (ex: staging.2i2c.cloud)", + ), + connection_type: str = typer.Argument( + ..., + help=f"Auth0 connection type. One of {USERNAME_KEYS.keys()}", + ), +): + """Create an Auth0 client app for a hub.""" + domain, admin_id, admin_secret = get_2i2c_auth0_admin_credentials() + auth_provider = KeyProvider(domain, admin_id, admin_secret) + # Users will be redirected to this URL after they log out + logout_url = f"https://{hub_domain}" + # This URL is invoked after OAuth authorization" + callback_url = f"https://{hub_domain}/hub/oauth_callback" + + client = auth_provider.ensure_client( + name=f"{cluster_name}-{hub_name}", + callback_url=callback_url, + logout_url=logout_url, + connection_name=connection_type, + ) + + jupyterhub_config = { + "jupyterhub": { + "hub": { + "config": { + "JupyterHub": {"authenticator_class": "auth0"}, + "Auth0OAuthenticator": auth_provider.get_client_creds( + client, connection_type + ), + } + } + } + } + print(json.dumps(jupyterhub_config, sort_keys=True, indent=4)) + + +@app.command() +def auth0_client_get_all(): + """Retrieve details about all existing 2i2c CILogon clients.""" + domain, admin_id, admin_secret = get_2i2c_auth0_admin_credentials() + auth_provider = KeyProvider(domain, admin_id, admin_secret) + clients = auth_provider._get_clients() + + for _, v in sorted(clients.items()): + print(f'{v["name"]}: {v.get("callbacks", None)}') diff --git a/deployer/cilogon_app.py b/deployer/cilogon_app.py index 3f87b2a0d5..b308ffbc05 100644 --- a/deployer/cilogon_app.py +++ b/deployer/cilogon_app.py @@ -414,12 +414,14 @@ def cilogon_client_create( "basehub", help="Type of hub for which we'll create a CILogon client (ex: basehub, daskhub)", ), - callback_url: str = typer.Argument( - ..., help="URL that is invoked after OAuth authorization" + hub_domain: str = typer.Argument( + ..., + help="The hub domain, as specified in `cluster.yaml` (ex: staging.2i2c.cloud)", ), ): """Create a CILogon OAuth client for a hub.""" admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() + callback_url = f"https://{hub_domain}/hub/oauth_callback" create_client( admin_id, admin_secret, cluster_name, hub_name, hub_type, callback_url ) @@ -431,13 +433,14 @@ def cilogon_client_update( hub_name: str = typer.Argument( ..., help="Name of the hub for which we'll update a CILogon client" ), - callback_url: str = typer.Argument( + hub_domain: str = typer.Argument( ..., - help="New callback_url to associate with the client. This URL is invoked after OAuth authorization", + help="The hub domain, as specified in `cluster.yaml` (ex: staging.2i2c.cloud)", ), ): """Update the CILogon OAuth client of a hub.""" admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() + callback_url = f"https://{hub_domain}/hub/oauth_callback" update_client(admin_id, admin_secret, cluster_name, hub_name, callback_url) diff --git a/extra_scripts/README.md b/extra_scripts/README.md index 340513edf5..170942e511 100644 --- a/extra_scripts/README.md +++ b/extra_scripts/README.md @@ -2,6 +2,5 @@ This folder contains some extra scripts that are not run as part of day-to-day operations, but can reduce the toil of some manual processes we undertake occasionally. -- **[`count-auth0-apps.py`](./count-auth0-apps.py):** This script lists duplicated Auth0 apps that may have been created by a misconfigured deployer. - **[`rsync-active-users.py`](./rsync-active-users.py):** This script uses `rsync` to synchronise the home directories of active users of a JupyterHub in parallel. This script is useful to run when migrating a hub. From c909ba95ed3d155161f870cc6c42c502c017776e Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Mon, 13 Mar 2023 16:15:56 +0200 Subject: [PATCH 22/33] Comment cleanup to avoid confusions --- deployer/cilogon_app.py | 57 +++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/deployer/cilogon_app.py b/deployer/cilogon_app.py index b308ffbc05..d1e4baca43 100644 --- a/deployer/cilogon_app.py +++ b/deployer/cilogon_app.py @@ -8,11 +8,11 @@ The commands in this file can be used to: -- `create` a CILogon OAuth application for a hub and store the credentials safely +- `create` a CILogon client application for a hub and store the credentials safely - `update` the callback urls of an existing hub CILogon client -- `delete` a CILogon OAuth application when a hub is removed or changes auth methods +- `delete` a CILogon client application when a hub is removed or changes auth methods - `get` details about an existing hub CILogon client -- `get-all` existing 2i2c CILogon OAuth applications +- `get-all` existing 2i2c CILogon client applications """ import base64 @@ -103,7 +103,7 @@ def persist_client_credentials_in_config_file(client, hub_type, config_filename) f.truncate() subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) print_colour( - f"Successfully updated the {config_filename} file with the encrypted CILogon OAuth client app credentials." + f"Successfully updated the {config_filename} file with the encrypted CILogon client app credentials." ) return @@ -111,7 +111,7 @@ def persist_client_credentials_in_config_file(client, hub_type, config_filename) yaml.dump(auth_config, f) subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) print_colour( - f"Successfully persisted the encrypted CILogon OAuth client app credentials to file {config_filename}" + f"Successfully persisted the encrypted CILogon client app credentials to file {config_filename}" ) @@ -155,7 +155,7 @@ def remove_client_credentials_from_config_file(config_filename): else: config["jupyterhub"]["hub"]["config"].pop("CILogonOAuthenticator") except KeyError: - print_colour("No CILogon OAuth client app to delete from {config_filename}") + print_colour("No CILogon client app to delete from {config_filename}") return def clean_empty_nested_dicts(d): @@ -177,12 +177,12 @@ def clean_empty_nested_dicts(d): f.truncate() subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) - print_colour(f"CILogon OAuth client app removed from {config_filename}") + print_colour(f"CILogon client app removed from {config_filename}") return # If the file only contained the CILogon credentials, then we can safely delete it print_colour( - f"Deleted empty {config_filename} file after CILogon OAuth client app was removed." + f"Deleted empty {config_filename} file after CILogon client app was removed." ) Path(config_filename).unlink() @@ -195,7 +195,7 @@ def stored_client_id_same_with_cilogon_records( ] if stored_client_id != client_id: print_colour( - "CILogon records are different than the OAuth client app stored in the configuration file. Consider updating the file.", + "CILogon records are different than the client app stored in the configuration file. Consider updating the file.", "red", ) return False @@ -230,7 +230,7 @@ def create_client( client_id = load_client_id_from_file(config_filename) if client_id: print_colour( - f"Found existing CILogon OAuth client app in {config_filename}.", "yellow" + f"Found existing CILogon client app in {config_filename}.", "yellow" ) # Also check if what's in the file matches CILogon records in case the file was not updated accordingly # Exit anyway since manual intervention is required if different @@ -239,7 +239,7 @@ def create_client( ) # Ask CILogon to create the client - print(f"Creating a new CILogon OAuth client app with details {client_details}...") + print(f"Creating a new CILogon client app with details {client_details}...") headers = build_request_headers(admin_id, admin_secret) response = requests.post( build_request_url(), json=client_details, headers=headers, timeout=5 @@ -250,7 +250,7 @@ def create_client( return client = response.json() - print_colour("Done! Successfully created a new CILogon OAuth client app.") + print_colour("Done! Successfully created a new CILogon client app.") # Persist and encrypt the client credentials return persist_client_credentials_in_config_file(client, hub_type, config_filename) @@ -309,11 +309,12 @@ def get_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None): admin_id, admin_secret, cluster_name, hub_name, client_id ): return - else: - client_id = load_client_id_from_file(config_filename) - # No client has been found - if not client_id: - return + + client_id = load_client_id_from_file(config_filename) + # No client has been found + if not client_id: + return + headers = build_request_headers(admin_id, admin_secret) response = requests.get( build_request_url(client_id), params=None, headers=headers, timeout=5 @@ -352,11 +353,11 @@ def delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None client_id, ): return - else: - client_id = load_client_id_from_file(config_filename) - # Nothing to do if no client has been found - if not client_id: - return + + client_id = load_client_id_from_file(config_filename) + # Nothing to do if no client has been found + if not client_id: + return print(f"Deleting the CILogon client details for {client_id}...") headers = build_request_headers(admin_id, admin_secret) @@ -372,7 +373,7 @@ def delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None def get_all_clients(admin_id, admin_secret): - print("Getting all existing OAauth client applications...") + print("Getting all existing CILogon client applications...") headers = build_request_headers(admin_id, admin_secret) response = requests.get( build_request_url(), params=None, headers=headers, timeout=5 @@ -419,7 +420,7 @@ def cilogon_client_create( help="The hub domain, as specified in `cluster.yaml` (ex: staging.2i2c.cloud)", ), ): - """Create a CILogon OAuth client for a hub.""" + """Create a CILogon client for a hub.""" admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() callback_url = f"https://{hub_domain}/hub/oauth_callback" create_client( @@ -438,7 +439,7 @@ def cilogon_client_update( help="The hub domain, as specified in `cluster.yaml` (ex: staging.2i2c.cloud)", ), ): - """Update the CILogon OAuth client of a hub.""" + """Update the CILogon client of a hub.""" admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() callback_url = f"https://{hub_domain}/hub/oauth_callback" update_client(admin_id, admin_secret, cluster_name, hub_name, callback_url) @@ -458,7 +459,7 @@ def cilogon_client_get( @app.command() def cilogon_client_get_all(): - """Retrieve details about all existing 2i2c CILogon OAuth clients.""" + """Retrieve details about all existing 2i2c CILogon clients.""" admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() get_all_clients(admin_id, admin_secret) @@ -472,12 +473,12 @@ def cilogon_client_delete( ), client_id: str = typer.Option( "", - help="""(Optional) Id of the CILogon OAuth client to delete of the form `cilogon:/client_id/`. + help="""(Optional) Id of the CILogon client to delete of the form `cilogon:/client_id/`. If the id is not passed, it will be retrieved from the configuration file """, ), ): - """Delete an existing CILogon client. This deletes both the CILogon OAuth application, + """Delete an existing CILogon client. This deletes both the CILogon client application, and the client credentials from the configuration file.""" admin_id, admin_secret = get_2i2c_cilogon_admin_credentials() delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id) From 5cb2e91cc2880eb4c1e0c6d337c986c63ebb0886 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Tue, 14 Mar 2023 12:25:30 +0200 Subject: [PATCH 23/33] Move some file manipulation functions to another file to reuse them --- deployer/auth0_app.py | 1 + deployer/cilogon_app.py | 201 +++++++++++++++-------------------- deployer/file_acquisition.py | 92 ++++++++++++++++ 3 files changed, 179 insertions(+), 115 deletions(-) diff --git a/deployer/auth0_app.py b/deployer/auth0_app.py index 79cc95b4aa..3c7d35e2d0 100644 --- a/deployer/auth0_app.py +++ b/deployer/auth0_app.py @@ -244,6 +244,7 @@ def auth0_client_create( } } } + print(json.dumps(jupyterhub_config, sort_keys=True, indent=4)) diff --git a/deployer/cilogon_app.py b/deployer/cilogon_app.py index d1e4baca43..0e46190a72 100644 --- a/deployer/cilogon_app.py +++ b/deployer/cilogon_app.py @@ -17,7 +17,6 @@ import base64 import json -import subprocess from pathlib import Path import requests @@ -26,7 +25,12 @@ from yarl import URL from .cli_app import app -from .file_acquisition import find_absolute_path_to_cluster_file, get_decrypted_file +from .file_acquisition import ( + build_absolute_path_to_hub_encrypted_config_file, + get_decrypted_file, + persist_config_in_encrypted_file, + remove_jupyterhub_hub_config_key_from_encrypted_file, +) from .utils import print_colour yaml = YAML(typ="safe") @@ -62,17 +66,6 @@ def build_client_details(cluster_name, hub_name, callback_url): } -def build_config_filename(cluster_name, hub_name): - cluster_config_dir_path = find_absolute_path_to_cluster_file(cluster_name).parent - return cluster_config_dir_path.joinpath(f"enc-{hub_name}.secret.values.yaml") - - -def config_file_exists(config_filename): - if not Path(config_filename).is_file(): - return False - return True - - def persist_client_credentials_in_config_file(client, hub_type, config_filename): auth_config = {} jupyterhub_config = { @@ -93,32 +86,13 @@ def persist_client_credentials_in_config_file(client, hub_type, config_filename) else: auth_config = jupyterhub_config - if config_file_exists(config_filename): - subprocess.check_call(["sops", "--decrypt", "--in-place", config_filename]) - with open(config_filename, "r+") as f: - config = yaml.load(f) - config.update(auth_config) - f.seek(0) - yaml.dump(config, f) - f.truncate() - subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) - print_colour( - f"Successfully updated the {config_filename} file with the encrypted CILogon client app credentials." - ) - return - - with open(config_filename, "a+") as f: - yaml.dump(auth_config, f) - subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) + persist_config_in_encrypted_file(config_filename, auth_config) print_colour( f"Successfully persisted the encrypted CILogon client app credentials to file {config_filename}" ) def load_client_id_from_file(config_filename): - if not config_file_exists(config_filename): - return - with get_decrypted_file(config_filename) as decrypted_path: with open(decrypted_path) as f: auth_config = yaml.load(f) @@ -133,72 +107,21 @@ def load_client_id_from_file(config_filename): return auth_config["jupyterhub"]["hub"]["config"]["CILogonOAuthenticator"][ "client_id" ] - # Event if it exists, the config_file might contain other config too, not just CILogon credentials - except KeyError: - return - - -def remove_client_credentials_from_config_file(config_filename): - if not config_file_exists(config_filename): - return - - with get_decrypted_file(config_filename) as decrypted_path: - with open(decrypted_path) as f: - config = yaml.load(f) - - basehub = config.get("basehub", None) - try: - if basehub: - config["basehub"]["jupyterhub"]["hub"]["config"].pop( - "CILogonOAuthenticator" - ) - else: - config["jupyterhub"]["hub"]["config"].pop("CILogonOAuthenticator") except KeyError: - print_colour("No CILogon client app to delete from {config_filename}") return - def clean_empty_nested_dicts(d): - if isinstance(d, dict): - return { - key: value - for key, value in ( - (key, clean_empty_nested_dicts(value)) for key, value in d.items() - ) - if value - } - return d - - remaining_config = clean_empty_nested_dicts(config) - - if remaining_config: - with open(config_filename, "w") as f: - yaml.dump(remaining_config, f) - f.truncate() - - subprocess.check_call(["sops", "--encrypt", "--in-place", config_filename]) - print_colour(f"CILogon client app removed from {config_filename}") - return - - # If the file only contained the CILogon credentials, then we can safely delete it - print_colour( - f"Deleted empty {config_filename} file after CILogon client app was removed." - ) - Path(config_filename).unlink() - def stored_client_id_same_with_cilogon_records( - admin_id, admin_secret, cluster_name, hub_name, client_id + admin_id, admin_secret, cluster_name, hub_name, stored_client_id ): - stored_client_id = get_client(admin_id, admin_secret, cluster_name, hub_name)[ - "client_id" - ] - if stored_client_id != client_id: - print_colour( - "CILogon records are different than the client app stored in the configuration file. Consider updating the file.", - "red", - ) + cilogon_client = get_client(admin_id, admin_secret, cluster_name, hub_name) + if not cilogon_client: + return False + + cilogon_client_id = cilogon_client.get("client_id", None) + if cilogon_client_id != stored_client_id: return False + return True @@ -224,19 +147,27 @@ def create_client( See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-post.sh """ client_details = build_client_details(cluster_name, hub_name, callback_url) - config_filename = build_config_filename(cluster_name, hub_name) + config_filename = build_absolute_path_to_hub_encrypted_config_file( + cluster_name, hub_name + ) # Check if there's a client id already stored in the config file for this hub - client_id = load_client_id_from_file(config_filename) - if client_id: - print_colour( - f"Found existing CILogon client app in {config_filename}.", "yellow" - ) - # Also check if what's in the file matches CILogon records in case the file was not updated accordingly - # Exit anyway since manual intervention is required if different - return stored_client_id_same_with_cilogon_records( - admin_id, admin_secret, cluster_name, hub_name, client_id - ) + if Path(config_filename).is_file(): + client_id = load_client_id_from_file(config_filename) + if client_id: + print_colour( + f"Found existing CILogon client app in {config_filename}.", "yellow" + ) + # Also check if what's in the file matches CILogon records in case the file was not updated accordingly + # Exit anyway since manual intervention is required if different + if not stored_client_id_same_with_cilogon_records( + admin_id, admin_secret, cluster_name, hub_name, client_id + ): + print_colour( + "CILogon records are different than the client app stored in the configuration file. Consider updating the file.", + "red", + ) + return # Ask CILogon to create the client print(f"Creating a new CILogon client app with details {client_details}...") @@ -272,9 +203,14 @@ def update_client(admin_id, admin_secret, cluster_name, hub_name, callback_url): See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-put.sh """ client_details = build_client_details(cluster_name, hub_name, callback_url) - config_filename = build_config_filename(cluster_name, hub_name) - client_id = load_client_id_from_file(config_filename) + config_filename = build_absolute_path_to_hub_encrypted_config_file( + cluster_name, hub_name + ) + if not Path(config_filename).is_file(): + print_colour("Can't update a client that doesn't exist", "red") + return + client_id = load_client_id_from_file(config_filename) if not client_id: print_colour("Can't update a client that doesn't exist", "red") return @@ -302,12 +238,20 @@ def get_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None): See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-get.sh """ - config_filename = build_config_filename(cluster_name, hub_name) + config_filename = build_absolute_path_to_hub_encrypted_config_file( + cluster_name, hub_name + ) + if not Path(config_filename).is_file(): + return if client_id: if not stored_client_id_same_with_cilogon_records( admin_id, admin_secret, cluster_name, hub_name, client_id ): + print_colour( + "CILogon records are different than the client app stored in the configuration file. Consider updating the file.", + "red", + ) return client_id = load_client_id_from_file(config_filename) @@ -340,9 +284,27 @@ def delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None See: https://github.com/ncsa/OA4MP/blob/HEAD/oa4mp-server-admin-oauth2/src/main/scripts/oidc-cm-scripts/cm-delete.sh """ - config_filename = build_config_filename(cluster_name, hub_name) + config_filename = build_absolute_path_to_hub_encrypted_config_file( + cluster_name, hub_name + ) - if client_id: + if not client_id: + if Path(config_filename).is_file(): + client_id = load_client_id_from_file(config_filename) + # Nothing to do if no client has been found + if not client_id: + print_colour( + "No `client_id` to delete was provided and couldn't find any in `config_filename`", + "red", + ) + return + else: + print_colour( + f"No `client_id` to delete was provided and couldn't find any {config_filename} file", + "red", + ) + return + else: if not stored_client_id_same_with_cilogon_records( admin_id, admin_secret, @@ -352,13 +314,12 @@ def delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None hub_name, client_id, ): + print_colour( + "CILogon records are different than the client app stored in the configuration file. Consider updating the file.", + "red", + ) return - client_id = load_client_id_from_file(config_filename) - # Nothing to do if no client has been found - if not client_id: - return - print(f"Deleting the CILogon client details for {client_id}...") headers = build_request_headers(admin_id, admin_secret) response = requests.delete(build_request_url(client_id), headers=headers, timeout=5) @@ -368,8 +329,18 @@ def delete_client(admin_id, admin_secret, cluster_name, hub_name, client_id=None print_colour("Done!") - # Delete client credentials from file also - remove_client_credentials_from_config_file(config_filename) + # Delete client credentials from config file also if file exists + if Path(config_filename).is_file(): + print(f"Deleting the CILogon client details from the {config_filename} also...") + key = "CILogonOAuthenticator" + try: + remove_jupyterhub_hub_config_key_from_encrypted_file(config_filename, key) + except KeyError: + print_colour(f"No {key} found to delete from {config_filename}", "yellow") + return + print_colour(f"CILogonAuthenticator config removed from {config_filename}") + if not Path(config_filename).is_file(): + print_colour(f"Empty {config_filename} file also deleted.", "yellow") def get_all_clients(admin_id, admin_secret): diff --git a/deployer/file_acquisition.py b/deployer/file_acquisition.py index 72560844fe..7fb668317e 100644 --- a/deployer/file_acquisition.py +++ b/deployer/file_acquisition.py @@ -68,6 +68,98 @@ def find_absolute_path_to_cluster_file(cluster_name: str, is_test: bool = False) return cluster_yaml_path +def build_absolute_path_to_hub_encrypted_config_file(cluster_name, hub_name): + """Builds the absolute path to a `enc-{hub_name}.secret.values.yaml` file + for a named cluster and hub + + Args: + cluster_name (str): The name of the cluster we wish to perform actions on. + This corresponds to a folder name, and that folder should contain a + cluster.yaml file. + hub_name (str): The name of the hub we wish to perform actions on. + This hub name must be listed in the cluster's cluster.yaml file. + + Returns: + Path object: The absolute path to the `enc-{hub_name}.secret.values.yaml` + in the `cluster_name` named cluster. + Note that file doesn't need to exist. + """ + cluster_config_dir_path = find_absolute_path_to_cluster_file(cluster_name).parent + encrypted_file_path = cluster_config_dir_path.joinpath( + f"enc-{hub_name}.secret.values.yaml" + ) + + return encrypted_file_path + + +def persist_config_in_encrypted_file(encrypted_file, config): + """ + Write `config` to `encrypted_file` file. + If `encrypted_file` doesn't exist, create it first. + If `encrypted_file` exits, then merge exiting config with `config` and write the merged config to file. + """ + if Path(encrypted_file).is_file(): + subprocess.check_call(["sops", "--decrypt", "--in-place", encrypted_file]) + with open(encrypted_file, "r+") as f: + config = yaml.load(f) + config.update(config) + f.seek(0) + yaml.dump(config, f) + f.truncate() + return subprocess.check_call( + ["sops", "--encrypt", "--in-place", encrypted_file] + ) + + with open(encrypted_file, "a+") as f: + yaml.dump(config, f) + return subprocess.check_call(["sops", "--encrypt", "--in-place", encrypted_file]) + + +def remove_jupyterhub_hub_config_key_from_encrypted_file(encrypted_file, key): + """ + Remove config from the dict `config["basehub"]["jupyterhub"]["hub"]["config"][key]` + in `encrypted_file` (the "basehub" key is optional). + + If after removing this config, the file only contains a config dict with empty leaves, + delete the entire file, as it no longer holds any information. + """ + _assert_file_exists(encrypted_file) + + with get_decrypted_file(encrypted_file) as decrypted_path: + with open(decrypted_path) as f: + config = yaml.load(f) + + basehub = config.get("basehub", None) + if basehub: + config["basehub"]["jupyterhub"]["hub"]["config"].pop(key) + else: + config["jupyterhub"]["hub"]["config"].pop(key) + + def clean_empty_nested_dicts(d): + if isinstance(d, dict): + return { + key: value + for key, value in ( + (key, clean_empty_nested_dicts(value)) for key, value in d.items() + ) + if value + } + return d + + remaining_config = clean_empty_nested_dicts(config) + + if remaining_config: + with open(encrypted_file, "w") as f: + yaml.dump(remaining_config, f) + f.truncate() + + subprocess.check_call(["sops", "--encrypt", "--in-place", encrypted_file]) + return + + # If the file only contained configuration for `key`, then we can safely delete it + Path(encrypted_file).unlink() + + @contextmanager def get_decrypted_file(original_filepath): """ From 841bf6720a081623d5351cca70a53871a7afbc3b Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Tue, 14 Mar 2023 13:09:35 +0200 Subject: [PATCH 24/33] Have auth0 persist config in file --- deployer/auth0_app.py | 25 ++++++++++++++++++++++--- deployer/file_acquisition.py | 6 +++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/deployer/auth0_app.py b/deployer/auth0_app.py index 3c7d35e2d0..79eb2a36d3 100644 --- a/deployer/auth0_app.py +++ b/deployer/auth0_app.py @@ -1,4 +1,3 @@ -import json import re import typer @@ -8,7 +7,11 @@ from yarl import URL from .cli_app import app -from .file_acquisition import get_decrypted_file +from .file_acquisition import ( + build_absolute_path_to_hub_encrypted_config_file, + get_decrypted_file, + persist_config_in_encrypted_file, +) yaml = YAML(typ="safe") @@ -208,6 +211,10 @@ def auth0_client_create( ..., help="Name of the hub for which a new Auth0 client will be created", ), + hub_type: str = typer.Argument( + "basehub", + help="Type of hub for which we'll create an Auth0 client (ex: basehub, daskhub)", + ), hub_domain: str = typer.Argument( ..., help="The hub domain, as specified in `cluster.yaml` (ex: staging.2i2c.cloud)", @@ -219,6 +226,9 @@ def auth0_client_create( ): """Create an Auth0 client app for a hub.""" domain, admin_id, admin_secret = get_2i2c_auth0_admin_credentials() + config_filename = build_absolute_path_to_hub_encrypted_config_file( + cluster_name, hub_name + ) auth_provider = KeyProvider(domain, admin_id, admin_secret) # Users will be redirected to this URL after they log out logout_url = f"https://{hub_domain}" @@ -232,6 +242,7 @@ def auth0_client_create( connection_name=connection_type, ) + auth_config = {} jupyterhub_config = { "jupyterhub": { "hub": { @@ -245,7 +256,15 @@ def auth0_client_create( } } - print(json.dumps(jupyterhub_config, sort_keys=True, indent=4)) + if hub_type != "basehub": + auth_config["basehub"] = jupyterhub_config + else: + auth_config = jupyterhub_config + + persist_config_in_encrypted_file(config_filename, auth_config) + print( + f"Successfully persisted the encrypted Auth0 client app credentials to file {config_filename}" + ) @app.command() diff --git a/deployer/file_acquisition.py b/deployer/file_acquisition.py index 7fb668317e..79dbb63f45 100644 --- a/deployer/file_acquisition.py +++ b/deployer/file_acquisition.py @@ -92,7 +92,7 @@ def build_absolute_path_to_hub_encrypted_config_file(cluster_name, hub_name): return encrypted_file_path -def persist_config_in_encrypted_file(encrypted_file, config): +def persist_config_in_encrypted_file(encrypted_file, new_config): """ Write `config` to `encrypted_file` file. If `encrypted_file` doesn't exist, create it first. @@ -102,7 +102,7 @@ def persist_config_in_encrypted_file(encrypted_file, config): subprocess.check_call(["sops", "--decrypt", "--in-place", encrypted_file]) with open(encrypted_file, "r+") as f: config = yaml.load(f) - config.update(config) + config.update(new_config) f.seek(0) yaml.dump(config, f) f.truncate() @@ -111,7 +111,7 @@ def persist_config_in_encrypted_file(encrypted_file, config): ) with open(encrypted_file, "a+") as f: - yaml.dump(config, f) + yaml.dump(new_config, f) return subprocess.check_call(["sops", "--encrypt", "--in-place", encrypted_file]) From 24e2420514e6194248f9447512bf2758bb5e4f9d Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Tue, 14 Mar 2023 13:12:55 +0200 Subject: [PATCH 25/33] Add back the auth0 req --- requirements.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements.txt b/requirements.txt index 15259f7e84..62721b361b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,3 +27,6 @@ escapism==1.* # requests is used by deployer/cilogon_app.py requests==2.* + +# auth0 is used to communicate with Auth0's REST API that we support as a deployer sub-cmd +auth0-python==3.* From 853bb1117e7b812bc86905ad4512f79c8424582a Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Tue, 14 Mar 2023 13:47:26 +0200 Subject: [PATCH 26/33] Update docs --- .../configure-auth/auth0.md | 50 +++++++++++++------ .../configure-auth/cilogon.md | 20 ++------ .../configure-auth/github-orgs.md | 16 ++---- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/docs/hub-deployment-guide/configure-auth/auth0.md b/docs/hub-deployment-guide/configure-auth/auth0.md index f15c3a9d13..3f6ee9efc8 100644 --- a/docs/hub-deployment-guide/configure-auth/auth0.md +++ b/docs/hub-deployment-guide/configure-auth/auth0.md @@ -1,8 +1,11 @@ # Auth0 -[`auth0`](https://auth0.com) provides authentication for the majority of 2i2c hubs. It can -be configured with many different [connections](https://auth0.com/docs/identityproviders) -that users can authenticate with - such as Google, GitHub, etc. +```warning +This authentication method is now deprecated and should only be used if absolutely necessary. +Please use [](auth:cilogon) instead. +``` + +[`auth0`](https://auth0.com) can be configured with many different [connections](https://auth0.com/docs/identityproviders) that users can authenticate with - such as Google, GitHub, etc. :::{note} If you wish to authenticate users based on their membership in a GitHub organization or team, you'll need to use [the native GitHub OAuthenticator instead](auth:github-orgs). @@ -10,21 +13,38 @@ If you wish to authenticate users based on their membership in a GitHub organiza So we want to manage authentication by: -1. Explicitly listing the type of connection we want for this hub, via - `auth0.connection`. Currently common ones are `google-oauth2` for Google & - `github` for GitHub. *Users* of the hub will use this method to log in to - the hub. +1. **Create an Auth0 client and configure it** + This can be achieved by using the `deployer auth0-client-create` command. - You can set the auth0 connector for a hub with: + - The command needs to be passed the cluster and hub name for which a client id and secret will be generated, but also the hub type, the hub domain, and the connection type. + Currently common ones are `google-oauth2` for Google & `github` for GitHub. *Users* of the hub will use this method to log in to the hub. + Theoretically, every provider in [this list](https://auth0.com/docs/connections/identity-providers-social) is supported. However, we've currently only tested this with Google(`google-oauth2`) and GitHub (`github`) - ```yaml - auth0: - connection: google-oauth2 - ``` - Theoretically, every provider in [this list](https://auth0.com/docs/connections/identity-providers-social) - is supported. However, we've currently only tested this with Google - (`google-oauth2`) and GitHub (`github`) + - Example script invocation that creates an Auth0 client for the 2i2c dask-staging hub and configures Auth0 to use GitHub as a connection is: + + ```bash + deployer cilogon-client-create create 2i2c dask-staging daskhub dask-staging.2i2c.cloud github + ``` + + - If successful, the script will have created a secret values file under `config/clusters//enc-.secret.values.yaml`. This file holds the encrypted OAuth client id and secret that have been created for this hub, but also all the other config needed for the hub **for simplicity**. + + - The unencrypted file contents should look like this: + ```yaml + jupyterhub: + hub: + config: + JupyterHub: + authenticator_class: auth0 + Auth0OAuthenticator: + auth0_subdomain: 2i2c.us + userdata_url: https://{domain}/userinfo, + username_key: github, + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + scope: ["openid", "name", "profile", "email"], + logout_redirect_url: LOGOUT_URL + ``` 2. Explicitly list *admin users* for a given hub. These admin users will be the only ones allowed to log in to begin with. They can use the JupyterHub diff --git a/docs/hub-deployment-guide/configure-auth/cilogon.md b/docs/hub-deployment-guide/configure-auth/cilogon.md index db37b4fdfc..9d3e04aa17 100644 --- a/docs/hub-deployment-guide/configure-auth/cilogon.md +++ b/docs/hub-deployment-guide/configure-auth/cilogon.md @@ -54,17 +54,7 @@ The steps to enable the JupyterHub CILogonOAuthenticator for a hub are similar w client_secret: CLIENT_SECRET ``` -2. **Set the hub to _not_ configure Auth0 in the `config/clusters//cluster.yaml` file.** - To ensure the deployer does not provision and configure an OAuth app from Auth0, the following config should be added to the appropriate hub in the cluster's `cluster.yaml` file. - - ```yaml - hubs: - - name: - auth0: - enabled: false - ``` - -3. **If not already present, add the secret hub config file to the list of helm chart values file in `config/clusters/cluster.yaml`.** +2. **If not already present, add the secret hub config file to the list of helm chart values file in `config/clusters/cluster.yaml`.** If you created the `enc-.secret.values.yaml` file in step 2, add it the the `cluster.yaml` file like so: ```yaml @@ -78,9 +68,9 @@ The steps to enable the JupyterHub CILogonOAuthenticator for a hub are similar w ... ``` -4. **Edit the non-secret config under `config/clusters//.values.yaml`.** +3. **Edit the non-secret config under `config/clusters//.values.yaml`.** - 4.1. **A few rules of thumb when using this method of authentication:** + 3.1. **A few rules of thumb when using this method of authentication:** - The `admin_users` list need to match `allowed_idps` rules too. @@ -98,7 +88,7 @@ The steps to enable the JupyterHub CILogonOAuthenticator for a hub are similar w You can check the [CILogon scopes section](https://www.cilogon.org/oidc#h.p_PEQXL8QUjsQm) to checkout available values for `username_claim`. This *cannot* be changed afterwards without manual migration of user names, so choose this carefully. ``` - 4.2. **Most common configurations for 2i2c clusters:** + 3.2. **Most common configurations for 2i2c clusters:** 1. **Only display specific identity provider as a login options** @@ -206,7 +196,7 @@ The steps to enable the JupyterHub CILogonOAuthenticator for a hub are similar w To learn about all the possible config options of the `CILogonOAuthenticator` dict, checkout [the docs](https://oauthenticator.readthedocs.io/en/latest/api/gen/oauthenticator.cilogon.html#oauthenticator.cilogon.CILogonOAuthenticator.allowed_idps). ``` -5. Run the deployer as normal to apply the config. +4. Run the deployer as normal to apply the config. ## Switch Identity Providers or user accounts diff --git a/docs/hub-deployment-guide/configure-auth/github-orgs.md b/docs/hub-deployment-guide/configure-auth/github-orgs.md index c0aa57cc9a..3e332b0b6a 100644 --- a/docs/hub-deployment-guide/configure-auth/github-orgs.md +++ b/docs/hub-deployment-guide/configure-auth/github-orgs.md @@ -52,17 +52,7 @@ You can remove yourself from the org once you have confirmed that login is worki `sops --output config/clusters//enc-.secret.values.yaml --encrypt config/clusters//.secret.values.yaml` ``` -3. **Set the hub to _not_ configure Auth0 in the `config/clusters//cluster.yaml` file.** - To ensure the deployer does not provision and configure an OAuth app from Auth0, the following config should be added to the appropriate hub in the cluster's `cluster.yaml` file. - - ```yaml - hubs: - - name: - auth0: - enabled: false - ``` - -4. **If not already present, add the secret hub config file to the list of helm chart values file in `config/clusters/cluster.yaml`.** +3. **If not already present, add the secret hub config file to the list of helm chart values file in `config/clusters/cluster.yaml`.** If you created the `enc-.secret.values.yaml` file in step 2, add it the the `cluster.yaml` file like so: ```yaml @@ -76,7 +66,7 @@ You can remove yourself from the org once you have confirmed that login is worki ... ``` -5. **Edit the non-secret config under `config/clusters//.values.yaml`.** +4. **Edit the non-secret config under `config/clusters//.values.yaml`.** You should make sure the matching hub config takes one of the following forms. ```{warning} @@ -140,7 +130,7 @@ You can remove yourself from the org once you have confirmed that login is worki ``` ```` -6. Run the deployer as normal to apply the config. +5. Run the deployer as normal to apply the config. ### Granting access to the OAuth app From deeead904424f024cf25878be82f679447ee9d1e Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Tue, 14 Mar 2023 15:58:01 +0200 Subject: [PATCH 27/33] Add instruction about the profile scope needed to get the preferred username claim from GitHub --- docs/hub-deployment-guide/configure-auth/cilogon.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/hub-deployment-guide/configure-auth/cilogon.md b/docs/hub-deployment-guide/configure-auth/cilogon.md index 9d3e04aa17..d77f215f19 100644 --- a/docs/hub-deployment-guide/configure-auth/cilogon.md +++ b/docs/hub-deployment-guide/configure-auth/cilogon.md @@ -129,7 +129,6 @@ The steps to enable the JupyterHub CILogonOAuthenticator for a hub are similar w 3. **Authenticate using GitHub with CILogon**: *This example sets the GitHub nickname as the Hub username using the `username_claim` option* - ```yaml jupyterhub: hub: @@ -137,6 +136,8 @@ The steps to enable the JupyterHub CILogonOAuthenticator for a hub are similar w JupyterHub: authenticator_class: cilogon CILogonOAuthenticator: + scope: + - "profile" oauth_callback_url: https://{{ HUB_DOMAIN }}/hub/oauth_callback shown_idps: - http://github.com/login/oauth/authorize From d11f4a5d90ee40a93d18aab9bc3eab66e0eb4d14 Mon Sep 17 00:00:00 2001 From: Georgiana Date: Wed, 15 Mar 2023 11:01:44 +0200 Subject: [PATCH 28/33] Fix admonition syntax Co-authored-by: Erik Sundell --- docs/hub-deployment-guide/configure-auth/auth0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hub-deployment-guide/configure-auth/auth0.md b/docs/hub-deployment-guide/configure-auth/auth0.md index 3f6ee9efc8..a277563925 100644 --- a/docs/hub-deployment-guide/configure-auth/auth0.md +++ b/docs/hub-deployment-guide/configure-auth/auth0.md @@ -1,6 +1,6 @@ # Auth0 -```warning +```{warning} This authentication method is now deprecated and should only be used if absolutely necessary. Please use [](auth:cilogon) instead. ``` From 0aa6b6285a1980e935b54a939bc35a6d6137d132 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Wed, 15 Mar 2023 11:05:57 +0200 Subject: [PATCH 29/33] Remove warning as no longer true --- deployer/hub.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/deployer/hub.py b/deployer/hub.py index dadcfa19e9..f189df8d5b 100644 --- a/deployer/hub.py +++ b/deployer/hub.py @@ -26,8 +26,6 @@ def __init__(self, cluster, spec): def get_generated_config(self): """ Generate config automatically for each hub - - WARNING: MIGHT CONTAINS SECRET VALUES! """ generated_config = { "jupyterhub": { From 4f6324e52f16ec7cf64ba6cf05d6fb2c59ac21f1 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Wed, 15 Mar 2023 11:48:30 +0200 Subject: [PATCH 30/33] Keep admin and allowed lists in common cluster config --- config/clusters/carbonplan/common.values.yaml | 5 +++++ config/clusters/carbonplan/prod.values.yaml | 4 ---- config/clusters/carbonplan/staging.values.yaml | 4 ---- config/clusters/meom-ige/prod.values.yaml | 8 -------- config/clusters/meom-ige/staging.values.yaml | 8 -------- config/clusters/openscapes/common.values.yaml | 8 ++++++++ config/clusters/openscapes/prod.values.yaml | 8 -------- config/clusters/openscapes/staging.values.yaml | 8 -------- 8 files changed, 13 insertions(+), 40 deletions(-) diff --git a/config/clusters/carbonplan/common.values.yaml b/config/clusters/carbonplan/common.values.yaml index b716b9efd3..6896e96485 100644 --- a/config/clusters/carbonplan/common.values.yaml +++ b/config/clusters/carbonplan/common.values.yaml @@ -151,6 +151,11 @@ basehub: readinessProbe: enabled: false nodeSelector: {} + config: + Authenticator: + allowed_users: &users + - jhamman + admin_users: *users dask-gateway: traefik: diff --git a/config/clusters/carbonplan/prod.values.yaml b/config/clusters/carbonplan/prod.values.yaml index ebd869d4c3..c7de1151d2 100644 --- a/config/clusters/carbonplan/prod.values.yaml +++ b/config/clusters/carbonplan/prod.values.yaml @@ -12,7 +12,3 @@ basehub: # Only show the option to login with GitHub shown_idps: - http://github.com/login/oauth/authorize - Authenticator: - allowed_users: &users - - jhamman - admin_users: *users diff --git a/config/clusters/carbonplan/staging.values.yaml b/config/clusters/carbonplan/staging.values.yaml index b7f1552c37..ba37f0016c 100644 --- a/config/clusters/carbonplan/staging.values.yaml +++ b/config/clusters/carbonplan/staging.values.yaml @@ -12,7 +12,3 @@ basehub: # Only show the option to login with GitHub shown_idps: - http://github.com/login/oauth/authorize - Authenticator: - allowed_users: &users - - jhamman - admin_users: *users diff --git a/config/clusters/meom-ige/prod.values.yaml b/config/clusters/meom-ige/prod.values.yaml index 26e349f6ca..523302c619 100644 --- a/config/clusters/meom-ige/prod.values.yaml +++ b/config/clusters/meom-ige/prod.values.yaml @@ -15,11 +15,3 @@ basehub: # Only show the option to login with GitHub shown_idps: - http://github.com/login/oauth/authorize - Authenticator: - admin_users: &users - - amfriesz - - jules32 - - erinmr - - betolink - # Without this, any GitHub user can authenticate - allowed_users: *users diff --git a/config/clusters/meom-ige/staging.values.yaml b/config/clusters/meom-ige/staging.values.yaml index f02991eac0..6c75c5ec30 100644 --- a/config/clusters/meom-ige/staging.values.yaml +++ b/config/clusters/meom-ige/staging.values.yaml @@ -15,11 +15,3 @@ basehub: # Only show the option to login with GitHub shown_idps: - http://github.com/login/oauth/authorize - Authenticator: - admin_users: &users - - amfriesz - - jules32 - - erinmr - - betolink - # Without this, any GitHub user can authenticate - allowed_users: *users diff --git a/config/clusters/openscapes/common.values.yaml b/config/clusters/openscapes/common.values.yaml index 6d3593df50..03a90d9e1d 100644 --- a/config/clusters/openscapes/common.values.yaml +++ b/config/clusters/openscapes/common.values.yaml @@ -248,6 +248,14 @@ basehub: enabled: false readinessProbe: enabled: false + Authenticator: + admin_users: &users + - amfriesz + - jules32 + - erinmr + - betolink + # Without this, any GitHub user can authenticate + allowed_users: *users dask-gateway: gateway: extraConfig: diff --git a/config/clusters/openscapes/prod.values.yaml b/config/clusters/openscapes/prod.values.yaml index d302fd8309..c7c357869f 100644 --- a/config/clusters/openscapes/prod.values.yaml +++ b/config/clusters/openscapes/prod.values.yaml @@ -12,11 +12,3 @@ basehub: # Only show the option to login with GitHub shown_idps: - http://github.com/login/oauth/authorize - Authenticator: - admin_users: &users - - amfriesz - - jules32 - - erinmr - - betolink - # Without this, any GitHub user can authenticate - allowed_users: *users diff --git a/config/clusters/openscapes/staging.values.yaml b/config/clusters/openscapes/staging.values.yaml index 676eb0bf39..d43636264e 100644 --- a/config/clusters/openscapes/staging.values.yaml +++ b/config/clusters/openscapes/staging.values.yaml @@ -12,11 +12,3 @@ basehub: # Only show the option to login with GitHub shown_idps: - http://github.com/login/oauth/authorize - Authenticator: - admin_users: &users - - amfriesz - - jules32 - - erinmr - - betolink - # Without this, any GitHub user can authenticate - allowed_users: *users From f1744aff3caf49cc28a2bc6ba54c604cb49d1885 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Wed, 15 Mar 2023 12:32:45 +0200 Subject: [PATCH 31/33] Remove rebase comments --- config/clusters/cloudbank/avc.values.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/config/clusters/cloudbank/avc.values.yaml b/config/clusters/cloudbank/avc.values.yaml index a58cbc5bc1..2cdb26b0d8 100644 --- a/config/clusters/cloudbank/avc.values.yaml +++ b/config/clusters/cloudbank/avc.values.yaml @@ -32,7 +32,6 @@ jupyterhub: scopes: [read:users!group=section1, servers!group=section2] users: [sean.smorris@gmail.com] config: -<<<<<<< HEAD loadGroups: section1: - sean.smorris@gmail.com @@ -42,7 +41,6 @@ jupyterhub: - smorris@ausdk12.org - kae@gmail.com - ciara@gmail.com -======= JupyterHub: authenticator_class: cilogon CILogonOAuthenticator: @@ -51,7 +49,6 @@ jupyterhub: # Only show the option to login with Google shown_idps: - http://google.com/accounts/o8/id ->>>>>>> 1bf0e48c (Move cloudbank hubs from auth0 to cilogon) Authenticator: allowed_users: &avc_users - aculich@berkeley.edu From 4ffc44afa193c6e494e5453d8e5984ae24170803 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Wed, 15 Mar 2023 12:38:39 +0200 Subject: [PATCH 32/33] Nest the authenticator config correctly --- config/clusters/openscapes/common.values.yaml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/config/clusters/openscapes/common.values.yaml b/config/clusters/openscapes/common.values.yaml index 03a90d9e1d..720b986b4b 100644 --- a/config/clusters/openscapes/common.values.yaml +++ b/config/clusters/openscapes/common.values.yaml @@ -248,14 +248,15 @@ basehub: enabled: false readinessProbe: enabled: false - Authenticator: - admin_users: &users - - amfriesz - - jules32 - - erinmr - - betolink - # Without this, any GitHub user can authenticate - allowed_users: *users + config: + Authenticator: + admin_users: &users + - amfriesz + - jules32 + - erinmr + - betolink + # Without this, any GitHub user can authenticate + allowed_users: *users dask-gateway: gateway: extraConfig: From e2d98fe984086d665fd13a8ed306188b012ad3e8 Mon Sep 17 00:00:00 2001 From: Georgiana Dolocan Date: Tue, 21 Mar 2023 09:38:14 +0200 Subject: [PATCH 33/33] Update qcl hub to remove any ref to auth0 old config --- config/clusters/qcl/cluster.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/clusters/qcl/cluster.yaml b/config/clusters/qcl/cluster.yaml index b46812433e..3c9f62e742 100644 --- a/config/clusters/qcl/cluster.yaml +++ b/config/clusters/qcl/cluster.yaml @@ -23,8 +23,6 @@ hubs: display_name: "QuantifiedCarbon (QCL)" domain: jupyter.quantifiedcarbon.com helm_chart: basehub - auth0: - enabled: false helm_chart_values_files: - common.values.yaml - prod.values.yaml