MLflow Authentication Python API 深度指南:AuthServiceClient 与认证实体模型全解析
【免费下载链接】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
MLflow 作为面向 Agent、LLM 与机器学习模型的开源 AI 工程平台,其自带的 Basic Authentication 插件为追踪服务器提供了用户、角色(RBAC)与资源权限的一整套访问控制能力。本指南以官方 API 参考文档 docs/api_reference/source/auth/python-api.rst 为骨架,系统讲解mlflow.server.auth.client.AuthServiceClient的全部客户端方法与mlflow.server.auth.entities中的实体数据模型,并结合仓库源码剖析其底层 REST 调用链、权限等级设计与测试验证方式,帮助你用 Python 代码完整地管理 MLflow 认证体系。
一、认证插件与 Python API 的关系
MLflow 追踪服务器默认不启用身份认证,需要启动 Basic Authentication 插件(mlflow.server.auth)后才能使用认证能力。该插件在 mlflow/server/auth/ 目录下实现,核心模块包括:
client.py:面向用户的AuthServiceClient客户端类,即本文主角;entities.py:用户、角色、权限等 REST 响应的数据模型;routes.py:全部认证相关 REST 端点路径定义;permissions.py:权限等级(READ/USE/EDIT/MANAGE)与资源类型常量;config.py与basic_auth.ini:认证插件的配置读取与默认配置。
官方 API 文档正是通过 Sphinx 的autoclass与automodule指令,将client.py与entities.py中的公开 API 自动渲染成 python-api.rst 页面。因此,"Authentication Python API" 的完整内容就是客户端方法 + 实体模型两部分,下文逐一展开。
二、AuthServiceClient:认证服务的 Python 客户端
AuthServiceClient定义在 mlflow/server/auth/client.py#L35,官方文档对其定位的说明是:面向启用了默认基本认证插件的 MLflow 追踪服务器的客户端,并明确推荐使用mlflow.server.get_app_client()工厂函数来实例化,而非直接调用构造函数。
2.1 实例化方式
构造函数签名只有一个必填参数tracking_uri,即本地或远程追踪服务器的地址:
from mlflow.server.auth.client import AuthServiceClient # 直接构造(不推荐) client = AuthServiceClient("http://localhost:5000") # 推荐:通过应用客户端工厂构造 client = mlflow.server.get_app_client("basic-auth", "http://localhost:5000")get_app_client实现在 mlflow/server/init.py#L245,它根据app_name(例如"basic-auth")从 Python 入口点mlflow.app.client中查找并加载对应的客户端类,找不到时抛出MlflowException。使用工厂方法的优势在于:未来认证插件实现变化时,调用方代码无需改动。
2.2 底层 REST 调用机制
AuthServiceClient的所有方法都收敛到私有方法_request(client.py#L49):
def _request(self, endpoint, method, *, expected_status: int = 200, **kwargs): host_creds = get_default_host_creds(self.tracking_uri) resp = http_request(host_creds, endpoint, method, **kwargs) resp = verify_rest_response(resp, endpoint, expected_status=expected_status) if resp.status_code == 204 or not resp.content: return {} return resp.json()其工作流程为:
- 通过
get_default_host_creds(tracking_uri)解析主机凭据——这也是为什么所有需要鉴权的操作都要求先配置MLFLOW_TRACKING_USERNAME与MLFLOW_TRACKING_PASSWORD环境变量; - 用
http_request发起 HTTP 请求(端点路径来自routes.py中的常量); - 用
verify_rest_response校验响应状态码(默认期望 200); 204 No Content或空响应体统一返回{},否则解析 JSON。
端点路径集中在 mlflow/server/auth/routes.py,例如用户管理端点CREATE_USER = /api/2.0/mlflow/users/create、GET_USER = /api/2.0/mlflow/users/get,角色管理端点(RBAC 部分)则统一走/api/2.0/mlflow/roles/*(version=3)路径。每个端点同时暴露 REST 与 AJAX 两个变体,分别供 Python 客户端与 MLflow 前端 UI 使用。
三、用户管理 API
AuthServiceClient提供 5 个用户管理方法,覆盖用户的创建、查询、改密、管理员授权与删除全生命周期。
3.1 create_user 创建用户
client = AuthServiceClient("tracking_uri") user = client.create_user("newuser", "newpassword") print(f"user_id: {user.id}") print(f"username: {user.username}") print(f"password_hash: {user.password_hash}") print(f"is_admin: {user.is_admin}")输出示例(来自官方 docstring):
user_id: 3 username: newuser password_hash: REDACTED is_admin: False要点:
- 参数
username与password,其中 password 不允许为空字符串; - 若用户名已存在,抛出
mlflow.exceptions.RestException; - 返回
User实体对象,其password_hash属性恒为"REDACTED"——这是 entities.py#L51 中User.from_json的刻意设计:哈希值只允许在服务端存储,绝不通过 REST API 回传明文哈希; - 新建用户默认
is_admin=False。
3.2 get_user 查询用户
export MLFLOW_TRACKING_USERNAME=admin export MLFLOW_TRACKING_PASSWORD=passwordclient = AuthServiceClient("tracking_uri") client.create_user("newuser", "newpassword") user = client.get_user("newuser")用户不存在时抛出RestException。注意调用前必须先设置管理员凭据环境变量,因为用户管理端点要求认证。
3.3 update_user_password 修改密码
# 管理员路径 —— 无需 current_password client.update_user_password("newuser", "anotherpassword") # 自助服务路径 —— 必须提供 current_password client.update_user_password("newuser", "thirdpassword", current_password="anotherpassword")方法签名(client.py#L145):
def update_user_password(self, username: str, password: str, current_password: str | None = None)设计规则:
current_password为可选项,但用户修改自己的密码(自助服务)时必填,否则服务端拒绝请求;- 管理员修改他人密码时可省略该参数;
- 底层发送
PATCH /api/2.0/mlflow/users/update-password; - 若用户不存在、或 current_password 缺失/错误,抛出
RestException。
3.4 update_user_admin 设置管理员
client.update_user_admin("newuser", True)将is_admin更新为True/False,发送PATCH /api/2.0/mlflow/users/update-admin,用户不存在时抛出RestException。
3.5 delete_user 删除用户
client.delete_user("newuser")发送DELETE /api/2.0/mlflow/users/delete。删除操作同样受管理员权限约束。
3.6 用户管理 API 一览
| 方法 | HTTP | 端点(REST 路径) | 关键行为 |
|---|---|---|---|
create_user | POST | /mlflow/users/create | 重名抛异常,password 不可为空 |
get_user | GET | /mlflow/users/get | 不存在抛异常 |
update_user_password | PATCH | /mlflow/users/update-password | 自助改密需current_password |
update_user_admin | PATCH | /mlflow/users/update-admin | 设置/取消管理员 |
delete_user | DELETE | /mlflow/users/delete | 删除指定用户 |
测试用例位于 tests/server/auth/test_client.py,例如test_create_user、test_get_user分别验证了"未认证访问抛UNAUTHENTICATED(You are not authenticated.)"与"非管理员调用抛PERMISSION_DENIED(Permission denied.)"的异常路径,可作为调用方错误处理的参照。
四、角色管理 API(RBAC)
角色管理是AuthServiceClient在# ---- Role management (RBAC) ----注释(client.py#L256)之后集中提供的能力,让管理员把一组权限打包成角色,再批量授予用户。
4.1 角色的创建、查询与列表
# 创建角色(指定 workspace 与名称,description 可选) role = client.create_role(workspace="default", name="data-scientist", description="ML training access") print(role.id, role.name, role.workspace, role.description) # 按 ID 查询角色 role = client.get_role(role_id=1) # 列出某 workspace 下的全部角色 roles = client.list_roles(workspace="default") # 跨 workspace 列出全部角色(admin-only,服务端强制校验) all_roles = client.list_all_roles()签名说明:
create_role(workspace, name, description=None) -> Role;get_role(role_id) -> Role,role_id会被转为字符串作为查询参数;list_roles(workspace) -> list[Role];list_all_roles()与list_roles共用LIST_ROLES端点,但省略workspace参数后返回跨 workspace 的全量列表(仅管理员可用,服务端强制校验),见 client.py#L339-L343。
4.2 角色的更新与删除
# 更新角色名称与描述(均可选) role = client.update_role(role_id=1, name="ml-engineer", description="Updated") # 删除角色 client.delete_role(role_id=1)update_role只把非 None 字段放入请求体,发送PATCH /api/2.0/mlflow/roles/update。
4.3 角色权限(RolePermission)管理
角色本身不携带权限,需要向角色添加"资源级权限条目":
# 给角色添加一条权限:对实验资源类型、匹配模式 "42" 的实验授予 EDIT rp = client.add_role_permission( role_id=1, resource_type="experiment", resource_pattern="42", permission="EDIT", ) print(rp.id, rp.role_id, rp.resource_type, rp.resource_pattern, rp.permission) # 列出角色全部权限条目 perms = client.list_role_permissions(role_id=1) # 修改某条权限条目的权限等级 rp = client.update_role_permission(role_permission_id=1, permission="MANAGE") # 移除权限条目 client.remove_role_permission(role_permission_id=1)resource_pattern是资源匹配模式,可用于匹配单个资源 ID 或一组资源(结合 workspace 与资源类型共同定位目标)。权限等级取值必须是READ/USE/EDIT/MANAGE之一(详见下文权限模型一节)。
4.4 用户与角色的绑定
# 把角色分配给用户 assignment = client.assign_role(username="alice", role_id=1) print(assignment.id, assignment.user_id, assignment.role_id) # 解除角色 client.unassign_role(username="alice", role_id=1) # 查看某用户拥有的角色 roles = client.list_user_roles(username="alice") # 查看某角色下的全部用户-角色绑定 assignments = client.list_role_users(role_id=1)角色相关方法的端点路径集中在 routes.py#L53-L78,全部为/api/2.0/mlflow/roles/*(version=3)与/api/2.0/mlflow/users/roles/*系列,并成对提供 AJAX 路径供前端使用。
五、统一用户权限便捷 API
在# ---- Unified per-user permission convenience APIs ----注释(client.py#L345)之后,AuthServiceClient提供了一组面向单个用户的"统一授权/撤销/检查"便捷方法,用统一的(resource_type, resource_id)形态覆盖资源授权,并保留传统按资源 MANAGE 委托的语义。
# 授予用户对某资源的权限 client.grant_user_permission( username="alice", resource_type="experiment", resource_id="42", permission="EDIT", ) # 撤销用户对某资源的权限 client.revoke_user_permission(username="alice", resource_type="experiment", resource_id="42") # 查询用户对某资源的有效权限 result = client.get_user_permission( username="alice", resource_type="experiment", resource_id="42" ) print(result.allowed) # 是否允许访问(对应 Permission.can_use) print(result.permission) # 解析后的有效权限名,如 "EDIT"从 routes.py 的注释可知(routes.py#L16-L26),grant/revoke会写入用户在活动 workspace 下的合成角色__user_<id>__,而get_user_permission(对应GET /mlflow/users/permissions/get)按照与运行时鉴权相同的方式解析用户的有效权限,因此调用方看到的检查结果与实际请求的鉴权结果完全一致。返回的GetUserPermissionResult中,allowed镜像Permission.can_use(常规访问层),permission为解析后的有效权限名,见 entities.py#L502-L525。
六、entities 实体数据模型
mlflow/server/auth/entities.py 定义了认证 API 的所有数据载体。它们普遍具备三个特征:只读@property访问、to_json()序列化、from_json()反序列化。下文按功能分组说明。
6.1 用户实体 User
class User: id # 用户 ID username # 用户名 password_hash # 恒为 "REDACTED"(from_json 强制脱敏) is_admin # 是否为管理员(可写属性)User.to_json()输出{id, username, is_admin}(不含密码哈希),from_json将哈希固定为"REDACTED"(entities.py#L46-L53),从根源上杜绝哈希泄露。
6.2 角色相关实体
- Role(entities.py#L353):
id、name(可写)、workspace、description(可写)、permissions(RolePermission列表)。from_json在缺少 workspace 字段时回退到DEFAULT_WORKSPACE_NAME。 - RolePermission(entities.py#L416):
id、role_id、resource_type、resource_pattern、permission(可写)。 - UserRoleAssignment(entities.py#L468):
id、user_id、role_id,表示用户-角色绑定关系。
6.3 资源权限实体
针对不同类型的资源,认证系统各自定义了权限实体,字段模式统一为(<资源标识>, user_id, permission):
| 实体 | 资源标识字段 | 适用资源 |
|---|---|---|
ExperimentPermission | experiment_id | 实验 |
RegisteredModelPermission | name(+workspace) | 注册模型 |
ScorerPermission | experiment_id,scorer_name | 在线评分器 |
GatewaySecretPermission | secret_id | Gateway 密钥 |
GatewayEndpointPermission | endpoint_id | Gateway 端点 |
GatewayModelDefinitionPermission | model_definition_id | Gateway 模型定义 |
MCPServerPermission | name | MCP 服务器 |
RegisteredModelPermission与ScorerPermission拥有两个资源标识字段,分别用resolve_entity_workspace_name解析 workspace。这些实体的存在说明认证粒度不仅覆盖传统 ML 资源(实验、模型),也延伸到 Gateway、MCP 等新一代 Agent/LLM 能力面。
6.4 查询结果与工作区权限
- GetUserPermissionResult(entities.py#L502):
allowed: bool+permission: str,get_user_permission的返回类型。 - WorkspacePermission(entities.py#L528):
workspace、user_id、permission,构造时强制校验三者非空,缺失即抛MlflowException.invalid_parameter_value;额外暴露只读属性can_use,即get_permission(permission).can_use。from_json同样对缺失字段做显式校验。
七、权限等级模型与资源类型(底层支撑)
理解AuthServiceClient的权限参数取值,必须回到 mlflow/server/auth/permissions.py 中的权限模型。
7.1 五种权限等级
Permission是一个 dataclass,拥有can_read / can_use / can_update / can_delete / can_manage五个能力位(permissions.py#L7-L14)。系统预定义了五个等级(permissions.py#L17-L60):
| 权限名 | can_read | can_use | can_update | can_delete | can_manage | 语义 |
|---|---|---|---|---|---|---|
READ | ✅ | ❌ | ❌ | ❌ | ❌ | 只读 |
USE | ✅ | ✅ | ❌ | ❌ | ❌ | 可使用 |
EDIT | ✅ | ✅ | ✅ | ❌ | ❌ | 可编辑 |
MANAGE | ✅ | ✅ | ✅ | ✅ | ✅ | 完全管理 |
NO_PERMISSIONS | ❌ | ❌ | ❌ | ❌ | ❌ | 无权限 |
权限之间有优先级排序PERMISSION_PRIORITY(NO_PERMISSIONS < READ < USE < EDIT < MANAGE),max_permission(a, b)据此合并取较高者。
7.2 资源类型与可授权限约束
- 具体资源类型(
RESOURCE_TYPE_EXPERIMENT、RESOURCE_TYPE_REGISTERED_MODEL、RESOURCE_TYPE_PROMPT、RESOURCE_TYPE_SCORER、RESOURCE_TYPE_GATEWAY_SECRET、RESOURCE_TYPE_GATEWAY_ENDPOINT、RESOURCE_TYPE_GATEWAY_MODEL_DEFINITION、RESOURCE_TYPE_MCP_SERVER)只接受READ/USE/EDIT/MANAGE,显式NO_PERMISSIONS被拒绝——因为"缺失授权 + 配置的 default_permission"已经足以表达无访问权; - 工作区级资源类型(
RESOURCE_TYPE_WORKSPACE,resource_pattern必须为"*")只接受USE(工作区成员:访问 + 创建资源 + 继承 default_permission)与MANAGE(额外获得角色/用户管理工作区管理权),READ/EDIT被有意排除(permissions.py#L96-L134)。
所有非法的权限名、资源类型或不匹配的组合都会抛出MlflowException(INVALID_PARAMETER_VALUE),在调用add_role_permission等 API 前即可被服务端校验拦截。
八、配置与认证前提
要使用上述 Python API,需要先以 Basic Authentication 插件模式启动追踪服务器,并配置认证参数。
8.1 配置文件 basic_auth.ini
默认配置位于 mlflow/server/auth/basic_auth.ini:
[mlflow] default_permission = READ database_uri = sqlite:///basic_auth.db admin_username = admin admin_password = password1234 authorization_function = mlflow.server.auth:authenticate_request_basic_auth # 为 true 时,用户继承 reserved 'default' workspace 的 default_permission grant_default_workspace_access = false # workspace_cache_max_size = 10000 # workspace_cache_ttl_seconds = 3600 # auth_cache_max_size = 10000 # auth_cache_ttl_seconds = 08.2 配置项语义(来自 config.py)
read_auth_config()(mlflow/server/auth/config.py#L30)读取该文件并解析为AuthConfigNamedTuple:
default_permission:资源无显式授权时用户的默认权限(默认READ);database_uri:认证数据的存储后端(默认 SQLite);admin_username/admin_password:初始管理员凭据;authorization_function:鉴权函数入口(默认mlflow.server.auth:authenticate_request_basic_auth),可通过 mlflow/environment_variables.py 中的MLFLOW_AUTH_CONFIG_PATH指定自定义配置文件路径;grant_default_workspace_access:用户是否继承 default workspace 的默认权限(默认 false);workspace_cache_max_size/workspace_cache_ttl_seconds:资源到工作区查询缓存(默认 10000 / 3600 秒);auth_cache_max_size/auth_cache_ttl_seconds:用户名/密码校验缓存,默认关闭(TTL=0);开启后 PBKDF2 哈希比对在同一 (user, password) 上每个 TTL 窗口内最多执行一次,文档注释称请求密集型鉴权工作负载可带来约 3 倍吞吐提升,但缓存位于各 worker 进程内,会引入最长一个 TTL 的陈旧窗口,多 worker 部署与带外变更(直接 SQL、外部 IdP 同步)需要自行权衡;read_database_uri:可选的只读数据库 URI。
8.3 客户端凭据
所有需要鉴权的 API 调用都要通过环境变量携带凭据:
export MLFLOW_TRACKING_USERNAME=admin export MLFLOW_TRACKING_PASSWORD=password未认证调用将抛出RestException(UNAUTHENTICATED,"You are not authenticated."),已认证但权限不足则抛出PERMISSION_DENIED("Permission denied."),这与测试文件 tests/server/auth/test_client.py 中assert_unauthenticated/assert_unauthorized两个辅助上下文管理器断言的行为完全一致。
九、测试验证与最佳实践
仓库在 tests/server/auth/ 下对客户端 API 提供了成体系的测试覆盖:
- test_client.py:用户管理全流程(创建、查询、改密、管理员、删除)、当前用户查询,以及未认证/越权异常路径;
- test_client_rbac.py:角色 CRUD、角色权限条目、用户-角色绑定的行为验证;
- test_client_workspace.py:workspace 相关授权行为验证。
测试通过_init_server(app="mlflow.server.auth:create_app", ...)以隔离的 SQLite 后端启动真实 Flask 服务器(test_client.py#L43-L59),因此是端到端的 REST 验证。
实际集成时的建议:
- 一律通过
get_app_client("basic-auth", tracking_uri)获取客户端,避免直接依赖AuthServiceClient的实现细节; - 密码哈希只读不看:
User.password_hash恒为"REDACTED",不要依赖它做任何校验逻辑; - 区分管理员路径与自助服务路径:改密时,用户改自己的密码必须传
current_password,管理员改他人密码可省略; - 角色权限条目的
permission只能取READ/USE/EDIT/MANAGE,workspace 级授权只接受USE/MANAGE,非法取值会在服务端被拒绝; - 用
get_user_permission做授权预检:它按运行时鉴权同样的逻辑解析有效权限,返回的allowed与permission即真实请求会看到的结果; - 生产环境务必修改
basic_auth.ini中的默认管理员密码,并按需开启auth_cache_ttl_seconds(注意多 worker 的陈旧窗口)。
十、结语
MLflow Authentication Python API 以AuthServiceClient为统一入口,向上提供用户、角色(RBAC)、角色权限与按用户便捷授权四层操作能力,向下以entities实体模型承载所有 REST 响应,并由permissions.py的 READ/USE/EDIT/MANAGE 权限模型与多类资源类型构成授权语义的底层支撑。配合 python-api.rst 自动生成的 API 参考、routes.py 的端点清单以及 tests/server/auth/ 的端到端测试,你可以据此在团队中落地一套"按角色授权、按资源管控、按用户审计"的完整访问控制体系。
【免费下载链接】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),仅供参考