MLflow 基本认证(Basic Auth)实战:用 --app-name=basic-auth 为 Tracking Server 开启用户认证与权限控制
MLflow 基本认证Basic Auth实战用 --app-namebasic-auth 为 Tracking Server 开启用户认证与权限控制【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflow导读本文以 examples/auth/README.md 为骨架完整演示如何为 MLflow Tracking Server 启用内置的 Basic Authentication 应用通过/signup注册用户、用环境变量注入凭据并验证「无权限写入被拒绝、授权后可写入」的完整闭环。读完本文你将掌握mlflow server --app-namebasic-auth的启动方式、用户注册与凭据注入模式、权限模型READ / USE / EDIT / MANAGE及权限管理客户端的核心用法并能对照仓库源码理解底层鉴权与鉴权失败时的 401/403 行为。示例概述认证与授权特性MLflow 提供了基于HTTP Basic Authentication的默认认证应用basic-auth。该特性解决两类问题认证Authentication确认「你是谁」——客户端在每次 HTTP 请求中携带Authorization: Basic ...头服务端校验用户名与密码授权Authorization确认「你能做什么」——服务端根据当前用户对目标资源如 Experiment拥有的权限级别决定是否放行创建、读取、更新、删除等操作。示例存放于 examples/auth/ 目录包含两个文件README.md三步快速运行说明与预期输出auth.py完整的 Python 演示脚本展示两个用户user_a、user_b的权限差异与授权过程。第一步启动带认证的 Tracking Server在 examples/auth/README.md 中启动服务只有一条命令mlflow server --app-namebasic-auth--app-name用于选择 MLflow 的应用插件。在 mlflow/cli/init.py 中该参数与--dev等启动参数一同被解析用于加载指定名称的 app 工厂。当指定basic-auth时MLflow 会加载 mlflow/server/auth/init.py 中实现的认证应用它在普通 Tracking Server 之上挂载了用户注册、登录、权限管理页面与路由并在每个受保护请求前执行认证与鉴权。首次启动提示源码 mlflow/server/auth/config.py 与 basic_auth.ini 中明确说明——MLflow 不内置默认管理员密码。首次启动时若认证数据库中尚无admin_username指定的管理员用户服务端会使用admin_password或环境变量MLFLOW_AUTH_ADMIN_PASSWORD创建管理员并在两者都缺失时拒绝启动。因此首次启动通常配合export MLFLOW_AUTH_ADMIN_PASSWORDstrong-password mlflow server --app-namebasic-auth启动后打开浏览器访问http://localhost:5000/signup即可进入用户注册页面。第二步注册两个测试用户按照 README在http://localhost:5000/signup注册两个用户user_a/password_auser_b/password_b注册页面由认证应用的路由定义提供对应 mlflow/server/auth/routes.py 中的SIGNUP端点。用户信息含密码哈希持久化在认证数据库默认sqlite:///basic_auth.db见下文配置章节中。第三步理解 auth.py 中的凭据注入模式运行示例脚本前先理解 auth.py 的关键机制——通过环境变量注入 HTTP Basic 凭据。MLflow Python 客户端在发起 REST 请求时会读取 mlflow/environment_variables.py 中定义的两个环境变量MLFLOW_TRACKING_USERNAME请求用户名MLFLOW_TRACKING_PASSWORD请求密码。auth.py定义了User上下文管理器在进入with块时把用户名/密码写入这两个环境变量退出时恢复原值class User: MLFLOW_TRACKING_USERNAME MLFLOW_TRACKING_USERNAME MLFLOW_TRACKING_PASSWORD MLFLOW_TRACKING_PASSWORD def __init__(self, username, password) - None: self.username username self.password password self.env {} def _record_env_var(self, key): if key : os.environ.get(key): self.env[key] key def _restore_env_var(self, key): if value : self.env.get(key): os.environ[key] value else: del os.environ[key] def __enter__(self): self._record_env_var(User.MLFLOW_TRACKING_USERNAME) self._record_env_var(User.MLFLOW_TRACKING_PASSWORD) os.environ[User.MLFLOW_TRACKING_USERNAME] self.username os.environ[User.MLFLOW_TRACKING_PASSWORD] self.password return self def __exit__(self, *_exc): self._restore_env_var(User.MLFLOW_TRACKING_USERNAME) self._restore_env_var(User.MLFLOW_TRACKING_PASSWORD) self.env.clear()__enter__先保存环境变量原值若存在再覆盖为当前用户凭据__exit__恢复原值或删除变量。这样同一进程中可以安全地切换不同用户身份而不污染后续代码的执行环境。脚本主体设置 Tracking URI 并获取认证应用的客户端tracking_uri http://localhost:5000 mlflow.set_tracking_uri(tracking_uri) client mlflow.server.get_app_client(basic-auth, tracking_uri) A User(user_a, password_a) B User(user_b, password_b)mlflow.server.get_app_client()是 mlflow/server/init.py 提供的通用入口它遍历mlflow.app.client入口点按app_name找到对应的客户端类并实例化。对于basic-auth返回的是 mlflow/server/auth/client.py 中的AuthServiceClient封装了用户管理、角色管理、权限授予等管理 API。第四步运行脚本观察权限控制效果在服务已启动、两个用户已注册的前提下运行python auth.py4.1 阶段一user_a 创建 Experiment 并记录指标with A: exp_a mlflow.set_experiment(uuid.uuid4().hex) with mlflow.start_run(): mlflow.log_metric(a, 1)user_a以随机名称创建一个新的 Experiment并在其中启动一次 Run、记录指标a1。README 中对应的预期日志如下2023/05/02 14:03:58 INFO mlflow.tracking.fluent: Experiment with name experiment_a does not exist. Creating a new experiment.示例输出中的experiment_a是uuid4().hex随机名的示意日志本身来自 MLflow fluent API 在创建新 Experiment 时的 INFO 提示。4.2 阶段二user_b 尝试写入被拒绝403with B: mlflow.set_experiment(exp_a.name) try: with mlflow.start_run(): # not allowed mlflow.log_metric(b, 2) except Exception as e: print(str(e))user_b尝试在user_a创建的 Experiment 中启动 Run 并记录指标。由于default_permission READ默认配置见下文user_b对该 Experiment 只拥有只读权限写入请求被服务端拒绝。README 中给出的预期输出API request to endpoint /api/2.0/mlflow/runs/create failed with error code 403 ! 200. Response body: Permission denied这里的关键信息403对应 HTTP Forbidden而非 401未认证。两者在源码中有明确区分mlflow/server/auth/init.py 中make_basic_auth_response()返回 401 并附带WWW-Authenticate: Basic realmmlflow头凭据缺失或错误make_forbidden_response()则返回状态码 403、正文Permission denied身份有效但权限不足。客户端侧mlflow.tracking的 REST 调用发现返回码不是预期的 200会抛出异常并打印上述错误信息。这正是示例希望演示的认证成功 ≠ 授权成功。4.3 阶段三授予 EDIT 权限后写入成功# Grant B permission to edit As experiment with A: client.create_experiment_permission(str(exp_a.experiment_id), B.username, EDIT) # B can edit now, should be able to log a metric with B: mlflow.set_experiment(exp_a.name) with mlflow.start_run(): mlflow.log_metric(b, 2)user_a作为 Experiment 的创建者拥有 MANAGE 级权限通过认证客户端调用权限授予 API把user_b对该 Experiment 的权限提升为EDIT。随后user_b再次尝试写入这次能够成功记录指标b2。API 演进提示示例 auth.py 中使用的是create_experiment_permission(experiment_id, username, permission)这一历史接口形态。当前仓库中 mlflow/server/auth/client.py 的AuthServiceClient提供的是统一形态的权限便捷接口grant_user_permission(username, resource_type, resource_id, permission)如resource_typeexperiment、revoke_user_permission(username, resource_type, resource_id)与get_user_permission(username, resource_type, resource_id)语义一致调用时需按当前 API 传入resource_type。权限模型READ / USE / EDIT / MANAGE权限级别定义在 mlflow/server/auth/permissions.py 中每个Permission由一组布尔能力位组成权限can_readcan_usecan_updatecan_deletecan_manage典型含义READ✅❌❌❌❌只能查看资源与运行记录USE✅✅❌❌❌可使用如发起推理不可修改EDIT✅✅✅❌❌可读取、使用并更新资源MANAGE✅✅✅✅✅完全控制含删除与授权管理NO_PERMISSIONS❌❌❌❌❌无任何权限仅内部语义源码中权限按优先级排列NO_PERMISSIONS READ USE EDIT MANAGE并提供max_permission()用于合并取最大权限。授权解析的一个重要设计是资源权限的继承关系从 mlflow/server/auth/init.py 的多个解析函数可以清晰看到Run 的权限继承自其所属 Experiment_get_permission_from_run_id先取 run 的experiment_id再查 Experiment 权限LoggedModel 的权限继承自其所属 Experiment_get_model_permissionPrompt 优化任务等资源的权限同样回退到所属 Experiment。也就是说示例中把权限授予到 Experiment 层级即可覆盖该 Experiment 下所有 Run、LoggedModel 的读写控制。服务端配置basic_auth.ini 与环境变量认证应用的默认配置文件是 mlflow/server/auth/basic_auth.ini由 config.py 中的read_auth_config()读取可通过环境变量MLFLOW_AUTH_CONFIG_PATH指定自定义路径。核心配置项如下配置项默认值说明default_permissionREAD用户对未显式授权资源的默认权限database_urisqlite:///basic_auth.db认证数据库用户、权限等的存储 URIadmin_usernameadmin管理员用户名首次启动时创建admin_password空管理员密码不设默认值首次启动必填也可用环境变量authorization_functionmlflow.server.auth:authenticate_request_basic_auth可插拔的授权函数入口支持自定义鉴权逻辑grant_default_workspace_accessfalse是否让用户继承默认工作空间的default_permissionworkspace_cache_max_size/workspace_cache_ttl_seconds10000/3600资源到工作空间映射的缓存大小与 TTLauth_cache_max_size/auth_cache_ttl_seconds10000/0凭据校验缓存默认关闭0开启后能显著减少 PBKDF2 哈希比对开销相关的环境变量定义于 mlflow/environment_variables.pyMLFLOW_AUTH_ADMIN_USERNAME/MLFLOW_AUTH_ADMIN_PASSWORD覆盖配置文件中的管理员用户名/密码config.py 中优先级高于文件MLFLOW_AUTH_CONFIG_PATH自定义 auth 配置文件路径MLFLOW_TRACKING_USERNAME/MLFLOW_TRACKING_PASSWORD客户端侧注入 Basic Auth 凭据MLFLOW_FLASK_SERVER_SECRET_KEYFlask 会话签名密钥登录/CSRF 等场景使用。关于auth_cache_ttl_secondsbasic_auth.ini 注释指出开启凭据缓存后密码修改、管理员标记变更、删除等操作会立即在「处理该变更的 worker」上失效缓存但多 worker 部署下其他 worker 可能到 TTL 到期才感知因此默认关闭需要显式设置正值如 60才启用。客户端管理 API 一览除示例中使用的权限授予外mlflow/server/auth/client.py 的AuthServiceClient还提供完整的管理能力均通过 HTTP 调用服务端管理路由实现用户管理create_user(username, password)、get_user(username)、update_user_password(username, password, current_passwordNone)用户修改自己的密码时必须提供current_password管理员修改他人密码可省略、update_user_admin(username, is_admin)、delete_user(username)角色管理RBACcreate_role/get_role/list_roles/update_role/delete_role以及add_role_permission/remove_role_permission/list_role_permissions/update_role_permission、assign_role/unassign_role/list_user_roles/list_role_users用户级权限便捷接口grant_user_permission(username, resource_type, resource_id, permission)、revoke_user_permission(username, resource_type, resource_id)、get_user_permission(username, resource_type, resource_id)。例如用当前 API 复现示例中的授权步骤等价于create_experiment_permissionwith A: client.grant_user_permission(B.username, experiment, str(exp_a.experiment_id), EDIT)源码级原理一次写入请求如何被拦截从 mlflow/server/auth/init.py 的实现可以还原完整的请求链路认证每个受保护请求先经过认证逻辑从Authorization头解析 Basic 凭据调用存储层的store.authenticate_user(username, password)校验密码以 PBKDF2 哈希比对。未携带或携带错误凭据时返回 401并附带WWW-Authenticate: Basic realmmlflow响应头make_basic_auth_response引导客户端重新认证。鉴权认证通过后根据请求端点映射到对应的权限解析函数。例如创建 Run 时对应POST /api/2.0/mlflow/runs/create解析experiment_id并调用_get_permission_from_experiment_id→_get_experiment_permission→_get_role_permission_or_default最终得到该用户在此资源上的Permission。若权限不足返回 403Permission deniedmake_forbidden_response。放行权限满足如 EDIT 允许创建 Run、记录指标则正常处理请求并返回 200。示例中user_b在未授权时收到403 ! 200正是第 2 步的拒绝结果在获得 EDIT 授权后走第 3 步成功。这也解释了为什么示例的预期输出里同时出现了「Creating a new experiment」日志user_a 阶段和「403 Permission denied」user_b 阶段。完整运行清单与验证安装带认证依赖的 MLflow认证应用需要Flask-WTF做 CSRF 校验缺少时会给出pip install mlflow[auth]的安装提示设置管理员密码并启动服务export MLFLOW_AUTH_ADMIN_PASSWORDstrong-password mlflow server --app-namebasic-auth访问http://localhost:5000/signup注册user_a与user_b运行python auth.py预期依次出现创建 Experiment 的 INFO 日志 → 针对/api/2.0/mlflow/runs/create的 403Permission denied错误 →授权 EDIT 后user_b成功记录指标脚本正常结束。注意事项与延伸阅读默认配置下default_permission READ即用户对未显式授权的资源只有只读能力生产环境建议显式评估该默认值是否符合你的安全策略。首次启动务必通过环境变量或配置文件提供管理员密码否则服务拒绝启动管理员用户创建后admin_username/admin_password配置将被忽略改密请通过管理 API 完成。认证与授权逻辑可插拔通过authorization_function可替换默认的mlflow.server.auth:authenticate_request_basic_auth实现自定义鉴权仓库tests/server/auth/fixtures/下提供了多种自定义配置的测试样例可作为参考。若需进一步深入可阅读认证应用的数据库模型与迁移脚本mlflow/server/auth/db/、路由定义mlflow/server/auth/routes.py以及服务端测试tests/server/auth/其中覆盖了管理员引导、权限解析、fail-closed 标志、RBAC 客户端等完整行为。【免费下载链接】mlflowThe open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.项目地址: https://gitcode.com/GitHub_Trending/ml/mlflow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考