Saltar al contenido

¿Cómo administro la complejidad y la caducidad de las contraseñas para las conexiones de clústeres de bases de datos compatibles con Aurora PostgreSQL?

7 minutos de lectura
0

Quiero administrar la complejidad y la caducidad de las contraseñas de las conexiones a un clúster de bases de datos (DB) compatible con una edición de Amazon Aurora PostgreSQL.

Descripción corta

Para administrar las contraseñas de tu clúster de base de datos compatible con Aurora PostgreSQL, puedes usar los siguientes métodos:

Resolución

Uso de un enlace de verificación de contraseñas con una TLE

Para usar un enlace de verificación de contraseñas con una TLE, primero debes configurar la TLE en tu clúster de base de datos compatible con Aurora PostgreSQL. Luego, crea el enlace de verificación de contraseñas

Nota: Cuando asignas un nombre al enlace, no puedes usar user-password-check-rules.

Ejemplo de un código de enlace de verificación de contraseñas:

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_$
);

Nota: Modifica el código según tus requisitos. Por ejemplo, puedes agregar más contraseñas a la tabla bad_passwords, cambiar la longitud requerida de la contraseña o comprobar la complejidad de la contraseña. 

Para comprobar si una contraseña cumple los requisitos de longitud, ejecuta el siguiente comando:

CREATE ROLE user1 PASSWORD '123456';

Resultado esperado:

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)"

Nota: El ejemplo anterior muestra un error porque la contraseña debe tener al menos 8 caracteres.

Para comprobar si una contraseña es demasiado común, ejecuta el siguiente comando:

CREATE ROLE user1 PASSWORD 'password';

Resultado esperado:

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)"

Nota: El ejemplo anterior muestra un error porque no puedes usar contraseñas del diccionario de contraseñas común.

Para comprobar la caducidad de la contraseña, sigue estos pasos:

  1. Ejecuta el siguiente comando para comprobar cuándo fue la última vez que un usuario cambió una contraseña:

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

    Resultado esperado:

    user_name | lasttime
    ----------+----------------------------
    user1     | 2025-10-01 18:48:07.319908
    (1 row)
  2. Ejecute el siguiente comando para establecer que la última vez tenga 91 días:

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

    Resultado esperado:

    UPDATE 1
  3. Ejecuta el siguiente comando para comprobar que la última vez fue hace 91 días:

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

    Resultado esperado:

    user_name | lasttime
    ----------+----------------------------
    user1     | 2025-07-02 18:55:36.248913
    (1 row)
  4. Ejecuta el siguiente comando para probar la función de caducidad de la contraseña:

    ALTER USER user1 WITH PASSWORD 'NewTestPass786!';

    Resultado esperado:

    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. Ejecuta el siguiente comando para comprobar que la contraseña de usuario ha cambiado y cuándo se ha actualizado por última vez:

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

    Resultado esperado:

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

Activación de la función de administración de contraseñas restringidas

Establece el parámetro rds.restrict_password_commands en 1 para que solo los usuarios de la base de datos a los que concedas el rol rds_password puedan administrar las contraseñas.

Sigue estos pasos:

  1. Crea un grupo de parámetros de clúster de base de datos.
  2. Asocia el grupo de parámetros del clúster de base de datos a tu clúster de base de datos.
  3. Modifica el grupo de parámetros del clúster de base de datos para establecer rds.restrict_password_commands en 1.

Nota: Para aplicar el cambio, debes reiniciar la instancia de base de datos principal compatible con Aurora PostgreSQL.

Uso de la autenticación de bases de datos de IAM

Con la autenticación de bases de datos de IAM, debes utilizar un token de autenticación para conectarte al clúster de base de datos en lugar de una contraseña.

Para usar la autenticación de bases de datos de IAM, sigue estos pasos:

  1. Activa la autenticación de bases de datos de IAM.
  2. Crea una política de IAM para el acceso a la base de datos de IAM.
  3. Conéctate al clúster de base de datos como usuario principal o como usuario que pueda crear y conceder permisos.
  4. Concede a tus usuarios el rol rds_iam.
  5. Usa la autenticación de IAM para conectarte a tu clúster de base de datos.

Creación de una política de contraseñas personalizada para los usuarios de IAM

Para obtener más información, consulta Configuración de una política de contraseñas de cuenta para usuarios de IAM.

Uso de Secrets Manager

Utiliza AWS Secrets Manager para administrar las contraseñas de los usuarios principales. Utiliza las claves de condición de IAM para aplicar la administración de Aurora de las contraseñas de los usuarios principales.

Para obtener más información, consulta Administración de contraseñas con Amazon Aurora y AWS Secrets Manager.

Información relacionada

Información sobre los roles y permisos de PostgreSQL

Nuevo: Extensiones de lenguaje de confianza para PostgreSQL en Amazon Aurora y Amazon RDS

OFICIAL DE AWSActualizada hace 5 meses