Skip to content

Commit

Permalink
Register the West STAC Transaction API resource server client with Gl…
Browse files Browse the repository at this point in the history
…obus Auth and create the dependent scope
  • Loading branch information
lukaszlacinski committed Nov 21, 2024
1 parent 74e64ac commit fb397ce
Showing 1 changed file with 142 additions and 0 deletions.
142 changes: 142 additions & 0 deletions scripts/globus_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import os
import sys
import argparse
import json
from globus_sdk import NativeAppAuthClient, RefreshTokenAuthorizer, AuthClient
from globus_sdk.scopes import AuthScopes
from globus_sdk import AuthAPIError
from globus_sdk.tokenstorage import SimpleJSONFileAdapter


globus_client_id = "ab9883f5-37d4-4066-b69f-ff3313e16dd8"
view_my_groups_and_memberships_scope_uuid = "73320ffe-4cb4-4b25-a0a3-83d53d59ce4f"


class WestDeployment:
def __init__(self):
self.native_client = NativeAppAuthClient(client_id=globus_client_id, app_name="West Deployment Client")
self.scopes = [AuthScopes.manage_projects, "openid", "profile", "email"]
filename = os.path.expanduser("~/.deployment_tokens.json")
self.token_storage = SimpleJSONFileAdapter(filename)

def do_login_flow(self):
self.native_client.oauth2_start_flow(requested_scopes=self.scopes, refresh_tokens=True)
authorize_url = self.native_client.oauth2_get_authorize_url(prompt="login")
print("Please go to this URL and login: {0}".format(authorize_url))
auth_code = input("Please enter the code here: ").strip()
return self.native_client.oauth2_exchange_code_for_tokens(auth_code)

def get_tokens(self, resource_server, prompt=None):
if not self.token_storage.file_exists() or prompt:
response = self.do_login_flow()
self.token_storage.store(response)
tokens = response.by_resource_server[resource_server]
else:
tokens = self.token_storage.get_token_data(resource_server)
return tokens

def get_auth_client(self, prompt=None):
tokens = self.get_tokens(AuthClient.resource_server, prompt)
auth_authorizer = RefreshTokenAuthorizer(
tokens["refresh_token"],
self.native_client,
access_token=tokens["access_token"],
expires_at=tokens["expires_at_seconds"],
on_refresh=self.token_storage,
)
auth_client = AuthClient(authorizer=auth_authorizer)
return auth_client

def get_user_info(self):
r = self.auth_client.userinfo()
self.sub = r.data.get("sub")
self.email = r.data.get("email")
print(f"sub: {self.sub}, email: {self.email}")

def get_project(self):
r = self.auth_client.get_projects()
# print(json.dumps(r.data, indent=4))
project_id = None
for project in r.data.get("projects", []):
project_name = project.get("project_name", "")
display_name = project.get("display_name", "")
if project_name != "ESGF2 Data Challenges" or display_name != "ESGF2 Data Challenges":
continue
admin_identities = project.get("admins", []).get("identities", [])
for identity in admin_identities:
if identity.get("id") == self.sub:
project_id = project.get("id")
break
if project_id:
break

if not project_id:
r = self.auth_client.create_project("ESGF2 Data Challenges", self.email, admin_ids=[self.sub])
project_id = r.data.get("project", {}).get("id")
self.project_id = project_id
print(f"project_id: {self.project_id}")

def get_client(self, new_client_name):
r = self.auth_client.get_clients()
for client in r.data.get("clients", []):
project_id = client.get("project", "")
if project_id != self.project_id:
continue
name = client.get("name", "")
if name != new_client_name:
continue
print(json.dumps(client, indent=4))
print(f"Error: client '{new_client_name}' already exists")
sys.exit(1)

def create_client(self, new_client_name):
r = self.auth_client.create_client(new_client_name, self.project_id, client_type="resource_server")

self.service_client_id = r.data.get("client").get("id")
r = self.auth_client.create_client_credential(self.service_client_id, "STAC Transaction API service client")
print(json.dumps(r.data, indent=4))
self.service_client_secret = r.data.get("credential").get("secret")

def get_dependent_scope(self):
r = self.auth_client.create_scope(
self.service_client_id,
"ESGF West STAC Transaction API",
"Verify membership in ESGF Publisher groups",
"esgf",
dependent_scopes=[
{
"scope": view_my_groups_and_memberships_scope_uuid,
"optional": False,
"requires_refresh_token": True,
}
],
advertised=True,
)
print(json.dumps(r.data, indent=4))

def setup_service_client(self, name_suffix):
self.auth_client = self.get_auth_client()
self.get_user_info()
self.get_project()
new_client_name = f"ESGF2 Data Challenge Transaction API service client - {name_suffix}"
self.get_client(new_client_name)
try:
self.create_client(new_client_name)
except AuthAPIError:
self.auth_client = self.get_auth_client(prompt="login")
self.create_client(new_client_name)

self.get_dependent_scope()


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--client-name-suffix",
required=True,
help="suffix that will be added to the client name 'ESGF2 Data Challenge Transaction API service client - '",
)
args = parser.parse_args()

wd = WestDeployment()
wd.setup_service_client(args.client_name_suffix)

0 comments on commit fb397ce

Please sign in to comment.