如何阻止 Amazon RDS for PostgreSQL 在日志文件中以明文形式记录我的密码?

上次更新时间:2021 年 2 月 17 日

我想使用 Amazon Relational Database Service (Amazon RDS) for PostgreSQL 运行 CREATE USER 或 ALTER USER 语句。当我这样做时,PostgreSQL 会在日志文件中以明文形式记录我的密码。如何才能阻止 PostgreSQL 在日志文件中以明文形式显示我的密码?

简短描述

如果将 log_statement 参数设置为 ddl 或 all,然后运行 CREATE ROLE/USER ...WITH PASSWORD ... ; 或者 ALTER ROLE/USER ...WITH PASSWORD ... ;, 命令,则 PostgreSQL 会在 PostgreSQL 日志中创建一个条目。PostgreSQL 会以明文形式记录密码,这可能导致潜在的安全风险。

目前,PostgreSQL 不会识别敏感信息。根据 PostgreSQL 引擎的设计,这是预期的行为。

以下示例使用含密码的 CREATE ROLE 语句,然后以明文形式在日志中显示密码:

USER@postgresdb:pg> CREATE ROLE test_role WITH PASSWORD 'test123';
CREATE ROLE
Time: 0.003s

日志中的输出:

2020-04-15 14:57:29 UTC:x.x.x.x(42918):USER@pg::LOG: statement: CREATE ROLE test_role WITH PASSWORD 'test123'

以下示例使用含密码的 ALTER ROLE 语句,然后以明文形式在日志中显示密码:

USER@postgresdb:pg> ALTER ROLE test_role WITH PASSWORD 'test';
You're about to run a destructive command.
Do you want to proceed? (y/n): y
Your call!
ALTER ROLE
Time: 0.004sOutput in the logs:

日志中的输出:

2020-04-15 14:59:45 UTC:x.x.x.x(42918):USER@pg::STATEMENT: ALTER ROLE test_role SET PASSWORD 'test'
解决方法 使用 PSQL 客户端和动态变量来传入密码

使用 PSQL 客户端和 -c 选项传入 CREATE ROLE/AFTER ROLE 命令。您也可以使用动态变量。这可以防止 PostgreSQL 在日志中记录密码。请参阅以下示例:

$ psql --host=xxxxxxxxxxx.eu-west-1.rds.amazonaws.com --port=5432 --username=USER --dbname=pg -c "create user aaa with password ':pass'" -v pass=test123
Password for user USER:
CREATE ROLE

日志中的输出:

2020-04-08 15:19:32 UTC:x.x.x.x(32974):USER@pg::LOG: statement: create user aaa with password ':pass'
使用 PGAudit 插件

使用 pgaudit 扩展程序删节 PostgreSQL 日志中记录的密码。

    为您的 Amazon RDS PostgreSQL 实例启用 pgaudit。 在客户参数组中,设置 pgaudit.log 参数以指定要记录的语句类。此参数可以使用多个值,例如 DDL、role、write 和 read。

注意:pgaudit.log='DDL' 和 log_statement='DDL' 之间的主要区别在于,pgaudit DDL 不会在 Postgres 日志中记录任何 CREATE/ALTER ROLE 查询。

您可以通过向 pgaudit.log 添加 ROLE 来记录 CREATE/ALTER ROLE 日志。这会删节您的密码。

日志中的输出:

2020-07-09 13:33:50 UTC:x.x.x.x(58670):grysa@pg::LOG:  
AUDIT: SESSION,3,1,ROLE,CREATE ROLE,,,CREATE ROLE test_role WITH LOGIN 
PASSWORD <REDACTED>,<not logged>
在事务块内的会话级别将 log_statement 设置为 none

在事务块内的会话级别log_statement 参数设置为 none,以阻止 PostgreSQL 完整记录操作。

注意:如果将 pgaudit.log 和 log_statement 都设置为 DDL,则必须在会话级别将 log_statement 设置为 none。

示例:

BEGIN;
SET LOCAL log_statement = 'none';
ALTER ROLE ... WITH PASSWORD ...;
COMMIT;
在本地创建密码哈希值

在本地创建密码哈希值,然后在创建或更改角色或用户密码时使用此哈希值。

注意:您创建并用于运行语句的哈希值在日志中仍然可见。您可以将此解密,但它不会记录为明文形式。

示例:

$ username='test_1'; dbpass='test123'; echo -n "${dbpass}${username}" | md5sum | awk '{print "md5" $1}'
md574e183386ccb9039d0537aeb03c03db9

USER@postgresdb:pg> CREATE ROLE test_1 WITH PASSWORD 'md574e183386ccb9039d0537aeb03c03db9';
CREATE ROLE
Time: 0.003s

日志中的输出:

2020-04-15 15:12:08 UTC:x.x.x.x(42918):grysa@pg::LOG: statement: CREATE ROLE test_1 WITH PASSWORD 
'md574e183386ccb9039d0537aeb03c03db9'
使用 \password 命令

使用 PostgreSQL 时,您可以使用 PostgreSQL 客户端中内置的 \password 函数。当您创建或更改现有的角色密码时,此函数会提示您输入新密码。PostgreSQL 只记录密码的哈希值。

注意:此解决方法还会在 Postgres 日志中显示密码的哈希值,但不以将其记录为明文形式。

运行以下命令:

pg=> CREATE ROLE test_role NOLOGIN;
CREATE ROLE
pg=> \password test_role
Enter new password:
Enter it again:
pg=> ALTER ROLE test_role LOGIN;
ALTER ROLE
pg=>

日志中的输出:

2020-04-09 12:29:29 UTC:x.x.x.x(39876):grysa@pg::LOG: statement: CREATE ROLE test_role NOLOGIN;
2020-04-09 12:30:02 UTC:x.x.x.x(39876):grysa@pg::LOG: statement: show password_encryption
2020-04-09 12:30:02 UTC:x.x.x.x(39876):grysa@pg::LOG: statement: ALTER USER test_role PASSWORD 'md5175cad7c36a640b1fcfa0144056923f5'
2020-04-09 12:30:30 UTC:x.x.x.x(39876):grysa@pg::LOG: statement: ALTER ROLE test_role LOGIN;