Oracle Database Vault (DBV) restricts highly privileged database accounts (DBA, SYSDBA) from accessing application data. On Exadata, this is particularly important: Exadata DBAs have elevated OS access (root on compute nodes, cellcli on storage cells), making privilege separation inside the database itself critical for compliance frameworks such as SOX, PCI-DSS, and HIPAA.

This guide implements DB Vault entirely via command line — no OEM Cloud Control. All steps apply to Oracle Database 19c on Exadata in both CDB and non-CDB deployments.


Understanding DB Vault Roles

Before implementing, understand the mandatory role separation:

Role Purpose Best Practice
DV_OWNER Creates/manages DB Vault configuration Separate account, not DBA
DV_ACCTMGR Manages database user accounts Separate account, replaces DBA for account management
DV_ADMIN Administers DB Vault after initial setup Assigned to DV_OWNER initially
DBA Standard DBA role — restricted by DB Vault Cannot access application data in realms

The key principle: the DV_OWNER (Vault administrator) and DV_ACCTMGR (account manager) must be different individuals from the DBA team. This enforces separation of duties.


Phase 1: Pre-Implementation Assessment

1.1 Verify Prerequisites

-- Verify Oracle Database Vault is installed (licence check)
SELECT * FROM dba_registry WHERE comp_name = 'Oracle Database Vault';

-- If not installed, verify the option is available
SELECT * FROM v$option WHERE parameter = 'Oracle Database Vault';
# On the Exadata compute node: verify DBV components are installed
$ORACLE_HOME/bin/dbv help  # should return help output (not "command not found")

# Check if the DBV option is linked in the Oracle binary
$ORACLE_HOME/bin/oraversion -component ORACLE_DATABASE_VAULT

1.2 Identify Privileged Account Usage

Before enabling DB Vault, capture which accounts currently access application schemas using DBA privileges — DB Vault will block this access:

-- Identify DBA-privileged accounts with application schema access (last 30 days)
SELECT DISTINCT s.username,
       a.owner,
       a.action_name,
       COUNT(*) AS access_count
FROM dba_audit_trail a
JOIN dba_users s ON a.username = s.username
WHERE a.timestamp >= SYSDATE - 30
  AND a.owner IN (SELECT username FROM dba_users WHERE account_status = 'OPEN' AND default_tablespace NOT IN ('SYSTEM','SYSAUX'))
  AND s.username IN (SELECT grantee FROM dba_role_privs WHERE granted_role = 'DBA')
GROUP BY s.username, a.owner, a.action_name
ORDER BY access_count DESC;

Document all legitimate DBA access to application schemas — these will need exceptions or alternative access paths after DB Vault is enabled.


Phase 2: Enable Oracle Database Vault

2.1 Create DB Vault Owner and Account Manager Accounts

Run as SYSDBA before enabling DB Vault:

-- Create DB Vault owner account (separate from DBA)
CREATE USER c##dv_owner_admin IDENTIFIED BY "DVOwner#2026!"
  CONTAINER = ALL;  -- for CDB: use c## prefix

-- Create DB Vault account manager
CREATE USER c##dv_acctmgr_admin IDENTIFIED BY "DVAcctMgr#2026!"
  CONTAINER = ALL;

-- Required minimum grants (Oracle will complete the setup during configuration)
GRANT CREATE SESSION TO c##dv_owner_admin  CONTAINER = ALL;
GRANT CREATE SESSION TO c##dv_acctmgr_admin CONTAINER = ALL;

For non-CDB or PDB-specific implementation:

-- PDB-level (connect to specific PDB first)
ALTER SESSION SET CONTAINER = PDB_PROD;

CREATE USER dv_owner_admin IDENTIFIED BY "DVOwner#2026!";
CREATE USER dv_acctmgr_admin IDENTIFIED BY "DVAcctMgr#2026!";
GRANT CREATE SESSION TO dv_owner_admin;
GRANT CREATE SESSION TO dv_acctmgr_admin;

2.2 Run the DB Vault Configuration Script

# Run the DB Vault configuration script (as oracle OS user)
cd $ORACLE_HOME/rdbms/lib

# For CDB:
sqlplus / as sysdba

SQL> @?/rdbms/admin/dbvca.sql
-- The script will prompt for:
-- DV owner username:    c##dv_owner_admin
-- DV owner password:    DVOwner#2026!
-- DV account manager:   c##dv_acctmgr_admin
-- DV account manager password: DVAcctMgr#2026!

Alternatively, use dvcfg (pre-19c) or the PL/SQL API directly:

-- Configure DB Vault using the DVSYS API (19c+)
BEGIN
  CONFIGURE_DV(
    dvowner_uname     => 'c##dv_owner_admin',
    dvowner_passwd    => 'DVOwner#2026!',
    dvacctmgr_uname   => 'c##dv_acctmgr_admin',
    dvacctmgr_passwd  => 'DVAcctMgr#2026!'
  );
END;
/

2.3 Enable DB Vault (Requires Database Restart)

-- Enable DB Vault in the parameter file
ALTER SYSTEM SET enable_ddl_logging = TRUE SCOPE=BOTH;

-- Enable DB Vault (this step registers the option — requires restart)
EXEC DBMS_MACADM.ENABLE_DV;
# Restart the database to activate DB Vault
srvctl stop database -d ORCL
srvctl start database -d ORCL

2.4 Verify DB Vault Is Active

-- Connect as DV_OWNER to verify
CONNECT c##dv_owner_admin/DVOwner#2026!

SELECT * FROM DVSYS.DBA_DV_STATUS;
NAME                    STATUS
----------------------- -------
DATABASE VAULT          ENABLED
DATABASE VAULT CONFIGURE ENABLED

Phase 3: Create Realms

A Realm defines a protected zone. Objects in a realm are inaccessible to users outside the realm’s authorization list, even if those users have DBA or SELECT ANY TABLE privileges.

3.1 Create a Realm for the Application Schema

-- Connect as DV_OWNER
CONNECT c##dv_owner_admin/DVOwner#2026!

-- Create realm for the HR application schema
BEGIN
  DBMS_MACADM.CREATE_REALM(
    realm_name        => 'HR Application Realm',
    description       => 'Protects all HR schema objects from privileged user access',
    enabled           => DBMS_MACUTL.G_YES,
    audit_options     => DBMS_MACUTL.G_REALM_AUDIT_FAIL + DBMS_MACUTL.G_REALM_AUDIT_SUCCESS
  );
END;
/

3.2 Add Objects to the Realm

-- Add all objects owned by HR schema to the realm
BEGIN
  DBMS_MACADM.ADD_OBJECT_TO_REALM(
    realm_name  => 'HR Application Realm',
    object_owner => 'HR',
    object_name  => '%',      -- wildcard: all objects
    object_type  => '%'       -- wildcard: all object types
  );
END;
/

-- Add a specific sensitive table from a different schema
BEGIN
  DBMS_MACADM.ADD_OBJECT_TO_REALM(
    realm_name   => 'HR Application Realm',
    object_owner => 'PAYROLL',
    object_name  => 'SALARY_DETAILS',
    object_type  => 'TABLE'
  );
END;
/

3.3 Authorise Realm Participants

Authorised participants can access realm objects. These are the legitimate application accounts and DBAs who specifically need access:

-- Authorise the application owner (participant: can access objects)
BEGIN
  DBMS_MACADM.ADD_AUTH_TO_REALM(
    realm_name   => 'HR Application Realm',
    grantee      => 'HR',
    rule_set_name => NULL,
    auth_options => DBMS_MACUTL.G_REALM_AUTH_PARTICIPANT
  );
END;
/

-- Authorise a specific application service account
BEGIN
  DBMS_MACADM.ADD_AUTH_TO_REALM(
    realm_name   => 'HR Application Realm',
    grantee      => 'HR_APP_USER',
    auth_options => DBMS_MACUTL.G_REALM_AUTH_PARTICIPANT
  );
END;
/

-- Authorise a DBA for break-glass access (owner level: can manage realm objects)
BEGIN
  DBMS_MACADM.ADD_AUTH_TO_REALM(
    realm_name   => 'HR Application Realm',
    grantee      => 'DBA_BREAKGLASS',
    auth_options => DBMS_MACUTL.G_REALM_AUTH_OWNER
  );
END;
/

3.4 Test Realm Enforcement

-- Test: connect as DBA (should be blocked from HR objects)
CONNECT dba_user/dba_password

-- This should raise ORA-01031: insufficient privileges (DB Vault block)
SELECT * FROM HR.EMPLOYEES FETCH FIRST 1 ROW ONLY;

Expected error:

ORA-01031: insufficient privileges
-- This should work (DBA can still access system objects)
SELECT COUNT(*) FROM dba_tables WHERE owner = 'HR';   -- metadata: allowed

Phase 4: Create Command Rules

Command Rules restrict SQL commands (SELECT, INSERT, UPDATE, DELETE, ALTER SYSTEM, CONNECT, etc.) based on Rule Sets — conditions that must be true for the command to be allowed.

4.1 Restrict CONNECT During Maintenance Hours

-- Create a Rule: only allow CONNECT during business hours (Mon-Fri, 08:00-18:00)
BEGIN
  DBMS_MACADM.CREATE_RULE(
    rule_name => 'Business Hours Only',
    rule_expr => 'TO_CHAR(SYSDATE,''DY'') NOT IN (''SAT'',''SUN'')
                  AND TO_NUMBER(TO_CHAR(SYSDATE,''HH24'')) BETWEEN 8 AND 18'
  );
END;
/

-- Create a Rule Set containing this rule
BEGIN
  DBMS_MACADM.CREATE_RULE_SET(
    rule_set_name     => 'Business Hours Rule Set',
    description       => 'Allow connections only during business hours',
    enabled           => DBMS_MACUTL.G_YES,
    eval_options      => DBMS_MACUTL.G_RULESET_EVAL_ALL,  -- ALL rules must pass
    audit_options     => DBMS_MACUTL.G_RULESET_AUDIT_FAIL,
    fail_options      => DBMS_MACUTL.G_RULESET_FAIL_SHOW,  -- show error message
    fail_message      => 'Database access is restricted to business hours only',
    fail_code         => 20001,
    handler_options   => DBMS_MACUTL.G_RULESET_HANDLER_OFF
  );
END;
/

-- Add the rule to the rule set
BEGIN
  DBMS_MACADM.ADD_RULE_TO_RULE_SET(
    rule_set_name => 'Business Hours Rule Set',
    rule_name     => 'Business Hours Only'
  );
END;
/

-- Create Command Rule: CONNECT restricted to business hours for non-sys users
BEGIN
  DBMS_MACADM.CREATE_COMMAND_RULE(
    command         => 'CONNECT',
    rule_set_name   => 'Business Hours Rule Set',
    object_owner    => '%',
    object_name     => '%',
    enabled         => DBMS_MACUTL.G_YES
  );
END;
/

4.2 Prevent ALTER SYSTEM from Non-DBA Hosts

-- Create a Factor based on client IP address (network factor)
BEGIN
  DBMS_MACADM.CREATE_FACTOR(
    factor_name  => 'DB Admin Subnet',
    factor_type_name => 'Network',
    description  => 'Identifies whether the connection is from the DBA subnet',
    rule_set_name => NULL,
    get_expr     => 'UTL_INADDR.GET_HOST_ADDRESS(SYS_CONTEXT(''USERENV'',''IP_ADDRESS''))',
    validate_expr => NULL,
    identify_by  => DBMS_MACUTL.G_IDENTIFY_BY_CONTEXT,
    labeled_by   => DBMS_MACUTL.G_LABELED_BY_SELF,
    eval_options => DBMS_MACUTL.G_RULESET_EVAL_ALL,
    audit_options => DBMS_MACUTL.G_FACTOR_AUDIT_OFF,
    fail_options => DBMS_MACUTL.G_RULESET_FAIL_SHOW
  );
END;
/

-- Create a Rule: client IP must be in the DBA management subnet
BEGIN
  DBMS_MACADM.CREATE_RULE(
    rule_name => 'DBA Subnet Check',
    rule_expr => 'SYS_CONTEXT(''USERENV'',''IP_ADDRESS'') LIKE ''10.10.10.%'''
  );
END;
/

-- Rule Set for ALTER SYSTEM control
BEGIN
  DBMS_MACADM.CREATE_RULE_SET(
    rule_set_name => 'DBA Network Rule Set',
    description   => 'Allows ALTER SYSTEM only from DBA management network',
    enabled       => DBMS_MACUTL.G_YES,
    eval_options  => DBMS_MACUTL.G_RULESET_EVAL_ALL,
    audit_options => DBMS_MACUTL.G_RULESET_AUDIT_FAIL,
    fail_options  => DBMS_MACUTL.G_RULESET_FAIL_SHOW,
    fail_message  => 'ALTER SYSTEM is restricted to DBA management subnet',
    fail_code     => 20002,
    handler_options => DBMS_MACUTL.G_RULESET_HANDLER_OFF
  );
END;
/

BEGIN
  DBMS_MACADM.ADD_RULE_TO_RULE_SET(
    rule_set_name => 'DBA Network Rule Set',
    rule_name     => 'DBA Subnet Check'
  );
END;
/

-- Command Rule: ALTER SYSTEM restricted to DBA subnet
BEGIN
  DBMS_MACADM.CREATE_COMMAND_RULE(
    command       => 'ALTER SYSTEM',
    rule_set_name => 'DBA Network Rule Set',
    object_owner  => '%',
    object_name   => '%',
    enabled       => DBMS_MACUTL.G_YES
  );
END;
/

Phase 5: Simulation Mode (Exadata 19c+)

Before enforcing DB Vault policies, test them in Simulation Mode — violations are logged but not blocked. This allows you to identify unintended access patterns before going live.

-- Enable Simulation Mode for a realm (logs violations, does not block)
BEGIN
  DBMS_MACADM.UPDATE_REALM(
    realm_name   => 'HR Application Realm',
    description  => 'HR realm in simulation mode for 2 weeks',
    enabled      => DBMS_MACUTL.G_SIMULATION
  );
END;
/

-- Review simulation violations after 1 week
SELECT realm_name,
       username,
       machine,
       module,
       object_owner,
       object_name,
       command,
       violation_type,
       TO_CHAR(event_time, 'YYYY-MM-DD HH24:MI:SS') AS event_time
FROM dvsys.dba_dv_simulation_log
WHERE realm_name = 'HR Application Realm'
ORDER BY event_time DESC
FETCH FIRST 50 ROWS ONLY;

Review violations, add necessary realm authorisations for legitimate access, then switch from simulation to enforcement:

-- Switch realm from simulation to enforcement
BEGIN
  DBMS_MACADM.UPDATE_REALM(
    realm_name => 'HR Application Realm',
    enabled    => DBMS_MACUTL.G_YES
  );
END;
/

Phase 6: DB Vault on Exadata — Specific Considerations

Exadata Storage Cell Access

DB Vault operates at the database layer — it does not directly control OS-level access to Exadata storage cells. However:

  • DB Vault prevents DBAs from SELECT-ing application data even when they have OS access to the compute nodes.
  • For full separation, combine DB Vault with Exadata Security (cellcli access control) and OS-level auditing.

cellcli and DB Vault Integration

# On Exadata cells: restrict cellcli to specific OS users only
# (OS-level control, independent of DB Vault but complementary)
usermod -G celladmin restricted_dba_user

Auditing DB Vault Events on Exadata

DB Vault events are written to the Unified Audit Trail (Oracle 12c+):

-- View DB Vault audit records
SELECT event_timestamp,
       dbusername,
       os_username,
       ip_address,
       object_schema,
       object_name,
       sql_text,
       action_name,
       return_code
FROM unified_audit_trail
WHERE component = 'Database Vault'
  AND event_timestamp >= SYSDATE - 7
ORDER BY event_timestamp DESC
FETCH FIRST 100 ROWS ONLY;

Integrate these audit records with Oracle Audit Vault and Database Firewall (AVDF) for centralised, tamper-proof audit retention — the standard approach for SOX and PCI compliance on Exadata.


Phase 7: Verifying the Full Configuration

-- Connect as DV_OWNER: full status report
CONNECT c##dv_owner_admin/DVOwner#2026!

-- List all realms and their status
SELECT realm_name, description, enabled, audit_options
FROM dvsys.dba_dv_realm
ORDER BY realm_name;

-- List all realm authorisations
SELECT r.realm_name, a.grantee, a.auth_option
FROM dvsys.dba_dv_realm r
JOIN dvsys.dba_dv_realm_auth a ON r.realm_name = a.realm_name
ORDER BY r.realm_name, a.grantee;

-- List all command rules
SELECT command, rule_set_name, object_owner, object_name, enabled
FROM dvsys.dba_dv_command_rule
ORDER BY command;

-- List all rule sets
SELECT rule_set_name, enabled, eval_options, fail_message
FROM dvsys.dba_dv_rule_set
ORDER BY rule_set_name;

Disabling DB Vault (Break-Glass Procedure)

In an emergency requiring full DBA access to application data:

-- As DV_OWNER: temporarily disable a realm
BEGIN
  DBMS_MACADM.UPDATE_REALM(
    realm_name => 'HR Application Realm',
    enabled    => DBMS_MACUTL.G_NO
  );
END;
/

To fully disable DB Vault (requires database restart):

-- Disable DB Vault (DV_OWNER only)
EXEC DBMS_MACADM.DISABLE_DV;
srvctl stop database -d ORCL
srvctl start database -d ORCL

All disabling actions are audited. Ensure your audit policy captures DVSYS.DBMS_MACADM procedure calls so any break-glass usage is recorded and alerted.