Usar ganchos do PostgreSQL com suas extensões TLE - Amazon Aurora

Usar ganchos do PostgreSQL com suas extensões TLE

Um gancho é um mecanismo de retorno de chamada disponível no PostgreSQL que possibilita aos desenvolvedores chamar funções personalizadas ou outras rotinas durante operações regulares de banco de dados. O kit de desenvolvimento TLE é compatível com ganchos do PostgreSQL para que você possa integrar funções personalizadas com o comportamento do PostgreSQL no ambiente de execução. Por exemplo, você pode usar um gancho para associar o processo de autenticação ao seu próprio código personalizado ou modificar o processo de planejamento e execução de consultas de acordo com suas necessidades específicas.

Suas extensões TLE podem usar ganchos. Se um gancho tiver escopo global, ele se aplicará a todos os bancos de dados. Portanto, se sua extensão TLE usar um gancho global, você precisará criar sua extensão TLE em todos os bancos de dados que seus usuários puderem acessar.

Ao usar a extensão pg_tle para criar seu próprio Trusted Language Extensions, você pode usar os ganchos disponíveis de uma API SQL para criar as funções de sua extensão. Você deve registrar todos os ganchos com pg_tle. Para alguns ganchos, talvez você também precise definir vários parâmetros de configuração. Por exemplo, o gancho de verificação passcode pode ser configurado como ativado, desativado ou obrigatório. Para obter mais informações sobre os requisitos específicos dos ganchos pg_tle disponíveis, consulte Referência de ganchos para Trusted Language Extensions para PostgreSQL.

Exemplo: Criar uma extensão que use um gancho do PostgreSQL

O exemplo abordado nesta seção usa um gancho do PostgreSQL para conferir a senha fornecida durante operações específicas de SQL e impede que os usuários do banco de dados definam suas senhas como qualquer uma das contidas na tabela password_check.bad_passwords. A tabela contém as dez opções de senhas mais usadas, mas facilmente identificáveis.

Para configurar esse exemplo em seu cluster de banco de dados do Aurora PostgreSQL, você já deve ter instalado o Trusted Language Extensions. Para obter detalhes, consulte Configurar o Trusted Language Extensions em seu cluster de banco de dados do Aurora PostgreSQL.

Como configurar o exemplo de gancho de verificação de senha
  1. Use o psql para se conectar à instância de gravador do cluster de banco de dados do Aurora PostgreSQL.

    psql --host=db-instance-123456789012.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password --dbname=labdb
  2. Copie o código do Lista de códigos do gancho de verificação de senha e cole-o no banco de dados.

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

    Quando a extensão for carregada em seu banco de dados, você verá uma saída como a seguinte.

    install_extension ------------------- t (1 row)
  3. Enquanto ainda estiver conectado ao banco de dados, agora você poderá criar a extensão.

    CREATE EXTENSION my_password_check_rules;
  4. Você pode confirmar que a extensão foi criada no banco de dados usando o metacomando psql a seguir.

    \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)
  5. Abra outra sessão do terminal para trabalhar com o AWS CLI. Você precisa modificar seu grupo de parâmetros de banco de dados personalizado para ativar o gancho de verificação de senha. Para isso, use o comando modify-db-parameter-group da CLI, conforme mostrado no exemplo a seguir.

    aws rds modify-db-parameter-group \ --region aws-region \ --db-parameter-group-name your-custom-parameter-group \ --parameters "ParameterName=pgtle.enable_password_check,ParameterValue=on,ApplyMethod=immediate"

    Poderá levar alguns minutos para que a alteração na configuração do grupo de parâmetros tenha efeito. No entanto, esse parâmetro é dinâmico, portanto, você não precisa reiniciar a instância de gravador do cluster de banco de dados do Aurora PostgreSQL para que a configuração tenha efeito.

  6. Abra a sessão psql e consulte o banco de dados para verificar se o gancho password_check foi ativado.

    labdb=> SHOW pgtle.enable_password_check; pgtle.enable_password_check ----------------------------- on (1 row)

O gancho de verificação de senha agora está ativo. É possível testá-lo criando uma função e usando uma das senhas incorretas, conforme mostrado no exemplo a seguir.

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

A saída foi formatada para facilitar a leitura.

O exemplo a seguir mostra que o comportamento do metacomando interativo pgsql \password também é afetado pelo gancho password_check.

postgres=> SET password_encryption TO 'md5'; SET postgres=> \password Enter 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)"

Você poderá descartar essa extensão TLE e desinstalar seus arquivos de origem, se desejar. Para ter mais informações, consulte Descartar suas extensões TLE de um banco de dados.

Lista de códigos do gancho de verificação de senha

O código de exemplo mostrado aqui define a especificação da extensão TLE my_password_check_rules. Quando você copia esse código e o cola em seu banco de dados, o código da extensão my_password_check_rules é carregado no banco de dados e o gancho password_check é registrado para uso pela extensão.

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