Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow restricting profiles & profile_options based on JupyterHub groups #3883

Merged
merged 17 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/clusters/2i2c-aws-us/itcoocean.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ jupyterhub:
- display_name: "Bring your own image"
description: Specify your own docker image (must have python and jupyterhub installed in it)
slug: custom
allowed_teams:
allowed_groups:
- Hackweek-ITCOocean:itcoocean-hackweek-2023
- nmfs-opensci:2i2c-demo
- 2i2c-org:hub-access-for-2i2c-staff
Expand Down
16 changes: 8 additions & 8 deletions config/clusters/2i2c-aws-us/showcase.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ basehub:
profileList:
- display_name: "Magic Link Demo"
description: "For demoing magic links"
allowed_teams:
allowed_groups:
- 2i2c-community-showcase:magiclinks-demo
kubespawner_override:
image: pangeo/pangeo-notebook:2023.06.20
Expand All @@ -69,7 +69,7 @@ basehub:
node.kubernetes.io/instance-type: r5.xlarge
- display_name: "NASA TOPS-T ScienceCore-ClimateRisk"
description: "For collaborative work on 2i2c/MD's NASA TOPS-T ScienceCore Module"
allowed_teams:
allowed_groups:
- 2i2c-demo-hub-access:showcase-topst
- 2i2c-org:hub-access-for-2i2c-staff
- ScienceCore:climaterisk-team
Expand All @@ -82,7 +82,7 @@ basehub:
node.kubernetes.io/instance-type: r5.xlarge
- display_name: "NASA TOPS-T ScienceCore"
description: "JupyterHubs for NASA ScienceCore Modules"
allowed_teams:
allowed_groups:
- 2i2c-org:hub-access-for-2i2c-staff
- ScienceCore:2i2c-showcase
profile_options:
Expand Down Expand Up @@ -132,7 +132,7 @@ basehub:
node.kubernetes.io/instance-type: r5.xlarge
- display_name: "Shared Small: 1-4 CPU, 8-32 GB"
description: "A shared machine, the recommended option until you experience a limitation."
allowed_teams: &allowed_teams
allowed_groups: &allowed_groups
- 2i2c-org:hub-access-for-2i2c-staff
- 2i2c-community-showcase:access-2i2c-showcase
profile_options: &profile_options
Expand Down Expand Up @@ -188,7 +188,7 @@ basehub:
- display_name: "Small: 4 CPU, 32 GB"
description: "A dedicated machine for you."
profile_options: *profile_options
allowed_teams: *allowed_teams
allowed_groups: *allowed_groups
kubespawner_override:
mem_guarantee: 28.937G
cpu_guarantee: 0.4
Expand All @@ -199,7 +199,7 @@ basehub:
- display_name: "Medium: 16 CPU, 128 GB"
description: "A dedicated machine for you."
profile_options: *profile_options
allowed_teams: *allowed_teams
allowed_groups: *allowed_groups
kubespawner_override:
mem_guarantee: 120.513G
cpu_guarantee: 1.6
Expand All @@ -210,7 +210,7 @@ basehub:
- display_name: "Large: 64 CPU, 512 GB"
description: "A dedicated machine for you"
profile_options: *profile_options
allowed_teams: *allowed_teams
allowed_groups: *allowed_groups
kubespawner_override:
mem_guarantee: 489.13G
cpu_guarantee: 6.4
Expand All @@ -220,7 +220,7 @@ basehub:

- display_name: NVIDIA Tesla T4, ~16 GB, ~4 CPUs
slug: gpu
allowed_teams:
allowed_groups:
- 2i2c-org:hub-access-for-2i2c-staff
description: "Start a container on a dedicated node with a GPU"
profile_options:
Expand Down
65 changes: 31 additions & 34 deletions config/clusters/earthscope/common.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ basehub:
hub:
extraConfig:
001-username-claim: |
from oauthenticator.auth0 import Auth0OAuthenticator
from traitlets import List, Unicode, default
from urllib.parse import urlencode
from oauthenticator.generic import GenericOAuthenticator
from traitlets import List, Unicode

class CustomAuth0OAuthenticator(Auth0OAuthenticator):
class CustomGenericOAuthenticator(GenericOAuthenticator):
# required_scopes functionality comes in from https://github.com/jupyterhub/oauthenticator/pull/719
# Can be removed from here once that PR is merged
required_scopes = List(
Expand All @@ -62,28 +61,6 @@ basehub:
""",
)

# Upstreamed at https://github.com/jupyterhub/oauthenticator/pull/722
logout_redirect_to_url = Unicode(
config=True,
help="""
Redirect to this URL after the user is logged out.

Must be explicitly added to the "Allowed Logout URLs" in the configuration
for this Auth0 application. See https://auth0.com/docs/authenticate/login/logout/redirect-users-after-logout
for more information.
"""
)

@default("logout_redirect_url")
def _logout_redirect_url_default(self):
url = f"https://{self.auth0_domain}/v2/logout"
if self.logout_redirect_to_url:
# If a redirectTo is set, we must also include the `client_id`
# Auth0 expects `client_id` to be snake cased while `redirectTo` is camel cased
params = urlencode({"client_id": self.client_id, "redirectTo": self.logout_redirect_to_url})
url = f"{url}?{params}"
return url

async def check_allowed(self, username, auth_model):
if await super().check_allowed(username, auth_model):
return True
Expand All @@ -99,6 +76,14 @@ basehub:

return False

async def authenticate(self, *args, **kwargs):
resp = await super().authenticate(*args, **kwargs)
# Setup groups to be same as list of scopes granted
# This can go away after https://github.com/jupyterhub/oauthenticator/pull/735 is
# merged
resp["groups"] = resp["auth_state"]["scope"]
return resp

def populate_token(spawner, auth_state):
# For our deployment-service-check health check user, there is no auth_state.
# So these env variables need not be set.
Expand All @@ -112,15 +97,13 @@ basehub:

c.Spawner.auth_state_hook = populate_token

c.JupyterHub.authenticator_class = CustomAuth0OAuthenticator
c.JupyterHub.authenticator_class = CustomGenericOAuthenticator
config:
JupyterHub:
authenticator_class: auth0
CustomAuth0OAuthenticator:
CustomGenericOAuthenticator:
required_scopes:
# This allows EarthScope to control who can login to the hub
- geolab
Auth0OAuthenticator:
GenericOAuthenticator:
scope:
- openid
# This gives us refresh token
Expand All @@ -130,10 +113,14 @@ basehub:
# automatically granted this scope, so we can test. See
# https://2i2c.freshdesk.com/a/tickets/1280 for how this was granted.
- geolab
- geolab:dev
- geolab:power
extra_authorize_params:
# This isn't an actual URL, just a string. Must not have a trailing slash
audience: https://api.dev.earthscope.org
username_claim: sub
# Convert 'scope' from the OAuth2 response into JupyterHub groups
manage_groups: true
Comment on lines +122 to +123
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can go, as manage_groups is already set to true at line 100 through
c.GenericOAuthenticator.manage_groups = True

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the line 100!

CILogonOAuthenticator:
allowed_idps:
http://github.com/login/oauth/authorize:
Expand All @@ -152,6 +139,10 @@ basehub:
profileList:
- display_name: "Shared Small: 1-4 CPU, 8-32 GB"
description: "A shared machine, the recommended option until you experience a limitation."
allowed_groups:
- geolab
- geolab:dev
- geolab:power
profile_options: &profile_options
image:
display_name: Image
Expand Down Expand Up @@ -186,30 +177,36 @@ basehub:
mem_limit: null
node_selector:
node.kubernetes.io/instance-type: r5.xlarge

- display_name: "Small: 4 CPU, 32 GB"
description: "A dedicated machine for you."
allowed_groups:
- geolab
- geolab:dev
- geolab:power
profile_options: *profile_options
kubespawner_override:
mem_guarantee: 28.937G
cpu_guarantee: 0.4
mem_limit: null
node_selector:
node.kubernetes.io/instance-type: r5.xlarge

- display_name: "Medium: 16 CPU, 128 GB"
description: "A dedicated machine for you."
profile_options: *profile_options
allowed_groups:
- geolab:dev
- geolab:power
kubespawner_override:
mem_guarantee: 120.513G
cpu_guarantee: 1.6
mem_limit: null
node_selector:
node.kubernetes.io/instance-type: r5.4xlarge

- display_name: "Large: 64 CPU, 512 GB"
description: "A dedicated machine for you"
profile_options: *profile_options
allowed_groups:
- geolab:power
kubespawner_override:
mem_guarantee: 489.13G
cpu_guarantee: 6.4
Expand Down
12 changes: 6 additions & 6 deletions config/clusters/earthscope/enc-prod.secret.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ basehub:
jupyterhub:
hub:
config:
Auth0OAuthenticator:
client_id: ENC[AES256_GCM,data:qn8Xel6vzFKHuL7gP8aGKQr3C7AGORQ7sCyNvKulbDE=,iv:bWYt/w31HcaEDjUBW3DZv/Lb4Ny/BPEjoBTsjp0XP6g=,tag:/02E1lYfhfOMcd+P2+DV8Q==,type:str]
client_secret: ENC[AES256_GCM,data:qry2vIkYLTRd7rlg6RTO6pB+e4SP5mvzClqagyJbbzXYkdeiGQccVFsERQ15RT/BRDX/PX4Bj5ZxcuCY9wGsxw==,iv:k763ow53AuqWG7dSyqkaosa9O4NwufRnmmORRxssGQA=,tag:MX4zqeOS3vdxhhYUljipJA==,type:str]
GenericOAuthenticator:
client_id: ENC[AES256_GCM,data:+ctWM1MpyksEjMLTnVZAw+N0Wv6ZNXL+fHdeamt64Ow=,iv:1KBoaNQTaUmyAt1wAO9pmvOkoLCl+B2eCBIu3SsRKYA=,tag:sK3EmbdSJP3UldX51274xA==,type:str]
client_secret: ENC[AES256_GCM,data:UtnmnF84dQ50h741JNvLmfBkzoI6ui16YVV8tRh1GXyCIrcu5bgy5StRIIjw3uRVo7g7bFFdGN6lIeQIUVd+Pw==,iv:arvQ5RbKiHFFNdyksmIA9UVoHWRdXgeKAhDGPPE7qrU=,tag:2NdZqXXBpEIUhrA3oTnKPw==,type:str]
sops:
kms: []
gcp_kms:
Expand All @@ -14,8 +14,8 @@ sops:
azure_kv: []
hc_vault: []
age: []
lastmodified: "2024-02-01T19:48:36Z"
mac: ENC[AES256_GCM,data:Cw3rTUGqQlymWXXu/Z7qLSAIlULn5B3SAPxbzkeBDCFSO8u4fhuZXEjoEBvFFdujdEtU9Q7bASKRyl4aveZDJ+aZHboKNDV77d7atONojcEFj/DIy2ELQriMwyq1hx5hZS/onGgt8XLmcjXDJdMH6zEZOYrZl93uTuoS+Qt+4GI=,iv:oCWMr+17mgo+P1btrLglokBO3yYZ9JpZBTx36Vhtb3s=,tag:GEN4T0/9KQzz4+oTxvhbBQ==,type:str]
lastmodified: "2024-03-29T23:50:57Z"
mac: ENC[AES256_GCM,data:h9pUWffgf8vBqG4timmCMharFGj1jdP8iSaaczx1GfzouUG+hhlG82OQTFVSmLwhHkzlmxJxw+t7gi6Zwx9nNgVVfnwa4Qhw6V/XWrBRr8gre2I9+MuXXeYOcjiDqIyasF0TYxGW/kvLZ6+khGvi4iIhnk9rJOk/LpFhpj7IthQ=,iv:1yIFhnW1Mv+d5bBKFGgpMDCCt5zPGfP9YekGey4KF/g=,tag:YgXBpr03lP5q9y1sJ2CsUA==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.7.3
version: 3.8.1
12 changes: 6 additions & 6 deletions config/clusters/earthscope/enc-staging.secret.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ basehub:
jupyterhub:
hub:
config:
Auth0OAuthenticator:
client_id: ENC[AES256_GCM,data:urLrYypX6IUSVpqFAumEAi9aGJKyQv8oQuNqw5HNhKo=,iv:sQcq2R5wbS2P00nygxPQ3p2LdAsxkRQrk4jvnMWAjQg=,tag:eosLpXx6vWQMNjIxDcsC7Q==,type:str]
client_secret: ENC[AES256_GCM,data:PrphM7gVSfUOInO008VgfhNU4r1+I4oLRT+ypJv5848Bvy1nN+ARzTrPgu7Q3KIiCaXyfNd3Xv6ieb0lsKCLZw==,iv:Vnbo4jG0sARtOL28GxgGAKKITQb5Tx6/TNscWUNgkJU=,tag:RgxhqVzdfsmwMTTEMCn2Zw==,type:str]
GenericOAuthenticator:
client_id: ENC[AES256_GCM,data:Rpa6XhJLmHBkccOZM58T0IwcviJvc2+jbLbL3LDQxgI=,iv:57//hbKbkT8PDa1kanOoS4wlWLvc1hp8fyGgMMaUKzk=,tag:zyv29aa/M7cqar2izZDRTg==,type:str]
client_secret: ENC[AES256_GCM,data:w7feSVDwFN0mbxvLH1DEpw/eanx5+vJXZ7JPSTkVxIAm0aZod4H7lhlEy/gmMgPUJfBF32tXPrrYh6Z5E83oIQ==,iv:RQt6NCiDwAwn15XGxF7T+DVdYck0kw/hKEV9ULgxY1k=,tag:BRnwMh76yaMF7RyKPhBd/g==,type:str]
sops:
kms: []
gcp_kms:
Expand All @@ -14,8 +14,8 @@ sops:
azure_kv: []
hc_vault: []
age: []
lastmodified: "2024-02-01T19:48:31Z"
mac: ENC[AES256_GCM,data:ZYVgv+u0FD+jxYtgyITNLXr5bHNEEkkXtTM0SJGv8txbAVM4yt1k9CF95iVevPsRGG2yztY5vTDQaFGeg0tLGmG55fuuliZhMrB9RsDkmM3qEibVgQQTQZI5ZUciWHSBGm/NCMKnj6ujIx0h3E3cjtZBESIpONH+66kbuGhAlMo=,iv:ORwgid7PCff05bxWN9FuWNCN+wLY+bVZi0GfGDZwQj4=,tag:O+Bkh0UbeDzmAvYWJ5PpKQ==,type:str]
lastmodified: "2024-03-29T23:43:10Z"
mac: ENC[AES256_GCM,data:OnvUNbNHox7iF98w1aJSnrFJ1C3FSD+dz/l7ZK1z5uBnJAyhX3FhVoDGmA3TWAtS5U+ebiz8RbbVjJ/ge687ke2dL/Lnd9Ueay2tsF4ac1BYF6i5LqqsHqzaPwkrRVazB1aRgKx/O37Plm8KuAg2o9dN8jGtjnnSlbIxgJuJIUQ=,iv:Eo0iQ6qrbbcUkPFHzBwuMBGi1fCYnVWLPkkn9GQfrig=,tag:iUbwcWtat7qkfNE5i5MU6A==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.7.3
version: 3.8.1
9 changes: 5 additions & 4 deletions config/clusters/earthscope/prod.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ basehub:
name: "EarthScope"
hub:
config:
CustomAuth0OAuthenticator:
logout_redirect_to_url: https://geolab.earthscope.cloud
Auth0OAuthenticator:
auth0_domain: login.earthscope.org
GenericOAuthenticator:
token_url: https://login.earthscope.org/oauth/token
authorize_url: https://login.earthscope.org/authorize
userdata_url: https://login.earthscope.org/userinfo
logout_redirect_url: https://login.earthscope.org/v2/logout?client_id=2PbhUTbRU6e7uIaaEZIShotx15MbvsJJ
extra_authorize_params:
# This isn't an actual URL, just a string. Must not have a trailing slash
audience: https://api.earthscope.org
9 changes: 5 additions & 4 deletions config/clusters/earthscope/staging.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ basehub:
name: "EarthScope staging"
hub:
config:
CustomAuth0OAuthenticator:
logout_redirect_to_url: https://staging.geolab.earthscope.cloud
Auth0OAuthenticator:
auth0_domain: login-dev.earthscope.org
GenericOAuthenticator:
token_url: https://login-dev.earthscope.org/oauth/token
authorize_url: https://login-dev.earthscope.org/authorize
userdata_url: https://login-dev.earthscope.org/userinfo
logout_redirect_url: https://login-dev.earthscope.org/v2/logout?client_id=Kn6kSKtw9TqgrSrEmDS0rlBM7Sc69BkL
extra_authorize_params:
# This isn't an actual URL, just a string. Must not have a trailing slash
audience: https://api.dev.earthscope.org
8 changes: 4 additions & 4 deletions config/clusters/leap/common.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ basehub:
description: &profile_list_description "Start a container limited to a chosen share of capacity on a node of this type"
slug: medium-full
default: true
allowed_teams:
allowed_groups:
- 2i2c-org:hub-access-for-2i2c-staff
- leap-stc:leap-pangeo-full-access
profile_options:
Expand Down Expand Up @@ -235,13 +235,13 @@ basehub:

# NOTE: This is the second medium profile list entry, with less node
# share options for a different subset of users via the basehub
# specific allowed_teams configuration.
# specific allowed_groups configuration.
#
- display_name: "CPU only"
description: *profile_list_description
slug: medium-base
default: true
allowed_teams:
allowed_groups:
- leap-stc:leap-pangeo-base-access
profile_options:
requests:
Expand All @@ -262,7 +262,7 @@ basehub:
- display_name: GPU
slug: gpu
description: NVIDIA Tesla T4, 24GB RAM, 8 CPUs
allowed_teams:
allowed_groups:
- 2i2c-org:hub-access-for-2i2c-staff
- leap-stc:leap-pangeo-full-access
profile_options:
Expand Down
12 changes: 6 additions & 6 deletions config/clusters/meom-ige/common.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ basehub:
#
# - display_name: Grenoble demo
# default: true
# allowed_teams:
# allowed_groups:
# - 2i2c-org:hub-access-for-2i2c-staff
# - meom-group:hub-users # long term users
# - demo-dask-grenoble2023:demo # temporary users for event
Expand Down Expand Up @@ -93,7 +93,7 @@ basehub:
# RAM on a node, not total node capacity
- display_name: "Small"
default: true
allowed_teams: &allowed_teams_normal_use
allowed_groups: &allowed_groups_normal_use
- 2i2c-org:hub-access-for-2i2c-staff
- meom-group:hub-users # long term users
description: "~2 CPU, ~8G RAM"
Expand All @@ -103,31 +103,31 @@ basehub:
node_selector:
node.kubernetes.io/instance-type: n1-standard-2
- display_name: "Medium"
allowed_teams: *allowed_teams_normal_use
allowed_groups: *allowed_groups_normal_use
description: "~8 CPU, ~32G RAM"
kubespawner_override:
mem_limit: 32G
mem_guarantee: 22G
node_selector:
node.kubernetes.io/instance-type: n1-standard-8
- display_name: "Large"
allowed_teams: *allowed_teams_normal_use
allowed_groups: *allowed_groups_normal_use
description: "~16 CPU, ~64G RAM"
kubespawner_override:
mem_limit: 64G
mem_guarantee: 47G
node_selector:
node.kubernetes.io/instance-type: n1-standard-16
- display_name: "Very Large"
allowed_teams: *allowed_teams_normal_use
allowed_groups: *allowed_groups_normal_use
description: "~32 CPU, ~128G RAM"
kubespawner_override:
mem_limit: 128G
mem_guarantee: 100G
node_selector:
node.kubernetes.io/instance-type: n1-standard-32
- display_name: "Huge"
allowed_teams: *allowed_teams_normal_use
allowed_groups: *allowed_groups_normal_use
description: "~64 CPU, ~256G RAM"
kubespawner_override:
mem_limit: 256G
Expand Down
Loading