跳至内容

如何在 Amazon RDS for PostgreSQL 中创建密码策略?

3 分钟阅读
0

我想在 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 扩展

完成以下步骤:

  1. 创建自定义参数组,然后将其关联到您的 Amazon RDS for PostgreSQL 实例。
    **注意:**参数组更改将导致停机。使用维护时段来避免立即停机。

  2. 设置 TLE 扩展

  3. 登录您的实例,运行以下查询,然后确认 shared_preload_libraries 参数已更新:

    postgres=> SHOW shared_preload_libraries;shared_preload_libraries  
    rdsutils,pg_tle,pg_stat_statements  
    (1 row)  
    postgres=>
  4. 运行以下查询来创建 TLE 扩展:

    CREATE EXTENSION pg_tle;

    **注意:**要设置和配置 pg_tle 扩展,您的数据库用户角色必须具有 rds_superuser 角色权限。

  5. 向您的 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 表中,更改所需的密码长度,或者修改该函数以检查密码复杂性。

完成以下步骤:

  1. 运行以下 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 替换为密码检查规则的名称。

  2. 运行以下查询来创建扩展:

    postgres=> CREATE EXTENSION "example-password-check-rules";

    **注意:**在前面的命令中,****将 example-password-check-rules 替换为密码检查规则的名称。

  3. 修改与您的实例关联的自定义参数组,然后启用 pgtle.enable_password_check 参数。

  4. 要测试您的密码检查规则,请使用以下示例。
    示例:

    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 RDSKerberos 身份验证。此外,要将密码创建限制为一组角色或特定角色,请参阅委托和控制用户密码管理

相关信息

使用适用于 PostgreSQL 的可信语言扩展

适用于 PostgreSQL 的可信语言扩展的钩子参考