跳至内容

如何管理 Aurora PostgreSQL 兼容版数据库集群连接的密码复杂性和到期时间?

4 分钟阅读
0

我想管理 Amazon Aurora PostgreSQL 兼容版数据库 (DB) 集群连接的密码复杂性和到期时间。

简短描述

要管理 Aurora PostgreSQL 兼容版数据库集群的密码,您可以使用以下方法:

解决方法

在 TLE 中使用密码检查钩子

要在 TLE 中使用密码检查钩子,必须先在 Aurora PostgreSQL 兼容版数据库集群中设置 TLE。然后,创建密码检查钩子

**注意:**为钩子命名时,不能使用 user-password-check-rules

密码检查钩子代码示例:

SELECT pgtle.install_extension(
  'user-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 for bad passwords
    CREATE TABLE password_check.bad_passwords (plaintext) AS
    VALUES
      ('123456'),
      ('password'),
      ('12345678'),
      ('qwerty'),
      ('123456789'),
      ('12345'),
      ('1234'),
      ('111111'),
      ('1234567'),
      ('dragon');
    -- Create table for tracking user password changes
    CREATE TABLE password_check.usertime (
      user_name text PRIMARY KEY,
      lasttime timestamp
    );
    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;
        userexists bool;
        last_password_change timestamp;
      BEGIN
        -- Check if user already exists      
        SELECT EXISTS (SELECT user_name FROM password_check.usertime WHERE user_name = username) INTO userexists;
        -- If user exists, check password age
        IF (userexists) THEN
          SELECT lasttime INTO last_password_change
          FROM password_check.usertime
          WHERE user_name = username;
          -- Check if password is older than 90 days
          IF (CURRENT_TIMESTAMP - last_password_change) > INTERVAL '90 days' THEN
            RAISE EXCEPTION 'Password has expired. It must be changed every 90 days. Last change was on %', last_password_change;
          END IF;
          -- Update timestamp for new password change
          UPDATE password_check.usertime SET lasttime = CURRENT_TIMESTAMP WHERE user_name = username;
        ELSE
          -- First time user, add to tracking table
          INSERT INTO password_check.usertime VALUES(username, CURRENT_TIMESTAMP);
        END IF;
        -- Existing password length check
        IF length(password) < 8 THEN
          RAISE EXCEPTION 'Password must be at least 8 characters long.';
        END IF;
        -- Existing common password check
        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;
        -- Existing complexity check
        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_$
);

**注意:**请根据您的需求修改代码。例如,您可以向 bad_passwords 表中添加更多密码,更改密码长度要求,或检查密码复杂性。

要检查密码是否符合长度要求,请运行以下命令:

CREATE ROLE user1 PASSWORD '123456';

预期输出:

ERROR: Password must be at least 8 characters long.
CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamptz,bool)
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)"

**注意:**上述示例表明存在错误,因为密码长度必须至少为八个字符。

要检查密码是否过于常见,请运行以下命令:

CREATE ROLE user1 PASSWORD 'password';

预期输出:

ERROR: Cannot use passwords from the common password dictionary
CONTEXT: PL/pgSQL function password_check.passcheck_hook(text,text,pgtle.password_types,timestamptz,bool)
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)"

**注意:**上述示例表明存在错误,因为您无法使用通用密码词典中的密码。

要检查密码的到期时间,请完成以下步骤:

  1. 运行以下命令,查看用户上次更改密码的时间:

    SELECT * FROM password_check.usertime WHERE user_name = 'user1';

    预期输出:

    user_name | lasttime
    ----------+----------------------------
    user1     | 2025-10-01 18:48:07.319908
    (1 row)
  2. 运行以下命令,将上次更改时间设置为 91 天前:

    UPDATE password_check.usertime
    SET lasttime = CURRENT_TIMESTAMP - INTERVAL '91 days'
    WHERE user_name = 'user1';

    预期输出:

    UPDATE 1
  3. 运行以下命令,检查上次更改时间是否已设为 91 天前:

    SELECT * FROM password_check.usertime WHERE user_name = 'user1';

    预期输出:

    user_name | lasttime
    ----------+----------------------------
    user1     | 2025-07-02 18:55:36.248913
    (1 row)
  4. 运行以下命令,测试密码到期功能:

    ALTER USER user1 WITH PASSWORD 'NewTestPass786!';

    预期输出:

    NOTICE: Password has expired. It must be changed every 90 days. Last change was on 2025-07-02 18:55:36.248913
    ALTER ROLE
  5. 运行以下命令,验证用户密码是否已更改及上次更改时间是否已更新:

    SELECT * FROM password_check.usertime WHERE user_name = 'user1';

    预期输出:

    user_name | lasttime
    ----------+----------------------------
    user1     | 2025-10-01 19:18:42.028533
    (1 row)

开启受限密码管理功能

rds.restrict_password_commands 参数设置为 1,以便仅允许授予 rds_password 角色的数据库用户管理密码。

完成以下步骤:

  1. 创建数据库集群参数组
  2. 将数据库集群参数组与您的数据库集群相关联
  3. 修改数据库集群参数组,将 rds.restrict_password_commands 设置为 1

**注意:**要应用此更改,您必须重启 Aurora PostgreSQL 兼容版主数据库实例。

使用 IAM 数据库身份验证

使用 IAM 数据库身份验证,您可以使用身份验证令牌连接到数据库集群,而无需使用密码。

要使用 IAM 数据库身份验证,请完成以下步骤:

  1. 开启 IAM 数据库身份验证
  2. 为 IAM 数据库访问创建 IAM 策略
  3. 以主用户或可以创建和授予权限的用户身份连接到数据库集群
  4. 向用户授予 rds_iam 角色
  5. 使用 IAM 身份验证连接到您的数据库集群

为 IAM 用户创建自定义密码策略

有关更多信息,请参阅为 IAM 用户设置账户密码策略

使用 Secrets Manager

使用 AWS Secrets Manager 管理主用户密码。使用 IAM 条件键强制执行 Aurora 对主用户密码的管理

有关更多信息,请参阅使用 Amazon Aurora 和 AWS Secrets Manager 进行密码管理

相关信息

了解 PostgreSQL 角色和权限

新增功能 – Amazon Aurora 和 Amazon RDS 上适用于 PostgreSQL 的可信语言扩展

AWS 官方已更新 5 个月前