Files
cheney fe28ddeaac feat: HSM main/slave certificate comparison with batch SQL generation
- compare usercert_tab by subject raw bytes + certtype
- generate single annotated CSV report
- generate merge-<timestamp>.sql in current directory for DBA execution
- preserve GBK DN bytes via ATTACH + INSERT OR REPLACE / UPDATE
- compatible with sqlite3 3.6.20 and JDK 1.8
2026-11-04 15:18:42 +08:00

160 lines
5.4 KiB
Markdown
Raw Permalink 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.
# HSM 主备数据库证书比对工具
Java 8 命令行工具,用于比对 HSM 主库、从库 SQLite 数据库中的 `usercert_tab`,生成一份差异报表,并按人工标注的“合并选择”生成**在主库执行的批量 SQL 脚本**。
- 身份键:`subject` 原始字节 + `certtype`
- 三类差异:主库多、从库多、不一致
- 报表:单份 CSV(UTF-8 + BOM),含“合并选择”列
- 合并方式:生成 `merge-<时间戳>.sql`,由 DBA 在主库执行
- 工具本身只读源库,不直接修改任何数据库
- 脚本通过 `ATTACH` 从从库按原始字节复制,DN 中文(GBK 字节)不经过 Java 字符串
- 不生成日志文件,信息只输出到控制台
详细需求与设计见 `需求文档.md`、`设计文档.md`。
## 构建
要求:JDK 8 + Maven 3.x。
```bash
mvn clean package
# 产物:target/cert-compare.jar(fat jar,含 sqlite-jdbc 原生库)
```
当前构建:12 个单元测试全部通过,jar 约 9.8 MB。
## 配置
`config.properties`(UTF-8):
```properties
db.main=/app/cert-compare/main.db
db.slave=/app/cert-compare/slave.db
db.text.encoding=GB18030
dn.match=EXACT
sn.normalize=HEX
report.dir=/app/cert-compare/reports
report.csv.bom=true
```
相对路径以配置文件所在目录为基准。SQL 脚本不配置输出目录,直接写入运行时当前目录。
## 使用
### 交互模式
```bash
java -Dfile.encoding=UTF-8 -jar cert-compare.jar --config config.properties
```
```text
cert-compare> set main /app/cert-compare/main.db
cert-compare> set slave /app/cert-compare/slave.db
cert-compare> compare
cert-compare> sql --report /app/cert-compare/reports/compare-report-20261104-213307-annotated.csv
```
### 一次性命令
```bash
# 1. 生成报表
java -Dfile.encoding=UTF-8 -jar cert-compare.jar compare --config config.properties
# 2. 人工标注“合并选择”后生成批量 SQL
java -Dfile.encoding=UTF-8 -jar cert-compare.jar sql \
--config config.properties \
--report /app/cert-compare/reports/compare-report-20261104-213307-annotated.csv
# 3. 由 DBA 备份主库后执行脚本
cp -p /app/cert-compare/main.db /app/cert-compare/main.db.bak-$(date +%Y%m%d-%H%M%S)
sqlite3 /app/cert-compare/main.db < /app/cert-compare/merge-20261104-213307.sql
```
`sql` 只生成脚本,不写数据库、不需要确认参数;脚本直接写入运行时的当前目录。
### 合并选择规则
| 类型 | 默认值 | 允许值 |
| --- | --- | --- |
| 主库多 | 主 | 仅主 |
| 从库多 | 备 | 仅备 |
| 不一致 | 空 | 主 / 备 |
`sql` 生成前会重新比对并校验报表是否过期、标注是否完整;不合法时拒绝生成脚本并提示行号(退出码 5)。
## 报表
文件名:`compare-report-yyyyMMdd-HHmmss.csv`。
列为:`序号,类型,DN,DN_HEX,CN,CERTTYPE,主库SN,从库SN,主库生效,主库失效,从库生效,从库失效,主库状态,从库状态,差异字段,合并选择`。
- `合并选择` 放在最后一列,方便直接填写“主”或“备”。
- 报表不含“备注”列;日期非法、SN/DN 为空等异常在 `compare` 控制台“提示”中输出。
- `DN_HEX` 带 `HEX:` 前缀,避免 Excel 把长十六进制转为科学计数法。
- 报表可用 Excel 直接编辑,另存为 UTF-8 CSV 或 GBK CSV 均可读取。
- `sql` 只信任“合并选择”列,证书数据始终取自当前数据库。
## 生成的 SQL 脚本
- 文件名:`merge-yyyyMMdd-HHmmss.sql`,写入运行时当前目录,不覆盖历史脚本。
- `ATTACH DATABASE '<从库>' AS cert_src`,按 `hex(subject)` + `certtype` 定位。
- 从库多、不一致选备:`INSERT OR REPLACE ... SELECT`(整行复制)。
- `dn.match=TRIM` 且主备 DN 字节不同时:`UPDATE ... SET col = (SELECT ...)`,按主库字节定位。
- 主库多、不一致选主:不产生语句。
- 使用 `BEGIN IMMEDIATE` / `COMMIT` 包裹,可重复执行(幂等)。
- 末尾输出 `SELECT 'rows'` 与 `PRAGMA integrity_check` 供执行后自检。
- 脚本为 UTF-8 无 BOM,SQL 与字符串字面量全 ASCII,DN 只以十六进制出现。
- 兼容服务器 sqlite3 3.6.20。
## 测试数据
`scripts/test-data-main.sql` 与 `scripts/test-data-slave.sql` 会在原测试库中增加 3 组“不一致”数据:
| DN | CERTTYPE | 差异 | 主库 | 从库 |
| --- | --- | --- | --- | --- |
| `CN=diff-sn-01` | 0 | SN | `0A0B0C01` | `0A0B0C11` |
| `CN=diff-time-02` | 2 | 失效时间 | `20301231235959` | `20311231235959` |
| `CN=diff-stat-03` | 5 | 状态 | `0` | `1` |
执行前请备份:
```bash
cp -p main.db main.db.bak-$(date +%Y%m%d-%H%M%S)
cp -p slave.db slave.db.bak-$(date +%Y%m%d-%H%M%S)
sqlite3 main.db < scripts/test-data-main.sql
sqlite3 slave.db < scripts/test-data-slave.sql
```
当前测试库预期结果:
```text
主库 4 条,从库 15 条
一致 0、主库多 1、从库多 12、不一致 3
报表 16 条
执行脚本后主库 16 条(2 条选主、1 条选备)
```
## 部署
```bash
scp target/cert-compare.jar root@172.1.41.139:/app/cert-compare/
scp config.properties root@172.1.41.139:/app/cert-compare/
scp scripts/cert-compare.sh root@172.1.41.139:/app/cert-compare/
ssh root@172.1.41.139
cd /app/cert-compare
chmod +x cert-compare.sh
./cert-compare.sh
```
`cert-compare.sh` 已设置 `-Dfile.encoding=UTF-8 -Xmx256m`。
## 退出码
| 码 | 含义 |
| --- | --- |
| 0 | 成功 |
| 1 | 未预期内部错误 |
| 2 | 参数/配置错误 |
| 4 | 数据库/结构/完整性错误 |
| 5 | 报表过期、标注非法、SQL 脚本生成/写入失败 |