轮换数据库根凭证

Vault 的数据库机密引擎 代表数据库管理员来管理各种数据库凭据,所以我们必须在 Vault 中设置一个拥有很高权限的账号凭证,使得 Vaut 可以用它来签发或是吊销其他数据库凭证。因此我们一般会在 Vault 中配置数据库的“根账户”。

然而,这些配置在 Vault 中的长生命周期的凭据永远不会被修改,这将违反一些有关于数据库保存数据的合规要求(例如 Governance, Risk and Compliance, GRC)。

解决方案

使用 Vault 的 /database/rotate-root/:name API 端点来轮换存储的根凭据:

轮换数据库根凭据流程
图 1.10.5/1 - 轮换数据库根凭据流程

最佳实践:每次初始化好一个数据库机密引擎后,都使用该功能轮换该数据库的根凭据。

前置条件

  1. 一个已经初始化并解封的 Vault 服务器
  2. 一个 PostgreSQL 数据库(本实验使用 Docker 运行 Postgres,所以请确保已安装 Docker)
  3. 拥有如下 Vault 权限的 Vault 令牌:
# Mount secrets engines
path "sys/mounts/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}

# Configure the database secrets engine and create roles
path "database/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}

请注意,如果是进行实验或者学习,那么可以使用 Vault 的 root 令牌。然而我们不推荐在生产环境使用 root 令牌,而应该根据工作需要配置拥有合适权限的令牌。

步骤一:启用数据库机密引擎

用以下命令启用数据库引擎

$ vault secrets enable database

步骤二:启动 PostgreSQL 数据库

使用 Docker 启动一个 PostgreSQL 数据库实例:

$ docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=mysecretpassword postgres

这时在 localhost:5432 可以访问到该数据库,默认用户名为 postgres,密码为 mysecretpassword,读者可以连接一下数据库进行确认。

步骤三:配置 PostgreSQL 机密引擎

使用一下命令配置 PostgreSQL 机密引擎:

$ vault write database/config/postgresql \
     plugin_name=postgresql-database-plugin \
     connection_url="postgresql://{{username}}:{{password}}@localhost:5432/postgres?sslmode=disable" \
     allowed_roles="*" \
     username="postgres" \
     password="mysecretpassword"

要注意的是,由于本实验中没有为数据库启用 ssl,所以在 connection_url 连接字符串的末尾特意加上了 ?sslmode=disable请勿在生产环境这样做

步骤四:轮换根凭据

使用以下命令轮换根凭据:

$ vault write -force database/rotate-root/postgresql
Success! Data written to: database/rotate-root/postgresql

可以使用一下命令确认根凭据已被轮换:

$ psql -h postgres.host.address -p 5432 -U root postgres
Password for user root:

使用初始的用户名 postgres 以及密码 mysecretpassword无法连接到数据库,说明数据库根凭据已被轮换。

我们可以定期调用该命令来实现对根凭据的定期轮换。

警告:一旦轮换了根凭据,那么就只有 Vault 知道新的根账号密码了。这一点对该 Vault 机密引擎中配置的所有的数据库根凭据都是一样的。所以,应当配置一个 Vault 专用的根账号。

步骤五:验证配置

我们可以创建一个角色来验证数据库机密引擎可以正确动态生成一个凭据。

创建一个名为 readonly.sql 的文件,包含如下语句:

$ tee readonly.sql <<EOF
CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO "{{name}}";
EOF

创建一个名为 readonly 的角色,TTL 设置为 1 小时:

$ vault write database/roles/readonly db_name=postgresql \
         creation_statements=@readonly.sql \
         default_ttl=1h max_ttl=24h

现在,获取一个新的数据库凭据:

$ vault read database/creds/readonly
Key                Value
---                -----
lease_id           database/creds/readonly/999c43f0-f79e-ba90-24a8-4de5af33a2e9
lease_duration     1h
lease_renewable    true
password           A1a-u7wxtrpx09xp40yq
username           v-root-readonly-x6q809467q98yp4yx4z4-1525378026e

验证我们可以使用该凭据连接到数据库:

$ psql -h postgres.host.address -p 5432 \
       -U v-root-readonly-x6q809467q98yp4yx4z4-1525378026e postgres
Password for user v-root-readonly-x6q809467q98yp4yx4z4-1525378026:

postgres=> \du
Role name                                       |                         Attributes                         | Member of
------------------------------------------------+------------------------------------------------------------+----------
postgres                                        | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
v-root-readonly-x6q809467q98yp4yx4z4-1525378026 | Password valid until 2018-05-03 21:07:11+00                | {}
v-root-readonly-x7v65y1xuprzxv9vpt80-1525378873 | Password valid until 2018-05-03 21:21:18+00                | {}

postgres=> \q

以上步骤可以确认 Vault 成功地连接到了 PostgreSQL 数据库并依据 readonly.sql 文件中的语句创建了一个拥有相应权限的新用户。

results matching ""

    No results matching ""