如何在 Amazon RDS for PostgreSQL 中创建密码策略?
我想在 Amazon Relational Database Service (Amazon RDS) for PostgreSQL 中创建密码策略。
简短描述
默认情况下,Amazon RDS for PostgreSQL 不具有强制执行密码策略的功能。但是,您可以使用 PostgreSQL 钩子和可信语言扩展 (TLE) 扩展来扩展核心功能。要在创建或更改用户或角色的密码时自定义 PostgreSQL 处理密码的方式,请使用 passcheck 钩子。
**注意:**TLE 支持 Amazon RDS for PostgreSQL 版本 16.1 及更高版本、15.2 及更高版本、14.5 及更新版本以及 13.12 及更高版本的 Amazon RDS。有关详细信息,请参阅使用 PostgreSQL 的可信语言扩展的要求。
解决方法
**注意:**如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI。
创建客户参数组并设置 TLE 扩展
完成以下步骤:
-
创建自定义参数组,然后将其关联到您的 Amazon RDS for PostgreSQL 实例。
**注意:**参数组更改将导致停机。使用维护时段来避免立即停机。 -
登录您的实例,运行以下查询,然后确认 shared_preload_libraries 参数已更新:
postgres=> SHOW shared_preload_libraries;shared_preload_libraries rdsutils,pg_tle,pg_stat_statements (1 row) postgres=> -
运行以下查询来创建 TLE 扩展:
CREATE EXTENSION pg_tle;**注意:**要设置和配置 pg_tle 扩展,您的数据库用户角色必须具有 rds_superuser 角色权限。
-
向您的 Amazon RDS for PostgreSQL 实例主用户授予 pgtle_admin 角色。如果您使用了默认用户,则这是 postgres 主用户:
GRANT pgtle_admin TO example-user;**注意:**将 example-user 替换为 Amazon RDS for PostgreSQL 实例主用户。
设置 passcheck 钩子
PostgreSQL passcheck 钩子检查 SQL 操作的密码,不允许用户设置 password_check.bad_passwords 表中列出的密码。passcheck 钩子还会检查密码长度并确认密码包含大写和小写字母、数字和特殊字符。
**注意:**您可以根据自己的特定需求修改 PostgreSQL 钩子的函数。您可以将更多密码添加到 bad_passwords 表中,更改所需的密码长度,或者修改该函数以检查密码复杂性。
完成以下步骤:
-
运行以下 pgtle.install_extension SQL 命令。根据您的特定需求修改 SQL 代码:
SELECT pgtle.install_extension ( 'example-password-check-rules', '1.0', 'Do not let users use the 10 most commonly used passwords', $_pgtle_$ CREATE SCHEMA password_check; REVOKE ALL ON SCHEMA password_check FROM PUBLIC; GRANT USAGE ON SCHEMA password_check TO PUBLIC; CREATE TABLE password_check.bad_passwords (plaintext) AS VALUES ('123456'), ('password'), ('12345678'), ('qwerty'), ('123456789'), ('12345'), ('1234'), ('111111'), ('1234567'), ('dragon'); CREATE UNIQUE INDEX ON password_check.bad_passwords (plaintext); CREATE FUNCTION password_check.passcheck_hook(username text, password text, password_type pgtle.password_types, valid_until timestamptz, valid_null boolean) RETURNS void AS $$ DECLARE invalid bool := false; BEGIN -- Check password length IF length(password) < 8 THEN RAISE EXCEPTION 'Password must be at least 8 characters long.'; END IF; -- Check common passwords from password from bad_passwords table IF password_type = 'PASSWORD_TYPE_MD5' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE ('md5' || md5(bp.plaintext || username)) = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common password dictionary'; END IF; ELSIF password_type = 'PASSWORD_TYPE_PLAINTEXT' THEN SELECT EXISTS( SELECT 1 FROM password_check.bad_passwords bp WHERE bp.plaintext = password ) INTO invalid; IF invalid THEN RAISE EXCEPTION 'Cannot use passwords from the common password dictionary'; END IF; END IF; -- Check password contains uppercase lowercase number and special character IF NOT (password ~ '[A-Z]' AND password ~ '[a-z]' AND password ~ '[0-9]' AND password ~ '[^a-zA-Z0-9]') THEN RAISE EXCEPTION 'Password must contain uppercase letters, lowercase letters, numbers, and special characters'; END IF; END $$ LANGUAGE plpgsql SECURITY DEFINER; GRANT EXECUTE ON FUNCTION password_check.passcheck_hook TO PUBLIC; SELECT pgtle.register_feature('password_check.passcheck_hook', 'passcheck'); $_pgtle_$);**注意:**在前面的命令中,将 example-password-check-rules 替换为密码检查规则的名称。
-
运行以下查询来创建扩展:
postgres=> CREATE EXTENSION "example-password-check-rules";**注意:**在前面的命令中,****将 example-password-check-rules 替换为密码检查规则的名称。
-
修改与您的实例关联的自定义参数组,然后启用 pgtle.enable_password_check 参数。
-
要测试您的密码检查规则,请使用以下示例。
示例:postgres=> CREATE ROLE t_role PASSWORD 'password';ERROR: Cannot use passwords from the common password dictionary CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 25 at RAISE SQL statement "SELECT password_check.passcheck_hook($1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"**注意:**前面的示例表明存在错误,因为您无法使用通用密码词典中的密码。
示例:postgres=> CREATE ROLE t_role PASSWORD 'pass';ERROR: Password must be at least 8 characters long. CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 7 at RAISE SQL statement "SELECT password_check.passcheck_hook($1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"**注意:**前面的示例表明存在错误,因为密码长度必须至少为 8 个字符。
示例:postgres=> CREATE ROLE t_role PASSWORD 'passwordd';ERROR: Password must contain uppercase letters, lowercase letters, numbers, and special characters CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamp with time zone,boolean) line 31 at RAISE SQL statement "SELECT password_check.passcheck_hook($1::pg_catalog.text, $2::pg_catalog.text, $3::pgtle.password_types, $4::pg_catalog.timestamptz, $5::pg_catalog.bool)"**注意:**前面的示例表明存在错误,因为密码必须包含大写字母、小写字母、数字和特殊字符。
对于不支持 TLE 的 Amazon RDS for PostgreSQL 版本,使用 AWS Identity and Access Management (IAM) for Amazon RDS 或 Kerberos 身份验证。此外,要将密码创建限制为一组角色或特定角色,请参阅委托和控制用户密码管理。
