CMDB资产唯一标识不能用hostname或IP,因云主机重启会换IP、物理机重装会改hostname,导致老记录断连及关联监控日志权限失效;必须用绑定生命周期的source_type+source_id联合唯一索引,如"aliyun"+"i-bp1a2b3c4d5e6f7g8h9"。

CMDB 资产唯一标识为什么不能用 hostname 或 IP
生产环境里,用 hostname 或 ip_inner 当主键,等于给后续所有功能埋雷。云主机重启换 IP、物理机重装系统改 hostname,老记录就断连,关联的监控、日志、权限全部失效。
真正可用的唯一标识必须绑定资产生命周期,且由源头平台保证不变。推荐组合:source_type + source_id 作为联合唯一索引。
-
source_type填字符串,如"aliyun"、"vmware"、"physical" -
source_id必须是云平台返回的原生实例 ID,如阿里云的"i-bp1a2b3c4d5e6f7g8h9",不是你自动生成的uuid.New() - 如果对接 Prometheus,可用其
instance标签(如"10.1.2.3:9100"),但必须加前缀,比如存为"prometheus-10.1.2.3:9100",避免不同监控源冲突
GORM 中如何安全存多云特有属性
硬建几十个字段(比如 aliyun_region、tencent_zone、aws_lifecycle)会导致表结构膨胀、查询慢、迁移难。GORM v2 支持 JSON 字段,但要注意写法和查询方式。
核心表只保留通用字段:name、ip_inner、ip_outer、os、status、source_type、source_id、created_at。其余全塞进一个 cloud_metadata 字段。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- PostgreSQL 推荐用
jsonb类型,MySQL 用JSON类型(5.7+) - GORM struct tag 写成:
CloudMetadata string `gorm:"type:jsonb;column:cloud_metadata"` - 查 region 时别全量解析,用 GORM 的路径查询:
Where("cloud_metadata->>'region' = ?", "cn-hangzhou") - 避免在 WHERE 条件里对 JSON 字段做函数转换(如
JSON_EXTRACT),会跳过索引
变更日志必须带 diff 字符串,否则审计不通过
只记「谁在什么时间改了哪台机器」,审计时被问「到底改了什么」就只能翻代码或猜。日志表设计错,后期补成本极高,甚至要重建整套历史。
日志表至少含五个字段:asset_source_id、op_type("create"/"update"/"delete")、before_data(JSON)、after_data(JSON)、diff(纯文本,如 "os: 'centos7' → 'ubuntu22.04'")。
-
before_data和after_data存完整快照,不是增量;用于回滚或比对 -
diff字段必须是人可读字符串,不是 JSON patch —— 审计人员不看 patch,只扫一眼就知道改了啥 - 禁用软删除:CMDB 里删一条资产,必须留痕,
op_type = "delete"+before_data完整快照 - 按月分区日志表(如
audit_log_202608),避免单表过大拖慢查询
JWT 中间件 401 的真实原因往往不是密钥
登录成功但后续接口持续 401,90% 不是密钥错了,而是 token 和中间件之间的约定错位。
-
exp字段必须是int64秒级 Unix 时间戳,不是毫秒,也不是字符串:jwt.MapClaims{"exp": time.Now().Add(time.Hour).Unix()} - Authorization 头格式严格为
Bearer xxx:少空格(Bearerxxx)、多空格(Bearer xxx)、写成Token xxx都失败 - 中间件必须用
router.Use()全局注册;如果只在v1 := router.Group("/api/v1")下加v1.Use(jwtauth.Middleware()),那/api/users就绕过鉴权 - token payload 里建议加
source字段(如"source": "cmdb-admin"),方便后续做权限路由隔离
CMDB 的安全不是靠加密强度堆出来的,而是靠标识不可变、变更可溯、权限可验这三个点卡死。任何试图绕过 source_type+source_id 做主键、跳过 diff 字段、或把 JWT 当黑盒用的做法,上线后第一轮审计就会被拦下来。

















