Benutzer-Werkzeuge

Webseiten-Werkzeuge


dba:unified_auditing_oracle_migration_23ai

Oracle Unified Auditing – Pflicht in 23ai - Umstellung von Klassischen/Mixed Audit auf Unified Auditing in der 19c als Vorbereitung für die 23ai Migration

Aufgabe Sicherheit und Compliance zukunftsfähig machen – den Umstieg auf Oracle 23ai rechtzeitig vorbereiten.

Mit Oracle 23ai ist Unified Auditing verpflichtend. Eine Migration auf 23ai oder höher ist nur möglich, wenn bereits jetzt unter Oracle 19c auf Unified Auditing umgestellt wird.

Doch viele produktive 19c-Systeme verwenden nach wie vor klassisches oder Mixed Auditing – was zu Problemen bei Upgrade und Compliance in Zukunft führen kann.

Das Oracle Unified Auditing wurde mit der Oracle Database 12cR1 eingeführt.

Unified Auditing ist eine Kernel‑Eigenschaft des ORACLE_HOME – also immer ORACLE_HOME‑weit, nicht datenbank-spezifisch. D.h alle Instanzen aus dem selben Oracle Home müssen zusammen umgestellt werden!

Im ersten Schritt werden daher in allen Datenbank erstmal der klassische Audit Log „gepflegt“ und das Audit in einen eigenen Tablespace umgezogen für beide Methoden.

Das kann online bei nicht so kritischen System erfolgen, auch das Verkleinern des SYSAUX Tablespace ist online möglich solange nicht andere Objekte in dem Tablespace das verhindern.

Für die Pflege der Logs werden die notwendigen Jobs angelegt und in die Überwachung integriert.

Dann wird eine Audit Policy für die drei Typen (DEV / QS / Prod) der Datenbank nach dem Firmen Vorschriften erarbeitet, diese ersetzt dann später alle „alten“ Audit Regeln / default Policies.

Wenn das alles vorbereitet ist, wird die erste Datenbank komplett umgestellt, da dazu eine Downtime notwendig ist bietet sich das an mit einem geplanten Patch zu kombinieren.

Alle weiteren System werden dann nach dem gleichen Muster umgestellt.

Der große Verteil ist dann am Ende das über die Tabelle „UNIFIED_AUDIT_TRAIL“ alle Audits der Datenbank ausgelesen werden kann.

Soll ein eigener DB User die Verwaltung und Kontrolle der Audit Tabellen übernehmen, muss diesem die Rolle „AUDIT_ADMIN“ vergeben werden.

Leider muss nach jeden Patch geprüft werden ob der Oracle Kernel auch wieder mit Unified Auditing gelinkt wurde bzw. unter Windows ob die DDL auch wirklich mit aktualisiert wird! Hat das nicht geklappt einen Bug eröffnen um hier sanften Druck auf Oracle auszuüben, das auch bei jeden Path zu beachten! Je neuer die Versionen um so besser scheint es aber zu klappen.

Ablauf:

  1. Prüfen ob sich die 19c im Mixed Mode befindet und den Audit Status ermitteln
  2. Downtime 1 – DEV/QS online - in Prod mit mehr Vorsicht! Besser ohne die Applikation im Live Betrieb- Gefahr eines Locks auf der DB!!
    1. Audit Tabellen (Klassich und Unified ) in eigenen Tablespace umziehen
    2. Bei Bedarf SYSAUX Tablespace verkleinern, wenn noch möglich
    3. Lösch Jobs für die Logs erstellen
  3. Einstellungen des Klassischen Auditing in Unified Audit Policy umwandeln bzw. eigene Policy definieren
  4. Prüfen ob Lösch Jobs angelegt wurden bzw. aktiveren, Aufbewahrung Dauer einstellen
  5. Prüfen wer die Audit Daten verwendet und ob „etwas“ die Audits aus der Datenbank ließt
    1. Falls im Einsatz Überwachungstools entsprechend umstellen bzw. Umstellung für die Downtime planen
  6. Downtime 2 - Kann nur offline erfolgen!
    1. Umstellen auf Unified Auditing
      1. Linux : Relink Kernel
      2. Windows: Umbennen einer DDL
    2. Überwachungstools anpassen bei Bedarf
  7. Aufräumen
  8. Lösch Jobs überwachen
    1. Leider hat Oracle das am Ende in 19c nicht ganz konsequent umgesetzt, es ist im Detail genau darauf zu achten in welcher Ebenen (klassisch / Unified) man unterwegs ist und welche interne View auch wirklich den nun gültigen Zustand zeigt!

Abschätzung des Zeitaufwandes pro Datenbank:

  • Einmalig: Audit Policy erstellen und Skripte für die einzelnen Schritte verbreiten/testen 8-12h technisch
  • Fachlich Absprache mit Entwicklung/Compliance/Security xxxxh

~8-12h

  • Status Prüfen / Anlegen Audit Tablespace / Umzug auf eigenen Tablespace - ~2h
  • Jobs anlegen und prüfen - 0.5h
  • Neue Audit Policy ausrollen (aber nicht aktiveren!!) - 0,5h
  • Umstellen der DB während einer geplanten Downtime mit Aktivierung der Policy - ~1h
  • Kontrolle Job Verhalten / Optimierung / Aufräum-Arbeiten / Dokumentieren etc. - ~2h

~4-5h

Argumente für eine Umstellung

  • Standardisierung der Umgebung
  • Aufräumen / House Keeping aller Datenbanken
  • Deprecated Feature aus der DB entfernt
  • Vorbereitung für Oracle Versionen »19c wie 23ai
  • Datenbank Audit wird vereinfacht

Was ist in der 19c aktiviert? Ist Status prüfen

SYS auf 19c

SELECT PARAMETER, VALUE 
  FROM V$OPTION
WHERE PARAMETER='Unified Auditing';
 
 
PARAMETER             VALUE                                                           
--------------------  --------
Unified Auditing      FALSE   
 
 
-- gibt es aber schon Log einträge
 
SELECT COUNT(*)   FROM UNIFIED_AUDIT_TRAIL;
 
 COUNT(*)
----------
      1783

Die Aussage „Unified Auditing=FALSE“ und die Anzahl <> 0 von Datensätzen in der UNIFIED_AUDIT_TRAIL zeigt uns an, das wir die Datenbank 19c im Mixed Mode betreiben (also schon eine Audit Policies in der DB Exisiert).

Das klassisches Auditing ist damit noch aktiv ist, und gleichzeitig wird Unified Audition in Teilen bereits verwenden.

Gib es keine Audit Policy in der Datenbank 19c ( z.B in einer 19c, die historisch seit 9i immer wieder upgegradet wurde (select count(*) from audit_unified_enabled_policies ⇒ 0 ) werden auch keine Logs in die UNIFIED_AUDIT_TRAIL geschrieben!

Wie viele Log Einträge gibt es schon seit wann in der DB

Plugable DB Umgebung beachten!

Im klassischen Auditing hat die CDB eine AUD$ und jede PDB eine eigene AUD$ Tabelle und auf der jeweiligen Ebene muss im Detail das Auditing betrachtet werden.

Ein Grund mehr auf Unified Audit umzustellen.

select count(*) as cnt,'AUD' as tab,CON_ID  from CONTAINERS("SYS"."AUD$") group by CON_ID
union all
select count(*) as cnt,'UN' as tab,CON_ID   from AUDSYS.AUD$UNIFIED group by CON_ID;
 
 
 
select count(*) as cnt,'AUD' as tab,CON_ID  from CONTAINERS("SYS"."DBA_AUDIT_TRAIL") group by CON_ID
union all
select count(*) as cnt,'UN' as tab,CON_ID   from CDB_UNIFIED_AUDIT_TRAIL group by CON_ID;
 
 
select count(*) as cnt,'AUD' as tab,CON_ID,min(timestamp) as first_log,max(timestamp) as last_log  from CONTAINERS("SYS"."DBA_AUDIT_TRAIL") group by CON_ID
union all
select count(*) as cnt,'UN' as tab,CON_ID,min(EVENT_TIMESTAMP ) as  first_log,max(EVENT_TIMESTAMP )  as  last_log  from CDB_UNIFIED_AUDIT_TRAIL group by CON_ID;

Audit Tabellen (Klassisch und Unified ) in eigenen Tablespace umziehen

Wo liegen aktuell die Audit Tabellen

Was ist eingestellt über die View DBA_AUDIT_MGMT_CONFIG_PARAMS:

SELECT PARAMETER_NAME, PARAMETER_VALUE, AUDIT_TRAIL 
   FROM DBA_AUDIT_MGMT_CONFIG_PARAMS
;
 
 
PARAMETER_NAME, PARAMETER_VALUE, AUDIT_TRAIL
 
DB AUDIT TABLESPACE	SYSAUX	STANDARD AUDIT TRAIL
DB AUDIT TABLESPACE	SYSAUX	FGA AUDIT TRAIL
DB AUDIT TABLESPACE	SYSAUX	UNIFIED AUDIT TRAIL

Per Default liegt alles im SYSAUX Tablespace.

Wo sind die Audit Tabellen und wie groß ist das ganze?

SELECT t.OWNER,t.TABLE_NAME,s.TABLESPACE_NAME,s.PARTITION_NAME, t.BLOCKS ,nvl(p.PARTITIONING_TYPE,'NONE') AS PARTITIONING_TYPE 
  FROM dba_tables t
 LEFT JOIN DBA_PART_TABLES p ON ( p.TABLE_NAME = t.TABLE_NAME AND p.owner=t.owner)   
 INNER JOIN DBA_SEGMENTS s ON (s.SEGMENT_NAME=t.TABLE_NAME  AND s.owner=t.owner)   
  WHERE t.table_name LIKE  'AUD$%' AND t.owner IN ('SYS','AUDSYS')
ORDER BY 1,2;
 
OWNER   TABLE_NAME TABLESPACE_NAME PARTITION_NAME BLOCKS PARTITIONING_TYPE 
 
AUDSYS	AUD$UNIFIED	SYSAUX	SYS_P202	1391	RANGE	
 
SYS	AUD$	        SYSAUX                  54444	NONE

Nun können wir erkennen das unsere Audit Tabelle AUD$ für das Klassische Auditing noch im SYSAUX Tablespace (default) liegt und das die neue Audit log Tabelle für das Unified Audit „AUD$UNIFIED“ ebenfalls im SYSAUX liegt, nun allerdings als Partitionierte Tabelle!

Vor dem Aktiveren des Unifed Audits den Tablespace umstellen! Ansonsten verbleiben die bereits existierenden Partition im SYSAUX Tablespace und erst nach einem Intervall (default Monat) wird in den neuen Tablespace geschrieben mit einer neuen Partition (Partition Typ = RANGE )

Audit Daten bereinigen

Können alte Daten gelöscht werden? Am einfachsten alles löschen? Auf die Plubable Umgebung achten!

Als SYS per Hand:

SELECT COUNT(*) AS cnt,'AUD' AS tab FROM sys.aud$
UNION
SELECT COUNT(*) AS cnt,'UN' AS tab FROM AUDSYS.AUD$UNIFIED
 
-- alles
-- truncate table aud$;
 
-- delete alles älter als 180 Tage
DELETE aud$ WHERE TIMESTAMP# < (systimestamp - 180) 
commit;

Eleganter über die DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL Methode:

--lösche alles in der 19c
 
BEGIN
DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(
     audit_trail_type         => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD --AUDIT_TRAIL_AUD_ALL
   , use_last_arch_timestamp => FALSE
   , container                => DBMS_AUDIT_MGMT.CONTAINER_ALL
 );
END;
/
 
SELECT COUNT(*) AS cnt,'AUD' AS tab FROM sys.aud$
UNION
SELECT COUNT(*) AS cnt,'UN' AS tab FROM AUDSYS.AUD$UNIFIED
 
0

Problem: ORA-46258: Cleanup not initialized for the audit trail

Lösung: da wir noch nicht komplett auf Unified Audit umgestellt haben muss erst das init erfolgen:

BEGIN
 DBMS_AUDIT_MGMT.INIT_CLEANUP(
      audit_trail_type         => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD ----AUDIT_TRAIL_AUD_ALL
   ,  default_cleanup_interval => 24
 );
END;
/

Umziehen auf den neuen Tablespace

Audit Tablespace anlegen

Passenden Tablespace anlegen wie AUDITLOG mit uniform Size allocation.

CREATE SMALLFILE TABLESPACE "AUDITLOG"  LOGGING DATAFILE '&&AUDITLOG_TAB_LOC' 
	   SIZE 100M AUTOEXTEND ON NEXT 120M MAXSIZE 32000M 
           EXTENT MANAGEMENT LOCAL 
           UNIFORM SIZE 1M;
 
/
Klassisches Audit umziehen
BEGIN
DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
       audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_DB_STD,
       audit_trail_location_value =>  'AUDITLOG'); --<<Hier auf den richtigen Tablespace Namen achten sonst =>ORA-01403: Keine Daten gefunden 
END;
/
 
BEGIN
DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
          audit_trail_type            => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD
       ,  audit_trail_location_value  => 'AUDITLOG');  --<<Hier auf den richtigen Tablespace Namen achten sonst =>ORA-01403: Keine Daten gefunden 
END;
/

Prüfen das keine Objekte in der Datenbank ungültig wurden! Bei Bedarf neu übersetzen!

@?/rdbms/admin/utlrp.sql
Unfied Audit umziehen
BEGIN
DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
          audit_trail_type            => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED
       ,  audit_trail_location_value  => 'AUDITLOG');  --<<Hier auf den richtigen Tablespace Namen achten sonst =>ORA-01403: Keine Daten gefunden 
END;
/
Prüfen ob die Tabellen nun im richtigen TBS liegen
SELECT PARAMETER_NAME, PARAMETER_VALUE, AUDIT_TRAIL 
   FROM DBA_AUDIT_MGMT_CONFIG_PARAMS
WHERE PARAMETER_NAME='DB AUDIT TABLESPACE'
;
 
DB AUDIT TABLESPACE	AUDITLOG	STANDARD AUDIT TRAIL
DB AUDIT TABLESPACE	AUDITLOG FGA AUDIT TRAIL
DB AUDIT TABLESPACE	AUDITLOG UNIFIED AUDIT TRAIL
 
--
 
SELECT t.OWNER,t.TABLE_NAME,s.TABLESPACE_NAME,s.PARTITION_NAME, t.BLOCKS ,nvl(p.PARTITIONING_TYPE,'NONE') AS PARTITIONING_TYPE 
  FROM dba_tables t
 LEFT JOIN DBA_PART_TABLES p ON ( p.TABLE_NAME = t.TABLE_NAME AND p.owner=t.owner)   
 INNER JOIN DBA_SEGMENTS s ON (s.SEGMENT_NAME=t.TABLE_NAME  AND s.owner=t.owner)   
  WHERE ( t.table_name LIKE  'AUD$%' OR t.table_name LIKE 'FGA_L%') AND t.owner IN ('SYS','AUDSYS')
ORDER BY 1,2;
 
OWNER   TABLE_NAME      TABLESPACE_NAME  PARTITION_NAME  BLOCKS  PARTITIONING_TYPE  
---------------------------------------------------------------------------------
AUDSYS	AUD$UNIFIED	SYSAUX	        AUD_UNIFIED_P0	0	RANGE
AUDSYS	AUD$UNIFIED	AUDITLOG       SYS_P62832	0	RANGE
SYS	AUD$	        AUDITLOG     6820	NONE
SYS	FGA_LOG$	AUDITLOG     NONE
 
Prüfen ob sich SYSAUX wieder verkleinern lässt

Meist hat man keine Glück, da am Ende des Tablespace sich oft noch weitere Objekte befinden und der SYSAUX Tablespace nur bedingt reorganisiert werden kann.

Bzgl. dem Wachstum in SYSAUX Tablespace siehe auch Das Oracle AWR Repository - Abfrage und Pflege


Speicher Parameter der Unified Audit Tabelle prüfen und setzen

Die Tabelle AUDSYS.AUD$UNIFIED ist in 19c/23ai partitioniert nach Range (Datum des Log Eintrages).

Das erzeugen von neuen Partitionen kann über die Methode DBMS_AUDIT_MGMT.ALTER_PARTITION_INTERVAL gesteuert werden.

Was ist eingestellt:

SELECT 
   owner
  ,TABLE_NAME
  ,INTERVAL
  ,partitioning_type
  ,partition_count
  ,def_tablespace_name 
 FROM dba_part_Tables WHERE owner='AUDSYS';
 
 
 
OWNER   TABLE_NAME      INTERVAL                PARTITIONING_TYPE   PARTITION_COUNT  DEF_TABLESPACE_NAME
-----------------------------------------------------------------------------------------------------
AUDSYS	AUD$UNIFIED	INTERVAL '1' MONTH	RANGE	            1048575 	    SYSAUDIT

Anpassen mit:

BEGIN
 DBMS_AUDIT_MGMT.ALTER_PARTITION_INTERVAL(
   interval_number       => 14,        --  Each number of   interval_frequency   -- in this example all 14 Days
   interval_frequency    => 'DAY');     -- YEAR, MONTH, and DAY.
 END;

Lösch Jobs einrichten

Siehe auch Die Audit Logs der Datenbank unter Oracle 11g/12c mit DBMS_AUDIT_MGMT "aufräumen"

Das Problem bei Schreiben von Logs ist am Ende immer das man die Daten ja auch wieder löschen muss, sonst läuft alles recht schnell voll.

Hier wird mit Archive Timestamp gearbeitet, d.h. wir schreiben jeden Tag diesen Timestamp weiter und löschen alles älter als.

Für 26ai

Leider gibt es hier ein paar kleine Detailunterschied, die unterschiedliche Skripte zwischen 19c und 26ai bedingen:

-- Auditlog init ---------------------------
 
BEGIN
  DBMS_AUDIT_MGMT.INIT_CLEANUP(
      audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL,
      default_cleanup_interval => 24 /* hours */);
END;
/
 
--  Delete all after 180 Days
 
BEGIN
-- Standard database audit records in the SYS.AUD$ table
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
       audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD
     , last_archive_time => SYSTIMESTAMP-180);
 
--  Unified audit trail. In unified auditing, all audit records are written to the unified audit trail and are made --  available through the unified audit trail views, such as UNIFIED_AUDIT_TRAIL.
 DBMS_AUDIT_MGMT.set_last_archive_timestamp(
       audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED
     , last_archive_time => SYSTIMESTAMP-180);
 
-- Operating system audit trail. This refers to the audit records stored in operating system files.
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
       audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_OS
     , last_archive_time => SYSTIMESTAMP-180);
 
  --  Statistik erneuern
  DBMS_STATS.GATHER_TABLE_STATS( 'AUDSYS', 'AUD$UNIFIED');   
 
END;
/
 
-- Alternativ Alles mit 
 
 
BEGIN
-- delte all
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
       audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL
     , last_archive_time => SYSTIMESTAMP-180);
 
  --  Statistik erneuern
  DBMS_STATS.GATHER_TABLE_STATS( 'AUDSYS', 'AUD$UNIFIED');   
 
END;
/
 
 
-- =================
-- create the job to move the timeframe each day
-- Only in 26ai!
-- =================
 
BEGIN
 
  DBMS_SCHEDULER.CREATE_JOB (
    job_name   => 'AUDIT_ARCHIVE_BEFORE_TIMESTAMP',
    job_type   => 'PLSQL_BLOCK',
    job_action => 'DBMS_AUDIT_MGMT.set_last_archive_timestamp(
       audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL
     , last_archive_time => SYSTIMESTAMP-180);
     DBMS_STATS.GATHER_TABLE_STATS( ''AUDSYS'', ''AUD$UNIFIED'');   
    ',
     start_date      => sysdate,
     repeat_interval => 'FREQ=HOURLY;INTERVAL=24',
     enabled         =>  TRUE,
     comments        => 'Set the point in time before delete all audit log entries'
  );
END;
/
 
 
 
 
-- Create Auditlog purge Job ------------------
 
BEGIN
  DBMS_AUDIT_MGMT.create_purge_job(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL,
    audit_trail_purge_interval => 24 /* hours */,  
    audit_trail_purge_name     => 'PURGE_ALL_AUDIT_TRAILS',
    use_last_arch_timestamp    => TRUE);
END;
/

Vorteil ist nun, dass nach dem späteren Umstellen dann auch noch das alte Log nach 180 Tage nach und nach gelöscht wird und für das neue Verfahren alles bereits eingerichtet ist.

19c

-- pürfen ob schon etwas exisiert:
SELECT *
  FROM DBA_AUDIT_MGMT_CLEANUP_JOBS; 
 
 
 
-- falls Fehler ORA-46250: Ungültiger Wert für Argument "AUDIT_TRAIL_TYPE" 
-- kann das erst nach dem Einrichten von unfied Audit durchgeführt werden? testen!
BEGIN	
  DBMS_AUDIT_MGMT.INIT_CLEANUP(
    audit_trail_type          => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL  , --AUDIT_TRAIL_UNIFIED erst ab 26ai?? Testen!
    default_cleanup_interval  => 24);
END;
/
 
/* 
-- reicht das dann wie oben in  Oracle 19c?
-- Initialisierung der Audit-Trail-Bereinigung (einmalig erforderlich)
BEGIN
  DBMS_AUDIT_MGMT.INIT_CLEANUP(
    audit_trail_type          => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    default_cleanup_interval  => 24);
END;
 
BEGIN
  DBMS_AUDIT_MGMT.INIT_CLEANUP(
    audit_trail_type          => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,
    default_cleanup_interval  => 24);
END;
 
*/
 
 
-- =================
--
-- create the job to move the timeframe each day
--
-- use single calls in 19c not ALL !
--
-- =================
 
BEGIN
 
  DBMS_SCHEDULER.CREATE_JOB (
    job_name   => 'AUDIT_ARCHIVE_BEFORE_TIMESTAMP',
    job_type   => 'PLSQL_BLOCK',
    job_action => q'[ 
BEGIN
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
        audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD
      , last_archive_time => SYSTIMESTAMP-180);
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
        audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD
      , last_archive_time => SYSTIMESTAMP-180);      
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
        audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED
      , last_archive_time => SYSTIMESTAMP-180);
  -- optimierung
  DBMS_STATS.GATHER_TABLE_STATS( 'AUDSYS', 'AUD$UNIFIED');
END;
]',
     start_date      => sysdate,
     repeat_interval => 'FREQ=HOURLY;INTERVAL=24',
     enabled         =>  TRUE,
     comments        => 'Set the point in time before delete all audit log entries'
  );
END;
/
 
 
-- Purge-Job für Standard-Audit-Trail
BEGIN
  DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    audit_trail_purge_interval => 24,
    audit_trail_purge_name     => 'PURGE_STD_AUDIT',
    use_last_arch_timestamp    => TRUE);
END;
/
 
-- Purge-Job für FGA-Audit-Trail
BEGIN
  DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,
    audit_trail_purge_interval => 24,
    audit_trail_purge_name     => 'PURGE_FGA_AUDIT',
    use_last_arch_timestamp    => TRUE);
END;
/
 
-- Purge-Job für Unified Audit-Trail
BEGIN
  DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
    audit_trail_purge_interval => 24,
    audit_trail_purge_name     => 'PURGE_UNIFIED_AUDIT',
    use_last_arch_timestamp    => TRUE);
END;
/

Lösch Jobs prüfen

Prüfen wie alt die Einträge sind:

-- ab wann sollte es gelöscht sein:
SELECT sysdate -180 FROM dual;
24-SEP-25
 
-- Was ist an Anzahl noch da?
SELECT COUNT(*) AS cnt,'AUD' AS tab FROM sys.aud$
UNION
SELECT COUNT(*) AS cnt,'UN' AS tab FROM AUDSYS.AUD$UNIFIED
 
 
SELECT COUNT(*) AS cnt,'AUD' AS tab
      ,CON_ID,MIN(TIMESTAMP) AS first_log
      ,MAX(TIMESTAMP) AS last_log  
FROM CONTAINERS("SYS"."DBA_AUDIT_TRAIL") GROUP BY CON_ID
UNION ALL
SELECT COUNT(*) AS cnt
      ,'UN' AS tab,CON_ID
      , MIN(EVENT_TIMESTAMP ) AS  first_log
      , MAX(EVENT_TIMESTAMP )  AS  last_log  
FROM CDB_UNIFIED_AUDIT_TRAIL GROUP BY CON_ID;
 
--Das sollte dann nicht im Monat vor dem gewünschen x tagen liegen!

Bei Bedarf von Hand löschen mit „use_last_arch_timestamp ⇒ TRUE“ um das 180 Tage z.b. zu entfernen::

-- auf was steht der Time stamp
SELECT * FROM DBA_AUDIT_MGMT_LAST_ARCH_TS;
 
 
BEGIN
DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(
     audit_trail_type         => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL
   , use_last_arch_timestamp => TRUE
   , container                => DBMS_AUDIT_MGMT.CONTAINER_ALL
 );
END;
/
 
oder 
 
BEGIN
DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(
     audit_trail_type         => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED
   , use_last_arch_timestamp => TRUE
   , container                => DBMS_AUDIT_MGMT.CONTAINER_ALL
 );
END;
/
 
-- jetzt mit obiger Query prüfen ob alles weg ist bis zum Timestamp!

Gibt es die Jobs:

SELECT JOB_NAME
     , JOB_STATUS
     , AUDIT_TRAIL
     , JOB_FREQUENCY
     , USE_LAST_ARCHIVE_TIMESTAMP
     , JOB_CONTAINER 
  FROM DBA_AUDIT_MGMT_CLEANUP_JOBS;
 
 
JOB_NAME, JOB_STATUS, AUDIT_TRAIL, JOB_FREQUENCY, USE_LAST_ARCHIVE_TIMESTAMP, JOB_CONTAINER
----------------------------------------------------------------------------------------------
CLEANUP_AUDIT_TRAIL_ALL	ENABLED	ALL AUDIT TRAILS	FREQ=HOURLY;INTERVAL=24	YES	CURRENT

Sind die Jobs in der Vergangenheit gelaufen aber nur für das traditionelle Audit!

  SELECT AUDIT_TRAIL
       , MIN(CLEANUP_TIME) AS first_cleanup
       , MAX(CLEANUP_TIME) AS last_cleanup
       , COUNT(*) AS clean_cnt
      FROM DBA_AUDIT_MGMT_CLEAN_EVENTS
GROUP BY AUDIT_TRAIL;

Unified Cleanup → kein Event → kein Eintrag in DBA_AUDIT_MGMT_CLEAN_EVENTS!

Was ist der letzten Timestamp ab dem gelöscht werden soll:

-- Last Archival Timestamp (wichtig: Job löscht nur bis zu diesem Zeitpunkt)
SELECT * FROM DBA_AUDIT_MGMT_LAST_ARCH_TS;

siehe auch https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/DBMS_AUDIT_MGMT.html

auf Job Fehler und letzte Ausführung prüfen:

  SELECT log_date,
       job_name,
       operation,
       STATUS,
       additional_info
  FROM dba_scheduler_job_log
 WHERE job_name LIKE '%AUDIT%'
 ORDER BY log_date DESC
 fetch FIRST 10 ROWS ONLY;

Falls hier kein Job auftaucht siehe dazu Der Oracle Job Scheduler 10g/11g/12c/18c/19c für die Details: wie ist überhaupt ein Jobs möglich ( Parameter job_queue_processes > min 2 ), ist ein Job Windows nicht geschlossen und weitere komplexe Problem mit Oracle Scheduler Jobs.

Fehler ORA-46250: Invalid value for argument 'AUDIT_TRAIL_TYPE - DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL

AUDIT_TRAIL_ALL steht in der Doku für 19c unter https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/DBMS_AUDIT_MGMT.html#GUID-1EB3BBB1-4FC3-4BC3-8490-8300C950AC27__BABIDGEA aber kann nicht verwendet werden , wenn das Ziel SET_LAST_ARCHIVE_TIMESTAMP ist.

In 26ai funktioniert es dagegen.

Fehler in einer Oracle 19c 19.28

ORA-46250: Invalid value for argument 'AUDIT_TRAIL_TYPE'
ORA-06512: at "AUDSYS.DBMS_AUDIT_MGMT", line 208
ORA-06512: at "AUDSYS.DBMS_AUDIT_MGMT", line 1065
ORA-06512: at line 2

in 19c 19.28 nun die Parameter einzeln gesetzt:

BEGIN
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
        audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD
      , last_archive_time => SYSTIMESTAMP-180);
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
        audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD
      , last_archive_time => SYSTIMESTAMP-180);      
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
        audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED
      , last_archive_time => SYSTIMESTAMP-180);
  -- AUDIT_TRAIL_OS    
  DBMS_AUDIT_MGMT.set_last_archive_timestamp(
        audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_OS
      , last_archive_time => SYSTIMESTAMP-180);
 
  -- optimierung
  DBMS_STATS.GATHER_TABLE_STATS( 'AUDSYS', 'AUD$UNIFIED');
END;
/


Audit Policies definieren

Was wurde bisher klassisch Auditiert?

Überprüfen mit:

-- Klassische Auditing-Einstellungen anzeigen (nicht Unified Auditing)
-- 1. Statement Auditing
SELECT 'STATEMENT' AS AUDIT_TYPE,
       USER_NAME,
       AUDIT_OPTION AS PRIVILEGE,
       SUCCESS,
       FAILURE
FROM DBA_STMT_AUDIT_OPTS
UNION 
-- 2. Privilege Auditing
SELECT 'PRIVILEGE' AS AUDIT_TYPE,
       USER_NAME,
       PRIVILEGE,
       SUCCESS,
       FAILURE
FROM DBA_PRIV_AUDIT_OPTS

User Objekte:

SELECT * FROM DBA_OBJ_AUDIT_OPTS;

Welche Unfied Priv Roles gibt es schon:

SELECT p.policy_name
     , avg(
         CASE
           WHEN e.policy_name IS NOT NULL THEN 1
           ELSE 0
        END) AS STATUS
         , COUNT(*) AS pl_cnt
FROM audit_unified_policies p
LEFT JOIN audit_unified_enabled_policies e
       ON p.policy_name = e.policy_name
GROUP BY p.policy_name        
ORDER BY 2 DESC;

Neue Regeln definieren

siehe dazu https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-AUDIT-POLICY-Unified-Auditing.html und https://www.oracle.com/docs/tech/dbsec/unified-audit-best-practice-guidelines.pdf .

Minimale Regel definieren wie:

  • CREATE USER - ALTER USER - DROP USER
  • CREATE ROLE - ALTER ROLE - DROP ROLE
  • CREATE PROFILE - ALTER PROFILE - DROP PROFILE
  • CREATE SYNONYM - ALTER SYNONYM - DROP SYNONYM
  • CREATE DATABASE - LINK - ALTER DATABASE LINK - DROP DATABASE LINK
  • CREATE PROCEDURE - ALTER PROCEDURE - DROP PROCEDURE
  • CREATE TRIGGER - ALTER TRIGGER - DROP TRIGGER
  • GRANT - REVOKE
  • ALTER SYSTEM
  • AUDSYS.AUD$UNIFIED delete - truncate actions
  • LOGON AND LOGOFF

Welche

SELECT * FROM STMT_AUDIT_OPTION_MAP  

Defaults prüfen und ausschalten:

SELECT * 
  FROM audit_unified_enabled_policies;

Deaktivieren mit:

NOAUDIT POLICY ORA_SECURECONFIG;

Policy GPI_DB_MiN_SEC_AUDIT anlegen:

DROP AUDIT POLICY GPI_DB_MiN_SEC_AUDIT;
 
CREATE AUDIT POLICY GPI_DB_MiN_SEC_AUDIT
 PRIVILEGES
     CREATE EXTERNAL JOB, CREATE JOB, CREATE ANY JOB
 ACTIONS
    -- User Management
      CREATE USER, ALTER USER, DROP USER
    -- Role management
    , CREATE ROLE, ALTER ROLE, DROP ROLE
    -- Profile management
    , CREATE PROFILE, ALTER PROFILE, DROP PROFILE
    -- Synonym management
    , CREATE SYNONYM, ALTER SYNONYM, DROP SYNONYM
    -- Database link management
    , CREATE DATABASE LINK, ALTER DATABASE LINK, DROP DATABASE LINK
    -- Procedure management
    , CREATE PROCEDURE, ALTER PROCEDURE, DROP PROCEDURE
    -- Trigger management
    , CREATE TRIGGER, ALTER TRIGGER, DROP TRIGGER
    -- Table management
    , CREATE TABLE, ALTER TABLE, DROP TABLE, RENAME TABLE
    -- Privilege operations
    , GRANT   
    , REVOKE    
    -- System operations
    , ALTER SYSTEM
    , ALTER DATABASE    
    , CREATE TABLESPACE
    , DROP TABLESPACE
    , CREATE  DIRECTORY
    , DROP DIRECTORY
    -- Audit trail modifications
    , DELETE ON AUDSYS.AUD$UNIFIED
    , UPDATE ON AUDSYS.AUD$UNIFIED 
    -- Session Management
    , LOGON, LOGOFF
;
 
 
---
-- ===============
--  Define rule for Login
--  Exclude MONITOR to avoid to much logs
CREATE audit policy  GPI_SEC_AUDIT_LOGIN_LOGOFF
  actions logon,logoff
  WHEN 'sys_context(''userenv'', ''session_user'') != ''MONITOR'''
  evaluate per SESSION;
 
 
---
-- ===============
--  Define rule for truncate statement!
--
DROP AUDIT POLICY GPI_SEC_AUDIT_TRUNC;
 
CREATE AUDIT POLICY GPI_SEC_AUDIT_TRUNC
 ACTIONS TRUNCATE TABLE
    WHEN 'SYS_CONTEXT(''USERENV'',''CURRENT_SCHEMA'') = ''AUDSYS''     
     AND SYS_CONTEXT(''USERENV'',''CURRENT_OBJECT'') = ''AUD$UNIFIED'''
EVALUATE PER STATEMENT;
 
 
---
-- ===============
--  Define rule for User objects
 
--  ! Darauf achten jedes DML einzeln aufzuführen                 ! 
--  ! NICHT SELECT,INSERT,UPDATE, DDELETE ON scott.emp;           !
--  ! sonst wird JEDES SELECT,INSERT,UPDATE ins Audit geschrieben !
 
DROP AUDIT POLICY GPI_SEC_AUDIT_SCHEMA_SCOTT;
 
 
CREATE AUDIT POLICY GPI_SEC_AUDIT_SCHEMA_SCOTT
ACTIONS 
  SELECT ON scott.emp
, INSERT ON scott.emp
, UPDATE ON scott.emp
, DELETE ON scott.emp;
 
 
--=====================
-- Welche Actions existieren für DataPump in dieser Datenban?
-- ====================
 
SELECT name 
  FROM auditable_system_actions 
 WHERE component = 'Datapump';
 
 
-- Policy Beispiel für eine Actions component:
CREATE audit policy GPI_DATAPUMP_ACTION
  actions component = datapump ALL;
 
Vor den Aktvieren den Tablespace Umzug abschließen!

Aktiveren:

-- For the entire CDB (all PDBs):
--
AUDIT POLICY GPI_DB_MiN_SEC_AUDIT CONTAINER=ALL;
AUDIT POLICY GPI_SEC_AUDIT_TRUNC  CONTAINER=ALL;
AUDIT POLICY GPI_SEC_AUDIT_SCHEMA_SCOTT CONTAINER=ALL;
AUDIT POLICY GPI_SEC_AUDIT_LOGIN_LOGOFF CONTAINER=ALL;
AUDIT POLICY GPI_DATAPUMP_ACTION CONTAINER=ALL;
 
-- For specific PDBs only:
-- OR for normal DB Settings
AUDIT POLICY GPI_DB_MiN_SEC_AUDIT      ;
AUDIT POLICY GPI_SEC_AUDIT_TRUNC       ;
AUDIT POLICY GPI_SEC_AUDIT_SCHEMA_SCOTT;
AUDIT POLICY GPI_SEC_AUDIT_LOGIN_LOGOFF;
AUDIT POLICY GPI_DATAPUMP_ACTION;

Nach dem aktivieren ist die DB im Mixed Mode und schreibt z.B. LOGON und LOGOFF mit!

Überprüfen:

SELECT * 
  FROM audit_unified_enabled_policies 
 WHERE policy_name IN (  'GPI_DB_MIN_SEC_AUDIT','GPI_SEC_AUDIT_TRUNC','GPI_SEC_AUDIT_SCHEMA_SCOTT');

Auswerten

SELECT event_timestamp
     , action_name
     , unified_audit_policies
     , dbusername
  FROM unified_audit_trail
 WHERE unified_audit_policies = 'GPI_DB_MIN_SEC_AUDIT'
 ORDER BY event_timestamp DESC;

Finales Umstellen auf Unified Auditing

Ablauf Linux

  • Alle Datenbanken/Listner aus dem Oracle Home stoppen
  • Oracle DB Kernel neu linken
  • Alle Datenbanken/Listner aus dem Oracle Home starten

Linken des Kernels unter dem Eigentümer (User Oracle) mit:

cd $ORACLE_HOME/rdbms/lib
make -f ins_rdbms.mk uniaud_on ioracle 
 

Mit „make -f ins_rdbms.mk uniaud_off ioracle“ kann das auch wieder zurück gezogen werden.

prüfen was gelinkt wurde

ON = kzaiang.c

OFF = kzanang.c

Abfragen mit:

strings /u01/app/oracle/product/19c/19.24/bin/oracle | grep kzaiang
 
-?comment:Intel(R) C Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 17.0.2.174 Build 20170213  : kzaiang.c  ..... -?comment:
kzaiang.c
 
 
strings /u01/app/oracle/product/19c/19.24/bin/oracle | grep kzanang
#empty

Ablauf Windows

Unter Windows muss eine DDL ( %ORACLE_HOME%/bin/orauniaud19.dll.dbl ) durch Umbenennen „aktiviert“ werden, beim nächsten Start wird die DDL eingelesen und damit das Unfied Audit aktiviert.

Rem Enable
ren %ORACLE_HOME%/bin/orauniaud19.dll.dbl %ORACLE_HOME%/bin/orauniaud19.dll

Rem Disable
%ORACLE_HOME%/bin/orauniaud19.dll file to %ORACLE_HOME%/bin/orauniaud19.dll.dbl
Patch Verhalten Windows! Nach jedem Patch Vorgang prüfen ob eine neue orauniaud19.dll.dbl kopiert wurde, die alte löschen und diese neue vom Patch aktivieren! Falls der Bug nach 19.28 nicht verschwunden ist Bug bei Oracle eröffnen, sollte ja mal irgendwann auch gefixt werden!

Prüfen

Nach Neustart prüfen:

SELECT PARAMETER, VALUE 
  FROM V$OPTION
WHERE PARAMETER='Unified Auditing';
 
 
PARAMETER             VALUE                                                           
--------------------  --------
Unified Auditing      TRUE


Alte Audit Regeln deaktiveren

Nach dem aktiveren können nun die alten Regeln gelöscht werden.

Script zu deaktiveren:

disable_all_audit_options.sql
SET serveroutput ON
 
 
----------------------------------------------------------------------------
-- Script  : disable_all_audit_options.sql
-- Purpose : Disable all statement and privilege audit options found in
--           DBA_STMT_AUDIT_OPTS and DBA_PRIV_AUDIT_OPTS
-- Run as  : SYSDBA or user with AUDIT SYSTEM privilege
----------------------------------------------------------------------------
 
DECLARE
 
  -- Cursor: Statement Auditing (DBA_STMT_AUDIT_OPTS)
  cursor c_stmt_audit IS
    SELECT user_name,
           audit_option
      FROM DBA_STMT_AUDIT_OPTS;
 
  -- Cursor: Privilege Auditing (DBA_PRIV_AUDIT_OPTS)
  cursor c_priv_audit IS
    SELECT user_name,
           privilege
      FROM DBA_PRIV_AUDIT_OPTS;
 
  -- Dynamic SQL string
  v_sql          varchar2(1000);
  v_user_clause  varchar2(100);
  v_count_stmt   pls_integer := 0;
  v_count_priv   pls_integer := 0;
  v_count_err    pls_integer := 0;
 
BEGIN
 
  dbms_output.put_line('=== DISABLE STATEMENT AUDIT OPTIONS ===');
 
  <<STMT_AUDIT_OPTIONS>>
  FOR r_stmt IN c_stmt_audit loop
 
    -- Build user clause: NULL means "all users" -> no BY clause needed
    IF r_stmt.user_name IS NULL THEN
      v_user_clause := '';
    ELSE
      v_user_clause := ' BY ' || dbms_assert.enquote_name(r_stmt.user_name, FALSE);
    END IF;
 
    v_sql := 'noaudit ' || r_stmt.audit_option || v_user_clause;
 
    BEGIN
      EXECUTE IMMEDIATE v_sql;
      v_count_stmt := v_count_stmt + 1;
      dbms_output.put_line('  OK : ' || v_sql);
    exception
      WHEN others THEN
        v_count_err := v_count_err + 1;
        dbms_output.put_line('  ERR: ' || v_sql);
        dbms_output.put_line('       ' || sqlerrm);
    END;
 
  END loop STMT_AUDIT_OPTIONS;
 
  dbms_output.put_line('');
  dbms_output.put_line('=== DISABLE PRIVILEGE AUDIT OPTIONS ===');
 
  <<PRIV_AUDIT_OPTIONS>>
  FOR r_priv IN c_priv_audit loop
 
    -- Build user clause
    IF r_priv.user_name IS NULL THEN
      v_user_clause := '';
    ELSE
      v_user_clause := ' BY ' || dbms_assert.enquote_name(r_priv.user_name, FALSE);
    END IF;
 
    v_sql := 'noaudit ' || r_priv.privilege || v_user_clause;
 
    BEGIN
      EXECUTE IMMEDIATE v_sql;
      v_count_priv := v_count_priv + 1;
      dbms_output.put_line('  OK : ' || v_sql);
    exception
      WHEN others THEN
        v_count_err := v_count_err + 1;
        dbms_output.put_line('  ERR: ' || v_sql);
        dbms_output.put_line('       ' || sqlerrm);
    END;
 
  END loop PRIV_AUDIT_OPTIONS;
 
  dbms_output.put_line('');
  dbms_output.put_line('=== SUMMARY ===');
  dbms_output.put_line('  Statement options disabled : ' || v_count_stmt);
  dbms_output.put_line('  Privilege options disabled : ' || v_count_priv);
  dbms_output.put_line('  Errors                     : ' || v_count_err);
 
END;
/

Standby Datenbank beachten

Physical Standby‑DB

Oracle beschreibt keinen separaten Mechanismus für Standby‑Instanzen. Unified Auditing muss in beiden ORACLE_HOMEs aktiviert werden.

Unified Auditing ist eine Kernel‑Eigenschaft des ORACLE_HOME – also immer ORACLE_HOME‑weit, nicht datenbank-spezifisch.

Das bedeutet für uns damit eine Standby‑DB nach einem Switchover/Fallover Unified Auditing vollständig unterstützt, muss Unified Auditing im ORACLE_HOME sowohl der Primary als auch der Standby aktiviert werden.

Das geschieht durch ein relink von ioracle in beiden Umgebungen in einer Downtime beider Umgebungen.

A) Primary herunterfahren → relink → starten

B) Standby herunterfahren → relink → starten

Damit ist gewährleistet, dass nach einem Switchover der neue Primary bereits Unified Auditing vollständig unterstützt.

Active Data Guard

Wie verhält sich Unified Auditing auf einer Read‑Only Standby (Active Data Guard)?

Wenn die DB READ ONLY ist, schreibt Unified Auditing in Spillover‑Files (.bin) im ORACLE_BASE/audit. Quelle: Audit Active Data Guard / Spillover-Mechanismus

Diese Spillover‑Dateien werden automatisch in GV$UNIFIED_AUDIT_TRAIL sichtbar.

Siehe dazu auch https://blogs.oracle.com/database/audit-active-dataguard-with-data-safe-in-oracle-cloud

Das bedeutet: Unified Auditing funktioniert auch auf einer Standby‑DB, obwohl sie READ ONLY ist.

Die Audit‑Trail‑Daten landen dann automatisch im OS und werden vom UNIFIED_AUDIT_TRAIL‑View konsumiert.


Archivierung von Archive Logs

Manuell

Durch einfaches Umkopieren, z.b. in eine zentrale Audit Datenbank verschieben, auf Platte exportieren oder in einer für das Logging optimieren Datenbank speichern.

Im Prinzip:

INSERT INTO TABLE SELECT ... FROM UNIFIED_AUDIT_TRAIL ...;
Archive Zeitpunkt setzen

Wichtig ist es, nach dem Wegkopieren der Daten mit DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP, der DB mit zuteilen was nun nicht mehr in der DB benötigt wird, weil inzwischen korrekt archiviert iss.

Zum Löschen der bestehenden Audits den Last Archive Timestamp setzen ( falls in der Löschroutine CLEAN_AUDIT_TRAIL die Verwendung des Zeitpunktes gesetzt ist über use_last_arch_timestamp = TRUE ) :

BEGIN
 
DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
       audit_trail_type     => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL
   ,   last_archive_time    => systimestamp  
      -- last_archive_time must be specified in Coordinated Universal Time (UTC) 
      -- testen ob das so auch richtig konvertiert wird ohne Format Angabe!
   );
END;

Oracle Audit Vault

In einer größeren Umgebung kann das mit Oracle Produkten erfolgen wie Oracle Audit Vault

siehe ⇒ https://oracle.com/de/security/database-security/audit-vault-database-firewall/


Operating System Audit Records in die Datenbank kopieren

Wenn die Datenbank nicht zum schreiben geöffnet ist, werden die Audit Records in das Dateisystem und nicht in die Datenbank geschrieben - Stichwort Unified Auditing spillover files

Um diese Dateien nachzuladen kann mit DBMS_AUDIT_MGMT.LOAD_UNIFIED_AUDIT_FILES diese nachgeladen werden.

Dateien in den aktuellen Container laden:

BEGIN
 DBMS_AUDIT_MGMT.LOAD_UNIFIED_AUDIT_FILES;
-- Parameter aus der Doku klappen nicht???
--    container        => 1 
--  , load_batch_size  => 10); 
END;
/

siehe ⇒ https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/DBMS_AUDIT_MGMT.html#GUID-77C238AB-7B08-4D84-B3B8-4FC5CBDB4A3F

siehe auch https://databasesecurityninja.wordpress.com/tag/dbms_audit_mgmt-load_unified_audit_files/


Das Audit der Datenbank auswerten

View Details siehe ⇒ https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/UNIFIED_AUDIT_TRAIL.html

Eine erste Abfrage:

SELECT AUDIT_TYPE
    ,  OS_USERNAME
    , USERHOST
    , TERMINAL
    , DBUSERNAME
    , CLIENT_PROGRAM_NAME
    , EVENT_TIMESTAMP
    , EVENT_TIMESTAMP_UTC
    , ACTION_NAME
    , RETURN_CODE
    , SQL_TEXT
    , SQL_BINDS
    , SYSTEM_PRIVILEGE_USED
    , UNIFIED_AUDIT_POLICIES
    , AUTHENTICATION_TYPE
  FROM CDB_UNIFIED_AUDIT_TRAIL
 ORDER BY EVENT_TIMESTAMP_UTC

Performance

Bei Abfragen den Partiton Key EVENT_TIMESTAMP_UTC in der Where Klausel verwenden, damit das Partition Feature auch verwendet wird!

Statistiken auf der Basis Tabelle AUDSYS.AUD$UNIFIED mit DBMS_STATS.GATHER_TABLE_STATS regelmäßig erfassen z.b. beim Delete Job mit integrieren.

 BEGIN
   DBMS_STATS.GATHER_TABLE_STATS( 'AUDSYS', 'AUD$UNIFIED');
 END;
 /

ORA-942 beim anlegen einer neuen Datenbank in der Umgebung

Folgende Meldung fällt auf:

Unified Audit record write to audit trail table failed due to ORA-942. Writing the record to OS spillover file.

Ursache

Unified Auditing speichert alle Audit-Daten in seiner zentralen Tabelle AUD$UNIFIED, die im internen Schema AUDSYS liegt. Wenn Unified Auditing aktiviert ist, werden bestimmte Aktionen (z. B. CREATE DATABASE, CREATE USER) sofort auditiert.

Aber!: Während der Datenbank-Erstellung existiert die Tabelle AUD$UNIFIED noch nicht oder ist nicht zugreifbar.

Daher versucht der Audit-Mechanismus versucht trotzdem, einen Eintrag zu schreiben und erzeugt die ORA-942 Meldungen.

Das Verhalten ist dokumentiert in Oracle Support (Doc ID 2778566.1): „Unified Audit record write to audit trail table failed due to ORA-942. Writing the record to OS spillover file.“.

Kann ignoriert werden!


Rollen & Rechte in Unified Auditing (AUDIT_ADMIN, AUDIT_VIEWER)

AUDIT_ADMIN

Die Rolle AUDIT_ADMIN wird für alle administrativen Aufgaben rund um das Unified Auditing benötigt.

Die Rolle umfasst folgende Berechtigungen:

  • Erstellen, Ändern und Löschen von Audit-Policies
  • Aktivieren und Deaktivieren von Audit-Policies für einzelne oder alle Benutzer
  • Nutzung von DBMS_AUDIT_MGMT zur Verwaltung und Archivierung des Unified Audit Trail
  • Zugriff auf das Unified Audit Trail über die View UNIFIED_AUDIT_TRAIL
  • Verwaltung des Audit Trail Purging

AUDIT_VIEWER

Die Rolle AUDIT_VIEWER dient zum lesenden Zugriff auf die Auditdaten.

Die Rolle umfasst folgende Berechtigungen:

  • Nur Lesezugriff auf das Unified Audit Trail (View UNIFIED_AUDIT_TRAIL)
  • Keine Berechtigungen zum Erstellen oder Verändern von Audit-Policies
  • Kein Zugriff auf DBMS_AUDIT_MGMT

Fazit - Ausblick 26ai

Nach der Umstellung ist das Auditieren übersichtlicher und viel mächtiger geworden.

Besonders die neuen Möglichkeiten die Policies in 23ai dann zu mit Regeln noch stärkere zu konfigurieren bieten interessante Möglichkeiten.

Wie das Logging nur von Fehlern:

CREATE AUDIT POLICY audit_error_dml_operation
 ACTIONS
  SELECT, INSERT, UPDATE, DELETE
 -- nicht für Hintergrund prozesse
WHEN 'SYS_CONTEXT(''USERENV'', ''CLIENT_IDENTIFIER'') IS NOT NULL'
 EVALUATE PER STATEMENT
-- nur fehler
 ONLY WHEN NOT SUCCESSFUL;

siehe für 26ai ⇒ https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/CREATE-AUDIT-POLICY-Unified-Auditing.html

Un die Feingranulare Spaltenüberwachung neu in 23ai: Spaltenebene-Auditing ist möglich (UPDATE(col1, col2) oder SELECT(col2) on table) – das spart Ressourcen und reduziert Menge an Audit Daten.


Hilfs-Sript zum anlegen einer Policy aus dem Bestand

----------------------------------------------------------------------------
-- Script  : generate_unified_audit_policy.sql
-- Purpose : Generate CREATE AUDIT POLICY statement from existing
--           DBA_STMT_AUDIT_OPTS and DBA_PRIV_AUDIT_OPTS entries
-- Run as  : SYSDBA or user with AUDIT SYSTEM privilege
----------------------------------------------------------------------------
DECLARE
 
  -- Cursors
  cursor c_stmt_audit IS
    SELECT DISTINCT audit_option
      FROM DBA_STMT_AUDIT_OPTS
     ORDER BY audit_option;
 
  cursor c_priv_audit IS
    SELECT DISTINCT privilege
      FROM DBA_PRIV_AUDIT_OPTS
     ORDER BY privilege;
 
  -- Collector types
  TYPE t_varchar_tab IS TABLE OF varchar2(200) INDEX BY pls_integer;
 
  v_stmt_options  t_varchar_tab;
  v_priv_options  t_varchar_tab;
 
  -- Output buffer
  v_policy_name   varchar2(30)   := 'MIGRATED_AUDIT_POLICY';
  v_clob          CLOB           := empty_clob();
  v_line          varchar2(4000);
  v_idx           pls_integer;
  v_stmt_count    pls_integer    := 0;
  v_priv_count    pls_integer    := 0;
 
  ----------------------------------------------------------------------------
  -- Helper: append line to CLOB output buffer
  ----------------------------------------------------------------------------
  PROCEDURE append_line(p_text IN varchar2) IS
  BEGIN
    v_clob := v_clob || p_text || chr(10);
  END append_line;
 
BEGIN
 
  -- -------------------------------------------------------------------------
  -- Collect statement options
  -- -------------------------------------------------------------------------
  <<COLLECT_STMT>>
  FOR r_stmt IN c_stmt_audit loop
    v_stmt_count := v_stmt_count + 1;
    v_stmt_options(v_stmt_count) := r_stmt.audit_option;
  END loop COLLECT_STMT;
 
  -- -------------------------------------------------------------------------
  -- Collect privilege options
  -- -------------------------------------------------------------------------
  <<COLLECT_PRIV>>
  FOR r_priv IN c_priv_audit loop
    v_priv_count := v_priv_count + 1;
    v_priv_options(v_priv_count) := r_priv.privilege;
  END loop COLLECT_PRIV;
 
  -- -------------------------------------------------------------------------
  -- Generate: Header
  -- -------------------------------------------------------------------------
  append_line('----------------------------------------------------------------------------');
  append_line('-- Generated : ' || to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS'));
  append_line('-- Source    : DBA_STMT_AUDIT_OPTS / DBA_PRIV_AUDIT_OPTS');
  append_line('-- Statement options : ' || v_stmt_count);
  append_line('-- Privilege options : ' || v_priv_count);
  append_line('----------------------------------------------------------------------------');
  append_line('');
 
  -- -------------------------------------------------------------------------
  -- Guard: nothing to generate
  -- -------------------------------------------------------------------------
  IF v_stmt_count = 0 AND v_priv_count = 0 THEN
    dbms_output.put_line('INFO: No audit options found — nothing to generate.');
    RETURN;
  END IF;
 
  -- -------------------------------------------------------------------------
  -- Generate: CREATE AUDIT POLICY
  -- -------------------------------------------------------------------------
  append_line('create audit policy ' || v_policy_name);
 
  -- ACTIONS block (Statement Auditing)
  IF v_stmt_count > 0 THEN
    append_line('  actions');
    v_idx := 1;
    <<BUILD_STMT_ACTIONS>>
    while v_idx <= v_stmt_count loop
      IF v_idx < v_stmt_count OR v_priv_count > 0 THEN
        -- more entries follow → trailing comma
        append_line('    ' || v_stmt_options(v_idx) || ',');
      ELSE
        -- last entry overall → no comma, start PRIVILEGES or close
        append_line('    ' || v_stmt_options(v_idx));
      END IF;
      v_idx := v_idx + 1;
    END loop BUILD_STMT_ACTIONS;
  END IF;
 
  -- PRIVILEGES block (Privilege Auditing)
  IF v_priv_count > 0 THEN
    append_line('  privileges');
    v_idx := 1;
    <<BUILD_PRIV_ACTIONS>>
    while v_idx <= v_priv_count loop
      IF v_idx < v_priv_count THEN
        append_line('    ' || v_priv_options(v_idx) || ',');
      ELSE
        -- last privilege → no trailing comma
        append_line('    ' || v_priv_options(v_idx));
      END IF;
      v_idx := v_idx + 1;
    END loop BUILD_PRIV_ACTIONS;
  END IF;
 
  append_line(';');
  append_line('');
 
  -- -------------------------------------------------------------------------
  -- Generate: AUDIT statement to enable the policy
  -- -------------------------------------------------------------------------
  append_line('-- Enable policy for all users');
  append_line('audit policy ' || v_policy_name || ';');
  append_line('');
  append_line('-- Optional: enable only for specific users');
  append_line('-- audit policy ' || v_policy_name || ' by SCOTT, HR;');
  append_line('');
  append_line('-- Optional: enable with condition (e.g. exclude monitoring user)');
  append_line('-- audit policy ' || v_policy_name);
  append_line('--   when q''[sys_context(''userenv'',''session_user'') != ''MONITOR_USER'']''');
  append_line('--   evaluate per session;');
 
  -- -------------------------------------------------------------------------
  -- Output via DBMS_OUTPUT (line by line, max 32767 per put_line)
  -- -------------------------------------------------------------------------
  dbms_output.put_line('');
  dbms_output.put_line('=== GENERATED UNIFIED AUDIT POLICY ===');
  dbms_output.put_line('');
 
  <<OUTPUT_CLOB>>
  DECLARE
    v_offset  pls_integer := 1;
    v_amount  pls_integer := 200;
    v_buffer  varchar2(200);
    v_len     pls_integer;
    v_pos     pls_integer;
    v_char    varchar2(1);
    v_out     varchar2(4000) := '';
  BEGIN
    v_len := dbms_lob.getlength(v_clob);
 
    <<READ_CLOB_CHARS>>
    while v_offset <= v_len loop
      v_char := dbms_lob.substr(v_clob, 1, v_offset);
      IF v_char = chr(10) THEN
        dbms_output.put_line(v_out);
        v_out := '';
      ELSE
        v_out := v_out || v_char;
      END IF;
      v_offset := v_offset + 1;
    END loop READ_CLOB_CHARS;
 
    -- flush last line if no trailing newline
    IF v_out IS NOT NULL THEN
      dbms_output.put_line(v_out);
    END IF;
  END;
 
  dbms_output.put_line('');
  dbms_output.put_line('=== SUMMARY ===');
  dbms_output.put_line('  Statement actions : ' || v_stmt_count);
  dbms_output.put_line('  Privilege actions : ' || v_priv_count);
 
exception
  WHEN others THEN
    dbms_output.put_line('ERROR: ' || sqlerrm);
    raise;
END;

Quellen

Das DBA Kochbuch zum dem Thema

dba_koch_buch_unified_audit_umstellung_19c.sql
================================================================================
  Umstellung Oracle 19c auf Unified Auditing – DBA Kochbuch
  Autor  : Gunther Pipperr | https://pipperr.de
  Version: 2026-03
  Ziel   : Oracle 19c  Datenbank von Mixed Mode auf Unified Auditing
================================================================================
 
WICHTIG: Unified Auditing ist eine ORACLE_HOME-Eigenschaft, nicht datenbankspezifisch.
         Alle Instanzen aus demselben Oracle Home werden zusammen umgestellt!
         Leider muss nach jedem Patch geprüft werden ob der Kernel wieder korrekt
         gelinkt wurde.
 
Die beiden Hilfsskripte liegen neben dieser Datei:
  generate_unified_audit_policy.sql  – generiert Unified Policy aus klassischen Optionen
  disable_all_audit_options.sql      – deaktiviert alle klassischen Audit-Optionen
 
Die Policies liegen IN:
  gpi_audit_policies.sql           – gpi_DB_MIN_SEC_AUDIT + gpi_SEC_AUDIT_TRUNC
 
================================================================================
SCHRITT 1STATUS PRÜFEN (jederzeit, ohne Downtime)
================================================================================
 
-- immer in sqlplus setzen!
SET TAB OFF
SET PAGESIZE 100
SET LINESIZE 200
 
 
-- Ist Unified Auditing aktiv? (TRUE = Unified Only, FALSE = Mixed Mode)
COL PARAMETER FORMAT A30
COL VALUE     FORMAT A10
SELECT PARAMETER, VALUE FROM V$OPTION WHERE PARAMETER = 'Unified Auditing';
 
-- Wie viele Einträge in klassischer und Unified Audit Trail?
COL tab    FORMAT A5
COL CON_ID FORMAT 99999
COL FIRST_LOG FORMAT A30
COL LAST_LOG FORMAT A30
SELECT COUNT(*) AS cnt, 'AUD' AS tab, CON_ID,
       MIN(TIMESTAMP)     AS first_log,
       MAX(TIMESTAMP)     AS last_log
  FROM CONTAINERS("SYS"."DBA_AUDIT_TRAIL") GROUP BY CON_ID
UNION ALL
SELECT COUNT(*) AS cnt, 'UN'  AS tab, CON_ID,
       MIN(EVENT_TIMESTAMP) AS first_log,
       MAX(EVENT_TIMESTAMP) AS last_log
  FROM CDB_UNIFIED_AUDIT_TRAIL GROUP BY CON_ID;
 
-- Wo liegen die Audit-Tabellen und in welchem Tablespace?
COL OWNER           FORMAT A10
COL TABLE_NAME      FORMAT A20
COL TABLESPACE_NAME FORMAT A25
COL PARTITION_NAME  FORMAT A20
COL PARTITIONING_TYPE FORMAT A10
COL BLOCKS         FORMAT 999999
SELECT t.OWNER, t.TABLE_NAME, s.TABLESPACE_NAME, s.PARTITION_NAME,
       t.BLOCKS, NVL(p.PARTITIONING_TYPE, 'NONE') AS PARTITIONING_TYPE
  FROM dba_tables t
  LEFT JOIN DBA_PART_TABLES p ON (p.TABLE_NAME = t.TABLE_NAME AND p.owner = t.owner)
 INNER JOIN DBA_SEGMENTS   s ON (s.SEGMENT_NAME = t.TABLE_NAME AND s.owner = t.owner)
 WHERE t.table_name LIKE 'AUD$%'
   AND t.owner IN ('SYS', 'AUDSYS')
 ORDER BY 1, 2;
 
-- Aktuelle Audit-Konfiguration (Tablespace, Cleanup-Intervall)
COL PARAMETER_NAME  FORMAT A35
COL PARAMETER_VALUE FORMAT A30
COL AUDIT_TRAIL     FORMAT A20
SELECT PARAMETER_NAME, PARAMETER_VALUE, AUDIT_TRAIL
  FROM DBA_AUDIT_MGMT_CONFIG_PARAMS;
 
-- Welche klassischen Statement/Privilege-Optionen sind aktiv?
COL AUDIT_TYPE  FORMAT A12
COL USER_NAME   FORMAT A20
COL PRIVILEGE   FORMAT A35
COL SUCCESS     FORMAT A10
COL FAILURE     FORMAT A10
SELECT 'STATEMENT' AS AUDIT_TYPE, USER_NAME, AUDIT_OPTION AS PRIVILEGE,
       SUCCESS, FAILURE FROM DBA_STMT_AUDIT_OPTS
UNION
SELECT 'PRIVILEGE' AS AUDIT_TYPE, USER_NAME, PRIVILEGE,
       SUCCESS, FAILURE FROM DBA_PRIV_AUDIT_OPTS
ORDER BY 1, 2, 3;
 
-- Welche Unified Audit Policies sind definiert und aktiviert?
COL POLICY_NAME FORMAT A40
COL STATUS      FORMAT 999
COL PL_CNT      FORMAT 99999
 
SELECT p.policy_name,
       CASE WHEN e.policy_name IS NOT NULL THEN 1 ELSE 0 END AS STATUS,
       COUNT(*) AS pl_cnt
  FROM audit_unified_policies p
  LEFT JOIN audit_unified_enabled_policies e
         ON p.policy_name = e.policy_name
 GROUP BY p.policy_name, e.policy_name
 ORDER BY STATUS DESC;
 
 
-- alle mit 1 deaktivieren
NOAUDIT POLICY  ORA_SECURECONFIG;
NOAUDIT POLICY  ORA_LOGON_FAILURES;
 
SELECT *  FROM audit_unified_enabled_policies;
--no rows selected
 
 
================================================================================
SCHRITT 2 – DOWNTIME 1
  DEV/QS: Online möglich
  PROD  : Besser ohne laufende Applikation – Gefahr eines Locks auf der DB!
================================================================================
 
-- Applikation stoppen / Verbindungen prüfen
COL username format a20
SELECT COUNT(*), STATUS,username FROM V$SESSION WHERE username IS NOT NULL GROUP BY STATUS,username;
 
 
================================================================================
SCHRITT 3 – AUDIT-TABELLEN IN EIGENEN TABLESPACE UMZIEHEN
================================================================================
 
-- 3a: Tablespace anlegen (Pfad anpassen!)
-- TIPP: &&AUDITLOG_TAB_LOC als Variable in SQL*Plus setzen oder Pfad direkt ersetzen
DEFINE AUDITLOG_TAB_LOC = '/u01/app/oracle/oradata/FMWCDB/auditlog01.dbf'
 
CREATE SMALLFILE TABLESPACE "AUDITLOG"
  LOGGING DATAFILE '&&AUDITLOG_TAB_LOC'
  SIZE 100M AUTOEXTEND ON NEXT 120M MAXSIZE 8000M
  EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1M;
 
-- 3b: Klassisches Audit (AUD$) in neuen Tablespace verschieben
BEGIN
  DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_DB_STD,
    audit_trail_location_value => 'AUDITLOG');
END;
/
 
-- 3c: FGA Audit (Fine Grained Auditing) verschieben
BEGIN
  DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,
    audit_trail_location_value => 'AUDITLOG');
END;
/
 
-- 3d: Unified Audit (AUD$UNIFIED) verschieben
BEGIN
  DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
    audit_trail_location_value => 'AUDITLOG');
END;
/
 
-- 3e: Prüfen ob Verschiebung erfolgreich
COL PARAMETER_NAME  FORMAT A35
COL PARAMETER_VALUE FORMAT A30
COL AUDIT_TRAIL     FORMAT A20
SELECT PARAMETER_NAME, PARAMETER_VALUE, AUDIT_TRAIL
  FROM DBA_AUDIT_MGMT_CONFIG_PARAMS
 WHERE PARAMETER_NAME = 'DB AUDIT TABLESPACE';
 
 
================================================================================
SCHRITT 4 – SYSAUX VERKLEINERN (bei Bedarf)
================================================================================
 
-- Freien Platz in SYSAUX prüfen
COL TABLESPACE_NAME FORMAT A15
COL USED_MB         FORMAT 99999
COL FREE_MB         FORMAT 99999
SELECT t.tablespace_name,
       ROUND(t.bytes/1024/1024)                         AS total_mb,
       ROUND((t.bytes - f.free_bytes)/1024/1024)        AS used_mb,
       ROUND(f.free_bytes/1024/1024)                    AS free_mb
  FROM (SELECT tablespace_name, SUM(bytes) AS bytes FROM dba_data_files
         WHERE tablespace_name = 'SYSAUX' GROUP BY tablespace_name) t
  JOIN (SELECT tablespace_name, SUM(bytes) AS free_bytes FROM dba_free_space
         WHERE tablespace_name = 'SYSAUX' GROUP BY tablespace_name) f
    ON t.tablespace_name = f.tablespace_name;
 
-- SYSAUX kann nur verkleinert werden wenn genug zusammenhängender freier Platz
-- vorhanden ist (SHRINK nicht direkt möglich für SYSAUX in 19c).
-- Option: ALTER DATABASE DATAFILE '...' RESIZE xxxM; (Pfad aus dba_data_files)
SELECT FILE_NAME, BYTES/1024/1024 AS MB FROM DBA_DATA_FILES
 WHERE TABLESPACE_NAME = 'SYSAUX';
 
 
================================================================================
SCHRITT 5 – LÖSCH-JOBS FÜR AUDIT-LOGS EINRICHTEN (19c!)
================================================================================
-- ACHTUNG: 19c und 23ai unterscheiden sich hier deutlich!
-- In 19c muss AUDIT_TRAIL_ALL für INIT_CLEANUP funktioniert,
-- aber CREATE_PURGE_JOB muss GETRENNT für AUD_STD, FGA_STD und UNIFIED
-- angelegt werden (AUDIT_TRAIL_ALL wird für create_purge_job in 19c NICHT
-- vollständig unterstützt).
 
-- 5a: Cleanup initialisieren (19c: AUDIT_TRAIL_ALL funktioniert hier)
BEGIN
  DBMS_AUDIT_MGMT.INIT_CLEANUP(
    audit_trail_type         => DBMS_AUDIT_MGMT.AUDIT_TRAIL_ALL,
    default_cleanup_interval => 24);
END;
/
 
-- 5b: Scheduler-Job anlegen – setzt den Archive-Timestamp (19c Variante)
--     Archiv-Timestamp = "älter als N Tage darf gelöscht werden" (hier: 180 Tage)
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name   => 'AUDIT_ARCHIVE_BEFORE_TIMESTAMP',
    job_type   => 'PLSQL_BLOCK',
    job_action => q'[
BEGIN
  DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
    audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    last_archive_time => SYSTIMESTAMP - 180);
  DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
    audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,
    last_archive_time => SYSTIMESTAMP - 180);
  DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
    audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
    last_archive_time => SYSTIMESTAMP - 180);
  DBMS_STATS.GATHER_TABLE_STATS('AUDSYS', 'AUD$UNIFIED');
END;
]',
    start_date      => SYSDATE,
    repeat_interval => 'FREQ=HOURLY;INTERVAL=24',
    enabled         => TRUE,
    comments        => 'Setzt Archive-Timestamp: Einträge älter als 180 Tage werden löschbar');
END;
/
 
-- 5c: Purge-Job für klassisches Audit (19c: GETRENNT anlegen!)
BEGIN
  DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    audit_trail_purge_interval => 24,
    audit_trail_purge_name     => 'PURGE_STD_AUDIT',
    use_last_arch_timestamp    => TRUE);
END;
/
 
-- 5d: Purge-Job für FGA Audit (19c: GETRENNT anlegen!)
BEGIN
  DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,
    audit_trail_purge_interval => 24,
    audit_trail_purge_name     => 'PURGE_FGA_AUDIT',
    use_last_arch_timestamp    => TRUE);
END;
/
 
-- 5e: Purge-Job für Unified Audit (19c: GETRENNT anlegen!)
BEGIN
  DBMS_AUDIT_MGMT.CREATE_PURGE_JOB(
    audit_trail_type           => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
    audit_trail_purge_interval => 24,
    audit_trail_purge_name     => 'PURGE_UNIFIED_AUDIT',
    use_last_arch_timestamp    => TRUE);
END;
/
 
-- Prüfen ob Purge-Jobs angelegt wurden
COL JOB_NAME                   FORMAT A25
COL JOB_STATUS                 FORMAT A10
COL AUDIT_TRAIL                FORMAT A15
COL JOB_FREQUENCY              FORMAT A35
COL USE_LAST_ARCHIVE_TIMESTAMP FORMAT A15
SELECT JOB_NAME, JOB_STATUS, AUDIT_TRAIL, JOB_FREQUENCY,
       USE_LAST_ARCHIVE_TIMESTAMP
  FROM DBA_AUDIT_MGMT_CLEANUP_JOBS;
 
 
================================================================================
SCHRITT 6 – KLASSISCHE AUDIT-OPTIONEN IN UNIFIED POLICY UMWANDELN
================================================================================
 
-- 6a: Hilfsskript ausführen um Unified Policy aus klassischen Optionen zu generieren
--     Das generierte CREATE AUDIT POLICY Statement in gpi_audit_policies.sql einbauen
@generate_unified_audit_policy.sql
 
-- 6b: Klassische Audit-Optionen deaktivieren (nach Sicherung / Absprache!)
@disable_all_audit_options.sql
 
-- 6c: Eigene Policies anlegen und aktivieren
--     Siehe: gpi_audit_policies.sql (gpi_DB_MIN_SEC_AUDIT + gpi_SEC_AUDIT_TRUNC)
@gpi_audit_policies.sql
 
-- 6d: Prüfen welche Policies aktiv sind
COL POLICY_NAME    FORMAT A35
COL ENABLED_OPT    FORMAT A15
COL USER_NAME      FORMAT A20
COL ENTITY_NAME    FORMAT A20
COL ENTITY_TYPE    FORMAT A15
COL SUCCESS        FORMAT A8
COL FAILURE        FORMAT A8
SELECT * FROM audit_unified_enabled_policies;
 
 
================================================================================
SCHRITT 7 – LÖSCH-JOBS ÜBERWACHEN UND ARCHIV-TIMESTAMP PRÜFEN
================================================================================
 
-- Letzten Archive-Timestamp prüfen
COL AUDIT_TRAIL    FORMAT A20
COL LAST_ARCHIVE_TS FORMAT A35
SELECT * FROM DBA_AUDIT_MGMT_LAST_ARCH_TS;
 
-- Cleanup-Ereignisse (wurde schon gelöscht?)
COL AUDIT_TRAIL  FORMAT A20
COL first_cleanup FORMAT A30
COL last_cleanup  FORMAT A30
COL clean_cnt     FORMAT 99999
SELECT AUDIT_TRAIL,
       MIN(CLEANUP_TIME) AS first_cleanup,
       MAX(CLEANUP_TIME) AS last_cleanup,
       COUNT(*)          AS clean_cnt
  FROM DBA_AUDIT_MGMT_CLEAN_EVENTS
 GROUP BY AUDIT_TRAIL;
 
-- Scheduler-Job Logs (letzte 10 Läufe)
COL log_date        FORMAT A30
COL job_name        FORMAT A35
COL operation       FORMAT A15
COL STATUS          FORMAT A10
COL additional_info FORMAT A40
SELECT log_date, job_name, operation, STATUS, additional_info
  FROM dba_scheduler_job_log
 WHERE job_name LIKE '%AUDIT%'
 ORDER BY log_date DESC
 FETCH FIRST 10 ROWS ONLY;
 
 
================================================================================
SCHRITT 8 – PRÜFEN WER AUDIT-DATEN VERWENDET
================================================================================
 
-- Lesen externe Tools die Audit-Daten? (DB-Links, Scheduler-Jobs, Views prüfen)
-- Prüfen ob DBA_AUDIT_TRAIL / AUD$ direkt referenziert wird:
COL OWNER       FORMAT A15
COL NAME        FORMAT A30
COL TYPE        FORMAT A15
COL REFERENCED_OWNER FORMAT A15
COL REFERENCED_NAME  FORMAT A30
SELECT OWNER, NAME, TYPE, REFERENCED_OWNER, REFERENCED_NAME
  FROM DBA_DEPENDENCIES
 WHERE REFERENCED_NAME IN ('AUD$', 'DBA_AUDIT_TRAIL', 'DBA_FGA_AUDIT_TRAIL')
   AND OWNER NOT IN ('SYS', 'SYSTEM')
 ORDER BY 1, 2;
 
-- Aktive Sessions die Audit-Tabellen lesen
SELECT s.USERNAME, s.OSUSER, s.PROGRAM, s.MODULE, s.ACTION
  FROM V$SESSION s
 WHERE s.USERNAME IS NOT NULL
   AND EXISTS (
     SELECT 1 FROM V$SQL q
      WHERE q.SQL_ID = s.SQL_ID
        AND UPPER(q.SQL_TEXT) LIKE '%AUD$%')
 ORDER BY 1;
 
 
================================================================================
SCHRITT 9 – ÜBERWACHUNGSTOOLS ABSTIMMEN
================================================================================
 
-- Falls externe Überwachungstools (SIEM, Splunk, etc.) die klassischen
-- Audit-Views lesen (DBA_AUDIT_TRAIL, DBA_FGA_AUDIT_TRAIL):
-- → Umstellung auf UNIFIED_AUDIT_TRAIL / CDB_UNIFIED_AUDIT_TRAIL planen
-- → Umstellung für Downtime 2 koordinieren
-- → Testabfrage auf Unified Trail:
COL AUDIT_TYPE           FORMAT A15
COL DBUSERNAME           FORMAT A20
COL ACTION_NAME          FORMAT A25
COL EVENT_TIMESTAMP      FORMAT A30
COL UNIFIED_AUDIT_POLICIES FORMAT A35
SELECT AUDIT_TYPE, DBUSERNAME, ACTION_NAME,
       EVENT_TIMESTAMP, UNIFIED_AUDIT_POLICIES
  FROM CDB_UNIFIED_AUDIT_TRAIL
 ORDER BY EVENT_TIMESTAMP DESC
 FETCH FIRST 20 ROWS ONLY;
 
 
================================================================================
SCHRITT 10 – DOWNTIME 2 (NUR OFFLINE MÖGLICH!)
  Applikation muss gestoppt sein.
  Alle Datenbankinstanzen aus dem Oracle Home müssen neu gestartet werden.
================================================================================
 
-- Applikation stoppen, alle Verbindungen trennen
-- Prüfen ob noch Verbindungen aktiv:
SELECT COUNT(*), USERNAME FROM V$SESSION
 WHERE TYPE = 'USER' GROUP BY USERNAME;
 
 
-- herunterfahren
SHUTDOWN IMMEDIATE;
 
================================================================================
SCHRITT 11 – UMSTELLEN AUF UNIFIED AUDITING
================================================================================
 
-- LINUX: Oracle Kernel neu linken (als oracle-User, DB kann laufen!)
-- cd $ORACLE_HOME/rdbms/lib
-- make -f ins_rdbms.mk uniaud_on ioracle
--
-- Prüfen ob Relink erfolgreich:
-- strings $ORACLE_HOME/bin/oracle | grep kzaiang   → muss Treffer zeigen
-- strings $ORACLE_HOME/bin/oracle | grep kzanang   → sollte keine Treffer zeigen
--
-- WINDOWS: DLL umbenennen (als Administrator)
-- ren %ORACLE_HOME%\bin\orauniaud19.dll.dbl  %ORACLE_HOME%\bin\orauniaud19.dll
--
-- Datenbank neu starten (ZWINGEND nach dem Relink)
SHUTDOWN IMMEDIATE;
STARTUP;
 
-- Prüfen ob Unified Auditing jetzt aktiv (VALUE = TRUE):
COL PARAMETER FORMAT A30
COL VALUE     FORMAT A10
SELECT PARAMETER, VALUE FROM V$OPTION WHERE PARAMETER = 'Unified Auditing';
 
 
================================================================================
SCHRITT 12 – ÜBERWACHUNGSTOOLS ANPASSEN
================================================================================
 
-- Nach dem Neustart: externe Tools auf UNIFIED_AUDIT_TRAIL umstellen
-- Default-Policies prüfen und ggf. deaktivieren:
COL POLICY_NAME FORMAT A35
SELECT * FROM audit_unified_enabled_policies ORDER BY POLICY_NAME;
 
-- Oracle Default Policy deaktivieren wenn nicht benötigt:
-- NOAUDIT POLICY ORA_SECURECONFIG;
 
-- Eigene Policies erneut prüfen:
SELECT p.policy_name,
       AVG(CASE WHEN e.policy_name IS NOT NULL THEN 0 ELSE 1 END) AS enabled,
       COUNT(*) AS pl_cnt
  FROM audit_unified_policies p
  LEFT JOIN audit_unified_enabled_policies e ON p.policy_name = e.policy_name
 GROUP BY p.policy_name ORDER BY 2 DESC;
 
 
================================================================================
SCHRITT 13 – AUFRÄUMEN
================================================================================
 
-- Noch vorhandene klassische Audit-Einträge leeren (nach Archivierung!)
-- Archiv-Timestamp auf jetzt setzen:
BEGIN
  DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
    audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    last_archive_time => SYSTIMESTAMP);
  DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
    audit_trail_type  => DBMS_AUDIT_MGMT.AUDIT_TRAIL_FGA_STD,
    last_archive_time => SYSTIMESTAMP);
END;
/
 
-- Klassische Audit-Daten bereinigen:
BEGIN
  DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(
    audit_trail_type         => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD,
    use_last_arch_timestamp  => TRUE,
    container                => DBMS_AUDIT_MGMT.CONTAINER_ALL);
END;
/
 
-- Prüfen ob klassischer Trail leer:
SELECT COUNT(*) AS cnt, 'AUD' AS tab FROM SYS.AUD$
UNION ALL
SELECT COUNT(*) AS cnt, 'FGA' AS tab FROM SYS.FGA_LOG$;
 
-- Unified Audit Spillover-Dateien einlesen (OS-Dateien aus vorheriger Phase):
BEGIN
  DBMS_AUDIT_MGMT.LOAD_UNIFIED_AUDIT_FILES;
END;
/
 
 
================================================================================
SCHRITT 14 – LÖSCH-JOBS ÜBERWACHEN
================================================================================
 
-- Regelmäßig prüfen ob Jobs laufen und Daten löschen:
COL JOB_NAME     FORMAT A35
COL JOB_STATUS   FORMAT A10
COL AUDIT_TRAIL  FORMAT A20
SELECT JOB_NAME, JOB_STATUS, AUDIT_TRAIL, JOB_FREQUENCY,
       USE_LAST_ARCHIVE_TIMESTAMP
  FROM DBA_AUDIT_MGMT_CLEANUP_JOBS;
 
-- Letzten Cleanup-Zeitpunkt prüfen:
SELECT AUDIT_TRAIL,
       MIN(CLEANUP_TIME) AS first_cleanup,
       MAX(CLEANUP_TIME) AS last_cleanup,
       COUNT(*)          AS clean_cnt
  FROM DBA_AUDIT_MGMT_CLEAN_EVENTS
 GROUP BY AUDIT_TRAIL;
 
-- Datengröße überwachen:
SELECT t.OWNER, t.TABLE_NAME, s.TABLESPACE_NAME,
       ROUND(s.BYTES/1024/1024) AS MB
  FROM dba_tables t
 INNER JOIN DBA_SEGMENTS s ON (s.SEGMENT_NAME = t.TABLE_NAME AND s.owner = t.owner)
 WHERE t.table_name LIKE 'AUD$%'
   AND t.owner IN ('SYS', 'AUDSYS')
 ORDER BY 1, 2;
 
-- Scheduler-Job Logs (letzte 10 Läufe):
SELECT log_date, job_name, STATUS, additional_info
  FROM dba_scheduler_job_log
 WHERE job_name LIKE '%AUDIT%'
 ORDER BY log_date DESC
 FETCH FIRST 10 ROWS ONLY;
 
================================================================================
  Ende des Kochbuchs
================================================================================
gpi_audit_policies.sql
-- =============================================================================
-- gpi_audit_policies.sql
-- Minimale Sicherheits-Audit-Policies für Oracle 19c (FMW-RCU Umgebung).
-- Ausführen als: SYS (CDB$ROOT für CDB, oder PDB direkt für Single-Tenant)
-- Verwendung  : @gpi_audit_policies.sql
-- Quelle      : Gunther Pipperr | https://pipperr.de
-- =============================================================================
 
-- =============================================================================
-- Policy 1: gpi_DB_MIN_SEC_AUDIT
-- Überwacht privilegierte DDL-Operationen und kritische Systemänderungen.
-- =============================================================================
 
DROP AUDIT POLICY gpi_DB_MIN_SEC_AUDIT;
 
CREATE audit policy gpi_DB_MIN_SEC_AUDIT
  privileges
    CREATE external job,
    CREATE job,
    CREATE any job,
    -- VPD
    EXEMPT ACCESS POLICY,
  actions
    -- User / Role / Profile Management
    CREATE USER,    ALTER USER,    DROP USER,
    CREATE ROLE,    ALTER ROLE,    DROP ROLE,
    CREATE profile, ALTER profile, DROP profile,
    -- Synonyms (ALTER SYNONYM does not exist in 19c)
    CREATE synonym, DROP synonym,
    -- Database Links (ALTER DATABASE LINK does not exist in 19c)
    CREATE DATABASE link, DROP DATABASE link,
    -- Code Objects (ALTER PROCEDURE / ALTER TRIGGER not auditable as actions)
    CREATE PROCEDURE, DROP PROCEDURE,
    CREATE TRIGGER,   DROP TRIGGER,
    -- Table DDL
    CREATE TABLE, ALTER TABLE, DROP TABLE,
    -- rename
    RENAME,
    -- Grants / Revokes
    GRANT,
    REVOKE,
    -- System / Database
    ALTER system,
    ALTER DATABASE,
    -- Tablespace
    CREATE tablespace,
    DROP tablespace,    
    -- Directory
    CREATE directory,
    DROP directory,
    -- Audit Trail Protection (Object-specific actions)
    DELETE   ON audsys.aud$unified,
    UPDATE   ON audsys.aud$unified,
    -- Session
    logon,
    logoff
;
 
-- =============================================================================
-- Policy 2: gpi_SEC_AUDIT_TRUNC
-- Überwacht TRUNCATE auf der Unified Audit Tabelle selbst (Manipulationsschutz).
-- =============================================================================
 
DROP AUDIT POLICY gpi_SEC_AUDIT_TRUNC;
 
CREATE AUDIT POLICY gpi_SEC_AUDIT_TRUNC
  ACTIONS TRUNCATE TABLE
    WHEN 'SYS_CONTEXT(''USERENV'', ''CURRENT_SCHEMA'') = ''AUDSYS''
     AND SYS_CONTEXT(''USERENV'', ''CURRENT_OBJECT'') = ''AUD$UNIFIED'''
  EVALUATE PER STATEMENT;
 
 
-- =============================================================================
-- Policy 3: gpi_DATAPUMP_ACTION
-- Überwacht datapump
-- =============================================================================
 
DROP AUDIT POLICY gpi_DATAPUMP_ACTION;
 
CREATE audit policy gpi_DATAPUMP_ACTION
  actions component = datapump ALL;
 
 
 
-- =============================================================================
-- Policies aktivieren
-- =============================================================================
 
-- Für CDB (alle Container):
-- AUDIT POLICY gpi_DB_MIN_SEC_AUDIT CONTAINER=ALL;
-- AUDIT POLICY gpi_SEC_AUDIT_TRUNC  CONTAINER=ALL;
 
-- Für Single-Instance oder einzelne PDB:
AUDIT POLICY gpi_DB_MIN_SEC_AUDIT;
AUDIT POLICY gpi_SEC_AUDIT_TRUNC;
AUDIT POLICY gpi_DATAPUMP_ACTION;
 
-- =============================================================================
-- Prüfen ob welce Policies nun aktiv sind
-- =============================================================================
COL POLICY_NAME FORMAT A35
COL ENABLED_OPTION FORMAT A15
COL ENTITY_NAME   FORMAT A20
COL ENTITY_TYPE   FORMAT A20
COL SUCCESS     FORMAT A8
COL FAILURE     FORMAT A8
SELECT POLICY_NAME
     , ENABLED_OPTION
     , ENTITY_NAME
     , ENTITY_TYPE
     , SUCCESS
     , FAILURE
  FROM audit_unified_enabled_policies
 WHERE 1=1
 ORDER BY POLICY_NAME;
Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
"Autor: Gunther Pipperr"
dba/unified_auditing_oracle_migration_23ai.txt · Zuletzt geändert: von gpipperr