PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

AFTER LOGON (Oracle) trigger in PostgreSQL con estensione – login_hook

Prima di entrare nei dettagli, grazie all'autore dell'estensione 'login hook' per averlo sviluppato e mantenuto.

Molte volte, nell'esercizio di migrazione da Oracle a Postgres, ho visto l'uso del trigger Oracle Database Event – ​​DOPO L'ACCESSO. È un tipo di trigger di eventi utente/database Oracle (LOGON) che si attiva quando un utente si connette a un database, in genere viene utilizzato per impostare l'ambiente utente ed eseguire funzioni associate ai ruoli dell'applicazione sicura.

Diciamo, ad esempio, che abbiamo un utente dell'applicazione a cui volevamo che si connettesse dall'applicazione SOLO e non da altri programmi o client (Oracle/SQL*Plus). Ciò può essere ottenuto creando un trigger di evento del database DOPO L'ACCESSO in Oracle.

Postgres supporta la maggior parte dei trigger standard, ma non esiste un trigger AFTER LOGON. Per risolvere il problema, ho selezionato login_hook estensione che ha fatto il lavoro abbastanza bene.

Vediamo cosa convertiremo da Oracle a Postgres con l'aiuto dell'estensione. Esiste un trigger in Oracle che impedisce agli utenti dell'applicazione di connettersi al database da altri programmi/client (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;

Dal codice sopra, è chiaro che MIGUSER (utente dell'applicazione) è limitato a connettersi tramite SQL*PLUS client e qualsiasi tentativo effettuato dall'utente risulterà nel seguente errore:

[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

Per aggirare il requisito di cui sopra, dobbiamo prima compilare l'estensione login_hook a Postgres. I passaggi sono molto semplici come qualsiasi altra compilazione di estensioni

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

Ora, siamo tutti pronti per utilizzare questa estensione. Nel nostro caso, impediremo all'utente dell'applicazione di utilizzare il client Postgres psql . Per fare ciò, usa la funzione modello fornita su login_hook pagina dell'estensione e modificarla per acquisire il nome dell'applicazione del client da pg_stat_activity visualizzalo e terminalo usando pg_terminate_backend() funzione di sistema. Nota:puoi utilizzare la stessa funzione modello per diversi scopi per gestire l'utente dell'applicazione.

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;

Ora, vediamo se l'utente dell'applicazione può utilizzare Postgres psql per connettersi al 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()

Freddo. Siamo in grado di impedire le connessioni degli utenti dell'applicazione da qualsiasi altro programma/client in Postgres.

Grazie.

–Raghav