mirror of
https://github.com/clearml/clearml
synced 2025-05-08 22:59:24 +00:00
Fix Jupyter password might not be used in some protected Jupyterlab instances
This commit is contained in:
parent
3012837bf3
commit
3377efe738
@ -700,28 +700,13 @@ class ScriptInfo(object):
|
|||||||
cookies = None
|
cookies = None
|
||||||
password = None
|
password = None
|
||||||
if server_info and server_info.get("password"):
|
if server_info and server_info.get("password"):
|
||||||
# we need to get the password
|
password, cookies = cls._authenticate_jupyter(server_info)
|
||||||
from ....config import config
|
|
||||||
|
|
||||||
password = config.get("development.jupyter_server_password", "")
|
|
||||||
if not password:
|
if not password:
|
||||||
cls._get_logger().warning(
|
|
||||||
"Password protected Jupyter Notebook server was found! "
|
|
||||||
"Add `sdk.development.jupyter_server_password=<jupyter_password>` to ~/clearml.conf"
|
|
||||||
)
|
|
||||||
return os.path.join(os.getcwd(), "error_notebook_not_found.py")
|
return os.path.join(os.getcwd(), "error_notebook_not_found.py")
|
||||||
|
|
||||||
r = requests.get(url=server_info["url"] + "login")
|
|
||||||
cookies = {"_xsrf": r.cookies.get("_xsrf", "")}
|
|
||||||
r = requests.post(
|
|
||||||
server_info["url"] + "login?next",
|
|
||||||
cookies=cookies,
|
|
||||||
data={"_xsrf": cookies["_xsrf"], "password": password},
|
|
||||||
)
|
|
||||||
cookies.update(r.cookies)
|
|
||||||
|
|
||||||
# get api token from ENV - if not defined then from server info
|
# get api token from ENV - if not defined then from server info
|
||||||
auth_token = os.getenv("JUPYTERHUB_API_TOKEN") or server_info.get("token") or ""
|
auth_token = os.getenv("JUPYTERHUB_API_TOKEN") or server_info.get("token") or ""
|
||||||
|
verify = True
|
||||||
try:
|
try:
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
url=server_info["url"] + "api/sessions",
|
url=server_info["url"] + "api/sessions",
|
||||||
@ -729,8 +714,10 @@ class ScriptInfo(object):
|
|||||||
headers={
|
headers={
|
||||||
"Authorization": "token {}".format(auth_token),
|
"Authorization": "token {}".format(auth_token),
|
||||||
},
|
},
|
||||||
|
verify=verify
|
||||||
)
|
)
|
||||||
except requests.exceptions.SSLError:
|
except requests.exceptions.SSLError:
|
||||||
|
verify = False
|
||||||
# disable SSL check warning
|
# disable SSL check warning
|
||||||
from urllib3.exceptions import InsecureRequestWarning
|
from urllib3.exceptions import InsecureRequestWarning
|
||||||
|
|
||||||
@ -743,13 +730,28 @@ class ScriptInfo(object):
|
|||||||
headers={
|
headers={
|
||||||
"Authorization": "token {}".format(auth_token),
|
"Authorization": "token {}".format(auth_token),
|
||||||
},
|
},
|
||||||
verify=False,
|
verify=verify,
|
||||||
)
|
)
|
||||||
# enable SSL check warning
|
# enable SSL check warning
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
warnings.simplefilter("default", InsecureRequestWarning)
|
warnings.simplefilter("default", InsecureRequestWarning)
|
||||||
|
|
||||||
|
if r.status_code == 403 and server_info.get("password", False) is False:
|
||||||
|
# server info json might set password=False even tho that is not the case
|
||||||
|
# retry the request
|
||||||
|
password, cookies = cls._authenticate_jupyter(server_info)
|
||||||
|
if not password:
|
||||||
|
return os.path.join(os.getcwd(), "error_notebook_not_found.py")
|
||||||
|
r = requests.get(
|
||||||
|
url=server_info["url"] + "api/sessions",
|
||||||
|
cookies=cookies,
|
||||||
|
headers={
|
||||||
|
"Authorization": "token {}".format(auth_token),
|
||||||
|
},
|
||||||
|
verify=verify
|
||||||
|
)
|
||||||
|
|
||||||
# send request to the jupyter server
|
# send request to the jupyter server
|
||||||
try:
|
try:
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
@ -853,8 +855,47 @@ class ScriptInfo(object):
|
|||||||
|
|
||||||
return script_entry_point
|
return script_entry_point
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _authenticate_jupyter(cls, server_info):
|
||||||
|
"""
|
||||||
|
Authenticate to the Jupyter server using a password.
|
||||||
|
The password is fetched from `CLEARML_JUPYTER_PASSWORD` env var or the
|
||||||
|
`sdk.development.jupyter_server_password` configuration entry. The env var
|
||||||
|
has a higher priority than the configuration entry.
|
||||||
|
|
||||||
|
:param server_info: A dictionary containing Jupyter server information
|
||||||
|
|
||||||
|
:return: If the authentication succeded, return a tuple contain the password used
|
||||||
|
for authentication and the cookies obtained after authenticating. Otherwise,
|
||||||
|
return a tuple of Nones
|
||||||
|
"""
|
||||||
|
cookies = None
|
||||||
|
password = None
|
||||||
|
# we need to get the password
|
||||||
|
from ....config import config
|
||||||
|
from ....config.defs import JUPYTER_PASSWORD
|
||||||
|
|
||||||
|
password = JUPYTER_PASSWORD.get(default=config.get("development.jupyter_server_password", ""))
|
||||||
|
if not password:
|
||||||
|
cls._get_logger().warning(
|
||||||
|
"Password protected Jupyter Notebook server was found! "
|
||||||
|
"Add `sdk.development.jupyter_server_password=<jupyter_password>` to ~/clearml.conf"
|
||||||
|
)
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
r = requests.get(url=server_info["url"] + "login")
|
||||||
|
cookies = {"_xsrf": r.cookies.get("_xsrf", "")}
|
||||||
|
r = requests.post(
|
||||||
|
server_info["url"] + "login?next",
|
||||||
|
cookies=cookies,
|
||||||
|
data={"_xsrf": cookies["_xsrf"], "password": password},
|
||||||
|
)
|
||||||
|
cookies.update(r.cookies)
|
||||||
|
return password, cookies
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_sagemaker(cls):
|
def is_sagemaker(cls):
|
||||||
return Path(cls._sagemaker_metadata_path).is_file()
|
return Path(cls._sagemaker_metadata_path).is_file()
|
||||||
|
@ -28,6 +28,8 @@ SUPPRESS_UPDATE_MESSAGE_ENV_VAR = EnvEntry("CLEARML_SUPPRESS_UPDATE_MESSAGE", "T
|
|||||||
|
|
||||||
MAX_SERIES_PER_METRIC = EnvEntry("CLEARML_MAX_SERIES_PER_METRIC", default=100, type=int)
|
MAX_SERIES_PER_METRIC = EnvEntry("CLEARML_MAX_SERIES_PER_METRIC", default=100, type=int)
|
||||||
|
|
||||||
|
JUPYTER_PASSWORD = EnvEntry("CLEARML_JUPYTER_PASSWORD")
|
||||||
|
|
||||||
# Repository detection
|
# Repository detection
|
||||||
VCS_REPO_TYPE = EnvEntry("CLEARML_VCS_REPO_TYPE", "TRAINS_VCS_REPO_TYPE", default="git")
|
VCS_REPO_TYPE = EnvEntry("CLEARML_VCS_REPO_TYPE", "TRAINS_VCS_REPO_TYPE", default="git")
|
||||||
VCS_REPOSITORY_URL = EnvEntry("CLEARML_VCS_REPO_URL", "TRAINS_VCS_REPO_URL")
|
VCS_REPOSITORY_URL = EnvEntry("CLEARML_VCS_REPO_URL", "TRAINS_VCS_REPO_URL")
|
||||||
|
Loading…
Reference in New Issue
Block a user