BastionSSO/user_manage_api/api_document.md

593 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ubuntu User Management API
## 基本信息
- 服务地址示例: `http://127.0.0.1:8000`
- API 版本: `1.0.0`
- 文档地址: `/docs`
- OpenAPI 地址: `/openapi.json`
- 请求与响应格式: `application/json`
## 鉴权
所有业务接口都需要 Bearer Token。
请求头:
```http
Authorization: Bearer <TOKEN>
```
`TOKEN` 来自 `.env`:
```env
TOKEN=your-token
SERVER_NAME=user-manage-api
```
鉴权失败响应:
```json
{
"detail": {
"code": "unauthorized",
"message": "Invalid bearer token."
}
}
```
## 通用错误格式
业务错误:
```json
{
"code": "not_found",
"message": "user not found"
}
```
参数错误:
```json
{
"code": "invalid_parameter",
"message": "..."
}
```
常见错误码:
| HTTP 状态码 | code | 描述 |
| --- | --- | --- |
| 400 | `invalid_parameter` | 请求参数格式或校验失败 |
| 400 | `invalid_home_dir` | `home_dir` 不在 `HOME_BASE_DIR` 下 |
| 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 范围限制。
优先级:
```text
白名单 > 黑名单 > UID/GID 范围
```
相关配置:
```env
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 目录规则
相关配置:
```env
HOME_BASE_DIR=/home
LINK_HOME_DIR=
```
创建用户时:
- `home_dir` 为空时,默认使用 `HOME_BASE_DIR/username`
- `home_dir` 不为空时,必须位于 `HOME_BASE_DIR` 下。
- `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[] | 否 | `[]` | 附加用户组,会自动去重 |
| `shell` | string | 否 | `/bin/bash` | 登录 shell |
| `home_dir` | string/null | 否 | `null` | 用户 home 路径,必须在 `HOME_BASE_DIR` 下 |
### 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 列表
### 健康检查
```http
GET /health
```
描述:
返回服务器名称和在线状态。服务器名称来自 `.env` 中的 `SERVER_NAME`
成功响应:
```json
{
"server_name": "user-manage-api",
"status": "online"
}
```
字段说明:
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| `server_name` | string | 服务器名称,由 `SERVER_NAME` 配置 |
| `status` | string | 固定为 `online` |
### 创建用户
```http
POST /users
```
描述:
创建系统用户。密码必须由调用方提前生成 hashAPI 不处理明文密码。
请求体:
```json
{
"username": "alice",
"password_hash": "$6$salt$hash",
"primary_group": null,
"groups": ["dev"],
"shell": "/bin/bash",
"home_dir": "/home/alice"
}
```
最小请求体:
```json
{
"username": "alice",
"password_hash": "$6$salt$hash"
}
```
成功响应:
```json
{
"status": "ok",
"message": "User created."
}
```
注意:
- `username` 在黑名单中且不在白名单中时禁止创建。
- `primary_group``groups` 中的用户组必须存在且可见。
- `home_dir` 必须在 `HOME_BASE_DIR` 下。
- 启用 `LINK_HOME_DIR` 后,账号 home 仍为 `HOME_BASE_DIR/username`,实际目录位于 `LINK_HOME_DIR/username`
### 删除用户
```http
DELETE /users/{username}
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `username` | string | 要删除的用户名 |
成功响应:
```json
{
"status": "ok",
"message": "User deleted."
}
```
注意:
- 用户不存在或被隐藏时返回 `404`
- 用户在 `LOCKED_USERS` 中时返回 `423 user_locked`
- 删除账号后,如果 home 是软链接,会删除该软链接。
- 如果 home 是普通目录,不会删除目录内容。
### 修改用户密码
```http
PATCH /users/{username}/password
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `username` | string | 要修改密码的用户名 |
请求体:
```json
{
"password_hash": "$6$rounds=5000$salt$hash"
}
```
成功响应:
```json
{
"status": "ok",
"message": "User password updated."
}
```
注意:
- `password_hash` 必须是调用方提前生成的 Linux 密码 hash。
- 用户不存在或被隐藏时返回 `404`
- 用户在 `LOCKED_USERS` 中时返回 `423 user_locked`
### 获取用户列表
```http
GET /users
```
描述:
返回可见用户列表。会应用白名单、黑名单和 UID 范围规则。
成功响应:
```json
[
{
"username": "alice",
"uid": 1000,
"gid": 1000,
"home_dir": "/home/alice",
"shell": "/bin/bash"
}
]
```
### 获取用户详情
```http
GET /users/{username}
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `username` | string | 用户名 |
成功响应:
```json
{
"username": "alice",
"uid": 1000,
"gid": 1000,
"home_dir": "/home/alice",
"shell": "/bin/bash"
}
```
### 创建用户组
```http
POST /groups
```
请求体:
```json
{
"groupname": "dev"
}
```
成功响应:
```json
{
"status": "ok",
"message": "Group created."
}
```
注意:
- `groupname` 在黑名单中且不在白名单中时禁止创建。
### 删除用户组
```http
DELETE /groups/{groupname}
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `groupname` | string | 要删除的用户组名 |
成功响应:
```json
{
"status": "ok",
"message": "Group deleted."
}
```
注意:
- 用户组不存在或被隐藏时返回 `404`
- 用户组仍有成员时返回 `422 precondition_failed`
### 获取用户组列表
```http
GET /groups
```
描述:
返回可见用户组列表。会应用白名单、黑名单和 GID 范围规则。
成功响应:
```json
[
{
"groupname": "dev",
"gid": 1000,
"members": ["alice"]
}
]
```
### 获取用户组详情
```http
GET /groups/{groupname}
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `groupname` | string | 用户组名 |
成功响应:
```json
{
"groupname": "dev",
"gid": 1000,
"members": ["alice"]
}
```
### 添加或替换用户附加组
```http
POST /users/{username}/groups
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `username` | string | 用户名 |
请求体:
```json
{
"groups": ["dev", "ops"],
"mode": "append"
}
```
参数说明:
| 字段 | 类型 | 描述 |
| --- | --- | --- |
| `groups` | string[] | 要添加或替换的用户组列表 |
| `mode` | string | `append` 追加用户组,`replace` 替换全部附加组 |
成功响应:
```json
{
"status": "ok",
"message": "User groups updated."
}
```
注意:
- 用户不存在或被隐藏时返回 `404`
- 用户在 `LOCKED_USERS` 中时返回 `423 user_locked`
- 目标用户组不存在或被隐藏时返回 `404`
### 移除用户附加组
```http
DELETE /users/{username}/groups
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `username` | string | 用户名 |
请求体:
```json
{
"groups": ["dev"],
"mode": "append"
}
```
说明:
`mode` 字段会被接收,但删除操作只使用 `groups`
成功响应:
```json
{
"status": "ok",
"message": "User groups removed."
}
```
注意:
- 用户不存在或被隐藏时返回 `404`
- 用户在 `LOCKED_USERS` 中时返回 `423 user_locked`
### 获取用户所属用户组
```http
GET /users/{username}/groups
```
路径参数:
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| `username` | string | 用户名 |
成功响应:
```json
{
"username": "alice",
"groups": ["dev", "ops"]
}
```
说明:
返回的 `groups` 会过滤掉不可见用户组。
## curl 示例
```bash
curl -X GET 'http://127.0.0.1:8000/users' \
-H 'Authorization: Bearer <TOKEN>'
```
```bash
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",
"shell": "/bin/bash"
}'
```