Wer war das ...? Auditing in APEX-Anwendungen ...?

Immer mehr Anwendungen stehen mittlerweile vor der Anforderung, dass Tabellenzugriffe auditiert werden müssen. Jede Operation muss also mitgeloggt werden. Während dies für DML-Anweisungen (INSERT, UPDATE, DELETE) mit einfachen Mitteln (Trigger) realisierbar wäre, stellt sich dies für SELECT-Anweisungen auf den ersten Blick etwas komplizierter dar, denn einen SELECT-Trigger gibt es nicht ...

Hier kommen die Auditing-Möglichkeiten der Datenbank ins Spiel. Mit dem Kommando AUDIT SELECT ON {Tabellenname} wird Auditing von Abfragen für eine bestimmte Tabelle aktiviert und im sog. Audit-Trail der Datenbank mitgeschrieben. Allerdings werden hier keine APEX-spezifischen Informationen mitgeschrieben, was bedeutet, dass alle durch APEX ausgeführten Operationen unter den Datenbankuser APEX_PUBLIC_USER erfasst werden (der tatsächlich angemeldete Datenbankuser ist bei allen APEX Sitzungen stets APEX_PUBLIC_USER oder ANONYMOUS, wenn Sie das PL/SQL Embedded Gateway nutzen). Diese Informationen sind zuwenig; für ein wirkungsvolles Auditing werden auch die APEX-spezifischen Informationen benötigt.

Daher soll das Standard-Auditing hier gar nicht weiter betrachtet werden; dieser Tipp beschäftigt sich mit dem wesentlich mächtigeren Fine-Grained Auditing ; dieses erlaubt mit wenigen Eingriffen das Loggen der für APEX relevanten Informationen wie dem APEX-Usernamen, der APEX-Applikations-ID oder der Session-ID. Darüber hinaus erlaubt Fine-Grained Auditing (wie der Name schon vermuten lässt) eine feingranulare Einrichtung des Auditings. Es wird nicht einfach nur die Tabelle EMP auditiert, sondern bspw. die Spalten SAL und COMM und dies nur für die Zeilen mit der DEPTNO=20.

Fine-Grained Auditing ist Bestandteil der Enterprise Edition der Datenbank; wenn Sie also mit einer Standard-Edition oder einer OracleXE arbeiten, können Sie diesen Tipp nicht nachvollziehen.

Die folgenden Schritte zeigen, wie ein Auditing für die Tabelle EMP aufgesetzt wird. Sobald die Spalten SAL oder COMM von Mitarbeitern mit DEPTNO = 20 abgefragt werden, soll ein Log-Eintrag geschrieben werden.

Bestimmte Informationen wie der Datenbank-Username, die Datenbanksession oder die ID des Betriebssystem-Prozesses werden von Fine-Grained Auditing automatisch mitgeschrieben; für die APEX-spezifischen Details muss ein sog. Handler eingerichtet werden, welcher diese Informationen in eine eigene Tabelle schreibt. Diese Tabelle legen wir zunächst wie folgt an ...

create table apex_audit_log (
  audit_entryid  number,
  db_session     number,
  zeitpunkt      timestamp,
  apex_user      varchar2(200),
  apex_app       number,
  apex_page      number,
  apex_session   number,
  ip_address     varchar2(200)
)
/

Die Spalten AUDIT_ENTRYID und DB_SESSION dienen zum späteren Join mit der View DBA_FGA_AUDIT_TRAIL, welche die standardmäßig mitgeloggten Audit-Informationen enthält. Als nächstes wird eine PL/SQL-Prozedur benötigt, welche Einträge in diese Tabelle schreibt. Diese PL/SQL-Prozedur wird später von Fine-Grained Auditing automatisch aufgerufen, daher müssen die Parameter (die Signatur) stets wie hier vorgestellt aussehen.

create or replace procedure do_apex_audit_log (
  schema varchar2,
  object varchar2,
  policy varchar2
) AS
  v_ipaddr varchar2(20);
BEGIN
  -- IP-Adresse des Browsers feststellen
  -- Achtung: Wenn der Browser durch einen Proxyserver kommt, 
  --          wird nur dessen Adresse ermittelt
  begin
    v_ipaddr := owa_util.get_cgi_env('REMOTE_ADDR');
  exception 
    when others then v_ipaddr := null;
  end;
  -- Eintragen ...
  insert into apex_audit_log 
   (db_session, audit_entryid, zeitpunkt, apex_user, apex_app, apex_page, apex_session, ip_address)
  values (
    -- Session ID der DATENBANK (nicht die der APEX-Session)
    sys_context('userenv','sessionid'), 
    -- Entry-ID für Join mit Standard Audit-Trail
    sys_context('userenv','entryid'), 
    -- Zeitpunkt des Eintrags
    systimestamp, 
    -- APEX-Userid
    v('APP_USER'), 
    -- APEX Applikations ID
    v('APP_ID'), 
    -- APEX-Seite
    v('APP_PAGE_ID'), 
    -- APEX-Session-ID
    v('SESSION'), 
    -- oben ermittelte IP-Adresse
    v_ipaddr
  );
END do_apex_audit_log;
/
sho err

Bis hierhin ist dies allerdings noch eine gewöhnliche PL/SQL-Prozedur - das ändert sich, wenn als nächstes die Auditing-Policy aktiviert wird. Damit wird die Prozedur "scharf" geschaltet und von nun an automatisch bei jedem SELECT auf die EMP-Tabelle ausgeführt ... wenn ...

  • Die Zeilen der DEPTNO 20 betroffen sind und
  • Eine APEX-Session aktiv ist, also die APEX-Variable APP_USER gesetzt ist
BEGIN
 DBMS_FGA.ADD_POLICY (
  object_schema      =>  '{Name des APEX-Parsing Schemas}', 
  object_name        =>  'EMP', 
  policy_name        =>  'APEX_AUDIT_EMP_SAL', 
  audit_condition    =>  'deptno = 20 and v(''APP_USER'') is not null', 
  audit_column       =>  'sal,comm', 
  handler_schema     =>  '{Name des APEX-Parsing Schemas}', 
  handler_module     =>  'DO_APEX_AUDIT_LOG', 
  enable             =>   TRUE, 
  statement_types    =>  'SELECT', 
  audit_trail        =>   DBMS_FGA.DB + DBMS_FGA.EXTENDED,
  audit_column_opts  =>   DBMS_FGA.ANY_COLUMNS
 ); 
END;
/
sho err

Probieren Sie es aus. Setzen Sie zunächst mit SQL*Plus ein SELECT auf die Tabelle EMP ab und achten Sie darauf, dass Zeilen der DEPTNO 20 betroffen sind. Die Tabelle APEX_AUDIT_LOG bleibt leer; es lag ja keine APEX Session vor.

Erzeugen Sie nun eine APEX-Applikation mit einem Bericht auf die Tabelle EMP und führen Sie diesen aus. Anschließend sollten Sie Einträge in der Tabelle finden ...

Einträge in der Tabelle "APEX_AUDIT_LOG"
Abbildung 1: "Einträge in der Tabelle "APEX_AUDIT_LOG""

An diesen Einträgen ist schon erkennbar, dass der APEX-User ADMIN zum gegebenen Zeitpunkt aus Applikation 136, Seite 3 einen Audit-Eintrag ausgelöst hat. Diese Information lässt sich nun mit den standardmäßig mitgeschriebenen Einträgen kombinieren ...

select 
  ap.zeitpunkt,
  ap.apex_user,
  ap.apex_app,
  ap.apex_page,
  ap.apex_session,
  au.sql_text,
  au.sql_bind,
  au.scn,
  au.object_name
from apex_audit_log ap, sys.dba_fga_audit_trail au
where ap.audit_entryid = au.entryid
and ap.db_session = au.session_id

An den Spalten SQL_TEXT und SQL_BIND kann sogar die jeweilige SQL-Abfrage und die übergebenen Parameter erkannt werden; man kann die durch die APEX-Applikation getätigte Abfrage also sehr genau nachvollziehen.

Kombination der Einträge in der Tabelle "APEX_AUDIT_LOG" mit dem Standard-Audit-Trail
Abbildung 2: Kombination der Einträge in der Tabelle "APEX_AUDIT_LOG" mit dem Standard-Audit-Trail

Mit dieser SQL-Abfrage ließe sich nun abschließend wiederum eine APEX-Applikation erstellen, die für dann bspw. dem Datenschutzbeauftragten bereitgestellt wird; dieser kann somit -stets online- die Einhaltung der ggfs. bestehenden Datenschutzrichtlinien überprüfen. Beachten Sie dabei nur, dass eine solche Anwendung das Audit-Trail lesen können muss. Die Bereitstellung der Informationen an ein Datenbankschema COMPLIANCE_APP könnte dann wie folgt aussehen:

create or replace view audit_info as
select 
  ap.zeitpunkt,
  ap.apex_user,
  ap.apex_app,
  ap.apex_page,
  ap.apex_session,
  au.sql_text,
  au.sql_bind,
  au.object_name
from apex_audit_log ap, sys.dba_fga_audit_trail au
where ap.audit_entryid = au.entryid
and ap.db_session = au.session_id
/

grant select on audit_info to compliance_app

Mehr Informationen zu Auditing in der Datenbank finden Sie ...

Zurück zur Community-Seite