PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

AFTER LOGON(Oracle) trigger w PostgreSQL z rozszerzeniem – login_hook

Zanim przejdziemy do szczegółów, dziękuję autorowi rozszerzenia „login hook” za jego opracowanie i utrzymanie.

Wielokrotnie w ćwiczeniu migracji z Oracle do Postgres widziałem użycie wyzwalacza zdarzenia bazy danych Oracle – PO ZALOGOWANIU. Jest to jedyny typ wyzwalacza zdarzeń bazy danych/użytkownika Oracle (LOGON), który jest uruchamiany, gdy użytkownik łączy się z bazą danych, zwykle używany do ustawiania środowiska użytkownika i wykonywania funkcji związanych z bezpiecznymi rolami aplikacji.

Załóżmy na przykład, że mamy użytkownika aplikacji, do którego chcieliśmy, aby łączył się z aplikacji TYLKO a nie z innych programów lub klientów (Oracle/SQL*Plus). Można to osiągnąć, tworząc wyzwalacz zdarzenia bazy danych PO ZALOGOWANIU w Oracle.

Postgres obsługuje większość standardowych wyzwalaczy, ale nie ma wyzwalacza PO ZALOGOWANIU. Aby obejść ten problem, wybrałem login_hook rozszerzenie, które wykonało swoją robotę całkiem dobrze.

Zobaczmy, co zamierzamy przekonwertować z Oracle na Postgres za pomocą rozszerzenia. W Oracle znajduje się wyzwalacz, który uniemożliwia użytkownikom aplikacji łączenie się z bazą danych z innych programów/klientów (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;

Z powyższego kodu jasno wynika, że ​​MIGUSER (użytkownik aplikacji) jest ograniczony do łączenia się przez SQL*PLUS klienta i każda próba podjęta przez użytkownika spowoduje następujący błąd:

[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

Aby obejść powyższe wymaganie, najpierw musimy skompilować rozszerzenie login_hook w Postgresie. Kroki są bardzo proste, jak każda inna kompilacja rozszerzeń

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

Teraz wszyscy jesteśmy gotowi do korzystania z tego rozszerzenia. W naszym przypadku uniemożliwimy użytkownikowi aplikacji korzystanie z klienta Postgres psql . Aby to zrobić, użyj funkcji szablonu dostępnej w login_hook stronę rozszerzenia i zmodyfikuj ją, aby przechwycić nazwę aplikacji klienta z pg_stat_activity wyświetlić i zakończyć za pomocą pg_terminate_backend() funkcja systemu. Uwaga:Możesz użyć tej samej funkcji szablonu do kilku celów do zarządzania użytkownikami aplikacji.

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;

Zobaczmy teraz, czy użytkownik aplikacji może używać Postgresa psql aby połączyć się z bazą danych.

[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()

Fajny. Jesteśmy w stanie uniemożliwić połączenia użytkowników aplikacji z dowolnym innym programem/klientem w Postgres.

Dziękuję.

–Raghaw


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kolumny MySQL z DEFAULT NULL - stylistyczny wybór, czy to prawda?

  2. Uwierzytelnianie hasła Postgres nie powiodło się

  3. Jak wstawić aktualizowalny rekord z kolumną JSON w PostgreSQL za pomocą JOOQ?

  4. Chmura Barmana – Część 1:Archiwum WAL

  5. MySQL czy PostgreSQL? Który powinienem wybrać do mojego projektu Django?