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
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# 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 脚本生成/写入失败 |
|
||||
Reference in New Issue
Block a user