GBase 8a修改数据库密码对应用影响更小的方法探讨

GBase 8a的安全策略中,支持在密码失败指定次数(login_attempt_max)后将账号锁定。数据库业务,包括但不限于业务应用、定时任务、脚本、ETL、中间件等,在修改了数据库密码后,如果继续用原有免密发起多次连接尝试,将会导致账号被锁。本文介绍一些修改密码对应用影响更小的几个方法。

解决方案的核心就是如何拿到最新的密码。其中业务必须每次新建立连接时,都要获取最新的密码。

备注:修改数据库密码,不会对已有的连接产生影响,可以继续使用。只对新建立的连接用新的密码进行验证。

如下讲到的所有密码,均为加密存储,不是明文。 具体的加密和解密方案,由使用者决定,一般是AES/SM4对称加密,或者指定位置,比如REST接口,统一加解密。

密码放在共享配置文件里

适合私有网,小规模业务。

配置方法

将密码配置文件,保存在共享文件系统,比如NFS,https,sftp(比较慢)访问里。

读取密码方案

所有应用都从该配置文件读取访问密码。

修改密码方案

  • DBA修改数据库密码成功
  • 更新配置文件。

至于修改密码和更新文件之间的间隔,

  • 修改密码后,更新操作耗时很短,rename覆盖的方式在毫秒级。
  • 可以通过flock等约定方式,一旦发现在写入,则临时阻塞读取。
  • 临时将配置文件的读权限去掉,更新后再恢复。【建议】

读取不到,不让读,均可以通过延迟重试来解决,总比数据库账号被锁要好处理。

密码保存在配置中心

适合中小规模使用。

将密码保存到Nacos / Apollo / Spring Cloud Config(Java)、Consul等配置中心。

配置方法

数据库账号密码存加密配置项。

读取密码方案

应用接入配置监听,配置变更自动推送,实时刷新连接池。

修改密码方案

  • DBA 修改 DB 用户密码
  • 运维在配置中心更新对应加密密码
  • 所有在线应用自动感知变更,新建连接使用新密码;
  • 旧连接用完自动释放

修改密码和配置修改的间隔,与前一个方案一样,可以通过允许报错后延迟重试,但不能锁住数据库账号的方案规避。

密码保存在数据库内

将密码保存在一个数据库的独立表里,然后用一个通用的账号和密码读取。通用账号只有读取这个配置表的权限,密码无需修改。

配置方法

独立的库,独立的表,该表只用于保存密码(对称加密后)。

每个密码可以增加个【状态】字段,分为正常和更新中2个状态,后者表示暂时不可用,需要等待更新完成。

读取密码方案

配置单独的数据库用户和密码,只能读取该库的该表。 该用户无需修改密码。

应用读取到加密后的密码,解密后,连接数据库。

修改密码方案

修改密码和修改配置表,可以放到一个存储过程里执行。如下是修改一个用户的密码流程。

  • 1、更新密码配置为更新状态
  • 2、修改密码,如果失败,则更新配置表为正常状态,通知人工修改免密失败,返回
  • 3、更新配置表,同时将状态改成正常。如果成功则返回
  • 4、修改配置表失败,重试依然不行,通知人工介入。

采用第三方认证

比如各种KMS,HashiCorp Vault等。

配置方法

密码作为保密数据被保存在KMS里

读取方法

用户通过访问KMS获得最新的密码。

修改密码

  • 管理员通过KMS发起修改密码/密码轮换请求
  • KMS访问数据库,修改密码。如果修改密码失败,KMS可以继续提供之前的密码。
  • KMS更新本地密码。如果失败,需要人工介入。

总结

从个人接触过的项目看,任何存在多应用访问的密码修改,都涉及到这个问题,不单单是数据库密码。

其中采用第三方是比较正规的方案,比如KMS,配置中心等。而采用动态证书代替固定密码,比如kerberos等也是个好注意。

小规模应用,用共享文件,通过NFS或https访问等更方便。

如果不想配置额外服务,将密码的密文保存在数据库中也是一个简单可行的方案。