1. ホーム
  2. データベース
  3. ポストグレスキュー

Postgresqlのユーザーログインエラーの回数を制限するサンプルコード

2022-01-10 07:06:46

OracleではFAILED_LOGIN_ATTEMPTSを設定することでユーザーログインのエラー回数を制限できますが、postgresqlではこの機能はサポートされていません。PostgreSQLはイベントトリガーをサポートしていますが、イベントはDDLに限定されており、ログインとログアウトのイベントにイベントトリガーを使用する方法はありません。

しかし、新しいセッションにログインすることでイベントを発生させたい場合、フックを使えば可能ですが、複雑で、クライアントサイド認証にパスワードの入力回数を判断するロジックを追加するためにカーネルのコードを修正する必要があります。ここでは、よりシンプルに同様の機能を実装する方法を紹介します。

ここでは、ログイン時に指定した関数を実行するsession_execプラグインを使用しています。

ダウンロードはこちら

https://github.com/okbob/session_exec

ダウンロード、解凍後、以下の設定が必要です。

  1. session_execset に session_preload_libraries をセットします。
  2. session_exec.login_name にログイン関数の名前を指定します。

このプラグインは、以下の機能を備えています。

  1. 関数が存在しない場合、警告を表示します。
  2. 関数の実行に失敗した場合、接続を拒否します。

このプラグインを使用すると、ユーザーのログインエラーの回数を制限するための簡単な関数を書くことができます。


1. データベースのログ情報を記録するための外部テーブルを作成します。

CREATE SERVER pglog FOREIGN DATA WRAPPER file_fdw;

CREATE FOREIGN TABLE pglog ( 
 log_time timestamp(3) with time zone, 
 user_name text, 
 database_name text, 
 process_id integer,
 connection_from text,
 session_id text, 
 session_line_num bigint, 
 command_tag text, 
 session_start_time timestamp with time zone, 
 virtual_transaction_id text, 
 transaction_id bigint, 
 error_severity text, 
 sql_state_code text, 
 message text, 
 detail text, 
 hint text, 
 internal_query text, 
 internal_query_pos integer, 
 context text, 
 query text, 
 query_pos integer, 
 location text, 
 application_name text,
 backend_type text 
) SERVER pglog 
OPTIONS ( program 'find $PGDATA/log -type f -name "*.csv" -mtime -1 -exec cat {} \;', format 'csv' ); 

2. データベースのログからログイン情報を抽出するために、t_loginテーブルを作成します。

create table t_login
(
login_time timestamp(3) with time zone --insert time,
user_name text,
flag int -- flag bit, 0 for expired data
);

ログイン情報を挿入します。

bill=# insert into t_login select log_time,user_name from pglog where command_tag='authentication' and error_severity= 'FATAL'
bill-# ;
INSERT 0 4

3. ログイン時に実行される関数を作成する

create or replace function lock_user() returns void as $$
declare
res text;
c1 timestamp(3) with time zone;
begin
select login_time from t_login where flag = 0 order by login_time desc limit 1 into c1; --get the latest time in the current log
insert into t_login select log_time,user_name from pglog where command_tag='authentication' and error_severity= 'FATAL' and log_time > c1; --insert insert the latest data into the t_login table
update t_login set flag = 1 where login_time > c1; 
for res in select user_name from t_login where flag = 1 group by user_name having count(*) >=3 --check if the number of failed login attempts is greater than 3, if greater than 3 then lock the user
loop
EXECUTE format('alter user %I nologin',res); -- lock the user
EXECUTE 'select pg_terminate_backend(pid) from pg_stat_activity where usename=$1' using res; -- break the current locked user session
raise notice 'Account % is locked!',res;
end loop;
end;
$$ language plpgsql strict;

4. 4. postgresql.conf ファイルを編集し、ログイン機能を設定します。

session_preload_libraries='session_exec'
session_exec.login_name='lock_user'

5. テスト
test1のユーザーログインエラーを3回以上再現する。

bill=# select * from t_login;
     login_time | user_name | flag 
----------------------------+-----------+------
 2020-08-26 07:26:45.42+08 | test1 | 1
 2020-08-26 07:26:50.179+08 | test1 | 1
 2020-08-26 07:26:52.487+08 | test1 | 1
 2020-08-26 07:26:54.537+08 | test1 | 1
(4 rows)

test1ユーザーでログインした場合、接続できない

pg13@cnndr4pptliot-> psql bill test1
Password for user test1: 
NOTICE: c1 = <NULL>
psql: error: could not connect to server: FATAL: terminating connection due to administrator command
CONTEXT: SQL statement "select pg_terminate_backend(pid) from pg_stat_activity where usename=$1"
PL/pgSQL function lock_user() line 13 at EXECUTE

再度ログインすると、ユーザーがロックされていることが確認できます。

pg13@cnndr4pptliot-> psql bill test1
Password for user test1: 
psql: error: could not connect to server: FATAL: role "test1" is not permitted to log in

6. ユーザーのロックを解除する
この時点でユーザーのロックを解除したい場合は、実行が必要です。

bill=# alter user test1 login;
ALTER ROLE

それから、t_loginの有効期限切れのデータも変更する必要があることに注意してください。

bill=# update t_login set flag = 0;
UPDATE 4

参考リンクです。
https://github.com/okbob/session_exec

Postgresqlの制限ユーザーログインエラーについての記事です。Postgresql limit user login errorについては、過去の記事を検索していただくか、引き続き以下の関連記事をご覧ください。