311 lines
9.5 KiB
Markdown
311 lines
9.5 KiB
Markdown
# Office 365 Web 管理平台
|
||
|
||
基于你指定的 [`eggyrooch-blip/office365-tools`](https://github.com/eggyrooch-blip/office365-tools) 思路重新封装,做成了一套可直接 Web 管理的 Office 365 / Microsoft 365 账号管理后台。当前项目只保留国际版 Microsoft 365 / Microsoft Graph 实现。
|
||
|
||
当前版本覆盖的核心能力:
|
||
|
||
- 单个账号增删改查
|
||
- 用户列表勾选后批量删除、批量启用、批量停用、批量重置密码
|
||
- 批量创建、批量更新、批量删除
|
||
- 单个与批量重置密码
|
||
- 批量模板 CSV 下载后上传执行
|
||
- 批量任务进度展示,详细处理过程写入日志文件
|
||
- 许可证 SKU 列表与剩余席位查看
|
||
- 基于 `.env` 的租户配置
|
||
- 可选的后台登录保护
|
||
|
||
## 项目结构
|
||
|
||
```text
|
||
.
|
||
├── app.py
|
||
├── office365_admin/
|
||
│ ├── __init__.py
|
||
│ ├── batch.py
|
||
│ ├── graph.py
|
||
│ ├── routes.py
|
||
│ ├── services.py
|
||
│ ├── settings.py
|
||
│ ├── static/
|
||
│ └── templates/
|
||
├── tests/
|
||
└── reference-office365-tools/ # 参考仓库,保留用于对照
|
||
```
|
||
|
||
## 启动方式
|
||
|
||
1. 创建虚拟环境并安装依赖
|
||
|
||
```bash
|
||
python3 -m venv .venv
|
||
source .venv/bin/activate
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
2. 复制配置文件
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
3. 在 `.env` 中填写你的租户配置
|
||
|
||
必填项:
|
||
|
||
- `CLIENT_ID`
|
||
- `TENANT_ID`
|
||
- `CLIENT_SECRET`
|
||
- `DEFAULT_PASSWORD`
|
||
|
||
常用项:
|
||
|
||
- `DEFAULT_DOMAIN`
|
||
- `DEFAULT_LICENSE_SKU`
|
||
- `ADMIN_USERNAME`
|
||
- `ADMIN_PASSWORD`
|
||
|
||
4. 启动服务
|
||
|
||
```bash
|
||
python3 app.py
|
||
```
|
||
|
||
默认访问地址:
|
||
|
||
- [http://127.0.0.1:8000](http://127.0.0.1:8000)
|
||
|
||
## Docker Compose 部署
|
||
|
||
项目已经提供:
|
||
|
||
- [Dockerfile](/Users/youbin/Desktop/Office365UserManage/Dockerfile)
|
||
- [docker-compose.yml](/Users/youbin/Desktop/Office365UserManage/docker-compose.yml)
|
||
- [.dockerignore](/Users/youbin/Desktop/Office365UserManage/.dockerignore)
|
||
|
||
部署前提:
|
||
|
||
- 服务器或本机已安装 Docker Engine
|
||
- 已安装 Docker Compose 插件,确保 `docker compose version` 可以正常执行
|
||
|
||
部署步骤:
|
||
|
||
1. 先准备好本地 `.env`
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
必填项至少包括:
|
||
|
||
- `CLIENT_ID`
|
||
- `TENANT_ID`
|
||
- `CLIENT_SECRET`
|
||
- `DEFAULT_PASSWORD`
|
||
|
||
2. 在项目根目录执行构建并启动
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
3. 查看容器状态
|
||
|
||
```bash
|
||
docker compose ps
|
||
```
|
||
|
||
4. 查看运行日志
|
||
|
||
```bash
|
||
docker compose logs -f office365manage
|
||
```
|
||
|
||
5. 停止服务
|
||
|
||
```bash
|
||
docker compose down
|
||
```
|
||
|
||
说明:
|
||
|
||
- Compose 会读取你本地的 `.env`,但 `.env` 不会被打包进镜像,也不会进入 Git。
|
||
- 容器内固定监听 `8000` 端口,并通过 `8000:8000` 映射到宿主机。
|
||
- 应用日志会落在宿主机的 `./logs` 目录,便于排查任务执行详情。
|
||
- 如果你要改宿主机端口,可以修改 [docker-compose.yml](/Users/youbin/Desktop/Office365UserManage/docker-compose.yml) 中 `ports` 左侧的端口值。
|
||
- 如果宿主机的 `8000` 端口已经被本地 `python3 app.py` 等进程占用,请先停止原有服务,或者修改映射端口后再启动 Compose。
|
||
|
||
## 批量导入格式
|
||
|
||
### 批量创建 CSV
|
||
|
||
```csv
|
||
userPrincipalName,displayName,givenName,surname,department,jobTitle,usageLocation,skuPartNumber,password
|
||
alice,Alice Zhang,Alice,Zhang,Sales,Manager,US,ENTERPRISEPACK,Temp123!
|
||
bob@contoso.com,Bob Li,Bob,Li,IT,Engineer,US,ENTERPRISEPACK,
|
||
```
|
||
|
||
说明:
|
||
|
||
- `userPrincipalName` 可以只写用户名,系统会自动拼接 `DEFAULT_DOMAIN`
|
||
- `password` 为空时使用 `DEFAULT_PASSWORD`
|
||
- `skuPartNumber` 为空时使用 `DEFAULT_LICENSE_SKU`
|
||
|
||
### 批量更新 CSV
|
||
|
||
```csv
|
||
userPrincipalName,department,jobTitle,accountEnabled,skuPartNumber
|
||
alice@contoso.com,Operations,Lead,true,O365_BUSINESS
|
||
bob@contoso.com,Finance,Analyst,false,
|
||
```
|
||
|
||
说明:
|
||
|
||
- 至少要有一列账号标识
|
||
- 批量更新里的空白字段默认忽略,不会清空已有值
|
||
|
||
### 批量删除文本
|
||
|
||
```text
|
||
alice
|
||
bob@contoso.com
|
||
charlie@contoso.com
|
||
```
|
||
|
||
### 批量重置密码 CSV
|
||
|
||
```csv
|
||
userPrincipalName,password,forceChangePasswordNextSignIn
|
||
alice@contoso.com,Temp123!,true
|
||
bob@contoso.com,Another123!,true
|
||
```
|
||
|
||
也可以直接传纯文本账号列表,此时统一使用 `DEFAULT_PASSWORD`。
|
||
|
||
## 配置说明
|
||
|
||
### `.env` 参数配置与获取方式
|
||
|
||
| 参数名 | 是否必填 | 说明 | 获取方式 / 示例 |
|
||
| --- | --- | --- | --- |
|
||
| `CLIENT_ID` | 是 | Entra 应用的客户端 ID | 在应用注册概览页复制“应用程序(客户端) ID” |
|
||
| `TENANT_ID` | 是 | 租户 ID | 在应用注册概览页复制“目录(租户) ID” |
|
||
| `CLIENT_SECRET` | 是 | 应用客户端密钥值 | 在“证书和密码”中新建客户端密码后复制 `Value` |
|
||
| `DEFAULT_PASSWORD` | 是 | 新建账号或重置密码时的默认密码 | 由你自行定义,建议使用高强度临时密码 |
|
||
| `DEFAULT_DOMAIN` | 建议 | 用户名自动补全时使用的默认域名 | 例如 `yourtenant.onmicrosoft.com` 或已验证自定义域名 |
|
||
| `DEFAULT_USAGE_LOCATION` | 建议 | 账号默认使用地区 | 国际版常见示例:`US`、`SG`、`JP` |
|
||
| `DEFAULT_LICENSE_SKU` | 可选 | 创建用户时默认分配的许可证 SKU | 例如 `ENTERPRISEPACK`、`M365_BUSINESS_PREMIUM` |
|
||
| `WEB_AUTH_ENABLED` | 可选 | 是否启用平台网页登录保护 | `true` 或 `false` |
|
||
| `ADMIN_USERNAME` | 建议 | 本平台网页登录用户名 | 例如 `admin` |
|
||
| `ADMIN_PASSWORD` | 建议 | 本平台网页登录密码 | 由你自行定义;这不是 Microsoft 365 账号密码 |
|
||
| `SESSION_SECRET` | 建议 | Flask 会话密钥 | 建议使用随机长字符串 |
|
||
| `HOST` | 可选 | Web 服务监听地址 | 默认 `0.0.0.0` |
|
||
| `PORT` | 可选 | Web 服务监听端口 | 默认 `8000` |
|
||
| `DEBUG` | 可选 | 是否启用调试模式 | 默认 `false` |
|
||
|
||
说明:
|
||
|
||
- `DEFAULT_LICENSE_SKU` 需要填写租户里实际存在的 SKU Part Number;如果不确定,可以先启动系统,在“许可证概览”里查看。
|
||
- `ADMIN_USERNAME` / `ADMIN_PASSWORD` 是这个管理平台自己的登录账号,不是 Microsoft 365 管理员邮箱账号。
|
||
- 如果不填写 `DEFAULT_DOMAIN`,创建用户时必须填写完整邮箱格式的 `userPrincipalName`。
|
||
|
||
### Entra ID 应用注册配置
|
||
|
||
在使用本工具之前,需要在 Microsoft Entra ID(Azure AD)中注册应用程序并配置权限。
|
||
|
||
#### 步骤 1:创建应用注册
|
||
|
||
1. 登录 Microsoft Entra 管理中心
|
||
2. 导航到 `身份` -> `应用注册`
|
||
3. 点击 `+ 新建注册`
|
||
4. 填写应用信息:
|
||
- 名称:输入应用名称,例如 `Office 365 用户管理工具`
|
||
- 支持的帐户类型:选择“仅此组织目录中的帐户”
|
||
- 重定向 URI:无需填写,本项目使用客户端凭据流程
|
||
5. 点击 `注册`
|
||
|
||
#### 步骤 2:获取应用信息
|
||
|
||
注册完成后,在应用概览页面可以获取:
|
||
|
||
- 应用程序(客户端) ID:复制此值作为 `CLIENT_ID`
|
||
- 目录(租户) ID:复制此值作为 `TENANT_ID`
|
||
|
||
#### 步骤 3:创建客户端密钥
|
||
|
||
1. 在应用注册页面,导航到 `证书和密码`
|
||
2. 点击 `+ 新建客户端密码`
|
||
3. 填写描述和过期时间
|
||
4. 点击 `添加`
|
||
5. 重要:立即复制密钥值,它只会显示一次;将其填写为 `CLIENT_SECRET`
|
||
|
||
#### 步骤 4:配置 API 权限
|
||
|
||
1. 在应用注册页面,导航到 `API 权限`
|
||
2. 点击 `+ 添加权限` -> `Microsoft Graph` -> `应用程序权限`
|
||
|
||
必需权限列表:
|
||
|
||
| 权限名称 | 说明 | 是否必需 |
|
||
| --- | --- | --- |
|
||
| `User.ReadWrite.All` | 读取和写入所有用户配置文件 | 必需,用于创建、更新、删除用户 |
|
||
| `User-PasswordProfile.ReadWrite.All` | 读取和写入所有用户的密码配置文件 | 必需,用于重置密码 |
|
||
| `LicenseAssignment.ReadWrite.All` | 读取和写入所有许可证分配 | 必需,用于分配许可证 |
|
||
| `Directory.ReadWrite.All` | 读取和写入目录数据 | 可选,更高权限,可替代部分用户写入权限 |
|
||
| `AuditLog.Read.All` | 读取审核日志数据 | 可选,用于后续扩展登录活动或审计场景 |
|
||
|
||
权限配置步骤:
|
||
|
||
1. 搜索并选择每个权限
|
||
2. 点击 `添加权限`
|
||
3. 添加完成后,点击 `为 [你的组织名称] 授予管理员同意`
|
||
4. 确认授予同意
|
||
|
||
重要提示:
|
||
|
||
- 所有应用程序权限都需要管理员同意才能生效。
|
||
- 确保你是该应用程序的 `所有者`。
|
||
- 权限生效可能需要几分钟。
|
||
- 如果权限 Owner 发生变化,或者管理员重新授予了同意,建议重启本项目服务以重新获取访问令牌。
|
||
|
||
#### 步骤 5:验证权限配置
|
||
|
||
在 `API 权限` 页面,确认所有需要的权限状态都显示为“已授予(管理员同意)”。
|
||
|
||
### Graph 端点
|
||
|
||
项目固定使用国际版端点:
|
||
|
||
- Graph API: `https://graph.microsoft.com/v1.0`
|
||
- Token Endpoint: `https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token`
|
||
- Scope: `https://graph.microsoft.com/.default`
|
||
|
||
### 平台登录
|
||
|
||
如果你希望平台访问前需要登录,请配置:
|
||
|
||
```env
|
||
WEB_AUTH_ENABLED=true
|
||
ADMIN_USERNAME=admin
|
||
ADMIN_PASSWORD=ChangeMe123!
|
||
SESSION_SECRET=random-long-secret
|
||
```
|
||
|
||
如果 `WEB_AUTH_ENABLED=true` 但没有设置用户名密码,系统会自动降级为无登录保护模式,并在页面状态区显示提醒。
|
||
|
||
## 测试
|
||
|
||
```bash
|
||
pytest
|
||
```
|
||
|
||
## 日志
|
||
|
||
服务运行后会把详细操作日志写入:
|
||
|
||
- [logs/office365_admin.log](/Users/youbin/Desktop/Office365UserManage/logs/office365_admin.log)
|
||
|
||
## 说明
|
||
|
||
- `reference-office365-tools` 是我拉下来的参考仓库,当前运行时不会直接引用它。
|
||
- Web 平台的 Graph 调用逻辑已经按后台服务方式重构,便于继续扩展审批流、组织架构、日志审计等能力。
|