sql >> Databasteknik >  >> RDS >> PostgreSQL

EFTER LOGON(Oracle) trigger i PostgreSQL med tillägg – login_hook

Innan du går in på detaljerna, tack till författaren av "login hook"-tillägget för att utveckla och underhålla det.

Många gånger, i Oracle till Postgres migreringsövning, har jag sett användningen av Oracle Database Event trigger – EFTER LOGON PÅ. Det är en typ av Oracle-databas/användarhändelseutlösare (LOGON) som aktiveras när en användare ansluter till en databas, vanligtvis används den för att ställa in användarmiljön och utföra funktioner som är associerade med säkra applikationsroller.

Låt oss till exempel säga att vi har en applikationsanvändare där vi ville att han skulle ansluta från applikationen ENDAST och inte från några andra program eller klienter (Oracle/SQL*Plus). Detta kan uppnås genom att skapa en databashändelseutlösare EFTER LOGON PÅ i Oracle.

Postgres stöder de flesta standardutlösare, men det finns ingen AFTER LOGON-utlösare. För att komma runt valde jag login_hook förlängning som gjorde jobbet ganska bra.

Låt oss se vad vi ska konvertera från Oracle till Postgres med hjälp av förlängning. Det finns en trigger i Oracle som hindrar applikationsanvändarna från att ansluta till databasen från andra program/klienter(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;

Från ovanstående kod är det tydligt att MIGUSER (applikationsanvändare) är begränsad att ansluta via SQL*PLUS klienten och alla försök som användaren gör kommer att resultera i följande fel:

[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

För att kringgå ovanstående krav måste vi först kompilera tillägget login_hook i Postgres. Stegen är mycket enkla som alla andra tilläggskompilering

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

Nu är vi alla redo att använda detta tillägg. I vårt fall kommer vi att förhindra applikationsanvändaren från att använda Postgres-klienten psql . För att göra detta, använd mallfunktionen som finns på login_hook tilläggssidan och ändra den för att fånga klientens applikationsnamn från pg_stat_activity visa och avsluta den med pg_terminate_backend() systemfunktion. Obs:Du kan använda samma mallfunktion för flera ändamål för att hantera applikationsanvändare.

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;

Låt oss nu se om applikationsanvändare kan använda Postgres psql för att ansluta till databasen.

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

Häftigt. Vi kan förhindra applikationsanvändarnas anslutningar från något annat program/klient i Postgres.

Tack.

–Raghav


  1. Långsam fråga när du använder ORDER BY

  2. Hur ändrar jag datatypen för en kolumn i MySQL?

  3. Kontrollera statistikmål i PostgreSQL

  4. vad är @JoinColumn och hur det används i Hibernate