def session_consent(scopes, no_local_server): """ Update your current CLI auth session by authenticating with a specific scope or set of scopes. This command is necessary when the CLI needs access to resources which require the user to explicitly consent to access. """ session_params = {"scope": " ".join(scopes)} # use a link login if remote session or user requested if no_local_server or is_remote_session(): do_link_auth_flow(session_params=session_params) # otherwise default to a local server login flow else: click.echo( "You are running 'globus session consent', " "which should automatically open a browser window for you to " "authenticate with specific identities.\n" "If this fails or you experience difficulty, try " "'globus session consent --no-local-server'" "\n---" ) do_local_server_auth_flow(session_params=session_params) click.echo("\nYou have successfully updated your CLI session.\n")
def login_command(force, no_local_server): # if not forcing, stop if user already logged in if not force and check_logged_in(): safeprint(_LOGGED_IN_RESPONSE) return # use a link login if remote session or user requested if no_local_server or is_remote_session(): do_link_login_flow() # otherwise default to a local server login flow else: do_local_server_login_flow()
def login_command(no_local_server, force): """ Get credentials for the Globus CLI Necessary before any Globus CLI commands which require authentication will work This command directs you to the page necessary to permit the Globus CLI to make API calls for you, and gets the OAuth2 tokens needed to use those permissions. The default login method opens your browser to the Globus CLI's authorization page, where you can read and consent to the permissions required to use the Globus CLI. The CLI then takes care of getting the credentials through a local server. If the CLI detects you are on a remote session, or the --no-local-server option is used, the CLI will instead print a link for you to manually follow to the Globus CLI's authorization page. After consenting you will then need to copy and paste the given access code from the web to the CLI. """ # if not forcing, stop if user already logged in if not force and check_logged_in(): click.echo(_LOGGED_IN_RESPONSE) return # use a link login if remote session or user requested if no_local_server or is_remote_session(): do_link_auth_flow(force_new_client=True) # otherwise default to a local server login flow else: click.echo( "You are running 'globus login', which should automatically open " "a browser window for you to login.\n" "If this fails or you experience difficulty, try " "'globus login --no-local-server'" "\n---") do_local_server_auth_flow(force_new_client=True) # print epilog click.echo(_LOGIN_EPILOG)
def login_command(no_local_server, force): # if not forcing, stop if user already logged in if not force and check_logged_in(): safeprint(_LOGGED_IN_RESPONSE) return # use a link login if remote session or user requested if no_local_server or is_remote_session(): do_link_auth_flow(force_new_client=True) # otherwise default to a local server login flow else: safeprint( "You are running 'globus login', which should automatically open " "a browser window for you to login.\n" "If this fails or you experience difficulty, try " "'globus login --no-local-server'" "\n---") do_local_server_auth_flow(force_new_client=True) # print epilog safeprint(_LOGIN_EPILOG)
def login_command(no_local_server, force): # if not forcing, stop if user already logged in if not force and check_logged_in(): safeprint(_LOGGED_IN_RESPONSE) return # use a link login if remote session or user requested if no_local_server or is_remote_session(): do_link_auth_flow(force_new_client=True) # otherwise default to a local server login flow else: safeprint( "You are running 'globus login', which should automatically open " "a browser window for you to login.\n" "If this fails or you experience difficulty, try " "'globus login --no-local-server'" "\n---" ) do_local_server_auth_flow(force_new_client=True) # print epilog safeprint(_LOGIN_EPILOG)
def endpoint_activate(endpoint_id, myproxy, myproxy_username, myproxy_password, myproxy_lifetime, web, no_browser, delegate_proxy, proxy_lifetime, no_autoactivate, force): """ Executor for `globus endpoint activate` """ default_myproxy_username = lookup_option(MYPROXY_USERNAME_OPTNAME) client = get_client() # validate options if web + myproxy + bool(delegate_proxy) > 1: raise click.UsageError( "--web, --myproxy, and --delegate-proxy are mutually exclusive.") if no_autoactivate and not (myproxy or web or delegate_proxy): raise click.UsageError( "--no-autoactivate requires another activation method be given.") if myproxy_username and not myproxy: raise click.UsageError("--myproxy-username requires --myproxy.") if myproxy_password and not myproxy: raise click.UsageError("--myproxy-password requires --myproxy.") # NOTE: "0" is a legitimate, though weird, value # In the case where someone is setting this value programatically, # respecting it behaves more consistently/predictably if myproxy_lifetime is not None and not myproxy: raise click.UsageError("--myproxy-lifetime requires --myproxy.") if no_browser and not web: raise click.UsageError("--no-browser requires --web.") if proxy_lifetime and not delegate_proxy: raise click.UsageError("--proxy-lifetime requires --delegate-proxy.") # check if endpoint is already activated unless --force if not force: res = client.endpoint_autoactivate(endpoint_id, if_expires_in=60) if "AlreadyActivated" == res["code"]: formatted_print( res, simple_text=("Endpoint is already activated. Activation " "expires at {}".format(res["expire_time"]))) return # attempt autoactivation unless --no-autoactivate if not no_autoactivate: res = client.endpoint_autoactivate(endpoint_id) if "AutoActivated" in res["code"]: formatted_print( res, simple_text=( "Autoactivation succeeded with message: {}".format( res["message"]))) return # override potentially confusing autoactivation failure response else: message = ("The endpoint could not be auto-activated.\n\n" + activation_requirements_help_text(res, endpoint_id)) res = {"message": message} # myproxy activation if myproxy: # get username and password if not (myproxy_username or default_myproxy_username): myproxy_username = click.prompt("Myproxy username") if not myproxy_password: myproxy_password = click.prompt("Myproxy password", hide_input=True) no_server_msg = ("This endpoint has no myproxy server " "and so cannot be activated through myproxy") requirements_data = client.endpoint_get_activation_requirements( endpoint_id).data if not len(requirements_data["DATA"]): raise click.ClickException(no_server_msg) for data in requirements_data["DATA"]: # skip non-myproxy values # although the API does not practice this today, in theory other # activation types may have fields with the same names... if data["type"] != "myproxy": continue if data["name"] == "passphrase": data["value"] = myproxy_password if data["name"] == "username": data["value"] = myproxy_username or default_myproxy_username if data["name"] == "hostname" and data["value"] is None: raise click.ClickException(no_server_msg) # NOTE: remember that "0" is a possible value if (data["name"] == "lifetime_in_hours" and myproxy_lifetime is not None): data["value"] = str(myproxy_lifetime) res = client.endpoint_activate(endpoint_id, requirements_data) # web activation elif web: url = ("https://www.globus.org/app/" "endpoints/{}/activate".format(endpoint_id)) if no_browser or is_remote_session(): res = {"message": "Web activation url: {}".format(url), "url": url} else: webbrowser.open(url, new=1) res = { "message": "Browser opened to web activation page", "url": url } # delegate proxy activation elif delegate_proxy: requirements_data = client.endpoint_get_activation_requirements( endpoint_id).data filled_requirements_data = fill_delegate_proxy_activation_requirements( requirements_data, delegate_proxy, lifetime_hours=proxy_lifetime or 12) res = client.endpoint_activate(endpoint_id, filled_requirements_data) # output formatted_print(res, text_format=FORMAT_TEXT_RAW, response_key='message')
def endpoint_activate( endpoint_id, myproxy, myproxy_username, myproxy_password, myproxy_lifetime, web, no_browser, delegate_proxy, proxy_lifetime, no_autoactivate, force, ): """ Executor for `globus endpoint activate` """ default_myproxy_username = lookup_option(MYPROXY_USERNAME_OPTNAME) client = get_client() # validate options if web + myproxy + bool(delegate_proxy) > 1: raise click.UsageError( "--web, --myproxy, and --delegate-proxy are mutually exclusive." ) if no_autoactivate and not (myproxy or web or delegate_proxy): raise click.UsageError( "--no-autoactivate requires another activation method be given." ) if myproxy_username and not myproxy: raise click.UsageError("--myproxy-username requires --myproxy.") if myproxy_password and not myproxy: raise click.UsageError("--myproxy-password requires --myproxy.") # NOTE: "0" is a legitimate, though weird, value # In the case where someone is setting this value programatically, # respecting it behaves more consistently/predictably if myproxy_lifetime is not None and not myproxy: raise click.UsageError("--myproxy-lifetime requires --myproxy.") if no_browser and not web: raise click.UsageError("--no-browser requires --web.") if proxy_lifetime and not delegate_proxy: raise click.UsageError("--proxy-lifetime requires --delegate-proxy.") # check if endpoint is already activated unless --force if not force: res = client.endpoint_autoactivate(endpoint_id, if_expires_in=60) if "AlreadyActivated" == res["code"]: formatted_print( res, simple_text=( "Endpoint is already activated. Activation " "expires at {}".format(res["expire_time"]) ), ) return # attempt autoactivation unless --no-autoactivate if not no_autoactivate: res = client.endpoint_autoactivate(endpoint_id) if "AutoActivated" in res["code"]: formatted_print( res, simple_text=( "Autoactivation succeeded with message: {}".format(res["message"]) ), ) return # override potentially confusing autoactivation failure response else: message = ( "The endpoint could not be auto-activated.\n\n" + activation_requirements_help_text(res, endpoint_id) ) res = {"message": message} # myproxy activation if myproxy: # get username and password if not (myproxy_username or default_myproxy_username): myproxy_username = click.prompt("Myproxy username") if not myproxy_password: myproxy_password = click.prompt("Myproxy password", hide_input=True) no_server_msg = ( "This endpoint has no myproxy server " "and so cannot be activated through myproxy" ) requirements_data = client.endpoint_get_activation_requirements( endpoint_id ).data if not len(requirements_data["DATA"]): raise click.ClickException(no_server_msg) for data in requirements_data["DATA"]: # skip non-myproxy values # although the API does not practice this today, in theory other # activation types may have fields with the same names... if data["type"] != "myproxy": continue if data["name"] == "passphrase": data["value"] = myproxy_password if data["name"] == "username": data["value"] = myproxy_username or default_myproxy_username if data["name"] == "hostname" and data["value"] is None: raise click.ClickException(no_server_msg) # NOTE: remember that "0" is a possible value if data["name"] == "lifetime_in_hours" and myproxy_lifetime is not None: data["value"] = str(myproxy_lifetime) res = client.endpoint_activate(endpoint_id, requirements_data) # web activation elif web: url = "https://app.globus.org/file-manager" "?origin_id={}".format(endpoint_id) if no_browser or is_remote_session(): res = {"message": "Web activation url: {}".format(url), "url": url} else: webbrowser.open(url, new=1) res = {"message": "Browser opened to web activation page", "url": url} # delegate proxy activation elif delegate_proxy: requirements_data = client.endpoint_get_activation_requirements( endpoint_id ).data filled_requirements_data = fill_delegate_proxy_activation_requirements( requirements_data, delegate_proxy, lifetime_hours=proxy_lifetime or 12 ) res = client.endpoint_activate(endpoint_id, filled_requirements_data) # output formatted_print(res, text_format=FORMAT_TEXT_RAW, response_key="message")
def session_update(identities, no_local_server, all): if (not (identities or all)) or (identities and all): raise click.UsageError("Either give one or more IDENTITIES or use --all") auth_client = get_auth_client() # if --all use every identity id in the user's identity set if all: res = auth_client.oauth2_userinfo() try: identity_ids = [user["sub"] for user in res["identity_set"]] except KeyError: click.echo( "Your current login does not have the consents required " "to view your full identity set. Please log in again " "to agree to the required consents.", err=True, ) click.get_current_context().exit(1) # otherwise try to resolve any non uuid values to identity ids else: identity_ids = [] identity_names = [] for val in identities: try: uuid.UUID(val) identity_ids.append(val) except ValueError: identity_names.append(val) if identity_names: res = auth_client.get_identities(usernames=identity_names)["identities"] for name in identity_names: for identity in res: if identity["username"] == name: identity_ids.append(identity["id"]) break else: click.echo("No such identity {}".format(val), err=True) click.get_current_context().exit(1) # create session params once we have all identity ids session_params = { "session_required_identities": ",".join(identity_ids), "session_message": "Authenticate to update your CLI session.", } # use a link login if remote session or user requested if no_local_server or is_remote_session(): do_link_auth_flow(session_params=session_params) # otherwise default to a local server login flow else: click.echo( "You are running 'globus session update', " "which should automatically open a browser window for you to " "authenticate with specific identities.\n" "If this fails or you experience difficulty, try " "'globus session update --no-local-server'" "\n---" ) do_local_server_auth_flow(session_params=session_params) click.echo( "\nYou have successfully updated your CLI session.\n" "Use 'globus session show' to see the updated session." )
def endpoint_activate( endpoint_id, myproxy, myproxy_username, myproxy_password, myproxy_lifetime, web, no_browser, delegate_proxy, proxy_lifetime, no_autoactivate, force, ): """ Activate an endpoint using Autoactivation, Myproxy, Delegate Proxy, or Web activation. Note that --web, --delegate-proxy, and --myproxy activation are mutually exclusive options. \b Autoactivation will always be attempted unless the --no-autoactivate option is given. If autoactivation succeeds any other activation options will be ignored as the endpoint has already been successfully activated. \b To use Web activation use the --web option. The CLI will try to open your default browser to the endpoint's activation page, but if a remote CLI session is detected, or the --no-browser option is given, a url will be printed for you to manually follow and activate the endpoint. \b To use Myproxy activation give the --myproxy option. Myproxy activation requires your username and password for the myproxy server the endpoint is using for authentication. e.g. for default Globus Connect Server endpoints this will be your login credentials for the server the endpoint is hosted on. You can enter your username when prompted, give your username with the --myproxy-username option, or set a default myproxy username in config with "globus config init" or "globus config set cli.default_myproxy_username". For security it is recommended that you only enter your password when prompted to hide your inputs and keep your password out of your command history, but you may pass your password with the hidden --myproxy-password or -P options. \b To use Delegate Proxy activation use the --delegate-proxy option with a file containing an X.509 certificate as an argument (e.g. an X.509 gotten from the myproxy-logon command). This certificate must be a valid credential or proxy credential for the user from an identity provider accepted by the endpoint being activated, and the endpoint must be configured with a gridmap that will match the globus user using this command with the local user the certificate was made to. Note if the X.509 is valid, but the endpoint does not recognize the identity provider or the user the error will not be detected until the user attempts to perform an operation on the endpoint. """ default_myproxy_username = lookup_option(MYPROXY_USERNAME_OPTNAME) client = get_client() # validate options if web + myproxy + bool(delegate_proxy) > 1: raise click.UsageError( "--web, --myproxy, and --delegate-proxy are mutually exclusive.") if no_autoactivate and not (myproxy or web or delegate_proxy): raise click.UsageError( "--no-autoactivate requires another activation method be given.") if myproxy_username and not myproxy: raise click.UsageError("--myproxy-username requires --myproxy.") if myproxy_password and not myproxy: raise click.UsageError("--myproxy-password requires --myproxy.") # NOTE: "0" is a legitimate, though weird, value # In the case where someone is setting this value programatically, # respecting it behaves more consistently/predictably if myproxy_lifetime is not None and not myproxy: raise click.UsageError("--myproxy-lifetime requires --myproxy.") if no_browser and not web: raise click.UsageError("--no-browser requires --web.") if proxy_lifetime and not delegate_proxy: raise click.UsageError("--proxy-lifetime requires --delegate-proxy.") # check if endpoint is already activated unless --force if not force: res = client.endpoint_autoactivate(endpoint_id, if_expires_in=60) if "AlreadyActivated" == res["code"]: formatted_print( res, simple_text=("Endpoint is already activated. Activation " "expires at {}".format(res["expire_time"])), ) return # attempt autoactivation unless --no-autoactivate if not no_autoactivate: res = client.endpoint_autoactivate(endpoint_id) if "AutoActivated" in res["code"]: formatted_print( res, simple_text=( "Autoactivation succeeded with message: {}".format( res["message"])), ) return # override potentially confusing autoactivation failure response else: message = ("The endpoint could not be auto-activated.\n\n" + activation_requirements_help_text(res, endpoint_id)) res = {"message": message} # myproxy activation if myproxy: # fetch activation requirements requirements_data = client.endpoint_get_activation_requirements( endpoint_id).data # filter to the myproxy requirements; ensure that there are values myproxy_requirements_data = [ x for x in requirements_data["DATA"] if x["type"] == "myproxy" ] if not len(myproxy_requirements_data): raise click.ClickException( "This endpoint does not support myproxy activation") # get username and password if not (myproxy_username or default_myproxy_username): myproxy_username = click.prompt("Myproxy username") if not myproxy_password: myproxy_password = click.prompt("Myproxy password", hide_input=True) # fill out the requirements data -- note that because everything has been done # by reference, `requirements_data` still refers to the document containing # these values for data in myproxy_requirements_data: if data["name"] == "passphrase": data["value"] = myproxy_password if data["name"] == "username": data["value"] = myproxy_username or default_myproxy_username if data["name"] == "hostname" and data["value"] is None: raise click.ClickException( "This endpoint has no myproxy server " "and so cannot be activated through myproxy") # NOTE: remember that "0" is a possible value if data["name"] == "lifetime_in_hours" and myproxy_lifetime is not None: data["value"] = str(myproxy_lifetime) res = client.endpoint_activate(endpoint_id, requirements_data) # web activation elif web: url = "https://app.globus.org/file-manager?origin_id={}".format( endpoint_id) if no_browser or is_remote_session(): res = {"message": "Web activation url: {}".format(url), "url": url} else: webbrowser.open(url, new=1) res = { "message": "Browser opened to web activation page", "url": url } # delegate proxy activation elif delegate_proxy: requirements_data = client.endpoint_get_activation_requirements( endpoint_id).data filled_requirements_data = fill_delegate_proxy_activation_requirements( requirements_data, delegate_proxy, lifetime_hours=proxy_lifetime or 12) res = client.endpoint_activate(endpoint_id, filled_requirements_data) # output formatted_print(res, text_format=FORMAT_TEXT_RAW, response_key="message")