10 KiB
10 KiB
Ubuntu User Management API
基本信息
- 服务地址示例:
http://127.0.0.1:8000 - API 版本:
1.0.0 - 文档地址:
/docs - OpenAPI 地址:
/openapi.json - 请求与响应格式:
application/json
鉴权
所有业务接口都需要 Bearer Token。
请求头:
Authorization: Bearer <TOKEN>
TOKEN 来自 .env:
TOKEN=your-token
SERVER_NAME=user-manage-api
鉴权失败响应:
{
"detail": {
"code": "unauthorized",
"message": "Invalid bearer token."
}
}
通用错误格式
业务错误:
{
"code": "not_found",
"message": "user not found"
}
参数错误:
{
"code": "invalid_parameter",
"message": "..."
}
常见错误码:
| HTTP 状态码 | code | 描述 |
|---|---|---|
| 400 | invalid_parameter |
请求参数格式或校验失败 |
| 401 | unauthorized |
未提供 token 或 token 不正确 |
| 404 | not_found |
用户或用户组不存在,或被可见性规则隐藏 |
| 409 | resource_conflict |
用户或用户组已存在 |
| 422 | precondition_failed |
前置条件不满足,例如用户组仍有成员 |
| 423 | user_locked |
用户已锁定,只允许查看,不允许修改 |
| 500 | system_command_error |
系统命令执行失败 |
| 503 | system_timeout |
系统命令超时 |
| 503 | system_permission_denied |
系统命令权限不足 |
可见性规则
用户和用户组会受 .env 中的白名单、黑名单和 UID/GID 范围限制。
优先级:
白名单 > 黑名单 > UID/GID 范围
相关配置:
WHITELIST_USERS=
WHITELIST_GROUPS=
HIDDEN_USERS=root,daemon,nobody
HIDDEN_GROUPS=root,daemon,nogroup
LOCKED_USERS=
USER_UID_MIN=1000
USER_UID_MAX=60000
GROUP_GID_MIN=1000
GROUP_GID_MAX=60000
说明:
- 白名单中的用户/用户组始终可见并允许操作。
- 黑名单中的用户/用户组会被隐藏并禁止操作,除非同时在白名单中。
- 不在白名单和黑名单时,用户按 UID 范围判断,用户组按 GID 范围判断。
- 被隐藏的用户或用户组对 API 表现为
404 not_found。 LOCKED_USERS中的用户可以查看,但不能创建同名用户、删除、改密码、添加用户组或移除用户组。
Home 目录规则
相关配置:
HOME_BASE_DIR=/home
LINK_HOME_DIR=
DEFAULT_SHELL=/bin/bash
创建用户时:
- API 不接收客户端传入的
home_dir和shell。 - 用户 home 固定使用
HOME_BASE_DIR/username。 - 登录 shell 固定使用
DEFAULT_SHELL。 LINK_HOME_DIR为空时,用户目录直接创建在HOME_BASE_DIR下。LINK_HOME_DIR不为空时,实际目录创建在LINK_HOME_DIR/username,并在HOME_BASE_DIR/username创建软链接。
删除用户时:
- 会删除用户账号。
- 如果用户 home 是软链接,则删除该软链接。
- 如果用户 home 是普通目录,不会删除目录内容。
数据模型
UserCreateRequest
| 字段 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
username |
string | 是 | - | 用户名。格式: ^[a-z_][a-z0-9_-]{0,31}$ |
password_hash |
string | 是 | - | 预先生成的 Linux 密码 hash,长度 10 到 512 |
primary_group |
string/null | 否 | null |
主用户组。格式同用户组名 |
groups |
string[] | 否 | [] |
附加用户组,会自动去重 |
UserSummary
| 字段 | 类型 | 描述 |
|---|---|---|
username |
string | 用户名 |
uid |
integer | 用户 UID |
gid |
integer | 用户主 GID |
home_dir |
string | 用户 home 路径 |
shell |
string | 登录 shell |
GroupCreateRequest
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
groupname |
string | 是 | 用户组名。格式: ^[a-z_][a-z0-9_-]{0,31}$ |
GroupSummary
| 字段 | 类型 | 描述 |
|---|---|---|
groupname |
string | 用户组名 |
gid |
integer | 用户组 GID |
members |
string[] | 用户组成员 |
UserGroupsUpdateRequest
| 字段 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
groups |
string[] | 是 | - | 用户组列表,至少 1 个,会自动去重 |
mode |
string | 否 | append |
append 表示追加,replace 表示替换全部附加组 |
UserPasswordUpdateRequest
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
password_hash |
string | 是 | 新密码的 Linux hash,长度 10 到 512。API 不接收明文密码 |
ApiResponse
| 字段 | 类型 | 描述 |
|---|---|---|
status |
string | 固定为 ok |
message |
string | 操作结果描述 |
API 列表
健康检查
GET /health
描述:
返回服务器名称和在线状态。服务器名称来自 .env 中的 SERVER_NAME。
成功响应:
{
"server_name": "user-manage-api",
"status": "online"
}
字段说明:
| 字段 | 类型 | 描述 |
|---|---|---|
server_name |
string | 服务器名称,由 SERVER_NAME 配置 |
status |
string | 固定为 online |
创建用户
POST /users
描述:
创建系统用户。密码必须由调用方提前生成 hash,API 不处理明文密码。
请求体:
{
"username": "alice",
"password_hash": "$6$salt$hash",
"primary_group": null,
"groups": ["dev"]
}
最小请求体:
{
"username": "alice",
"password_hash": "$6$salt$hash"
}
成功响应:
{
"status": "ok",
"message": "User created."
}
注意:
username在黑名单中且不在白名单中时禁止创建。primary_group和groups中的用户组必须存在且可见。- 请求体不允许传入
shell或home_dir,两者由服务端配置决定。 - 启用
LINK_HOME_DIR后,账号 home 仍为HOME_BASE_DIR/username,实际目录位于LINK_HOME_DIR/username。
删除用户
DELETE /users/{username}
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
username |
string | 要删除的用户名 |
成功响应:
{
"status": "ok",
"message": "User deleted."
}
注意:
- 用户不存在或被隐藏时返回
404。 - 用户在
LOCKED_USERS中时返回423 user_locked。 - 删除账号后,如果 home 是软链接,会删除该软链接。
- 如果 home 是普通目录,不会删除目录内容。
修改用户密码
PATCH /users/{username}/password
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
username |
string | 要修改密码的用户名 |
请求体:
{
"password_hash": "$6$rounds=5000$salt$hash"
}
成功响应:
{
"status": "ok",
"message": "User password updated."
}
注意:
password_hash必须是调用方提前生成的 Linux 密码 hash。- 用户不存在或被隐藏时返回
404。 - 用户在
LOCKED_USERS中时返回423 user_locked。
获取用户列表
GET /users
描述:
返回可见用户列表。会应用白名单、黑名单和 UID 范围规则。
成功响应:
[
{
"username": "alice",
"uid": 1000,
"gid": 1000,
"home_dir": "/home/alice",
"shell": "/bin/bash"
}
]
获取用户详情
GET /users/{username}
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
username |
string | 用户名 |
成功响应:
{
"username": "alice",
"uid": 1000,
"gid": 1000,
"home_dir": "/home/alice",
"shell": "/bin/bash"
}
创建用户组
POST /groups
请求体:
{
"groupname": "dev"
}
成功响应:
{
"status": "ok",
"message": "Group created."
}
注意:
groupname在黑名单中且不在白名单中时禁止创建。
删除用户组
DELETE /groups/{groupname}
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
groupname |
string | 要删除的用户组名 |
成功响应:
{
"status": "ok",
"message": "Group deleted."
}
注意:
- 用户组不存在或被隐藏时返回
404。 - 用户组仍有成员时返回
422 precondition_failed。
获取用户组列表
GET /groups
描述:
返回可见用户组列表。会应用白名单、黑名单和 GID 范围规则。
成功响应:
[
{
"groupname": "dev",
"gid": 1000,
"members": ["alice"]
}
]
获取用户组详情
GET /groups/{groupname}
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
groupname |
string | 用户组名 |
成功响应:
{
"groupname": "dev",
"gid": 1000,
"members": ["alice"]
}
添加或替换用户附加组
POST /users/{username}/groups
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
username |
string | 用户名 |
请求体:
{
"groups": ["dev", "ops"],
"mode": "append"
}
参数说明:
| 字段 | 类型 | 描述 |
|---|---|---|
groups |
string[] | 要添加或替换的用户组列表 |
mode |
string | append 追加用户组,replace 替换全部附加组 |
成功响应:
{
"status": "ok",
"message": "User groups updated."
}
注意:
- 用户不存在或被隐藏时返回
404。 - 用户在
LOCKED_USERS中时返回423 user_locked。 - 目标用户组不存在或被隐藏时返回
404。
移除用户附加组
DELETE /users/{username}/groups
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
username |
string | 用户名 |
请求体:
{
"groups": ["dev"],
"mode": "append"
}
说明:
mode 字段会被接收,但删除操作只使用 groups。
成功响应:
{
"status": "ok",
"message": "User groups removed."
}
注意:
- 用户不存在或被隐藏时返回
404。 - 用户在
LOCKED_USERS中时返回423 user_locked。
获取用户所属用户组
GET /users/{username}/groups
路径参数:
| 参数 | 类型 | 描述 |
|---|---|---|
username |
string | 用户名 |
成功响应:
{
"username": "alice",
"groups": ["dev", "ops"]
}
说明:
返回的 groups 会过滤掉不可见用户组。
curl 示例
curl -X GET 'http://127.0.0.1:8000/users' \
-H 'Authorization: Bearer <TOKEN>'
curl -X POST 'http://127.0.0.1:8000/users' \
-H 'Authorization: Bearer <TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"username": "alice",
"password_hash": "$6$rounds=5000$salt$hash"
}'