Verified against current code; fixed stale/inaccurate sections and documented previously-undocumented features/flags/endpoints. Added a "Part of the HarborForge platform" reference and role/port. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
296 lines
7.5 KiB
Markdown
296 lines
7.5 KiB
Markdown
# Abstract Wizard
|
||
|
||
[English](#english) | [中文](#中文)
|
||
|
||
---
|
||
|
||
## English
|
||
|
||
Secure configuration file management service for first-time platform setup. Read, modify, and version-control JSON/YAML config files via REST API. Bound to localhost only — access remotely via an SSH tunnel.
|
||
|
||
Part of the [HarborForge](../README.md) platform — `AbstractWizard` is the Go secure first-time setup service. The container listens on port `8080` (in the bundled compose file it is published as `127.0.0.1:18080`). It is intentionally separate from the core API (`HarborForge.Backend`, port 8000) and is used to seed and adjust configuration before/around bootstrap.
|
||
|
||
### Quick Start
|
||
|
||
#### Docker Compose (Recommended)
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
The service listens on `127.0.0.1:18080`.
|
||
|
||
#### Run Locally
|
||
|
||
```bash
|
||
go build -o abstract-wizard .
|
||
CONFIG_DIR=./configs ./abstract-wizard
|
||
```
|
||
|
||
### Environment Variables
|
||
|
||
| Variable | Default | Description |
|
||
|----------|---------|-------------|
|
||
| `CONFIG_DIR` | `/config` | Base directory for config files |
|
||
| `LISTEN_ADDR` | `127.0.0.1:8080` | HTTP listen address |
|
||
| `MAX_BACKUPS` | `10` | Max backup versions per file |
|
||
| `CORS_ORIGINS` | _(empty)_ | Comma-separated allowed CORS origins. Empty or `*` allows all origins. |
|
||
|
||
### API
|
||
|
||
#### Health Check
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/health
|
||
```
|
||
|
||
#### Read Config
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/api/v1/config/app.json
|
||
```
|
||
|
||
#### Full Replace
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/config/app.json \
|
||
-d '{"database": {"host": "localhost", "port": 5432}}'
|
||
```
|
||
|
||
A backup is created automatically before each write. The response includes `backup_version`.
|
||
|
||
#### Partial Update (Deep Merge)
|
||
|
||
```bash
|
||
curl -X PATCH http://127.0.0.1:18080/api/v1/config/app.json \
|
||
-d '{"database": {"port": 3306}}'
|
||
```
|
||
|
||
Only the specified fields are updated; nested objects are merged recursively.
|
||
|
||
#### List Backups
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/api/v1/backups/app.json
|
||
```
|
||
|
||
#### Rollback
|
||
|
||
```bash
|
||
# Get the version from the backup list, then:
|
||
curl -X POST http://127.0.0.1:18080/api/v1/rollback/app.json \
|
||
-d '{"version": "20260215T120000Z"}'
|
||
```
|
||
|
||
#### Mode Switching
|
||
|
||
Get current mode:
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/api/v1/mode
|
||
```
|
||
|
||
Switch to readonly (rejects all writes):
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/mode \
|
||
-d '{"mode": "readonly"}'
|
||
```
|
||
|
||
Switch back to init (read/write):
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/mode \
|
||
-d '{"mode": "init"}'
|
||
```
|
||
|
||
### YAML Support
|
||
|
||
All endpoints support both JSON and YAML. The format is detected by file extension:
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/config/app.yaml \
|
||
-H "Content-Type: text/yaml" \
|
||
-d '
|
||
database:
|
||
host: localhost
|
||
port: 5432
|
||
'
|
||
```
|
||
|
||
### Security Model
|
||
|
||
The service binds to `127.0.0.1` by default and is not exposed externally. Use an SSH tunnel for remote access:
|
||
|
||
```bash
|
||
ssh -L 18080:127.0.0.1:18080 user@server
|
||
```
|
||
|
||
Then access via `http://127.0.0.1:18080` locally.
|
||
|
||
### Project Structure
|
||
|
||
```
|
||
├── main.go # Entry point, env config, graceful shutdown
|
||
├── config/
|
||
│ ├── validation.go # Path validation, traversal prevention
|
||
│ ├── parser.go # JSON/YAML parse, serialize, deep merge
|
||
│ ├── atomic.go # Atomic write (temp → fsync → rename)
|
||
│ └── backup.go # Timestamped backups, pruning, rollback
|
||
├── audit/
|
||
│ └── logger.go # Structured JSON audit log
|
||
├── server/
|
||
│ ├── server.go # HTTP server, routing, mode state machine, graceful shutdown
|
||
│ ├── middleware.go # Request logging middleware
|
||
│ ├── cors.go # CORS middleware (CORS_ORIGINS)
|
||
│ └── handlers.go # API handlers
|
||
├── Dockerfile # Multi-stage build (distroless, nonroot)
|
||
└── docker-compose.yaml # Example deployment
|
||
```
|
||
|
||
---
|
||
|
||
## 中文
|
||
|
||
用于平台首次安装的安全配置文件管理服务。通过 REST API 对 JSON/YAML 配置文件进行读取、修改和版本管理,仅监听 localhost,通过 SSH 隧道访问。
|
||
|
||
本组件是 [HarborForge](../README.md) 平台的一部分 —— `AbstractWizard` 是 Go 编写的安全首次安装服务。容器内监听 `8080` 端口(示例 compose 中映射为 `127.0.0.1:18080`),与核心 API(`HarborForge.Backend`,端口 8000)相互独立,用于在引导前后写入和调整配置。
|
||
|
||
### 快速开始
|
||
|
||
#### Docker Compose(推荐)
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
服务启动后监听 `127.0.0.1:18080`。
|
||
|
||
#### 本地运行
|
||
|
||
```bash
|
||
go build -o abstract-wizard .
|
||
CONFIG_DIR=./configs ./abstract-wizard
|
||
```
|
||
|
||
### 环境变量
|
||
|
||
| 变量 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `CONFIG_DIR` | `/config` | 配置文件存放目录 |
|
||
| `LISTEN_ADDR` | `127.0.0.1:8080` | 监听地址 |
|
||
| `MAX_BACKUPS` | `10` | 每个文件保留的最大备份数 |
|
||
| `CORS_ORIGINS` | _(空)_ | 逗号分隔的允许 CORS 来源;为空或 `*` 时允许所有来源 |
|
||
|
||
### API
|
||
|
||
#### 健康检查
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/health
|
||
```
|
||
|
||
#### 读取配置
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/api/v1/config/app.json
|
||
```
|
||
|
||
#### 完整替换配置
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/config/app.json \
|
||
-d '{"database": {"host": "localhost", "port": 5432}}'
|
||
```
|
||
|
||
写入前会自动创建备份,响应中包含 `backup_version`。
|
||
|
||
#### 局部更新(深度合并)
|
||
|
||
```bash
|
||
curl -X PATCH http://127.0.0.1:18080/api/v1/config/app.json \
|
||
-d '{"database": {"port": 3306}}'
|
||
```
|
||
|
||
仅更新指定字段,嵌套对象递归合并。
|
||
|
||
#### 查看备份列表
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/api/v1/backups/app.json
|
||
```
|
||
|
||
#### 回滚到指定版本
|
||
|
||
```bash
|
||
# 先从备份列表获取版本号,然后:
|
||
curl -X POST http://127.0.0.1:18080/api/v1/rollback/app.json \
|
||
-d '{"version": "20260215T120000Z"}'
|
||
```
|
||
|
||
#### 模式切换
|
||
|
||
查看当前模式:
|
||
|
||
```bash
|
||
curl http://127.0.0.1:18080/api/v1/mode
|
||
```
|
||
|
||
切换为只读模式(拒绝所有写操作):
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/mode \
|
||
-d '{"mode": "readonly"}'
|
||
```
|
||
|
||
切换回初始化模式(允许读写):
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/mode \
|
||
-d '{"mode": "init"}'
|
||
```
|
||
|
||
### YAML 支持
|
||
|
||
所有端点同时支持 JSON 和 YAML,格式由文件扩展名自动判断:
|
||
|
||
```bash
|
||
curl -X PUT http://127.0.0.1:18080/api/v1/config/app.yaml \
|
||
-H "Content-Type: text/yaml" \
|
||
-d '
|
||
database:
|
||
host: localhost
|
||
port: 5432
|
||
'
|
||
```
|
||
|
||
### 安全模型
|
||
|
||
服务默认仅监听 `127.0.0.1`,不暴露到外部网络。远程访问通过 SSH 隧道实现:
|
||
|
||
```bash
|
||
ssh -L 18080:127.0.0.1:18080 user@server
|
||
```
|
||
|
||
之后本地即可通过 `http://127.0.0.1:18080` 访问。
|
||
|
||
### 项目结构
|
||
|
||
```
|
||
├── main.go # 入口:环境变量、初始化、优雅关闭
|
||
├── config/
|
||
│ ├── validation.go # 路径校验,防止目录穿越
|
||
│ ├── parser.go # JSON/YAML 解析、序列化、深度合并
|
||
│ ├── atomic.go # 原子写入(temp → fsync → rename)
|
||
│ └── backup.go # 时间戳备份、清理、回滚
|
||
├── audit/
|
||
│ └── logger.go # 结构化 JSON 审计日志
|
||
├── server/
|
||
│ ├── server.go # HTTP 服务、路由、模式状态机、优雅关闭
|
||
│ ├── middleware.go # 请求日志中间件
|
||
│ ├── cors.go # CORS 中间件(CORS_ORIGINS)
|
||
│ └── handlers.go # API 处理函数
|
||
├── Dockerfile # 多阶段构建(distroless、nonroot)
|
||
└── docker-compose.yaml # 示例部署配置
|
||
```
|