Sebelum membahas detailnya, terima kasih kepada penulis ekstensi 'login hook' yang telah mengembangkan dan memeliharanya.
Sering kali, dalam latihan migrasi Oracle ke Postgres, saya telah melihat penggunaan pemicu Oracle Database Event – SETELAH LOGON. Ini adalah salah satu jenis Oracle database/user event trigger (LOGON) yang diaktifkan ketika pengguna terhubung ke database, biasanya digunakan untuk mengatur lingkungan pengguna dan melakukan fungsi yang terkait dengan peran aplikasi yang aman.
Katakanlah, misalnya, kita memiliki pengguna aplikasi tempat kita ingin dia terhubung dari aplikasi HANYA dan bukan dari program atau klien lain (Oracle/SQL*Plus). Ini dapat dicapai dengan membuat pemicu peristiwa database SETELAH LOGON ON di Oracle.
Postgres mendukung sebagian besar pemicu standar, tetapi tidak ada pemicu AFTER LOGON. Untuk mengatasinya, saya memilih login_hook
ekstensi yang melakukan pekerjaan dengan cukup baik.
Mari kita lihat apa yang akan kita konversi dari Oracle ke Postgres dengan bantuan ekstensi. Ada pemicu di Oracle yang mencegah pengguna aplikasi terhubung ke database dari program/klien lain (sqlplus).
CREATE OR REPLACE TRIGGER program_restrict
AFTER LOGON ON DATABASE
BEGIN
FOR x IN (SELECT username, program FROM SYS.v_$session WHERE audsid = USERENV ('sessionid'))
LOOP
IF LTRIM (RTRIM (x.username)) = 'MIGUSER' AND UPPER(substr(x.program,1,7)) = 'SQLPLUS'
THEN
raise_application_error(-20999,'Not authorized to use in the Production environment!');
END IF;
END LOOP;
END program_restrict;
Dari kode di atas, jelas bahwa MIGUSER
(pengguna aplikasi) dibatasi untuk terhubung melalui SQL*PLUS
klien dan upaya apa pun yang dilakukan pengguna akan menghasilkan kesalahan berikut:
[oracle@rrr ~]$ rlsqlplus miguser/miguser
... <trimmed banner>
ERROR:
ORA-04088: error during execution of trigger 'SYS.PROGRAM_RESTRICT'
ORA-00604: error occurred at recursive SQL level 1
ORA-20999: Not authorized to use in the Production environment!
ORA-06512: at line 6
ORA-06512: at line 6
Untuk mengatasi persyaratan di atas, pertama-tama kita perlu mengkompilasi ekstensi login_hook
di Postgres. Langkah-langkahnya sangat sederhana seperti kompilasi ekstensi lainnya
--Download zip/Git clone the extension
https://github.com/splendiddata/login_hook
-- Set the pg_config in your path
[root@node1-centos8 ~]# export PATH=/usr/pgsql-13/bin:$PATH
-- change to login_hook directory and run make/make install
[root@node1-centos8 ~]# cd login_hook
[root@node1-centos8 login_hook]# make
[root@node1-centos8 login_hook]# make install
-- add the login_hook.so to session_preload_libraries and restart the database
[root@node1-centos8 ~]# grep -i session_preload /var/lib/pgsql/13/data/postgresql.conf
session_preload_libraries = 'login_hook'
[root@node1-centos8 ~]# systemctl restart postgresql-13.service
-- connect to the database and create the extension
[postgres@node1-centos8 ~]$ psql
psql (13.1)
Type "help" for help.
postgres=# create extension login_hook;
CREATE EXTENSION
Sekarang, kita siap untuk menggunakan ekstensi ini. Dalam kasus kami, kami akan mencegah pengguna aplikasi menggunakan klien Postgres psql . Untuk melakukannya, gunakan fungsi template yang disediakan di login_hook
halaman ekstensi dan memodifikasinya untuk menangkap nama aplikasi klien dari pg_stat_activity lihat dan hentikan menggunakan pg_terminate_backend() fungsi sistem. Catatan:Anda dapat menggunakan fungsi template yang sama untuk beberapa tujuan untuk mengelola pengguna aplikasi.
CREATE OR REPLACE FUNCTION login_hook.login() RETURNS VOID LANGUAGE PLPGSQL AS $$
DECLARE
ex_state TEXT;
ex_message TEXT;
ex_detail TEXT;
ex_hint TEXT;
ex_context TEXT;
rec record;
BEGIN
IF NOT login_hook.is_executing_login_hook()
THEN
RAISE EXCEPTION 'The login_hook.login() function should only be invoked by the login_hook code';
END IF;
BEGIN
for rec in select pid,usename,application_name from pg_stat_activity where application_name ilike 'psql%'
loop
if rtrim(rec.usename) = 'miguser' and rtrim(rec.application_name) = 'psql' then
raise notice 'Application users(%) restricted to connect with any clients(%)',rec.usename,rec.application_name;
perform pg_terminate_backend(rec.pid);
end if;
end loop;
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS ex_state = RETURNED_SQLSTATE
, ex_message = MESSAGE_TEXT
, ex_detail = PG_EXCEPTION_DETAIL
, ex_hint = PG_EXCEPTION_HINT
, ex_context = PG_EXCEPTION_CONTEXT;
RAISE LOG e'Error in login_hook.login()\nsqlstate: %\nmessage : %\ndetail : %\nhint : %\ncontext : %'
, ex_state
, ex_message
, ex_detail
, ex_hint
, ex_context;
END ;
END$$;
-- Give exeuction grant on the function.
GRANT EXECUTE ON FUNCTION login_hook.login() TO PUBLIC;
Sekarang, mari kita lihat apakah pengguna aplikasi dapat menggunakan Postgres psql
untuk terhubung ke database.
[postgres@node1-centos8 ~]$ psql -U miguser -d postgres -p 5432
NOTICE: Application users(miguser) restricted to connect with any clients(psql)
psql: error: FATAL: terminating connection due to administrator command
CONTEXT: SQL statement "SELECT pg_terminate_backend(rec.pid)"
PL/pgSQL function login_hook.login() line 20 at PERFORM
SQL statement "select login_hook.login()
Dingin. Kami dapat mencegah koneksi pengguna aplikasi dari program/klien lain di Postgres.
Terima kasih.
–Raghav