def check_user(email): auth_client = ConfidentialAppAuthClient(config.CLIENT_ID, config.GLOBUS_SECRET) user_info = auth_client.get_identities(usernames=email) user_identity = user_info.data['identities'] identity_id = user_identity[0]['id'] if user_identity else None return identity_id
def authenticate(r: request) -> [str, abort]: """Authenticates a request using Globus Auth. If user is authenticated, return client_id from Globus introspection object, else abort. Parameters ---------- r : request Flask request object as made by the user. Returns ------- [str, abort] Returns client ID or abort message. """ if "Authorization" not in r.headers: abort(401, "You must be logged in to perform this function.") else: token = request.headers.get("Authorization") token = str.replace(str(token), "Bearer ", "") conf_app = ConfidentialAppAuthClient(app.config["GLOBUS_CLIENT"], app.config["GLOBUS_KEY"]) intro_obj = conf_app.oauth2_token_introspect(token) if "client_id" in intro_obj: return str(intro_obj["client_id"]) else: abort(400, "Failed to authenticate user")
def convert(): if 'Authorization' not in request.headers: abort(401, 'You must be logged in to perform this function.') token = request.headers.get('Authorization') token = str.replace(str(token), 'Bearer ', '') conf_app = ConfidentialAppAuthClient(os.environ["GL_CLIENT"], os.environ["GL_CLIENT_SECRET"]) intro_obj = conf_app.oauth2_token_introspect(token) if "client_id" in intro_obj: client_id = str(intro_obj["client_id"]) definition_entry = select_by_column( "definition", definition_id=request.json["definition_id"]) if definition_entry is not None and len(definition_entry) == 1: definition_entry = definition_entry[0] if definition_entry["definition_owner"] != client_id: abort(400, "You don't have permission to use this definition file") else: return convert_definition_file(definition_entry) else: abort(400, "Definition ID not valid") else: abort(400, "Failed to authenticate user")
def funcx_test_config(pytestconfig, funcx_test_config_name): # start with basic config load config = _CONFIGS[funcx_test_config_name] # if `--endpoint` was passed or `endpoint_uuid` is present in config, # handle those cases endpoint = pytestconfig.getoption("--endpoint") if endpoint: config["endpoint_uuid"] = endpoint elif config["endpoint_uuid"] is None: config["endpoint_uuid"] = _get_local_endpoint_id() if not config["endpoint_uuid"]: # If there's no endpoint_uuid available, the smoke tests won't work raise Exception("No target endpoint_uuid available to test against") # set URIs if passed client_args = config["client_args"] ws_uri = pytestconfig.getoption("--ws-uri") api_uri = pytestconfig.getoption("--service-address") # env vars to allow use of client creds in GitHub Actions api_client_id = os.getenv("FUNCX_SMOKE_CLIENT_ID") api_client_secret = os.getenv("FUNCX_SMOKE_CLIENT_SECRET") if ws_uri: client_args["results_ws_uri"] = ws_uri if api_uri: client_args["funcx_service_address"] = api_uri if api_client_id and api_client_secret: client = ConfidentialAppAuthClient(api_client_id, api_client_secret) scopes = [ "https://auth.globus.org/scopes/facd7ccc-c5f4-42aa-916b-a0e270e2c2a9/all", "urn:globus:auth:scope:search.api.globus.org:all", "openid", ] token_response = client.oauth2_client_credentials_tokens( requested_scopes=scopes) fx_token = token_response.by_resource_server["funcx_service"][ "access_token"] search_token = token_response.by_resource_server[ "search.api.globus.org"]["access_token"] openid_token = token_response.by_resource_server["auth.globus.org"][ "access_token"] fx_auth = AccessTokenAuthorizer(fx_token) search_auth = AccessTokenAuthorizer(search_token) openid_auth = AccessTokenAuthorizer(openid_token) client_args["fx_authorizer"] = fx_auth client_args["search_authorizer"] = search_auth client_args["openid_authorizer"] = openid_auth return config
def repo2docker(): if 'Authorization' not in request.headers: abort(401, 'You must be logged in to perform this function.') token = request.headers.get('Authorization') token = str.replace(str(token), 'Bearer ', '') conf_app = ConfidentialAppAuthClient(os.environ["GL_CLIENT"], os.environ["GL_CLIENT_SECRET"]) intro_obj = conf_app.oauth2_token_introspect(token) if "client_id" in intro_obj: client_id = str(intro_obj["client_id"]) build_id = str(uuid.uuid4()) if request.json is not None and "git_repo" in request.json and "container_name" in request.json: put_message({ "function_name": "repo2docker_container", "client_id": client_id, "build_id": build_id, "target": request.json["git_repo"], "container_name": request.json["container_name"] }) manager.start_thread() return build_id elif 'file' in request.files: file = request.files['file'] if file.filename == '': abort(400, "No file selected") if file: file_path = tempfile.mkstemp()[1] with open(file_path, "wb") as f: f.write(file.read()) put_message({ "function_name": "repo2docker_container", "client_id": client_id, "build_id": build_id, "target": file_path, "container_name": file.filename }) manager.start_thread() return build_id else: return abort(400, "Failed to upload file") else: abort(400, "No git repo or file") else: abort(400, "Failed to authenticate user")
def __init__( self, client_id: str, client_secret: str, expected_scopes: Iterable[str], expected_audience: Optional[str] = None, cache_config: Optional[dict] = None, ) -> None: self.auth_client = ConfidentialAppAuthClient(client_id, client_secret) self.default_expected_scopes = frozenset(expected_scopes) if expected_audience is None: self.expected_audience = client_id else: self.expected_audience = expected_audience if cache_config: dogpile_cache.configure( backend=cache_config.pop("backend", DEFAULT_CACHE_BACKEND), expiration_time=cache_config.pop("timeout", DEFAULT_CACHE_TIMEOUT), arguments=cache_config, replace_existing_backend=True, ) # Try to check a 'token' and fail fast here in case client_id/secret are bad: try: self.check_token("NotAToken").introspect_token() except GlobusAPIError as err: if err.http_status == 401: raise ConfigurationError("Check client_id and client_secret", err)
def get_uid_from_token(auth_token): # Step 1: Get Auth Client with Secrets. client_id = os.getenv("GLOBUS_FUNCX_CLIENT") secret = os.getenv("GLOBUS_FUNCX_SECRET") # Step 2: Transform token and introspect it. conf_app_client = ConfidentialAppAuthClient(client_id, secret) token = str.replace(str(auth_token), 'Bearer ', '') auth_detail = conf_app_client.oauth2_token_introspect(token) try: uid = auth_detail['username'] except KeyError as e: raise ValueError(str(e)) return uid
def ls_cc(self, name, id, pw): self.print_header(name, id) try: auth_client = ConfidentialAppAuthClient(client_id=id, client_secret=pw) scopes = "urn:globus:auth:scope:transfer.api.globus.org:all" cc_authorizer = ClientCredentialsAuthorizer(auth_client, scopes) transfer_client = TransferClient(authorizer=cc_authorizer) results = transfer_client.endpoint_search( filter_scope="my-endpoints") endpoint_list = list(results) if endpoint_list: print("Owned endpoints:") for ep in endpoint_list: print("{} ({})".format(ep['display_name'], ep['id'])) else: print("(No owned endpoints.)") results = transfer_client.endpoint_search( filter_scope="shared-with-me") endpoint_list = list(results) if endpoint_list: print("Shared endpoints:") for ep in endpoint_list: print("{} ({})".format(ep['display_name'], ep['id'])) else: print("(No shared endpoints.)") except AuthAPIError as e: print(e)
def getAuthClient(self): if self.authClient is None: clientId = self.getGlobusClientId() clientSecret = self.getGlobusClientSecret() self.authClient = ConfidentialAppAuthClient(clientId, clientSecret) return self.authClient
def __init__(self, config: UOCloudSyncConfig): confidential_client = ConfidentialAppAuthClient( client_id=config.get_client_id(), client_secret=config.get_client_secret()) scopes = "urn:globus:auth:scope:transfer.api.globus.org:all" cc_authorizer = ClientCredentialsAuthorizer(confidential_client, scopes) # create a new client self._transfer_client = TransferClient(authorizer=cc_authorizer) self._src_endpoint = None self._dest_endpoint = None
def pull(): if 'Authorization' not in request.headers: abort(401, 'You must be logged in to perform this function.') token = request.headers.get('Authorization') token = str.replace(str(token), 'Bearer ', '') conf_app = ConfidentialAppAuthClient(os.environ["GL_CLIENT"], os.environ["GL_CLIENT_SECRET"]) intro_obj = conf_app.oauth2_token_introspect(token) if "client_id" in intro_obj: client_id = intro_obj["client_id"] params = request.json if "build_id" in params: build_id = params["build_id"] build_entry = select_by_column("build", build_id=build_id) if build_entry is not None and len(build_entry) == 1: build_entry = build_entry[0] if build_entry["container_owner"] != client_id: abort(400, "You do not have access to this definition file") else: abort(400, "Invalid build ID") try: file_name = pull_container(build_entry) response = send_file(os.path.basename(file_name)) if os.path.exists(file_name): os.remove(file_name) return response except Exception as e: file_name = build_id + (".tar" if build_entry["container_type"] == "docker" else ".sif") if os.path.exists(file_name): os.remove(file_name) print(f"Exception {e}") abort(400, f"Failed to pull {build_id}") else: abort(400, "No build ID") else: abort(400, "Failed to authenticate user")
def start(client_id, client_secret, flow_id=None, flow_scope=None): """Use a confidential client to run and monitor a flow. """ global CLIENT_ID global CLIENT_SECRET global TOKENS global FLOW_ID if not CLIENT_ID: CLIENT_ID = client_id if not CLIENT_SECRET: CLIENT_SECRET = client_secret confidential_client = ConfidentialAppAuthClient( client_id=CLIENT_ID, client_secret=CLIENT_SECRET) if flow_scope: SCOPES.append(FLOW_SCOPE) TOKENS = confidential_client.oauth2_client_credentials_tokens( requested_scopes=SCOPES) cca = ClientCredentialsAuthorizer( confidential_client, MANAGE_FLOWS_SCOPE, TOKENS.by_resource_server['flows.globus.org']['access_token'], TOKENS.by_resource_server['flows.globus.org']['expires_at_seconds']) fc = FlowsClient.new_client(client_id=CLIENT_ID, authorizer_callback=authorizer_callback, authorizer=cca) #fc.delete_flow(FLOW_ID) #flow_id, flow_scope = create_flow(fc, flow_id, flow_scope) res = run_and_monitor(fc, FLOW_ID, FLOW_SCOPE) if res == "SUCCEEDED": return else: raise Exception("Flow did not succeed")
def upload_file(): if 'Authorization' not in request.headers: abort(401, 'You must be logged in to perform this function.') token = request.headers.get('Authorization') token = str.replace(str(token), 'Bearer ', '') conf_app = ConfidentialAppAuthClient(os.environ["GL_CLIENT"], os.environ["GL_CLIENT_SECRET"]) intro_obj = conf_app.oauth2_token_introspect(token) if "client_id" in intro_obj: client_id = str(intro_obj["client_id"]) if 'file' not in request.files: abort(400, "No file") file = request.files['file'] if file.filename == '': abort(400, "No file selected") if file: filename = file.filename definition_id = str(uuid.uuid4()) create_table_entry("definition", definition_id=definition_id, definition_type="docker" if filename == "Dockerfile" else "singularity", definition_name=filename, location="s3", definition_owner=client_id) s3 = boto3.client('s3') s3.upload_fileobj(file, "xtract-container-service", f'{definition_id}/{filename}') return definition_id else: return abort(400, "Failed to upload file") else: abort(400, "Failed to authenticate user")
def __init__(self): self.log = logging.getLogger(self.__class__.__name__) self.log.debug(" init - started") self.client_user = os.environ.get('MC_CONFIDENTIAL_CLIENT_USER') self.client_token = os.environ.get('MC_CONFIDENTIAL_CLIENT_PW') if (not self.client_user) or (not self.client_token): missing = [] if not self.client_user: missing.append('MC_CONFIDENTIAL_CLIENT_USER') if not self.client_token: missing.append('MC_CONFIDENTIAL_CLIENT_PW') message = "Missing environment values: {}".format( ", ".join(missing)) raise EnvironmentError(message) self.log.info("Env variables are ok") self.log.info(" -- MC_CONFIDENTIAL_CLIENT_USER = {}".format( self.client_user)) auth_client = ConfidentialAppAuthClient( client_id=self.client_user, client_secret=self.client_token) if not auth_client: error = "No Authentication Client" self.log.error("Error: " + str(error)) raise AuthenticationException(error) self.log.info("set_transfer_client - auth_client = {}".format( auth_client.client_id)) scopes = "urn:globus:auth:scope:transfer.api.globus.org:all" cc_authorizer = ClientCredentialsAuthorizer(auth_client, scopes) transfer_client = TransferClient(authorizer=cc_authorizer) self.log.debug("get_transfer_interface - transfer_client") self.log.debug(transfer_client) if not transfer_client: error = "No transfer interface" self.log.error("Error: " + str(error)) raise AuthenticationException(error) self.log.debug(" init - done") self._auth_client = auth_client self._transfer_client = transfer_client
class GlobusClientUtil: def __init__(self, *args, **kwargs): # GlobusClientUtil(<filename>) reads client id and secret from <filename> # GlobusClientUtil() is equivalent to GlobusClientUtil('/home/secrets/oauth2/client_secret_globus.json') # GlobusClientUtil(client_id, client_secret) uses the specified id and secret instead of reading from a file. cred_file = CLIENT_CRED_FILE if len(args) == 1: cred_file=args[0] if len(args) < 2: f=open(cred_file, 'r') config=json.load(f) f.close() self.initialize(config['web'].get('client_id'), config['web'].get('client_secret')) elif len(args) == 2: self.initialize(args[0], args[1]) def initialize(self, client_id, client_secret): self.client = ConfidentialAppAuthClient(client_id, client_secret) self.client_id = client_id def list_all_scopes(self): r = self.client.get("/v2/api/scopes") return r.text def list_scope(self, scope): r = self.client.get("/v2/api/scopes/{s}".format(s=scope)) return r.text def create_scope(self, scope): # if "scope" is a dict, use it. Otherwise, see if it's a json string or a file containing json. if not isinstance(scope, dict): try: scope = json.loads(scope) except ValueError: # if this fails, we have nothing left to try, so don't bother catching errors f = open(scope, 'r') scope = json.load(f) f.close() r = self.client.post("/v2/api/clients/{client_id}/scopes".format(client_id = self.client_id), json_body=scope) return r.text def update_scope(self, scope_id, args): r = self.client.put("/v2/api/scopes/{scope_id}".format(scope_id = scope_id), json_body={"scope" : args}) return r.text def add_fqdn_to_client(self, fqdn): r = self.client.post('/v2/api/clients/{client_id}/fqdns'.format(client_id=self.client_id), json_body={'fqdn':fqdn}) return r.text def get_clients(self): r = self.client.get('/v2/api/clients') return r.text def verify_access_token(self, token): r = self.client.oauth2_validate_token(token) return r.text def introspect_access_token(self, token): r = self.client.oauth2_token_introspect(token) return r.text def create_private_client(self, name, redirect_uris): nih_client_dict = { "client" : { "name" : name, "public_client" : False, "redirect_uris" : redirect_uris } } r = self.client.post("/v2/api/clients", json_body = nih_client_dict) return r.text def add_redirect_uris(self, redirect_uris): d={ "client": { "redirect_uris" : redirect_uris } } r = self.client.put("/v2/api/clients/{client_id}".format(client_id=self.client_id), json_body=d) return r.text def get_my_client(self): r = self.client.get('/v2/api/clients/{client_id}'.format(client_id=self.client_id)) return r.text def get_scopes_by_name(self, sname_string): scopes = self.client.get('/v2/api/scopes?scope_strings={sname}'.format(sname=sname_string)) if scopes == None: return None else: return scopes.get("scopes") def get_scopes_by_id(self, id_string): scopes = self.client.get('/v2/api/scopes?ids={ids}'.format(ids=id_string)) if scopes == None: return None else: return scopes.get("scopes") def my_scope_ids(self): c = self.client.get('/v2/api/clients/{client_id}'.format(client_id=self.client_id)) me = c.get("client") if me == None or me.get('scopes') == None: return [] else: return me.get('scopes') def my_scope_names(self): snames = [] scope_ids=self.my_scope_ids() if scope_ids != None: ids=",".join(scope_ids) print(str(ids)) scopes=self.get_scopes_by_id(ids) for s in scopes: snames.append(s.get('scope_string')) return snames def get_grant_types(self): grant_types=None c = self.client.get('/v2/api/clients/{client_id}'.format(client_id=self.client_id)) me = c.get("client") if me != None: grant_types = me.get('grant_types') return(grant_types) def add_scopes(self, new_scopes): scopes=set(self.my_scope_ids()) for s in self.get_scopes_by_name(",".join(new_scopes)): scopes.add(s.get('id')) d = { "client": { "scopes" : list(scopes) } } r=self.client.put('/v2/api/clients/{client_id}'.format(client_id=self.client_id), json_body=d) return r.text def add_dependent_scopes(self, parent_scope_name, child_scope_names): child_scope_ids = set() parent_scopes = self.get_scopes_by_name(parent_scope_name) if parent_scopes == None: return "no parent scope" if len(parent_scopes) != 1: return "{l} parent scopes: {p}".format(l=str(len(parent_scopes)), p=str(parent_scopes)) parent_scope_id = parent_scopes[0].get("id") for s in parent_scopes[0].get('dependent_scopes'): child_scope_ids.add(s.get('id')) new_child_scopes = self.get_scopes_by_name(",".join(child_scope_names)) for s in new_child_scopes: child_scope_ids.add(s.get('id')) dependent_scopes = [] for id in child_scope_ids: dependent_scopes.append({'scope' : id, 'optional' : False, 'requires_refresh_token' : False}) d = { "scope" : { "dependent_scopes" : dependent_scopes } } print(str(d)) r = self.client.put('/v2/api/scopes/{i}'.format(i=parent_scope_id), json_body=d) return r.text def create_scope_with_deps(self, name, description, suffix, dependent_scopes=[], advertised=True, allow_refresh_tokens=True): dependent_scope_arg = [] if len(dependent_scopes) > 0: child_scopes=self.get_scopes_by_name(",".join(dependent_scopes)) for s in child_scopes: dependent_scope_arg.append({ "scope" : s.get("id"), "optional" : False, "requires_refresh_token" : False }) scope = { "scope" : { "name" : name, "description" : description, "scope_suffix" : suffix, "dependent_scopes" : dependent_scope_arg, "advertised" : advertised, "allows_refresh_tokens": allow_refresh_tokens } } r = self.client.post("/v2/api/clients/{client_id}/scopes".format(client_id = self.client_id), json_body=scope) return r.text def delete_scope(self, scope_string): scopes = self.get_scopes_by_name(scope_string) if scopes == None or len(scopes) != 1: return "null or multiple scopes" scope_id = scopes[0].get('id') if scope_id == None: return "no scope id" r = self.client.delete('/v2/api/scopes/{scope_id}'.format(scope_id = scope_id)) return r.text def get_dependent_scopes(self, scope): result = {"scope_string" : scope.get("scope_string"), "dependent_scopes" : []} for ds in scope.get("dependent_scopes"): ds_id = ds.get('scope') ds_info = {"id" : ds_id} d = self.get_scopes_by_id(ds_id) if d != None: ds_info['scope_string'] = d[0].get('scope_string') result['dependent_scopes'].append(ds_info) return(result)
def get_auth_client(): """ Create an AuthClient for the portal """ return ConfidentialAppAuthClient(app.config['GLOBUS_CLIENT'], app.config['GLOBUS_KEY'])
def build(): if 'Authorization' not in request.headers: abort(401, "You must be logged in to perform this function.") token = request.headers.get('Authorization') token = str.replace(str(token), 'Bearer ', '') conf_app = ConfidentialAppAuthClient(os.environ["GL_CLIENT"], os.environ["GL_CLIENT_SECRET"]) intro_obj = conf_app.oauth2_token_introspect(token) if "client_id" in intro_obj: client_id = str(intro_obj["client_id"]) if request.method == "POST": params = request.json required_params = {"definition_id", "to_format", "container_name"} if set(params.keys()) >= required_params and params[ "to_format"] in ["docker", "singularity"]: definition_entry = select_by_column( "definition", definition_id=params["definition_id"]) if definition_entry is not None and len(definition_entry) == 1: definition_entry = definition_entry[0] if definition_entry["definition_owner"] != client_id: abort( 400, "You don't have permission to use this definition file" ) else: build_entry = select_by_column( "build", definition_id=params["definition_id"], container_type=params["to_format"]) if build_entry is not None and len(build_entry) == 1: build_entry = build_entry[0] build_id = build_entry["build_id"] build_entry["build_status"] = "pending" update_table_entry("build", build_id, **build_entry) else: build_id = str(uuid.uuid4()) build_entry = build_schema build_entry[ "build_id"] = build_id if build_id is not None else str( uuid.uuid4()) build_entry["container_name"] = params[ "container_name"] build_entry["definition_id"] = params[ "definition_id"] build_entry["container_type"] = params["to_format"] build_entry["container_owner"] = client_id build_entry["build_status"] = "pending" create_table_entry("build", **build_entry) put_message({ "function_name": "build_container", "build_entry": build_entry, "to_format": params["to_format"], "container_name": params["container_name"] }) manager.start_thread() return build_id else: abort( 400, f"""No definition DB entry for {params["definition_id"]}""" ) else: abort(400, f"Missing {set(params.keys())} parameters") elif request.method == "GET": build_entry = select_by_column("build", container_owner=client_id, build_id=request.json["build_id"]) if build_entry is not None and len(build_entry) == 1: return build_entry[0] else: abort(400, "Build ID not valid") else: abort(400, "Failed to authenticate user")
def get_client_credential_transfer_client(): client = ConfidentialAppAuthClient(GLOBUS_CLIENT_ID, GLOBUS_CLIENT_SECRET) scopes = "urn:globus:auth:scope:transfer.api.globus.org:all" cc_authorizer = ClientCredentialsAuthorizer(client, scopes) transfer_client = TransferClient(authorizer=cc_authorizer) return transfer_client
def get_auth_client(self): auth_client = ConfidentialAppAuthClient( client_id=self.client_user, client_secret=self.client_token) return auth_client
def load_app_client(): globus.client = ConfidentialAppAuthClient(GLOBUS_CLIENT_ID, GLOBUS_CLIENT_SECRET)
def initialize(self, client_id, client_secret): self.client = ConfidentialAppAuthClient(client_id, client_secret) self.client_id = client_id
parser = argparse.ArgumentParser() parser.add_argument("-t", "--tutorial", required=True, help="Tutorial Endpoint ID") parser.add_argument("-i", "--id", required=True, help="API_CLIENT_ID for Globus") parser.add_argument("-s", "--secret", required=True, help="API_CLIENT_SECRET for Globus") args = parser.parse_args() client = ConfidentialAppAuthClient(args.id, args.secret) scopes = [ "https://auth.globus.org/scopes/facd7ccc-c5f4-42aa-916b-a0e270e2c2a9/all", "urn:globus:auth:scope:search.api.globus.org:all", "openid", ] token_response = client.oauth2_client_credentials_tokens( requested_scopes=scopes) fx_token = token_response.by_resource_server["funcx_service"][ "access_token"] search_token = token_response.by_resource_server["search.api.globus.org"][ "access_token"] openid_token = token_response.by_resource_server["auth.globus.org"][ "access_token"]