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.
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.
Ablauf:
Abschätzung des Zeitaufwandes pro Datenbank:
~8-12h
~4-5h
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!
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;
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!
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; /
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; /
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
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; /
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
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
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;
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.
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.
-- 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; /
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.
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; /
Ü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;
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:
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;
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');
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;
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.
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
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
Nach Neustart prüfen:
SELECT PARAMETER, VALUE FROM V$OPTION WHERE PARAMETER='Unified Auditing'; PARAMETER VALUE -------------------- -------- Unified Auditing TRUE
Nach dem aktiveren können nun die alten Regeln gelöscht werden.
Script zu deaktiveren:
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; /
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.
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.
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 ...;
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;
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/
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 auch https://databasesecurityninja.wordpress.com/tag/dbms_audit_mgmt-load_unified_audit_files/
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
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; /
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!
Die Rolle AUDIT_ADMIN wird für alle administrativen Aufgaben rund um das Unified Auditing benötigt.
Die Rolle umfasst folgende Berechtigungen:
Die Rolle AUDIT_VIEWER dient zum lesenden Zugriff auf die Auditdaten.
Die Rolle umfasst folgende Berechtigungen:
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.
---------------------------------------------------------------------------- -- 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;
Doku Oracle
23ai
Web:
23ai
================================================================================ 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 1 – STATUS 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 -- 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;