Skip to content

Commit

Permalink
Merge pull request #14 from esgf2-us/globus_setup
Browse files Browse the repository at this point in the history
Register the West STAC Transaction API resource server client
  • Loading branch information
sturoscy-personal authored Dec 4, 2024
2 parents 74e64ac + fb397ce commit abd5168
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 abd5168

Please sign in to comment.