数据库记录一致性校验

介绍如何配置数据库记录一致性校验,当平台数据库记录被窜改后能够及时报错

数据库记录一致性校验的原理是计算表里面每条记录的 md5 值,如果人工修改字段,平台的服务在读取,更新或者删除的时候就会发现计算的 md5 checksum 不一致,禁止接下来的操作。

配置

开启改选项会产生额外的计算量。默认开启以下服务的配置表:

  • keystone 服务:
    • user 表: 保存用户信息的表
  • region 服务:
    • guests_tbl 表: 保存虚拟机信息
  • logger 服务:
    • actionlog_tbl 表: 保存操作日志

分别编辑这两个服务的配置 configmap default-keystone 和 default-region 里面的 enable_db_checksum_tables 这个参数:

# 配置 keystone 服务配置
$ kubectl -n onecloud edit configmaps default-keystone
...
    enable_db_checksum_tables: true
...

# 重启 keystone 服务
$ kubectl -n onecloud rollout restart deployment default-keystone

# 配置 region 服务配置
$ kubectl -n onecloud edit configmaps default-region
...
    enable_db_checksum_tables: true
...

# 重启 region 服务
$ kubectl -n onecloud rollout restart deployment default-region

测试

当开启 enable_db_checksum_tables 的配置后,每条记录就会有一个 record_checksum 的字段,这里以 keystone 数据库的 user 表来测试,看看如果手动修改了记录会发生什么情况:

# 查看 cloudadmin 用户的 record_checksum, id 和 last_login_ip
$ climc user-show cloudadmin | egrep -w 'record_checksum|id|last_login_ip'
| id                  | 475925c93c344a54837fe49f852c5086 |
| last_login_ip       | 192.168.121.1                    |
| record_checksum     | 3d953f46c400ba3bd9562be8ae2a9d9c |

# 找到当前集群的数据库密码
$ kubectl get oc -n onecloud -o yaml | grep -A 4 mysql
    mysql:
      host: 192.168.121.21
      password: y4uzCV37gZEr
      port: 3306
      username: root

# 连上 keystone 数据库,把 cloudadmin 的 last_login_ip 字段改成 192.168.121.2
$ mysql -u root -py4uzCV37gZEr -h 192.168.121.21 keystone
MariaDB [keystone]> update user set last_login_ip = '192.168.121.2' where id = '475925c93c344a54837fe49f852c5086';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

# 再次查看 cloudadmin user,会提示记录被修改,checksum 不一致的报错
$ climc user-show cloudadmin
{"error":{"class":"UnclassifiedError","code":500,"details":"Record user(475925c93c344a54837fe49f852c5086) checksum changed, expected(3d953f46c400ba3bd9562be8ae2a9d9c) != calculated(701f345054c8fee78cebb130730c8ba0)","request":{"headers":{"User-Agent":"yunioncloud-go/201708","X-Auth-Token":"*"},"method":"GET","url":"http://192.168.121.21:30500/v3/users/cloudadmin"}}}

注意事项

为了兼容性,这个 db_checksum_tables 里面配置的表每次服务启动都会计算,如果数据量很大,可能会导致服务启动很慢,当第一次服务初始完每条记录的 checksum 后,可以配置 db_checksum_skip_init: true 参数跳过初始化 checksum 。比如关闭 keystone 服务第一次初始化 checksum 操作如下:

$ kubectl -n onecloud edit configmaps default-keystone
...
    db_checksum_skip_init: true
...

# 重启 keystone 服务
$ kubectl -n onecloud rollout restart deployment default-keystone