| Security Advisory | 
    
    
      Fine Grained Auditing is policy based conditional auditing that can be based on specific columns and specific column values. 
       
      DB Audit sends the audit trail to the SYS.FGA_LOG$ table in the database and omits SQL Text and SQL Bind. 
      XML Audit writes the audit trail in XML files sent to the operating system and omits SQL Text and SQL Bind. | 
    
    
      |   | 
    
    
      | Recommended Security Rules | 
    
    
       
       NEVER
      
        - If deploy an application on Oracle Database Enterprise Edition without Fine Grained Auditing. To do so is irresponsible as you are not just ignoring an incredible security tool ... you are wasting money.
 
       
       WITH GREAT CARE
      
        - Test your Fine Grained Auditing deployment to verify that it is giving you visibility into what is going on inside your database.
 
       
       CAUTIONS 
      
        - Be careful to protect the source and deployed code of a Fine Grained Auditing application from tampering.
 
       
       | 
    
    
      |   | 
    
    
      | How Oracle Works | 
    
    
      The code for a working demo can be found at the bottom of this page. The demo can be built with cut-and-paste in just a few minutes.
      Spend a few hours working with the demo then go to the Oracle docs, read up on this incredibly powerful tool, then deploy it in your organization. 
       
      But remember, auditing is worthless if no one is monitoring the audit output. If one person, or one group, is not responsible for monitoring then no one is monitoring. | 
    
    
      |   | 
    
    
      | DBMS_FGA Package Information | 
    
    
      | AUTHID | 
      CURRENT_USER | 
    
    
      | Constants | 
      
        
          
            
              | Name | 
              Data Type | 
              Value | 
             
            
              | EXTENDED | 
              PLS_INTEGER | 
              1 | 
             
            
              | DB | 
              PLS_INTEGER | 
              2 | 
             
            
              | DB_EXTENDED (default) | 
              PLS_INTEGER | 
              3 | 
             
            
              | XML | 
              PLS_INTEGER | 
              4 | 
             
            
              | ALL_COLUMNS | 
              BINARY_INTEGER | 
              1 | 
             
            
              | ANY_COLUMNS (default) | 
              BINARY_INTEGER | 
              0 | 
             
             | 
    
    
      | Dependencies | 
      
        
          
            
              | DBMS_CRYPTO_FFI | 
              DBMS_REGISTRY | 
              KUPM$MCP | 
             
            
              | DBMS_ISCHED | 
              DBMS_SCHEDULER | 
              MGWI_CRYPTO | 
             
            
              | DBMS_ISCHED_REMOTE_ACCESS | 
              DBMS_SQLHASH | 
              UTL_RAW | 
             
            
              | DBMS_METADATA_DIFF | 
              DBMS_REGISTRY | 
                | 
             
             | 
    
    
      | Documented in Types & Packages | 
      Yes | 
    
    
      | First Available | 
      9.0.1 | 
    
    
      | Initialization Parameters | 
      col name format a30 
      col value format a40 
       
      SELECT name, value 
      FROM gv$parameter 
      WHERE name LIKE '%audit%'; | 
    
    
      | Pragmas | 
      PRAGMA SUPPLEMENTAL_LOG_DATA(default, AUTO) | 
    
    
      | Security Model | 
      Owned by SYS with EXECUTE granted to the AUDIT_ADMIN and EXECUTE_CATALOG_ROLE roles | 
    
    
      | Source | 
      {ORACLE_HOME}/rdbms/admin/dbmsfga.sql | 
    
    
      | Subprograms | 
      
         | 
    
    
      |   | 
    
    
      | ADD_POLICY | 
    
    
      | Create a new audit policy | 
      dbms_fga.add_policy( 
      object_schema     IN VARCHAR2       := NULL, 
      object_name       IN VARCHAR2, 
      policy_name       IN VARCHAR2, 
      audit_condition   IN VARCHAR2       := NULL, 
      audit_column      IN VARCHAR2       := NULL, 
      handler_schema    IN VARCHAR2       := NULL, 
      handler_module    IN VARCHAR2       := NULL, -- alerting mechanism 
      enable            IN BOOLEAN        := NULL, 
      statement_types   IN VARCHAR2       := 'SELECT', 
      audit_trail       IN PLS_INTEGER    := 3, 
      audit_column_opts IN BINARY_INTEGER DEFAULT 0, 
      policy_owner      IN VARCHAR2       := NULL); | 
    
    
      exec dbms_fga.add_policy(object_schema=>'UWCLASS', object_name=> 'FGA_DEMO', policy_name=> 'UW Audit', 
      audit_condition=> 'status = ''A''', audit_column=> 'last_name, salary', handler_schema => 'UWCLASS',
      handler_module=> 'FGA_HANDLER', enable => TRUE, statement_types => 'INSERT, UPDATE', audit_trail => DBMS_FGA.DB_EXTENDED, audit_column_opts => dbms_fga.all_columns); 
       
      col object_schema format a30 
      col policy_name format a30 
       
      SELECT object_schema, object_name, policy_name, audit_trail, enabled 
      FROM dba_audit_policies; | 
    
    
      |   | 
    
    
      | DISABLE_POLICY | 
    
    
      | Disable an audit policy | 
      dbms_fga.disable_policy( 
      object_schema IN VARCHAR2 := NULL, 
      object_name   IN VARCHAR2, 
      policy_name   IN VARCHAR2); | 
    
    
      exec  dbms_fga.disable_policy('UWCLASS', 'FGA_DEMO', 'UW Audit'); 
       
      SELECT object_schema, object_name, policy_name, audit_trail, enabled 
      FROM dba_audit_policies; | 
    
    
      |   | 
    
    
      | DROP_POLICY | 
    
    
      | Drop an audit policy | 
      dbms_fga.drop_policy( 
      object_schema IN VARCHAR2 := NULL, 
      object_name   IN VARCHAR2, 
      policy_name   IN VARCHAR2); | 
    
    
      exec dbms_fga.drop_policy('UWCLASS', 'FGA_DEMO', 'UW Audit'); 
       
      SELECT object_schema, object_name, policy_name, audit_trail, enabled 
      FROM dba_audit_policies; | 
    
    
      |   | 
    
    
      | ENABLE_POLICY | 
    
    
      | Enable or disable an audit policy | 
      dbms_fga.enable_policy( 
      object_schema IN VARCHAR2 := NULL, 
      object_name   IN VARCHAR2, 
      policy_name   IN VARCHAR2 
      enable        IN BOOLEAN  := TRUE); | 
    
    
      exec dbms_fga.enable_policy('UWCLASS', 'FGA_DEMO', 'UW Audit', TRUE); 
       
      SELECT object_schema, object_name, policy_name, audit_trail, enabled 
      FROM dba_audit_policies; | 
    
    
      |   | 
    
    
      | DBMS_FGA Demo | 
    
    
      | As SYS | 
      conn sys@pdbdev as sysdba 
       
      desc fga_log$ 
       
      SELECT COUNT(*) 
      FROM fga_log$; 
       
      desc dba_common_audit_trail 
       
      SELECT COUNT(*) 
      FROM dba_common_audit_trail; 
       
      GRANT EXECUTE ON dbms_fga TO uwclass; 
      GRANT select ON dba_audit_policies TO uwclass; 
      GRANT select ON dba_fga_audit_trail TO uwclass; 
       
      col name format a30 
      col value format a40 
       
      SELECT name, value 
      FROM gv$parameter 
      WHERE name LIKE '%audit%'; 
       
      ALTER SYSTEM SET audit_sys_operations = TRUE SCOPE=SPFILE; 
      -- will require a restart so change it back 
      ALTER SYSTEM SET audit_sys_operations = FALSE SCOPE=SPFILE; 
       
      -- ALTER SYSTEM SET audit_file_dest = <dir> DEFERRED; | 
    
    
      | Session 1 | 
      conn sys@pdbdev as sysdba 
       
      desc fga_log$ 
       
      SELECT COUNT(*) 
      FROM fga_log$; 
       
      GRANT EXECUTE ON dbms_fga TO uwclass; 
       
      GRANT select ON dba_audit_policies TO uwclass; 
       
      conn uwclass/uwclass@pdbdev 
       
      CREATE TABLE uwclass.fga_demo
      ( 
      person_id  NUMBER(5), 
      last_name  VARCHAR2(25), 
      salary     NUMBER(9,3), 
      status     VARCHAR2(1)); 
       
      ALTER TABLE fga_demo 
      ADD CONSTRAINT pk_fga_demo 
      PRIMARY KEY (person_id) 
      USING INDEX 
      PCTFREE 0; 
       
      ALTER TABLE fga_demo 
      ADD CONSTRAINT cc_fga_demo_status 
      CHECK (status IN ('A','I')); 
       
      CREATE TABLE fga_tab ( 
      owner       VARCHAR2(30), 
      table_name  VARCHAR2(30), 
      policy_name VARCHAR2(30)); 
       
      
        
          CREATE OR REPLACE PROCEDURE fga_handler ( 
            sname VARCHAR2, tname VARCHAR2, pname VARCHAR2) AUTHID DEFINER IS 
             
            PRAGMA AUTONOMOUS_TRANSACTION; 
             
            BEGIN 
              INSERT INTO fga_tab 
              (owner, table_name, policy_name) 
              VALUES 
              (sname, tname, pname); 
              COMMIT; 
            END fga_handler; 
            / | 
         
       
       
      exec dbms_fga.add_policy(object_schema=>'UWCLASS', object_name=> 'FGA_DEMO', policy_name=> 'UW_Audit', audit_condition=> 'status =
      ''A''', audit_column=> 'last_name, salary', handler_schema => 'UWCLASS', handler_module=> 'FGA_HANDLER',
      enable => TRUE, statement_types => 'INSERT, UPDATE, SELECT',audit_trail => DBMS_FGA.DB_EXTENDED, audit_column_opts => dbms_fga.all_columns); 
       
      desc dba_audit_policies 
       
      set linesize 141 
      col policy_text format a30 
       
      SELECT object_schema, object_name, policy_name 
      FROM dba_audit_policies; 
       
      SELECT policy_text, policy_column, enabled 
      FROM dba_audit_policies; 
       
      SELECT pf_schema, pf_package, pf_function 
      FROM dba_audit_policies; 
       
      SELECT sel, ins, upd, del, audit_trail, policy_column_options 
      FROM dba_audit_policies; 
       
      SELECT * FROM fga_tab; 
      SELECT * FROM fga_demo; 
       
      GRANT ALL on fga_demo TO abc;
       
       
      -- run Session 2 
       
      SELECT * FROM fga_demo; 
      SELECT * FROM fga_tab; | 
    
    
      | Session 2 | 
      CREATE SYNONYM fga_demo FOR uwclass.fga_demo; 
       
      INSERT INTO fga_demo 
      (person_id, last_name, salary, status) 
      VALUES 
      (1, 'Morgan', 2500, 'A'); 
       
      COMMIT; 
       
      UPDATE fga_demo 
      SET salary = salary * 1.05; 
       
      COMMIT; 
       
      UPDATE fga_demo 
      SET status = 'I'; 
       
      COMMIT; 
       
      UPDATE fga_demo 
      SET salary = salary * 1.05; 
       
      COMMIT; 
       
      UPDATE fga_demo 
      SET status = 'A'; 
       
      COMMIT; 
       
      UPDATE fga_demo 
      SET salary = salary * 1.05; 
       
      COMMIT; | 
    
    
      | Clean up | 
      conn sys@pdbdev as sysdba 
       
      SELECT COUNT(*) 
      FROM fga_log$; 
       
      DELETE FROM fga_log$; 
       
      COMMIT; |