cisd/README.md
2026-04-10 10:31:04 +08:00

425 lines
15 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.

# TMS Framework
Single-process TMS monolith scaffold built with:
- JDK 17
- Spring Boot 3.5.x
- MyBatis-Plus
- TiDB (MySQL driver)
- Swagger (springdoc-openapi)
## Quick Start
```bash
cd tms-framework
mvn spring-boot:run
```
## Jar 包部署(外置配置)
完整部署手册:
- [docs/deployment/tms-deployment.md](/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md)
1. 构建 jar 包:
```bash
cd tms-framework
mvn -q -DskipTests package
cp target/tms-framework-*.jar /home/tms/tms-framework.jar
```
2. 在 CentOS 上准备部署目录:
```bash
sudo mkdir -p /home/tms/{bin,config,scripts,logs,run}
sudo chown -R "$(whoami)":"$(whoami)" /home/tms
cp scripts/tms.sh /home/tms/scripts/tms.sh
cp scripts/standard-init/*.sh /home/tms/bin/
cp config/application.yml.example /home/tms/config/application.yml
chmod +x /home/tms/bin/*.sh
chmod +x /home/tms/scripts/tms.sh
```
3. 启动 / 停止 / 状态:
```bash
/home/tms/scripts/tms.sh start
/home/tms/scripts/tms.sh status
/home/tms/scripts/tms.sh stop
```
说明:
- 脚本默认 `APP_HOME=/home/tms`,并通过 `--spring.config.additional-location=optional:file:<app_home>/config/``/home/tms/config/` 读取外部配置。
- 默认要求 `/home/tms/config/application.yml` 存在。
- 脚本不再强制指定 profile默认按 Spring 配置文件自身规则解析,可通过 `SPRING_PROFILES_ACTIVE=dev /home/tms/scripts/tms.sh start` 显式覆盖。
- 可通过 `JAR_PATH=/home/tms/tms-framework.jar` 覆盖 jar 路径。
- 如果部署路径不是 `/home/tms`,使用 `APP_HOME=/your/path /your/path/scripts/tms.sh start`
- 标准 CISD 初始化辅助脚本位于 `scripts/standard-init/`,部署时需复制到 `/home/tms/bin/`
- `apply_standard_db.sh` 依赖预置环境变量,例如 `DB_USER`、`DB_PASSWORD`,不要直接写入 `application.yml`
- 运行目录结构、配置项说明、文件上传 `fileId` 流程和故障排查,请查看上面的完整部署手册。
运行时建议:
- 本地构建和测试统一使用 JDK 17与项目和 CI 运行时保持一致。
Open:
- Swagger UI: http://localhost:8080/swagger-ui.html
- Internal API docs JSON: http://localhost:8080/v3/api-docs/internal-api
- Runtime-generated Swagger/OpenAPI docs are the source of truth for `/api/**`.
- Internal health API: `GET /api/v1/device/status`
- Internal sign preview API: `POST /api/v1/sign/preview`
- External sign API: `POST /openapi/v1/sign/signature`
- Init template API: `GET /api/v1/init/template`
- Init preview API: `POST /api/v1/init/preview`
- Current init config API: `GET /api/v1/init/config`
- Reset preview API: `POST /api/v1/init/reset/preview`
- Reset create task API: `POST /api/v1/init/reset/tasks`
- Reset execute API: `POST /api/v1/init/reset/tasks/{taskId}/execute`
- Auth login API: `POST /api/v1/auth/login`
- Compat password login API: `POST /api/v1/auth/password-login`
- Compat UKey login API: `POST /api/v1/auth/ukey-login`
- Compat UKey random API: `GET /api/v1/auth/ukey-login/randoms`
- UKey binding issue-sign API: `POST /api/v1/auth/roles/{roleCode}/ukeys/issue-sign`
- UKey binding API: `POST /api/v1/auth/roles/{roleCode}/ukeys/bind`
- Device info API: `GET /api/v1/device/info`
- Device profile API: `GET /api/v1/device/profile`
- Device runtime status API: `GET /api/v1/device/runtime-status`
- Upgrade package upload API: `POST /api/v1/upgrade-packages`
- Upgrade preview API: `POST /api/v1/upgrades/previews`
- Upgrade create task API: `POST /api/v1/upgrades`
- Upgrade execute API: `POST /api/v1/upgrades/{taskId}/execute`
- Upgrade list API: `GET /api/v1/upgrades`
- PCIe crypto count API: `GET /api/v1/device/crypto/device-count`
- PCIe crypto HMAC API: `POST /api/v1/device/crypto/hmac`
## CISD Reset
最小调用顺序:
- `POST /api/v1/init/reset/preview`
- `POST /api/v1/init/reset/tasks`
- `POST /api/v1/init/reset/tasks/{taskId}/execute`
- `GET /api/v1/init/reset/tasks/{taskId}`
- `GET /api/v1/init/reset/tasks/{taskId}/steps`
- `GET /api/v1/init/reset/tasks/{taskId}/steps/{stepNo}/log`
当前支持范围:
- 仅支持设备预置产品类型为 `ENTERPRISE``INDIRECT`
- `DIRECT` 当前明确不支持 reset
请求说明:
- reset 接口不再要求前端重复提交机构号、MQ 类型和 RabbitMQ 通道用户
- 后端会自动读取“最近一次成功初始化任务”的快照,提取 `orgCode`、`mqType`、`channelUsername`
- 如果当前设备没有有效初始化快照reset 预检和任务创建会直接失败
设备状态接口:
- `GET /api/v1/device/status`
- 返回字段 `initState`
- `UNINITIALIZED`: 当前没有有效初始化快照
- `INITIALIZING`: 初始化任务正在执行
- `INITIALIZED`: 当前设备已初始化
- `RESETTING`: 重置任务正在执行
- 前端仅根据 `initState` 判断展示初始化页、已初始化页或执行中页面
当前初始化配置展示接口:
- `GET /api/v1/init/config`
- 数据来源固定为最新一次成功初始化任务快照
- 只返回机构信息、部署信息、中间件信息和节点/签名核心字段
- 只用于展示,不用于编辑
当前 reset 实际会做的事情:
- 停止 `CMSP/CMTP`
- 删除数据库 `CMEP`
- 删除数据库 `orgCode`
- 删除 RabbitMQ 客户化账号、`/RQ` 权限、客户化队列
- 停止 RabbitMQ 进程
- 删除 TLQ license 文件
- 清理当前 reset 任务的 staging 目录
当前 reset 不做的事情:
- 不回滚 `cpconfig.cfg`
- 不删除 nginx 配置和已发布前端目录
- 不回滚应用配置文件中的 RabbitMQ 账号密码
- 不删除标准安装介质目录
运维前置条件:
- `scripts/standard-init/*.sh` 已部署到 `/home/tms/bin/`
- `/home/tms/bin/stop_standard_apps.sh`
- `/home/tms/bin/stop_standard_rabbitmq.sh`
- `/home/tms/bin/apply_standard_db.sh`
- `tms.init.executor.standard-db-username/password` 已正确配置
- `tms.init.executor.rabbitmq-ctl-command` 指向可执行的 `rabbitmqctl`
- 运行时 Swagger 文档以 `http://<ip>:8080/swagger-ui.html``http://<ip>:8080/v3/api-docs/internal-api` 为准
## Offline Upgrade
最小调用顺序:
- `POST /api/v1/upgrade-packages`
- `POST /api/v1/upgrades/previews`
- `POST /api/v1/upgrades`
- `POST /api/v1/upgrades/{taskId}/execute`
- `POST /api/v1/upgrades/{taskId}/rollback`
- `GET /api/v1/upgrades`
- `GET /api/v1/upgrades/{taskId}`
- `GET /api/v1/upgrades/{taskId}/log`
当前支持范围:
- 仅支持离线升级
- 当前支持任务类型:
- `TMS`
- `RECEIVER`
- `FIRMWARE`
- 当前不支持:
- 在线升级
- `CVE` / 操作系统补丁升级
当前流程:
- 先上传离线升级包,复用现有文件上传能力,得到 `fileId`
- 后端基于 `fileId` 解析升级包并做预检
- 预检结果返回 `taskType`、`productType`、当前版本、目标版本和版本变化提示
- 用户确认后创建升级任务
- 调用执行接口后,任务异步进入后台执行
- 升级失败后,如升级包提供 `rollback` 入口,可手工调用回滚接口
- 前端通过列表、详情和日志接口轮询任务状态
当前升级包要求:
- 外层为 zip 包
- 至少包含:
- `manifest.json`
- `signature.sig`
- `payload/` 下按需包含:
- `app/`
- `web/dist/`
- `config/`
- `sql/`
- `firmware/`
- `scripts/`
- `signature.sig` 需要能被配置的 PEM 公钥使用 `SM3withSM2` 软验签通过
- 服务端需要配置 `tms.upgrade.signature-public-key-pem-path`(公钥 PEM 文件路径)
- `manifest.json` 当前要求包含:
- `packageId`
- `taskType`
- `productType`
- `version`
- `minCompatibleVersion`
- `description`
- `entrypoints.execute`
- 可选 `entrypoints.precheck`
- 可选 `entrypoints.verify`
- 可选 `entrypoints.rollback`
当前执行规则:
- 同一时刻只允许一个升级任务处于 `RUNNING`
- 不允许目标版本低于当前版本
- 不满足最小兼容版本时拒绝升级
- `execute.sh` 必填,`precheck.sh`、`verify.sh`、`rollback.sh` 可选
- 执行顺序为:`precheck -> execute -> verify`
- `FIRMWARE` 不增加额外后端流程,具体固件刷写、重启、恢复提示由包内脚本负责
- 回滚不自动触发,需要调用回滚接口
- `TMS`、`RECEIVER` 升级成功后会更新 `tms_device_software_version``FIRMWARE` 暂不维护版本表
- 升级执行日志统一写入 `tms.upgrade.log-dir`
当前配置项:
- `tms.upgrade.staging-root-dir`
- `tms.upgrade.log-dir`
- `tms.upgrade.signature-public-key-pem-path`
升级包规范见:
- [2026-03-19-upgrade-package-spec.md](/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-19-upgrade-package-spec.md)
- [标准收发器升级包最小样例](/Users/waner/Work/CISD/文档/tms-framework/docs/examples/upgrade-package/standard-app/README.md)
- [离线升级包预检联调清单与示例](/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-19-upgrade-preview-integration-guide.md)
## Architecture (Monolith + Modular)
- One deployable Spring Boot application.
- Module-first packaging under `modules/*`.
- Default module layout: `controller + service + repository + entity + dto`.
- `sign` module has extra `controller/openapi`, `dto/openapi`, and `support`.
- Cross-cutting concerns moved to top-level `security` and `integration`.
## Project Structure
```text
src/main/java/com/cisd/tms
├── TmsApplication.java
├── common
│ ├── api
│ ├── config
│ │ └── properties
│ ├── constant
│ ├── enums
│ ├── exception
│ └── util
├── infrastructure
│ └── persistence
│ ├── entity
│ ├── mapper
│ └── mybatis
├── integration
│ ├── cips
│ ├── mq
│ ├── crypto
│ └── file
├── security
│ ├── internal
│ └── openapi
└── modules
├── system
│ ├── controller
│ ├── service
│ └── dto
├── sign
│ ├── controller
│ ├── controller/openapi
│ ├── service
│ ├── dto/internal
│ ├── dto/openapi
│ ├── support
│ ├── repository
│ └── entity
├── init
├── auth
## Auth Compat
当前仓库只包含后端认证接口,不包含登录页前端工程。
兼容旧管理端的登录调用说明见:
- [2026-03-23-auth-compat-integration-guide.md](/Users/waner/Work/CISD/文档/tms-framework/docs/plans/2026-03-23-auth-compat-integration-guide.md)
├── device
├── upgrade
├── cert
├── key
├── audit
├── backup
└── activation
```
```text
src/main/resources
├── application.yml
├── application-dev.yml
├── application-prod.yml
├── mapper
│ ├── init/InitTaskMapper.xml
│ ├── auth/AuthUserMapper.xml
│ └── device/DeviceNodeMapper.xml
└── db/migration
└── V1__init_auth_device_tables.sql
```
## API Boundary Rules
- `/api/**` controllers live under `controller`.
- External API controllers only in `*/controller/openapi`, path prefix `/openapi/**`.
- Internal and external DTOs are separated.
- Cross-module calls must go through `service`, not `repository`.
- Internal token interceptor exclusions: `/api/v1/device/status`, `/api/v1/auth/login`.
## Auth Configuration
```yaml
tms:
security:
internal-token: ${TMS_INTERNAL_TOKEN:change-me-internal-token}
openapi:
timestamp-skew-seconds: 300
clients:
demo-app: ${TMS_OPENAPI_DEMO_SECRET:change-me-openapi-secret}
```
## Crypto Card Configuration
```yaml
tms:
crypto-card:
enabled: ${TMS_CRYPTO_CARD_ENABLED:false}
mode: ${TMS_CRYPTO_CARD_MODE:MOCK} # MOCK / JNA
vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:/home/tms/libs/libsdf_ukey_syd1408-x64.so.1.0.0}
vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:sdf_ukey_syd1408}
```
- Internal PCIe debug APIs (strong-typed service):
- `GET /api/v1/device/crypto/device-count`
- `GET /api/v1/device/crypto/device-conf`
- `GET /api/v1/device/crypto/device-info`
- `GET /api/v1/device/crypto/random?length=16`
- `POST /api/v1/device/crypto/self-test`
- `POST /api/v1/device/crypto/hmac`
- `POST /api/v1/device/crypto/digest`
- `POST /api/v1/device/crypto/encrypt/plain`
- `POST /api/v1/device/crypto/decrypt/plain`
- `POST /api/v1/device/crypto/encrypt/kek`
- `POST /api/v1/device/crypto/decrypt/kek`
- `POST /api/v1/device/crypto/mac/plain`
- `POST /api/v1/device/crypto/file/create`
- `POST /api/v1/device/crypto/file/write`
- `POST /api/v1/device/crypto/file/read`
- `POST /api/v1/device/crypto/file/delete`
- `POST /api/v1/device/crypto/kek/generate`
- `GET /api/v1/device/crypto/kek/status?keyIndex=1`
- `GET /api/v1/device/crypto/lmk/seed-mac`
- `POST /api/v1/device/crypto/std/keypair/rsa`
- `POST /api/v1/device/crypto/std/keypair/ecc`
- `POST /api/v1/device/crypto/envelope/exchange/rsa`
- `POST /api/v1/device/crypto/envelope/exchange/ecc`
- `POST /api/v1/device/crypto/agreement/data-key/ecc`
- `POST /api/v1/device/crypto/agreement/session-key/ecc`
## PCIe Crypto Unified Wrapper (JNA)
The project keeps JNA native mappings for PCIe card `SDF/SDFE` interfaces from
`PCIE密码卡应用接口说明书 V1.02`, and provides strong-typed service APIs via
`com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService`.
```yaml
tms:
crypto-card:
enabled: ${TMS_CRYPTO_CARD_ENABLED:false}
mode: ${TMS_CRYPTO_CARD_MODE:JNA} # MOCK / JNA
vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:/home/tms/libs/libsdf_ukey_syd1408-x64.so.1.0.0}
vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:sdf_ukey_syd1408}
```
- JNA native mapping: `com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary`
- JNA implementation: `com.cisd.tms.integration.crypto.pcie.service.JnaPcieCryptoService`
- Mock fallback: `com.cisd.tms.integration.crypto.pcie.service.MockPcieCryptoService`
### OpenAPI Signature Rules
- Headers: `X-App-Id`, `X-Timestamp`, `X-Nonce`, `X-Signature`
- Canonical string: `appId + "\\n" + timestamp + "\\n" + nonce`
- Signature algorithm: `HMAC-SHA256` with app secret, lowercase hex
- Replay protection: nonce one-time in time window
## Build And Test
```bash
mvn -q -DskipTests compile
mvn -q test
```
## PCIe Real-Card Smoke
- Checklist: `docs/plans/2026-02-28-pcie-realcard-smoke-checklist.md`
- Script template: `scripts/pcie_realcard_smoke.sh`
Example:
```bash
export BASE_URL=http://127.0.0.1:8080
export INTERNAL_TOKEN=change-me-internal-token
export ALG_SM3=1
export ALG_SM4_ECB=1025
./scripts/pcie_realcard_smoke.sh
```
- CI is pinned to JDK 17 via `.github/workflows/ci.yml`.
- Maven Surefire preloads Mockito javaagent to avoid dynamic self-attach failures on newer JDKs.
## Current Status
- Structure refactored to lightweight monolith modules.
- Internal and external API entry points separated.
- Basic auth interceptors for internal/openapi are in place.
- `init/auth/device/sign/system` modules have runnable skeleton controllers and services.
- `init/auth/device` modules include mapper+xml+repository-impl+DDL skeleton for TiDB.