PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

AFTER LOGON(Oracle)-Trigger in PostgreSQL mit Erweiterung – login_hook

Bevor wir ins Detail gehen, vielen Dank an den Autor der Erweiterung „Login Hook“ für die Entwicklung und Pflege.

Bei der Migrationsübung von Oracle zu Postgres habe ich oft die Verwendung des Oracle Database Event-Triggers gesehen – AFTER LOGON ON. Es ist eine Art von Oracle-Datenbank-/Benutzerereignisauslöser (LOGON), der ausgelöst wird, wenn ein Benutzer eine Verbindung zu einer Datenbank herstellt, normalerweise wird er verwendet, um die Benutzerumgebung festzulegen und Funktionen auszuführen, die mit sicheren Anwendungsrollen verbunden sind.

Nehmen wir zum Beispiel an, wir haben einen Anwendungsbenutzer, bei dem wir wollten, dass er NUR von der Anwendung aus eine Verbindung herstellt und nicht von anderen Programmen oder Clients (Oracle/SQL*Plus). Dies kann erreicht werden, indem in Oracle ein Datenbankereignistrigger AFTER LOGON ON erstellt wird.

Postgres unterstützt die meisten Standardtrigger, aber es gibt keinen AFTER LOGON-Trigger. Um das Problem zu umgehen, habe ich login_hook ausgewählt Erweiterung, die den Job ziemlich gut gemacht hat.

Mal sehen, was wir mit Hilfe der Erweiterung von Oracle zu Postgres konvertieren werden. Es gibt einen Auslöser in Oracle, der die Anwendungsbenutzer daran hindert, sich von anderen Programmen/Clients (sqlplus) aus mit der Datenbank zu verbinden.

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;

Aus dem obigen Code geht hervor, dass MIGUSER (Anwendungsbenutzer) darf sich nur über SQL*PLUS verbinden Client und jeder Versuch des Benutzers führt zu folgendem Fehler:

[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

Um die obige Anforderung zu umgehen, müssen wir zuerst die Erweiterung login_hook kompilieren in Postgres. Die Schritte sind sehr einfach wie bei jeder anderen Erweiterungskompilierung

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

Jetzt sind wir bereit, diese Erweiterung zu verwenden. In unserem Fall verhindern wir, dass der Anwendungsbenutzer den Postgres-Client psql verwendet . Verwenden Sie dazu die Vorlagenfunktion, die auf login_hook bereitgestellt wird -Erweiterungsseite und ändern Sie sie, um den Anwendungsnamen des Clients aus pg_stat_activity zu erfassen ansehen und mit pg_terminate_backend() beenden Systemfunktion. Hinweis:Sie können dieselbe Vorlagenfunktion für mehrere Zwecke verwenden, um Anwendungsbenutzer zu verwalten.

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;

Sehen wir uns nun an, ob der Anwendungsbenutzer Postgres psql verwenden kann um sich mit der Datenbank zu verbinden.

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

Cool. Wir sind in der Lage, die Verbindungen der Anwendungsbenutzer von anderen Programmen/Clients in Postgres zu verhindern.

Danke.

–Raghav