Uso de enlaces de PostgreSQL con sus extensiones TLE
Un enlace es un mecanismo de devolución de llamada disponible en PostgreSQL que permite a los desarrolladores llamar a funciones personalizadas u otras rutinas durante las operaciones normales de la base de datos. El kit de desarrollo de TLE admite enlaces de PostgreSQL para que pueda integrar funciones personalizadas con el comportamiento de PostgreSQL en el tiempo de ejecución. Por ejemplo, puede utilizar un enlace para asociar el proceso de autenticación a su propio código personalizado o para modificar el proceso de planificación y ejecución de consultas según sus necesidades específicas.
Sus extensiones TLE pueden utilizar enlaces. Si un enlace tiene un alcance global, se aplica a todas las bases de datos. Por lo tanto, si su extensión TLE usa un enlace global, debe crear su extensión TLE en todas las bases de datos a las que puedan acceder sus usuarios.
Cuando usa la extensión pg_tle
para crear sus propias Extensiones de lenguaje de confianza, puede usar los enlaces disponibles de una API de SQL para crear las funciones de su extensión. Debe registrar cualquier enlace con pg_tle
. Para algunos enlaces, es posible que también tenga que establecer varios parámetros de configuración. Por ejemplo, el enlace de retención passcode
se puede configurar como activado, desactivado u obligatorio. Para obtener más información sobre los requisitos específicos de los enlaces pg_tle
disponibles, consulte Referencia de enlaces para Extensiones de lenguaje de confianza para PostgreSQL.
Ejemplo: Crear una extensión que utilice un enlace de PostgreSQL
El ejemplo descrito en esta sección utiliza un enlace de PostgreSQL para comprobar la contraseña proporcionada durante operaciones SQL específicas e impide que los usuarios de la base de datos establezcan sus contraseñas iguales a las que figuran en la tabla password_check.bad_passwords
. La tabla contiene las diez opciones de contraseñas más utilizadas, pero fáciles de descifrar.
Para configurar este ejemplo en su instancia de base de datos de RDS para PostgreSQL, ya tiene que tener Extensiones de lenguaje de confianza instalado. Para obtener más información, consulte Configuración de Extensiones de lenguaje de confianza en su instancia de base de datos de RDS para PostgreSQL.
Para configurar el ejemplo del enlace de verificación de contraseñas
Use
psql
para conectarse a la Instancia de base de datos RDS para PostgreSQL.psql --host=
db-instance-123456789012
.aws-region
.rds.amazonaws.com --port=5432
--username=postgres
--password --dbname=labdb
Copie el código de la Lista de códigos del enlace password_check y péguelo en su base de datos.
SELECT pgtle.install_extension ( 'my_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 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 common password dictionary'; END IF; 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_$ );
Cuando la extensión se haya cargado en la base de datos, verá un resultado como el siguiente.
install_extension ------------------- t (1 row)
Mientras siga conectado a la base de datos, ya podrá crear la extensión.
CREATE EXTENSION my_password_check_rules;
Puede confirmar que la extensión se ha creado en la base de datos mediante el siguiente metacomando
psql
.\dx
List of installed extensions Name | Version | Schema | Description -------------------------+---------+------------+------------------------------------------------------------- my_password_check_rules | 1.0 | public | Prevent use of any of the top-ten most common bad passwords pg_tle | 1.0.1 | pgtle | Trusted-Language Extensions for PostgreSQL plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language (3 rows)
Abra otra sesión de terminal para trabajar con la AWS CLI. Debe modificar su grupo de parámetros de base de datos personalizado para activar el enlace de verificación de contraseñas. Para ello, utilice el comando modify-db-parameter-group de la CLI tal como se muestra en el siguiente ejemplo.
aws rds modify-db-parameter-group \ --region
aws-region
\ --db-parameter-group-nameyour-custom-parameter-group
\ --parameters "ParameterName=pgtle.enable_password_check,ParameterValue=on,ApplyMethod=immediate"Cuando el parámetro se haya activado correctamente, verá un resultado como el siguiente.
( "DBParameterGroupName": "docs-lab-parameters-for-tle" }
Puede que el cambio en la configuración del grupo de parámetros tarde unos minutos en aplicarse. Sin embargo, este parámetro es dinámico, por lo que no es necesario reiniciar la instancia de base de datos de RDS para PostgreSQL para que la configuración surta efecto.
Abra la sesión
psql
y consulte la base de datos para comprobar que el enlace password_check esté activado.labdb=>
SHOW pgtle.enable_password_check;pgtle.enable_password_check ----------------------------- on (1 row)
El enlace password-check ahora está activo. Puede probarlo creando un rol nuevo y utilizando una de las contraseñas incorrectas, tal como se muestra en el siguiente ejemplo.
CREATE ROLE test_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 21 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)"
El resultado se ha modificado para que se pueda leer.
El siguiente ejemplo muestra que el comportamiento \password
del metacomando interactivo pgsql
también se ve afectado por el enlace password_check.
postgres=>
SET password_encryption TO 'md5';SET
postgres=>
\passwordEnter new password for user "postgres":
*****
Enter it again:
*****
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 12 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)"
Puede eliminar esta extensión TLE y desinstalar sus archivos de código fuente si lo desea. Para obtener más información, consulte Eliminar las extensiones TLE de una base de datos.
Lista de códigos del enlace password_check
El código de ejemplo que se muestra aquí define la especificación de la extensión TLE my_password_check_rules
. Al copiar este código y pegarlo en la base de datos, el código de la extensión my_password_check_rules
se carga en la base de datos y el enlace password_check
queda registrado para que lo utilice la extensión.
SELECT pgtle.install_extension ( 'my_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 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 common password dictionary'; END IF; 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_$ );