PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

AFTER LOGON(Oracle) тригер в PostgreSQL с разширение – login_hook

Преди да навлезем в подробности, благодаря на автора на разширението „кука за влизане“ за разработването и поддръжката му.

Много пъти, в упражнението за миграция на Oracle към Postgres, съм виждал използването на тригер за събитие на Oracle Database – СЛЕД ВХОДЯНЕ. Единственият му тип тригер за събитие на база данни/потребител на Oracle (LOGON), който се задейства, когато потребител се свърже с база данни, обикновено се използва за настройка на потребителската среда и изпълнение на функции, свързани със защитени роли на приложение.

Да кажем, например, че имаме потребител на приложение, където искахме да се свърже от приложението САМО а не от други програми или клиенти (Oracle/SQL*Plus). Това може да се постигне чрез създаване на тригер за събитие в базата данни СЛЕД ВХОДЯНЕ В Oracle.

Postgres поддържа повечето от стандартните тригери, но няма тригер AFTER LOGON. За заобикаляне, избрах login_hook разширение, което свърши работата доста добре.

Нека видим какво ще преобразуваме от Oracle в Postgres с помощта на разширение. В Oracle има тригер, който не позволява на потребителите на приложението да се свързват към базата данни от други програми/клиенти (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;

От горния код става ясно, че MIGUSER (потребител на приложение) е ограничен да се свързва чрез SQL*PLUS клиент и всеки опит, който потребителят направи, ще доведе до следната грешка:

[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

За да заобиколим горното изискване, първо трябва да компилираме разширението login_hook в Postgres. Стъпките са много прости като всяка друга компилация на разширения

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

Сега всички сме готови да използваме това разширение. В нашия случай ще попречим на потребителя на приложението да използва Postgres клиент psql . За да направите това, използвайте функцията за шаблон, предоставена на login_hook страница с разширение и я модифицирайте, за да улови името на приложението на клиента от pg_stat_activity прегледайте и го прекратете с помощта на pg_terminate_backend() системна функция. Забележка:Можете да използвате една и съща шаблонна функция за няколко цели, за да управлявате потребителя на приложението.

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;

Сега нека видим дали потребителят на приложението може да използва Postgres psql за да се свържете с базата данни.

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

Готино. Ние сме в състояние да предотвратим връзките на потребителите на приложението от всяка друга програма/клиент в Postgres.

Благодаря.

– Рагав


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Създаване на дъмп на база данни за конкретни таблици и записи Postgres

  2. Създайте уникално ограничение с нулеви колони

  3. Как да изберете идентификатор с група за максимална дата по категория в PostgreSQL?

  4. Rails и PostgreSQL:Ролята postgres не съществува

  5. Относно полезността на индексите на изразяване