/ tests / server / auth / auth_test_utils.py
auth_test_utils.py
 1  from pathlib import Path
 2  
 3  from mlflow.environment_variables import MLFLOW_TRACKING_PASSWORD, MLFLOW_TRACKING_USERNAME
 4  from mlflow.server.auth import auth_config
 5  
 6  from tests.helper_functions import random_str
 7  from tests.tracking.integration_test_utils import _send_rest_tracking_post_request
 8  
 9  PERMISSION = "READ"
10  NEW_PERMISSION = "EDIT"
11  ADMIN_USERNAME = auth_config.admin_username
12  ADMIN_PASSWORD = auth_config.admin_password
13  
14  
15  def write_isolated_auth_config(tmp_path: Path) -> Path:
16      """Write a basic_auth.ini under ``tmp_path`` whose ``database_uri`` points
17      at an SQLite file inside the same dir, and return the config path.
18  
19      Tests that spawn the auth server via ``_init_server`` must point
20      ``MLFLOW_AUTH_CONFIG_PATH`` at the returned file (through ``extra_env``) so
21      the spawned auth server writes to the temp DB instead of the repo-root
22      ``basic_auth.db`` shared with the dev server. Without this, integration
23      tests pollute (and depending on the fixture, delete) the developer's local
24      auth state.
25      """
26      config_path = tmp_path / "basic_auth.ini"
27      db_path = tmp_path / "basic_auth.db"
28      config_path.write_text(
29          "[mlflow]\n"
30          "default_permission = READ\n"
31          f"database_uri = sqlite:///{db_path}\n"
32          f"admin_username = {ADMIN_USERNAME}\n"
33          f"admin_password = {ADMIN_PASSWORD}\n"
34          "authorization_function = mlflow.server.auth:authenticate_request_basic_auth\n"
35          "grant_default_workspace_access = false\n"
36      )
37      return config_path
38  
39  
40  def create_user(tracking_uri: str, username: str | None = None, password: str | None = None):
41      username = random_str() if username is None else username
42      password = random_str() if password is None else password
43      response = _send_rest_tracking_post_request(
44          tracking_uri,
45          "/api/2.0/mlflow/users/create",
46          {
47              "username": username,
48              "password": password,
49          },
50          auth=(ADMIN_USERNAME, ADMIN_PASSWORD),
51      )
52      response.raise_for_status()
53      return username, password
54  
55  
56  class User:
57      def __init__(self, username, password, monkeypatch):
58          self.username = username
59          self.password = password
60          self.monkeypatch = monkeypatch
61  
62      def __enter__(self):
63          self.monkeypatch.setenv(MLFLOW_TRACKING_USERNAME.name, self.username)
64          self.monkeypatch.setenv(MLFLOW_TRACKING_PASSWORD.name, self.password)
65  
66      def __exit__(self, exc_type, exc_val, exc_tb):
67          self.monkeypatch.delenv(MLFLOW_TRACKING_USERNAME.name, raising=False)
68          self.monkeypatch.delenv(MLFLOW_TRACKING_PASSWORD.name, raising=False)