fix:权限调整
This commit is contained in:
parent
a30c029fc4
commit
58dc015e01
15
README.md
15
README.md
@ -20,6 +20,7 @@ mvn spring-boot:run
|
||||
完整部署手册:
|
||||
- [docs/deployment/tms-deployment.md](/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-deployment.md)
|
||||
- [docs/deployment/tms-init-admin-permission-checklist.md](/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-init-admin-permission-checklist.md)
|
||||
- [docs/deployment/tms-root-admin-actions.md](/Users/waner/Work/CISD/文档/tms-framework/docs/deployment/tms-root-admin-actions.md)
|
||||
|
||||
1. 构建 jar 包:
|
||||
|
||||
@ -39,6 +40,7 @@ cp scripts/tms.sh /home/tms/scripts/tms.sh
|
||||
cp scripts/standard-init/*.sh /home/tms/bin/
|
||||
sudo cp scripts/standard-init/root-sbin/tms-run-standard-vendor-step /usr/local/sbin/tms-run-standard-vendor-step
|
||||
sudo cp scripts/standard-init/root-sbin/tms-prepare-standard-permissions /usr/local/sbin/tms-prepare-standard-permissions
|
||||
sudo cp scripts/standard-init/root-sbin/tms-rabbitmqctl /usr/local/sbin/tms-rabbitmqctl
|
||||
cp scripts/resource-restore/*.sh /home/tms/bin/resource-restore/
|
||||
cp config/application.yml.example /home/tms/config/application.yml
|
||||
chmod +x /home/tms/bin/*.sh
|
||||
@ -48,6 +50,8 @@ sudo chown root:root /usr/local/sbin/tms-run-standard-vendor-step
|
||||
sudo chmod 755 /usr/local/sbin/tms-run-standard-vendor-step
|
||||
sudo chown root:root /usr/local/sbin/tms-prepare-standard-permissions
|
||||
sudo chmod 755 /usr/local/sbin/tms-prepare-standard-permissions
|
||||
sudo chown root:root /usr/local/sbin/tms-rabbitmqctl
|
||||
sudo chmod 755 /usr/local/sbin/tms-rabbitmqctl
|
||||
```
|
||||
|
||||
3. 启动 / 停止 / 状态:
|
||||
@ -67,6 +71,7 @@ sudo chmod 755 /usr/local/sbin/tms-prepare-standard-permissions
|
||||
- 标准 CISD 初始化辅助脚本位于 `scripts/standard-init/`,部署时需复制到 `/home/tms/bin/`。
|
||||
- `scripts/standard-init/root-sbin/tms-run-standard-vendor-step` 是标准版 vendor 客户化脚本的 root 受控入口,部署到 `/usr/local/sbin/` 后通过 sudoers 授权给 `tms` 使用。
|
||||
- `scripts/standard-init/root-sbin/tms-prepare-standard-permissions` 是标准版介质权限预处理脚本,由 `root` 在初始化前手工执行,用于修正 `/home/cmep4i/cpackage`、license、SQL load、CMSP/CMTP 目录权限。
|
||||
- `scripts/standard-init/root-sbin/tms-rabbitmqctl` 是 RabbitMQ CLI 的 root 受控入口,初始化和资源恢复默认通过 `sudo -n /usr/local/sbin/tms-rabbitmqctl` 执行,避免 `tms` 用户 Erlang cookie 与 RabbitMQ 服务端不一致。
|
||||
- 资源恢复辅助脚本位于 `scripts/resource-restore/`,部署时需复制到 `/home/tms/bin/resource-restore/`。
|
||||
- `apply_standard_db.sh` 依赖预置环境变量,例如 `DB_USER`、`DB_PASSWORD`,不要直接写入 `application.yml`。
|
||||
- 运行目录结构、配置项说明、文件上传 `fileId` 流程和故障排查,请查看上面的完整部署手册。
|
||||
@ -99,8 +104,8 @@ java -jar tms-framework.jar --tms.crypto.decrypt
|
||||
- 本地构建和测试统一使用 JDK 17,与项目和 CI 运行时保持一致。
|
||||
|
||||
Open:
|
||||
- Swagger UI: http://localhost:8080/swagger-ui.html
|
||||
- Internal API docs JSON: http://localhost:8080/v3/api-docs/internal-api
|
||||
- Swagger UI: http://localhost:8088/swagger-ui.html
|
||||
- Internal API docs JSON: http://localhost:8088/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`
|
||||
@ -208,8 +213,8 @@ Open:
|
||||
- `/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` 为准
|
||||
- `tms.init.executor.rabbitmq-ctl-command` 默认 `sudo -n /usr/local/sbin/tms-rabbitmqctl`
|
||||
- 运行时 Swagger 文档以 `http://<ip>:8088/swagger-ui.html` 和 `http://<ip>:8088/v3/api-docs/internal-api` 为准
|
||||
|
||||
## Offline Upgrade
|
||||
|
||||
@ -563,7 +568,7 @@ mvn -q test
|
||||
Example:
|
||||
|
||||
```bash
|
||||
export BASE_URL=http://127.0.0.1:8080
|
||||
export BASE_URL=http://127.0.0.1:8088
|
||||
export INTERNAL_TOKEN=change-me-internal-token
|
||||
export ALG_SM3=1
|
||||
export ALG_SM4_ECB=1025
|
||||
|
||||
@ -68,6 +68,7 @@ tms:
|
||||
standard-rabbit-stop-command: /home/tms/bin/stop_standard_rabbitmq.sh
|
||||
standard-post-check-command: /home/tms/bin/check_standard_runtime.sh
|
||||
standard-vendor-step-runner-command: /usr/local/sbin/tms-run-standard-vendor-step
|
||||
rabbitmq-ctl-command: sudo -n /usr/local/sbin/tms-rabbitmqctl
|
||||
upload-base-dir: /home/tms/uploads
|
||||
staging-root-dir: /tmp/tms-init-staging
|
||||
direct-receiver-license-target-path: /home/cmep4d/cmep/license/cmep.license
|
||||
|
||||
@ -364,12 +364,12 @@ java -version
|
||||
### 3.3 网络与端口
|
||||
|
||||
TMS 默认监听端口:
|
||||
- `8080`
|
||||
- `8088`
|
||||
|
||||
检查命令:
|
||||
|
||||
```bash
|
||||
ss -lntp | grep 8080
|
||||
ss -lntp | grep 8088
|
||||
```
|
||||
|
||||
### 3.4 建议具备的系统命令
|
||||
@ -398,12 +398,33 @@ TMS 统一部署到 `/home/tms`:
|
||||
│ ├── apply_standard_db.sh
|
||||
│ ├── start_standard_apps.sh
|
||||
│ ├── start_standard_nginx.sh
|
||||
│ └── check_standard_runtime.sh
|
||||
│ ├── stop_standard_apps.sh
|
||||
│ ├── stop_standard_nginx.sh
|
||||
│ ├── stop_standard_rabbitmq.sh
|
||||
│ ├── check_standard_runtime.sh
|
||||
│ └── resource-restore
|
||||
│ ├── apply-resource-backup.sh
|
||||
│ ├── restore-db.sh
|
||||
│ └── replay-mq.sh
|
||||
├── config
|
||||
│ └── application.yml
|
||||
├── gateway
|
||||
│ ├── gm
|
||||
│ │ ├── start.sh
|
||||
│ │ ├── nginx.conf
|
||||
│ │ └── config/http/tms.conf
|
||||
│ ├── tls13
|
||||
│ │ ├── start.sh
|
||||
│ │ ├── nginx.conf
|
||||
│ │ └── conf.d/tms.conf
|
||||
│ └── logs
|
||||
├── logs
|
||||
│ ├── tms-framework.out.log
|
||||
│ └── tms-framework.err.log
|
||||
├── root-sbin
|
||||
│ ├── tms-prepare-standard-permissions
|
||||
│ ├── tms-rabbitmqctl
|
||||
│ └── tms-run-standard-vendor-step
|
||||
├── run
|
||||
│ └── tms-framework.pid
|
||||
├── scripts
|
||||
@ -418,7 +439,9 @@ TMS 统一部署到 `/home/tms`:
|
||||
目录用途:
|
||||
- `/home/tms/bin`:初始化后置辅助脚本目录,由 `tms.init.executor.*command` 引用
|
||||
- `/home/tms/config`:Spring Boot 外部配置目录
|
||||
- `/home/tms/gateway`:TMS 独立网关配置、启动脚本和日志目录
|
||||
- `/home/tms/logs`:TMS 运行日志
|
||||
- `/home/tms/root-sbin`:root 受控脚本的部署包暂存目录,实际执行位置为 `/usr/local/sbin`
|
||||
- `/home/tms/run`:PID 文件目录
|
||||
- `/home/tms/scripts`:TMS 启停控制脚本目录
|
||||
- `/home/tms/tmp`:初始化执行日志和临时目录
|
||||
@ -432,10 +455,30 @@ TMS 统一部署到 `/home/tms`:
|
||||
| `/home/tms/scripts/tms.sh` | `scripts/tms.sh` |
|
||||
| `/home/tms/bin/apply_standard_db.sh` | `scripts/standard-init/apply_standard_db.sh` |
|
||||
| `/home/tms/bin/start_standard_apps.sh` | `scripts/standard-init/start_standard_apps.sh` |
|
||||
| `/home/tms/bin/stop_standard_apps.sh` | `scripts/standard-init/stop_standard_apps.sh` |
|
||||
| `/home/tms/bin/start_standard_nginx.sh` | `scripts/standard-init/start_standard_nginx.sh` |
|
||||
| `/home/tms/bin/stop_standard_nginx.sh` | `scripts/standard-init/stop_standard_nginx.sh` |
|
||||
| `/home/tms/bin/stop_standard_rabbitmq.sh` | `scripts/standard-init/stop_standard_rabbitmq.sh` |
|
||||
| `/home/tms/bin/check_standard_runtime.sh` | `scripts/standard-init/check_standard_runtime.sh` |
|
||||
| `/home/tms/bin/resource-restore/apply-resource-backup.sh` | `scripts/resource-restore/apply-resource-backup.sh` |
|
||||
| `/home/tms/bin/resource-restore/restore-db.sh` | `scripts/resource-restore/restore-db.sh` |
|
||||
| `/home/tms/bin/resource-restore/replay-mq.sh` | `scripts/resource-restore/replay-mq.sh` |
|
||||
| `/home/tms/root-sbin/tms-run-standard-vendor-step` | `scripts/standard-init/root-sbin/tms-run-standard-vendor-step` |
|
||||
| `/home/tms/root-sbin/tms-prepare-standard-permissions` | `scripts/standard-init/root-sbin/tms-prepare-standard-permissions` |
|
||||
| `/home/tms/root-sbin/tms-rabbitmqctl` | `scripts/standard-init/root-sbin/tms-rabbitmqctl` |
|
||||
| `/usr/local/sbin/tms-run-standard-vendor-step` | 由 `/home/tms/root-sbin/tms-run-standard-vendor-step` 复制安装 |
|
||||
| `/usr/local/sbin/tms-prepare-standard-permissions` | 由 `/home/tms/root-sbin/tms-prepare-standard-permissions` 复制安装 |
|
||||
| `/usr/local/sbin/tms-rabbitmqctl` | 由 `/home/tms/root-sbin/tms-rabbitmqctl` 复制安装 |
|
||||
| `/home/tms/gateway/tls13/start.sh` | `deployment/tms-gateway/tls13/start.sh` |
|
||||
| `/home/tms/gateway/tls13/nginx.conf` | `deployment/tms-gateway/tls13/nginx.conf` |
|
||||
| `/home/tms/gateway/tls13/conf.d/tms.conf` | `deployment/tms-gateway/tls13/conf.d/tms.conf` |
|
||||
| `/home/tms/gateway/gm/start.sh` | `deployment/tms-gateway/gm/start.sh` |
|
||||
| `/home/tms/gateway/gm/nginx.conf` | `deployment/tms-gateway/gm/nginx.conf` |
|
||||
| `/home/tms/gateway/gm/config/http/tms.conf` | `deployment/tms-gateway/gm/config/http/tms.conf` |
|
||||
| `/home/tms/config/application.yml` | 由 `config/application.yml.example` 复制生成 |
|
||||
|
||||
`scripts/cisd_init_precheck.sh` 和 `scripts/pcie_realcard_smoke.sh` 属于诊断脚本,不作为 TMS 常驻运行脚本默认部署。现场需要时可复制到 `/home/tms/tools/` 临时执行。
|
||||
|
||||
## 6. 部署步骤
|
||||
|
||||
### 6.1 构建 jar 包
|
||||
@ -448,7 +491,9 @@ mvn -q -DskipTests package
|
||||
### 6.2 创建运行目录
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /home/tms/{bin,config,scripts,logs,run,tmp,uploads,libs}
|
||||
sudo mkdir -p /home/tms/{bin,config,scripts,logs,run,tmp,uploads,libs,root-sbin,tools}
|
||||
sudo mkdir -p /home/tms/bin/resource-restore
|
||||
sudo mkdir -p /home/tms/gateway/{tls13,gm,logs/tls13,logs/gm}
|
||||
sudo chown -R "$(whoami)":"$(whoami)" /home/tms
|
||||
```
|
||||
|
||||
@ -458,9 +503,16 @@ sudo chown -R "$(whoami)":"$(whoami)" /home/tms
|
||||
cp target/tms-framework-*.jar /home/tms/tms-framework.jar
|
||||
cp scripts/tms.sh /home/tms/scripts/tms.sh
|
||||
cp scripts/standard-init/*.sh /home/tms/bin/
|
||||
cp scripts/resource-restore/*.sh /home/tms/bin/resource-restore/
|
||||
cp scripts/standard-init/root-sbin/* /home/tms/root-sbin/
|
||||
cp -R deployment/tms-gateway/tls13/* /home/tms/gateway/tls13/
|
||||
cp -R deployment/tms-gateway/gm/* /home/tms/gateway/gm/
|
||||
cp config/application.yml.example /home/tms/config/application.yml
|
||||
chmod +x /home/tms/scripts/tms.sh
|
||||
chmod +x /home/tms/bin/*.sh
|
||||
chmod +x /home/tms/bin/resource-restore/*.sh
|
||||
chmod +x /home/tms/gateway/tls13/start.sh
|
||||
chmod +x /home/tms/gateway/gm/start.sh
|
||||
```
|
||||
|
||||
### 6.4 检查部署结果
|
||||
@ -516,7 +568,7 @@ tms:
|
||||
### 7.3 标准版初始化关键配置
|
||||
|
||||
标准版初始化重点配置项:
|
||||
- `standard-home-dir`:默认 `/home/cemp4i`
|
||||
- `standard-home-dir`:默认 `/home/cmep4i`
|
||||
- `standard-cpconfig-path`:标准版 `cpconfig.cfg` 路径
|
||||
- `standard-db-script-base-dir`:默认 `${standard-home-dir}/cpackage`
|
||||
- `standard-db-load-dir`:默认 `${standard-home-dir}/mysql/loadfilepath`
|
||||
@ -524,6 +576,8 @@ tms:
|
||||
- `standard-web-front-zip-path`:默认 `${standard-home-dir}/cpackage/front/front.zip`
|
||||
- `standard-web-target-dir`:默认 `/usr/local/nginx/html`
|
||||
- `standard-web-organization-json-path`:默认 `/usr/local/nginx/html/organization.json`
|
||||
- `standard-vendor-step-runner-command`:默认 `/usr/local/sbin/tms-run-standard-vendor-step`,用于 `SET_RABBITMQ`、`SET_TLQ`、`TLQ_CONF_APPLY`、`DEPLOY_RECEIVER`
|
||||
- `rabbitmq-ctl-command`:默认 `sudo -n /usr/local/sbin/tms-rabbitmqctl`,初始化和资源恢复统一通过 root 受控 wrapper 调用 RabbitMQ CLI
|
||||
|
||||
### 7.4 不建议直接写入 application.yml 的凭据
|
||||
|
||||
@ -559,7 +613,7 @@ tms:
|
||||
- `DB_HOST`,默认 `127.0.0.1`
|
||||
- `DB_PORT`,默认 `4000`
|
||||
- `DB_NAME`,默认 `CMEP`
|
||||
- `LOAD_DIR`,默认 `/home/cemp4i/mysql/loadfilepath`
|
||||
- `LOAD_DIR`,默认 `/home/cmep4i/mysql/loadfilepath`
|
||||
|
||||
示例:
|
||||
|
||||
@ -579,8 +633,8 @@ export DB_PASSWORD='secret'
|
||||
- 启动 CMTP
|
||||
|
||||
依赖:
|
||||
- `/home/cemp4i/cmsp/start_cmsp.sh`
|
||||
- `/home/cemp4i/cmtp/start_cmtp.sh`
|
||||
- `/home/cmep4i/cmsp/start_cmsp.sh`
|
||||
- `/home/cmep4i/cmtp/start_cmtp.sh`
|
||||
- 用户 `cmep4i`
|
||||
|
||||
### 8.3 `start_standard_nginx.sh`
|
||||
@ -608,6 +662,50 @@ export DB_PASSWORD='secret'
|
||||
|
||||
该脚本仅用于初始化后的结果校验,不负责修复。
|
||||
|
||||
### 8.5 `tms-run-standard-vendor-step`
|
||||
|
||||
来源:
|
||||
- [tms-run-standard-vendor-step](/Users/waner/Work/CISD/文档/tms-framework/scripts/standard-init/root-sbin/tms-run-standard-vendor-step)
|
||||
|
||||
部署位置:
|
||||
- `/usr/local/sbin/tms-run-standard-vendor-step`
|
||||
|
||||
作用:
|
||||
- 作为 root 拥有的受控入口,按固定参数执行标准 vendor 脚本
|
||||
- 内部切换到 `cmep4i` 用户后执行 `/home/cmep4i/cpackage/toolsh/*.sh`
|
||||
- 当前只允许 `setfraq`、`setftq`、`settlq`、`setsptp`
|
||||
|
||||
部署命令:
|
||||
|
||||
```bash
|
||||
sudo cp scripts/standard-init/root-sbin/tms-run-standard-vendor-step /usr/local/sbin/tms-run-standard-vendor-step
|
||||
sudo chown root:root /usr/local/sbin/tms-run-standard-vendor-step
|
||||
sudo chmod 755 /usr/local/sbin/tms-run-standard-vendor-step
|
||||
```
|
||||
|
||||
sudoers 建议:
|
||||
|
||||
```sudoers
|
||||
Defaults:tms !requiretty
|
||||
|
||||
tms ALL=(root) NOPASSWD: \
|
||||
/usr/local/sbin/tms-rabbitmqctl *, \
|
||||
/usr/local/sbin/tms-run-standard-vendor-step setfraq, \
|
||||
/usr/local/sbin/tms-run-standard-vendor-step setftq, \
|
||||
/usr/local/sbin/tms-run-standard-vendor-step settlq, \
|
||||
/usr/local/sbin/tms-run-standard-vendor-step setsptp
|
||||
```
|
||||
|
||||
验证:
|
||||
|
||||
```bash
|
||||
su - tms
|
||||
sudo -n /usr/local/sbin/tms-run-standard-vendor-step setsptp
|
||||
ls -l /home/cmep4i/cmsp /home/cmep4i/cmtp
|
||||
```
|
||||
|
||||
执行后 `/home/cmep4i` 下由 vendor 脚本生成或替换的文件应保持为 `cmep4i` 可访问,不应再由 `tms` 直接写成 `tms:tms`。
|
||||
|
||||
## 9. 文件上传与 `fileId` 模型
|
||||
|
||||
### 9.1 核心原则
|
||||
@ -683,6 +781,207 @@ tail -n 100 /home/tms/logs/tms-framework.out.log
|
||||
tail -n 100 /home/tms/logs/tms-framework.err.log
|
||||
```
|
||||
|
||||
## 10.6 TMS 独立网关(可选)
|
||||
|
||||
当现场需要为 `tms-framework` 单独提供 HTTPS 入口时,建议新增独立 TMS 网关,而不是接管标准收发器现有 `/usr/local/nginx`。
|
||||
|
||||
这套独立网关的定位是:
|
||||
|
||||
- 只服务 TMS 前端和 TMS API
|
||||
- 独立于标准收发器现有 Nginx
|
||||
- 不参与 `START_NGINX`、`STOP_NGINX`、`POST_CHECK`
|
||||
|
||||
标准收发器现有 Nginx 仍然保持:
|
||||
|
||||
- 配置路径:`/usr/local/nginx/conf/nginx.conf`
|
||||
- Web 发布目录:`/usr/local/nginx/html`
|
||||
- 默认标准 Web 验收入口:`8000`
|
||||
|
||||
### 10.6.1 推荐端口
|
||||
|
||||
推荐保留如下边界:
|
||||
|
||||
- 标准收发器现有 Web:`8000`
|
||||
- TMS TLS 1.3 网关:`443`
|
||||
- TMS 国密网关:`8443`
|
||||
- TMS 后端:`127.0.0.1:8088`
|
||||
|
||||
因此在启用独立网关前,建议先检查:
|
||||
|
||||
```bash
|
||||
ss -lntp | grep -E ':443|:8443|:8000|:8088'
|
||||
```
|
||||
|
||||
### 10.6.2 推荐目录
|
||||
|
||||
建议按如下结构部署:
|
||||
|
||||
```text
|
||||
/home/tms
|
||||
├── web
|
||||
│ └── dist
|
||||
└── gateway
|
||||
├── tls13
|
||||
├── gm
|
||||
└── logs
|
||||
├── tls13
|
||||
└── gm
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `/home/tms/web/dist`:TMS 前端构建产物
|
||||
- `/home/tms/gateway/tls13`:TLS 1.3 网关配置
|
||||
- `/home/tms/gateway/gm`:国密网关配置
|
||||
- `/home/tms/gateway/logs/*`:对应网关日志
|
||||
|
||||
### 10.6.3 仓库模板位置
|
||||
|
||||
仓库已提供两套模板:
|
||||
|
||||
- TLS 1.3:
|
||||
- `deployment/tms-gateway/tls13/nginx.conf`
|
||||
- `deployment/tms-gateway/tls13/conf.d/tms.conf`
|
||||
- `deployment/tms-gateway/tls13/start.sh`
|
||||
- `deployment/tms-gateway/tls13/README.md`
|
||||
- 国密:
|
||||
- `deployment/tms-gateway/gm/nginx.conf`
|
||||
- `deployment/tms-gateway/gm/config/http/tms.conf`
|
||||
- `deployment/tms-gateway/gm/start.sh`
|
||||
- `deployment/tms-gateway/gm/README.md`
|
||||
|
||||
部署时建议将模板复制到:
|
||||
|
||||
- `/home/tms/gateway/tls13`
|
||||
- `/home/tms/gateway/gm`
|
||||
|
||||
### 10.6.4 前端发布目录
|
||||
|
||||
TMS 前端建议统一发布到:
|
||||
|
||||
```text
|
||||
/home/tms/web/dist
|
||||
```
|
||||
|
||||
不建议继续沿用其他项目使用过的 `/app/hsm/vue` 命名。
|
||||
|
||||
网关容器建议统一将:
|
||||
|
||||
```text
|
||||
/home/tms/web
|
||||
```
|
||||
|
||||
挂载到容器:
|
||||
|
||||
```text
|
||||
/app
|
||||
```
|
||||
|
||||
这样容器内静态资源根目录仍保持:
|
||||
|
||||
```text
|
||||
/app/dist
|
||||
```
|
||||
|
||||
### 10.6.5 后端代理约定
|
||||
|
||||
独立网关统一代理到:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8088
|
||||
```
|
||||
|
||||
需要放行的核心路由:
|
||||
|
||||
- `/`
|
||||
- `/api/v1/`
|
||||
- `/swagger-ui.html`
|
||||
- `/swagger-ui/`
|
||||
- `/v3/api-docs/`
|
||||
|
||||
特别注意:
|
||||
|
||||
- TMS 接口本身挂在 `/api/v1/**`
|
||||
- 网关 `proxy_pass` 不应把 `/api/v1/` 前缀错误改写掉
|
||||
- 若网关误把 `/api/v1/device/status` 转成 `/device/status`,后端会返回 404
|
||||
|
||||
因此后续修改网关配置时,应保持“原始请求路径透传到 TMS 后端”这一约束。
|
||||
|
||||
### 10.6.6 证书与镜像
|
||||
|
||||
TLS 1.3 网关:
|
||||
|
||||
- 默认使用 `nginx:latest`
|
||||
- 证书目录:`/home/tms/gateway/tls13/certs`
|
||||
- 默认文件名:
|
||||
- `rsa.dev.pem`
|
||||
- `rsa.dev.key`
|
||||
|
||||
国密网关:
|
||||
|
||||
- 默认使用 `gateway.lib:latest`
|
||||
- 证书目录:`/home/tms/gateway/gm/certs`
|
||||
- 默认文件名:
|
||||
- `sm2.sig.pem`
|
||||
- `sm2.sig.key`
|
||||
- `sm2.enc.pem`
|
||||
- `sm2.enc.key`
|
||||
- `rsa.dev.pem`
|
||||
- `rsa.dev.key`
|
||||
|
||||
补充说明:
|
||||
|
||||
- TLS 1.3 网关默认读取自己的 `/home/tms/gateway/tls13/certs`
|
||||
- 国密网关默认读取自己的 `/home/tms/gateway/gm/certs`
|
||||
- 如果现场希望 TLS 1.3 直接复用国密目录中的 RSA 证书,可在启动 TLS 1.3 网关时额外指定 `CERT_DIR=/home/tms/gateway/gm/certs`
|
||||
|
||||
如果现场为离线部署,可参考:
|
||||
|
||||
```bash
|
||||
docker load -i /Users/waner/Work/CISD/文档/manager/tls13/tls13.tar
|
||||
docker load -i /Users/waner/Work/CISD/文档/manager/gateway.tar
|
||||
```
|
||||
|
||||
### 10.6.7 启动与验收
|
||||
|
||||
TLS 1.3 网关:
|
||||
|
||||
```bash
|
||||
cd /home/tms/gateway/tls13
|
||||
bash start.sh
|
||||
```
|
||||
|
||||
国密网关:
|
||||
|
||||
```bash
|
||||
cd /home/tms/gateway/gm
|
||||
bash start.sh
|
||||
```
|
||||
|
||||
TLS 1.3 验收可先检查:
|
||||
|
||||
```bash
|
||||
curl -k https://127.0.0.1/
|
||||
curl -k https://127.0.0.1/swagger-ui.html
|
||||
curl -k https://127.0.0.1/api/v1/device/status
|
||||
```
|
||||
|
||||
国密入口建议使用现场指定的国密兼容浏览器或客户端进行验证。
|
||||
|
||||
### 10.6.8 与标准收发器 Nginx 的边界
|
||||
|
||||
本独立网关方案不改变以下既有边界:
|
||||
|
||||
- 不写入 `/usr/local/nginx/conf/nginx.conf`
|
||||
- 不使用 `/usr/local/nginx/html`
|
||||
- 不替代标准收发器 Web 发布流程
|
||||
- 不改变标准收发器初始化和 reset 当前逻辑
|
||||
|
||||
换句话说:
|
||||
|
||||
- 标准收发器 Nginx 继续服务标准产品自身的 Web
|
||||
- TMS 独立网关只负责 TMS 自己的前端和 API
|
||||
|
||||
## 11. 初始化前置检查
|
||||
|
||||
预检查脚本:
|
||||
@ -859,8 +1158,8 @@ pgrep -f '/usr/local/nginx/sbin/nginx'
|
||||
|
||||
```bash
|
||||
/home/tms/scripts/tms.sh status
|
||||
ss -lntp | grep 8080
|
||||
curl -s http://127.0.0.1:8080/api/v1/device/status
|
||||
ss -lntp | grep 8088
|
||||
curl -s http://127.0.0.1:8088/api/v1/device/status
|
||||
find /home/tms/uploads -maxdepth 2 -type f | sort
|
||||
ls -l /home/tms/bin
|
||||
ls -l /home/tms/config/application.yml
|
||||
@ -871,7 +1170,10 @@ ls -l /home/tms/config/application.yml
|
||||
```bash
|
||||
bash -n /home/tms/bin/apply_standard_db.sh
|
||||
bash -n /home/tms/bin/start_standard_apps.sh
|
||||
bash -n /home/tms/bin/stop_standard_apps.sh
|
||||
bash -n /home/tms/bin/start_standard_nginx.sh
|
||||
bash -n /home/tms/bin/stop_standard_nginx.sh
|
||||
bash -n /home/tms/bin/stop_standard_rabbitmq.sh
|
||||
bash -n /home/tms/bin/check_standard_runtime.sh
|
||||
```
|
||||
|
||||
|
||||
@ -9,12 +9,12 @@ set -euo pipefail
|
||||
# REQUEST_JSON=/tmp/cisd-init-standard-rabbit.json ./scripts/cisd_init_flow.sh
|
||||
#
|
||||
# Optional env:
|
||||
# BASE_URL=http://127.0.0.1:8080
|
||||
# BASE_URL=http://127.0.0.1:8088
|
||||
# INTERNAL_TOKEN=change-me-internal-token
|
||||
# OUT_DIR=/tmp/cisd-init-run
|
||||
# FETCH_FAILED_STEP_LOG=true
|
||||
|
||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8080}"
|
||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8088}"
|
||||
INTERNAL_TOKEN="${INTERNAL_TOKEN:-change-me-internal-token}"
|
||||
REQUEST_JSON="${REQUEST_JSON:-}"
|
||||
OUT_DIR="${OUT_DIR:-/tmp/cisd-init-run}"
|
||||
|
||||
@ -6,7 +6,7 @@ set -euo pipefail
|
||||
# chmod +x scripts/pcie_realcard_smoke.sh
|
||||
# ./scripts/pcie_realcard_smoke.sh
|
||||
|
||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8080}"
|
||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8088}"
|
||||
INTERNAL_TOKEN="${INTERNAL_TOKEN:-change-me-internal-token}"
|
||||
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-15}"
|
||||
|
||||
|
||||
@ -40,25 +40,44 @@ json_text() {
|
||||
sed -nE 's/.*"'"${key}"'"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/p' "${CONTEXT_FILE}" | head -n 1
|
||||
}
|
||||
|
||||
split_command() {
|
||||
local value="$1"
|
||||
# shellcheck disable=SC2206
|
||||
CTL_COMMAND=(${value})
|
||||
}
|
||||
|
||||
find_ctl() {
|
||||
local configured="${RABBITMQ_CTL_COMMAND:-}"
|
||||
if [[ -n "${configured}" ]]; then
|
||||
printf '%s' "${configured}"
|
||||
split_command "${configured}"
|
||||
return 0
|
||||
fi
|
||||
if [[ -x "/usr/local/sbin/tms-rabbitmqctl" ]] && command -v sudo >/dev/null 2>&1; then
|
||||
CTL_COMMAND=(sudo -n /usr/local/sbin/tms-rabbitmqctl)
|
||||
return 0
|
||||
fi
|
||||
for candidate in rabbitmqctl /usr/local/rabbitmq/sbin/rabbitmqctl /usr/local/rabbitmq-server/sbin/rabbitmqctl /usr/sbin/rabbitmqctl /usr/lib/rabbitmq/bin/rabbitmqctl; do
|
||||
if command -v "${candidate}" >/dev/null 2>&1; then
|
||||
command -v "${candidate}"
|
||||
CTL_COMMAND=("$(command -v "${candidate}")")
|
||||
return 0
|
||||
fi
|
||||
if [[ -x "${candidate}" ]]; then
|
||||
printf '%s' "${candidate}"
|
||||
CTL_COMMAND=("${candidate}")
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
run_ctl() {
|
||||
local timeout_seconds="${RABBITMQ_CTL_TIMEOUT_SECONDS:-30}"
|
||||
if command -v timeout >/dev/null 2>&1; then
|
||||
timeout "${timeout_seconds}" "${CTL_COMMAND[@]}" "$@"
|
||||
else
|
||||
"${CTL_COMMAND[@]}" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ -n "${MQ_REPLAY_COMMAND:-}" ]]; then
|
||||
log "delegating mq replay to configured command"
|
||||
"${MQ_REPLAY_COMMAND}" --context-file "${CONTEXT_FILE}" --work-dir "${WORK_DIR}" >> "${LOG_FILE}" 2>&1
|
||||
@ -85,15 +104,16 @@ if [[ -z "${USER_NAME}" || -z "${USER_PASS}" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CTL="$(find_ctl)" || {
|
||||
CTL_COMMAND=()
|
||||
find_ctl || {
|
||||
echo "[ERROR] rabbitmqctl not found" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
"${CTL}" status >> "${LOG_FILE}" 2>&1 || log "rabbitmqctl status failed, continue replay"
|
||||
"${CTL}" add_vhost "${VHOST}" >> "${LOG_FILE}" 2>&1 || true
|
||||
"${CTL}" add_user "${USER_NAME}" "${USER_PASS}" >> "${LOG_FILE}" 2>&1 || "${CTL}" change_password "${USER_NAME}" "${USER_PASS}" >> "${LOG_FILE}" 2>&1
|
||||
"${CTL}" set_permissions -p "${VHOST}" "${USER_NAME}" ".*" ".*" ".*" >> "${LOG_FILE}" 2>&1
|
||||
run_ctl status >> "${LOG_FILE}" 2>&1 || log "rabbitmqctl status failed, continue replay"
|
||||
run_ctl add_vhost "${VHOST}" >> "${LOG_FILE}" 2>&1 || true
|
||||
run_ctl add_user "${USER_NAME}" "${USER_PASS}" >> "${LOG_FILE}" 2>&1 || run_ctl change_password "${USER_NAME}" "${USER_PASS}" >> "${LOG_FILE}" 2>&1
|
||||
run_ctl set_permissions -p "${VHOST}" "${USER_NAME}" ".*" ".*" ".*" >> "${LOG_FILE}" 2>&1
|
||||
log "rabbitmq user and permissions replayed"
|
||||
|
||||
if [[ -n "${RABBIT_QUEUE_REPLAY_SCRIPT_PATH:-}" && -x "${RABBIT_QUEUE_REPLAY_SCRIPT_PATH}" ]]; then
|
||||
|
||||
@ -60,5 +60,4 @@ fi
|
||||
--host="${HOST}" \
|
||||
--port="${PORT}" \
|
||||
--user="${USERNAME}" \
|
||||
--password="${PASSWORD}" \
|
||||
"${DB_NAME}" < "${SQL_FILE}"
|
||||
--password="${PASSWORD}" < "${SQL_FILE}"
|
||||
|
||||
92
scripts/standard-init/root-sbin/tms-rabbitmqctl
Executable file
92
scripts/standard-init/root-sbin/tms-rabbitmqctl
Executable file
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$(id -u)" -ne 0 ]]; then
|
||||
echo "tms-rabbitmqctl must be executed as root through sudo" >&2
|
||||
exit 77
|
||||
fi
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "usage: tms-rabbitmqctl <allowed-rabbitmqctl-command> [args...]" >&2
|
||||
exit 64
|
||||
fi
|
||||
|
||||
require_arg_count() {
|
||||
local expected="$1"
|
||||
shift
|
||||
if [[ $# -ne "${expected}" ]]; then
|
||||
echo "unsupported rabbitmqctl arguments" >&2
|
||||
exit 64
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
status|list_users)
|
||||
require_arg_count 1 "$@"
|
||||
;;
|
||||
add_vhost|delete_user)
|
||||
require_arg_count 2 "$@"
|
||||
;;
|
||||
add_user|change_password|authenticate_user)
|
||||
require_arg_count 3 "$@"
|
||||
;;
|
||||
set_permissions)
|
||||
if [[ $# -ne 7 || "${2:-}" != "-p" ]]; then
|
||||
echo "unsupported rabbitmqctl set_permissions arguments" >&2
|
||||
exit 64
|
||||
fi
|
||||
;;
|
||||
clear_permissions)
|
||||
if [[ $# -ne 4 || "${2:-}" != "-p" ]]; then
|
||||
echo "unsupported rabbitmqctl clear_permissions arguments" >&2
|
||||
exit 64
|
||||
fi
|
||||
;;
|
||||
list_queues)
|
||||
if [[ ! ( $# -eq 2 || ( $# -eq 4 && "${2:-}" == "-p" ) ) ]]; then
|
||||
echo "unsupported rabbitmqctl list_queues arguments" >&2
|
||||
exit 64
|
||||
fi
|
||||
;;
|
||||
delete_queue)
|
||||
if [[ ! ( $# -eq 2 || ( $# -eq 4 && "${2:-}" == "-p" ) ) ]]; then
|
||||
echo "unsupported rabbitmqctl delete_queue arguments" >&2
|
||||
exit 64
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "unsupported rabbitmqctl command: $1" >&2
|
||||
exit 64
|
||||
;;
|
||||
esac
|
||||
|
||||
export ERLANG_HOME="${ERLANG_HOME:-/usr/local/erlang}"
|
||||
export RABBITMQ_HOME="${RABBITMQ_HOME:-/usr/local/rabbitmq}"
|
||||
export PATH="${ERLANG_HOME}/bin:${RABBITMQ_HOME}/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin"
|
||||
|
||||
if [[ -n "${RABBITMQ_CTL:-}" ]]; then
|
||||
RABBITMQ_CTL_CANDIDATES=("${RABBITMQ_CTL}")
|
||||
else
|
||||
RABBITMQ_CTL_CANDIDATES=(
|
||||
"${RABBITMQ_HOME}/sbin/rabbitmqctl"
|
||||
"/usr/local/rabbitmq/sbin/rabbitmqctl"
|
||||
"/usr/local/rabbitmq-server/sbin/rabbitmqctl"
|
||||
"/usr/sbin/rabbitmqctl"
|
||||
"/usr/lib/rabbitmq/bin/rabbitmqctl"
|
||||
)
|
||||
fi
|
||||
|
||||
RABBITMQ_CTL=""
|
||||
for candidate in "${RABBITMQ_CTL_CANDIDATES[@]}"; do
|
||||
if [[ -x "${candidate}" ]]; then
|
||||
RABBITMQ_CTL="${candidate}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! -x "${RABBITMQ_CTL}" ]]; then
|
||||
echo "rabbitmqctl not executable" >&2
|
||||
exit 69
|
||||
fi
|
||||
|
||||
exec "${RABBITMQ_CTL}" "$@"
|
||||
@ -15,6 +15,8 @@ public class InitExecutorProperties {
|
||||
private static final String DEFAULT_STANDARD_RUN_USER = "cmep4i";
|
||||
private static final String DEFAULT_STANDARD_VENDOR_STEP_RUNNER_COMMAND =
|
||||
"/usr/local/sbin/tms-run-standard-vendor-step";
|
||||
private static final String DEFAULT_RABBITMQ_CTL_COMMAND =
|
||||
"sudo -n /usr/local/sbin/tms-rabbitmqctl";
|
||||
|
||||
private Mode mode = Mode.SIMULATE;
|
||||
private int timeoutSec = 600;
|
||||
@ -104,7 +106,7 @@ public class InitExecutorProperties {
|
||||
private String rabbitAdminUsername = "admin";
|
||||
private String rabbitAdminPassword = "admin";
|
||||
// RabbitMQ 管理命令路径
|
||||
private String rabbitmqCtlCommand = "rabbitmqctl";
|
||||
private String rabbitmqCtlCommand = DEFAULT_RABBITMQ_CTL_COMMAND;
|
||||
private String rabbitmqAdminCommand = "/usr/sbin/rabbitmqadmin";
|
||||
// 标准版 RabbitMQ 初始化脚本(创建admin/通道账号、替换队列脚本机构号)
|
||||
private String standardRabbitSetupScriptPath = "";
|
||||
|
||||
@ -684,6 +684,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
||||
private String resolveRabbitmqCtlCommand() {
|
||||
List<String> candidates = new ArrayList<>();
|
||||
candidates.add(firstNonBlank(properties.getRabbitmqCtlCommand(), "rabbitmqctl"));
|
||||
candidates.add("sudo -n /usr/local/sbin/tms-rabbitmqctl");
|
||||
candidates.add("/usr/local/rabbitmq/sbin/rabbitmqctl");
|
||||
candidates.add("/usr/local/rabbitmq-server/sbin/rabbitmqctl");
|
||||
candidates.add("/usr/sbin/rabbitmqctl");
|
||||
@ -694,6 +695,12 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
||||
if (isBlank(candidate)) {
|
||||
continue;
|
||||
}
|
||||
if (candidateHasArguments(candidate)) {
|
||||
if (isRunnableCommandPrefix(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (candidate.contains("/")) {
|
||||
try {
|
||||
Path path = Paths.get(candidate).normalize().toAbsolutePath();
|
||||
@ -716,6 +723,37 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isRunnableCommandPrefix(String command) {
|
||||
List<String> parts = splitCommandPrefix(command);
|
||||
if (parts.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String executable = parts.get(0);
|
||||
if (executable.contains("/")) {
|
||||
try {
|
||||
Path path = Paths.get(executable).normalize().toAbsolutePath();
|
||||
return Files.exists(path) && Files.isRegularFile(path);
|
||||
} catch (InvalidPathException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !isBlank(findExecutableInPath(executable));
|
||||
}
|
||||
|
||||
private boolean candidateHasArguments(String command) {
|
||||
return splitCommandPrefix(command).size() > 1;
|
||||
}
|
||||
|
||||
private List<String> splitCommandPrefix(String command) {
|
||||
String value = normalize(command);
|
||||
if (isBlank(value)) {
|
||||
return List.of();
|
||||
}
|
||||
return Arrays.stream(value.split("\\s+"))
|
||||
.filter(part -> !isBlank(part))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private String findExecutableInPath(String commandName) {
|
||||
String pathValue = System.getenv("PATH");
|
||||
if (isBlank(pathValue)) {
|
||||
@ -1920,7 +1958,19 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
||||
}
|
||||
|
||||
private int runRabbitmqCommand(Path logFile, List<String> command, boolean ignoreFailure) throws IOException, InterruptedException {
|
||||
return runCommand(logFile, command, ignoreFailure, null, buildRabbitmqEnvironment());
|
||||
return runCommand(logFile, expandRabbitmqCommand(command), ignoreFailure, null, buildRabbitmqEnvironment());
|
||||
}
|
||||
|
||||
private List<String> expandRabbitmqCommand(List<String> command) {
|
||||
if (command == null || command.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
List<String> expanded = new ArrayList<>(splitCommandPrefix(command.get(0)));
|
||||
if (expanded.isEmpty()) {
|
||||
expanded.add(command.get(0));
|
||||
}
|
||||
expanded.addAll(command.subList(1, command.size()));
|
||||
return expanded;
|
||||
}
|
||||
|
||||
private int runCommand(Path logFile, List<String> command, boolean ignoreFailure) throws IOException, InterruptedException {
|
||||
|
||||
@ -13,7 +13,7 @@ spring:
|
||||
|
||||
server:
|
||||
# TMS HTTP 服务监听端口。
|
||||
port: 8080
|
||||
port: 8088
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
@ -135,9 +135,8 @@ tms:
|
||||
rabbit-admin-username: ${TMS_INIT_EXECUTOR_RABBIT_ADMIN_USERNAME:admin}
|
||||
# RabbitMQ 管理员密码(预制)。
|
||||
rabbit-admin-password: ${TMS_INIT_EXECUTOR_RABBIT_ADMIN_PASSWORD:admin}
|
||||
# RabbitMQ 控制命令(用于新增用户、授权等)。
|
||||
# 建议线上配置为绝对路径,例如 /usr/local/rabbitmq/sbin/rabbitmqctl。
|
||||
rabbitmq-ctl-command: ${TMS_INIT_EXECUTOR_RABBITMQ_CTL_COMMAND:/usr/local/rabbitmq/sbin/rabbitmqctl}
|
||||
# RabbitMQ 控制命令(用于新增用户、授权等);默认通过 root 受控 wrapper 执行,避免 tms 与 RabbitMQ 服务端 Erlang cookie 不一致。
|
||||
rabbitmq-ctl-command: ${TMS_INIT_EXECUTOR_RABBITMQ_CTL_COMMAND:sudo -n /usr/local/sbin/tms-rabbitmqctl}
|
||||
# RabbitMQ Admin CLI 命令路径(用于创建队列等)。
|
||||
rabbitmq-admin-command: ${TMS_INIT_EXECUTOR_RABBITMQ_ADMIN_COMMAND:/usr/sbin/rabbitmqadmin}
|
||||
# 标准版 RabbitMQ 初始化脚本路径(保留兼容;MQ_USER_APPLY 当前优先直接调用 rabbitmqctl/rabbitmqadmin)。
|
||||
@ -322,7 +321,7 @@ tms:
|
||||
# 备份/恢复标准收发器业务库名;第一版默认使用 CMEP。
|
||||
cmep-database-name: ${TMS_BACKUP_CMEP_DATABASE_NAME:CMEP}
|
||||
# 恢复完成后的最小健康检查地址。
|
||||
health-check-url: ${TMS_BACKUP_HEALTH_CHECK_URL:http://127.0.0.1:8080/actuator/health}
|
||||
health-check-url: ${TMS_BACKUP_HEALTH_CHECK_URL:http://127.0.0.1:8088/actuator/health}
|
||||
# 健康检查请求超时(秒)。
|
||||
health-check-timeout-seconds: ${TMS_BACKUP_HEALTH_CHECK_TIMEOUT_SECONDS:5}
|
||||
# 健康检查最大等待时间(秒);TMS 启动命令返回后,Spring Boot 仍可能需要一段时间才监听端口。
|
||||
@ -340,7 +339,7 @@ tms:
|
||||
internal-token: ${TMS_INTERNAL_TOKEN:change-me-internal-token}
|
||||
internal-auth:
|
||||
# 是否启用 /api/** 的内部登录鉴权;开发联调时可临时关闭。
|
||||
enabled: ${TMS_SECURITY_INTERNAL_AUTH_ENABLED:false}
|
||||
enabled: ${TMS_SECURITY_INTERNAL_AUTH_ENABLED:true}
|
||||
# 关闭内部鉴权后,注入请求上下文的调试角色。
|
||||
debug-role-code: ${TMS_SECURITY_INTERNAL_AUTH_DEBUG_ROLE_CODE:OPS_ADMIN}
|
||||
# 关闭内部鉴权后,注入请求上下文的调试认证等级。
|
||||
@ -349,7 +348,7 @@ tms:
|
||||
debug-session-token: ${TMS_SECURITY_INTERNAL_AUTH_DEBUG_SESSION_TOKEN:DEBUG-BYPASS}
|
||||
replay:
|
||||
# 是否启用防重放校验;本地 Postman/联调可临时设为 false,生产环境应保持 true。
|
||||
enabled: ${TMS_SECURITY_REPLAY_ENABLED:false}
|
||||
enabled: ${TMS_SECURITY_REPLAY_ENABLED:true}
|
||||
openapi:
|
||||
# 外部签名服务接口允许的时间戳偏差(秒),防重放。
|
||||
timestamp-skew-seconds: 300
|
||||
|
||||
@ -332,6 +332,33 @@ class ApplyResourceBackupScriptContractTest {
|
||||
Assertions.assertTrue(status.contains("database restore failed"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExecuteDatabaseSqlWithoutConnectingToTargetDatabaseFirst() throws Exception {
|
||||
Path commandLog = tempDir.resolve("mysql-restore.log");
|
||||
Path mysql = tempDir.resolve("mysql");
|
||||
Files.writeString(mysql, """
|
||||
#!/usr/bin/env bash
|
||||
for arg in "$@"; do
|
||||
printf 'ARG:%%s\\n' "$arg" >> "%s"
|
||||
done
|
||||
input="$(cat)"
|
||||
if [ -n "$input" ]; then
|
||||
printf 'STDIN:%%s\\n' "$input" >> "%s"
|
||||
fi
|
||||
""".formatted(commandLog, commandLog));
|
||||
mysql.toFile().setExecutable(true);
|
||||
Path sqlFile = tempDir.resolve("CMEP.sql");
|
||||
Files.writeString(sqlFile, "CREATE DATABASE IF NOT EXISTS `CMEP`;\nUSE `CMEP`;\nselect 1;");
|
||||
|
||||
int exitCode = runDbRestoreScriptForExit(mysql, "CMEP", sqlFile);
|
||||
|
||||
Assertions.assertEquals(0, exitCode);
|
||||
String log = Files.readString(commandLog);
|
||||
Assertions.assertTrue(log.contains("ARG:--host=127.0.0.1"));
|
||||
Assertions.assertFalse(log.contains("ARG:CMEP" + System.lineSeparator()));
|
||||
Assertions.assertTrue(log.contains("STDIN:CREATE DATABASE IF NOT EXISTS `CMEP`;"));
|
||||
}
|
||||
|
||||
private static void runScript(Path workDir, Map<String, String> environment) throws Exception {
|
||||
int exitCode = runScriptForExit(workDir, environment);
|
||||
Assertions.assertEquals(0, exitCode);
|
||||
@ -350,6 +377,23 @@ class ApplyResourceBackupScriptContractTest {
|
||||
return process.waitFor();
|
||||
}
|
||||
|
||||
private static int runDbRestoreScriptForExit(Path mysqlPath, String dbName, Path sqlFile) throws Exception {
|
||||
ProcessBuilder builder = new ProcessBuilder(
|
||||
"bash",
|
||||
Path.of("scripts/resource-restore/restore-db.sh").toAbsolutePath().normalize().toString(),
|
||||
"--mysql-path", mysqlPath.toString(),
|
||||
"--host", "127.0.0.1",
|
||||
"--port", "4000",
|
||||
"--username", "root",
|
||||
"--password", "secret",
|
||||
"--db-name", dbName,
|
||||
"--sql-file", sqlFile.toString()
|
||||
);
|
||||
builder.directory(Path.of(".").toAbsolutePath().normalize().toFile());
|
||||
Process process = builder.start();
|
||||
return process.waitFor();
|
||||
}
|
||||
|
||||
private Path fakeScript(String name, Path commandLog) throws Exception {
|
||||
Path script = tempDir.resolve(name);
|
||||
Files.writeString(script, """
|
||||
|
||||
@ -39,6 +39,36 @@ class MqReplayScriptContractTest {
|
||||
Assertions.assertTrue(log.contains("set_permissions -p /RQ tms .* .* .*"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReplayRabbitMqThroughPrefixedRootWrapperCommand() throws Exception {
|
||||
Path context = tempDir.resolve("mq-restore-context.json");
|
||||
Files.writeString(context, """
|
||||
{"schemaVersion":"1.0","productType":"ENTERPRISE","mqType":"RABBITMQ","orgCode":"BKCHCNBJXXX",
|
||||
"mq":{"channelUsername":"bank_user","channelPassword":"Secret123!"}}
|
||||
""");
|
||||
Path commandLog = tempDir.resolve("commands.log");
|
||||
Path sudo = fakeSudo(commandLog);
|
||||
Path wrapper = tempDir.resolve("tms-rabbitmqctl");
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(
|
||||
"bash",
|
||||
Path.of("scripts/resource-restore/replay-mq.sh").toAbsolutePath().normalize().toString(),
|
||||
"--context-file",
|
||||
context.toString(),
|
||||
"--work-dir",
|
||||
tempDir.resolve("work").toString()
|
||||
);
|
||||
builder.environment().put("RABBITMQ_CTL_COMMAND", sudo + " -n " + wrapper);
|
||||
Process process = builder.start();
|
||||
|
||||
Assertions.assertEquals(0, process.waitFor(), new String(process.getErrorStream().readAllBytes()));
|
||||
String log = Files.readString(commandLog);
|
||||
Assertions.assertTrue(log.contains("-n " + wrapper + " status"));
|
||||
Assertions.assertTrue(log.contains("-n " + wrapper + " add_vhost /RQ"));
|
||||
Assertions.assertTrue(log.contains("-n " + wrapper + " add_user bank_user Secret123!"));
|
||||
Assertions.assertTrue(log.contains("-n " + wrapper + " set_permissions -p /RQ bank_user .* .* .*"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDelegateToCustomReplayCommandWhenConfigured() throws Exception {
|
||||
Path context = tempDir.resolve("mq-restore-context.json");
|
||||
@ -71,4 +101,15 @@ class MqReplayScriptContractTest {
|
||||
script.toFile().setExecutable(true);
|
||||
return script;
|
||||
}
|
||||
|
||||
private Path fakeSudo(Path commandLog) throws Exception {
|
||||
Path script = tempDir.resolve("sudo");
|
||||
Files.writeString(script, """
|
||||
#!/usr/bin/env bash
|
||||
printf '%%s\\n' "$*" >> "%s"
|
||||
exit 0
|
||||
""".formatted(commandLog));
|
||||
script.toFile().setExecutable(true);
|
||||
return script;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1112,13 +1112,15 @@ class ConfigurableInitStepExecutorTest {
|
||||
Assertions.assertTrue(exampleContent.contains("standard-nginx-start-command: /home/tms/bin/start_standard_nginx.sh"));
|
||||
Assertions.assertTrue(exampleContent.contains("standard-nginx-stop-command: /home/tms/bin/stop_standard_nginx.sh"));
|
||||
Assertions.assertTrue(exampleContent.contains("standard-post-check-command: /home/tms/bin/check_standard_runtime.sh"));
|
||||
Assertions.assertTrue(exampleContent.contains("rabbitmq-ctl-command: sudo -n /usr/local/sbin/tms-rabbitmqctl"));
|
||||
|
||||
String applicationContent = Files.readString(applicationConfig);
|
||||
Assertions.assertTrue(applicationContent.contains("standard-app-start-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_START_COMMAND:/home/tms/bin/start_standard_apps.sh}"));
|
||||
Assertions.assertTrue(applicationContent.contains("standard-app-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_APP_STOP_COMMAND:/home/tms/bin/stop_standard_apps.sh}"));
|
||||
Assertions.assertTrue(applicationContent.contains("standard-nginx-start-command: ${TMS_INIT_EXECUTOR_STANDARD_NGINX_START_COMMAND:/home/tms/bin/start_standard_nginx.sh}"));
|
||||
Assertions.assertTrue(applicationContent.contains("standard-nginx-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_NGINX_STOP_COMMAND:/home/tms/bin/stop_standard_nginx.sh}"));
|
||||
Assertions.assertTrue(applicationContent.contains("standard-nginx-start-command: ${TMS_INIT_EXECUTOR_STANDARD_NGINX_START_COMMAND:sudo -n /usr/local/sbin/tms-start-standard-nginx}"));
|
||||
Assertions.assertTrue(applicationContent.contains("standard-nginx-stop-command: ${TMS_INIT_EXECUTOR_STANDARD_NGINX_STOP_COMMAND:sudo -n /usr/local/sbin/tms-stop-standard-nginx}"));
|
||||
Assertions.assertTrue(applicationContent.contains("standard-post-check-command: ${TMS_INIT_EXECUTOR_STANDARD_POST_CHECK_COMMAND:/home/tms/bin/check_standard_runtime.sh}"));
|
||||
Assertions.assertTrue(applicationContent.contains("rabbitmq-ctl-command: ${TMS_INIT_EXECUTOR_RABBITMQ_CTL_COMMAND:sudo -n /usr/local/sbin/tms-rabbitmqctl}"));
|
||||
|
||||
String readmeContent = Files.readString(readme);
|
||||
Assertions.assertTrue(readmeContent.contains("scripts/standard-init/"));
|
||||
@ -1247,6 +1249,61 @@ class ConfigurableInitStepExecutorTest {
|
||||
Assertions.assertTrue(callsContent.contains("set_permissions -p /RQ bank_user .* .* .*"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyStandardRabbitUserThroughPrefixedRootWrapperCommand() throws IOException {
|
||||
Path tempRoot = Files.createTempDirectory("init-executor-rabbit-wrapper-test");
|
||||
Path cpconfig = tempRoot.resolve("cpconfig.cfg");
|
||||
Path calls = tempRoot.resolve("calls.log");
|
||||
Path sudo = tempRoot.resolve("sudo");
|
||||
Path wrapper = tempRoot.resolve("tms-rabbitmqctl");
|
||||
Files.writeString(cpconfig, "MY_CIPSID_OR_BIC=AAAABBBBXXX\n");
|
||||
Files.writeString(
|
||||
sudo,
|
||||
"#!/bin/bash\n"
|
||||
+ "echo \"$*\" >> \"" + calls + "\"\n"
|
||||
+ "exit 0\n"
|
||||
);
|
||||
Assertions.assertTrue(sudo.toFile().setExecutable(true));
|
||||
|
||||
InitExecutorProperties properties = new InitExecutorProperties();
|
||||
properties.setMode(InitExecutorProperties.Mode.LOCAL);
|
||||
properties.setLogDir(tempRoot.resolve("logs").toString());
|
||||
properties.setStagingRootDir(tempRoot.resolve("staging").toString());
|
||||
properties.setStandardCpconfigPath(cpconfig.toString());
|
||||
properties.setRabbitmqCtlCommand(sudo + " -n " + wrapper);
|
||||
ConfigurableInitStepExecutor executor = new ConfigurableInitStepExecutor(properties, new ObjectMapper());
|
||||
|
||||
InitTaskEntity task = new InitTaskEntity();
|
||||
task.setTaskId("TASK-RABBIT-WRAPPER-1");
|
||||
task.setProductType("ENTERPRISE");
|
||||
task.setInitPlanJson(buildInitPlanJson(
|
||||
"ENTERPRISE",
|
||||
Map.of(
|
||||
"orgCodeType", "BIC",
|
||||
"orgCode", "AAAABBBBXXX",
|
||||
"orgNameCn", "测试机构",
|
||||
"deployMode", "SINGLE",
|
||||
"nodes", Map.of("node01Ip", "10.0.0.1"),
|
||||
"mq", Map.of("mqType", "RABBITMQ", "channelUsername", "bank_user", "channelPassword", "bank_pass"),
|
||||
"licenses", Map.of("receiverLicenseFileId", "receiver-001")
|
||||
)
|
||||
));
|
||||
|
||||
InitTaskStepEntity step = new InitTaskStepEntity();
|
||||
step.setStepNo(1);
|
||||
step.setStepCode("MQ_USER_APPLY");
|
||||
step.setCommandLine("internal::mq_user_apply");
|
||||
|
||||
InitStepExecutionResult result = executor.execute(task, step);
|
||||
|
||||
Assertions.assertTrue(result.isSuccess());
|
||||
String callsContent = Files.readString(calls);
|
||||
Assertions.assertTrue(callsContent.contains("-n " + wrapper + " status"));
|
||||
Assertions.assertTrue(callsContent.contains("-n " + wrapper + " add_vhost /RQ"));
|
||||
Assertions.assertTrue(callsContent.contains("-n " + wrapper + " add_user bank_user bank_pass"));
|
||||
Assertions.assertTrue(callsContent.contains("-n " + wrapper + " set_permissions -p /RQ bank_user .* .* .*"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyStandardRabbitUserForIndirectRabbitmqTlq() throws IOException {
|
||||
Path tempRoot = Files.createTempDirectory("init-executor-rabbit-setup-indirect-tlq-test");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user