OCI Security Best Practices for Oracle DBAs — What You’re Probably Missing

When Oracle DBAs move their databases to OCI, they typically focus on the database itself — configurations, performance, backup. The cloud security layer often gets less attention, usually because it’s managed by a separate infrastructure team. But as a DBA, you’re responsible for your database’s data. That responsibility doesn’t stop at the Oracle listener. Here’s the security layer I review on every OCI database deployment.


Network Security Groups vs Security Lists — Use NSGs

OCI has two mechanisms for controlling network traffic: Security Lists (applied to subnets) and Network Security Groups (applied to individual resources). Most tutorials use Security Lists because they’re simpler to explain. In production, you should use NSGs.

The difference matters: a Security List rule applies to everything in the subnet. An NSG rule applies only to resources explicitly attached to that NSG. If you have multiple DB Systems in the same subnet with different security requirements, Security Lists force you to open rules for all of them. NSGs let you be specific.

For your Oracle DB Systems, create a dedicated NSG:

  • Inbound port 1521 (or your listener port) from your application tier NSG only
  • Inbound port 22 (SSH) from your bastion host NSG only (not from 0.0.0.0/0)
  • No direct internet access to database subnets — ever

Bastion Service — Stop Using Jump Hosts

If you’re managing your OCI DB Systems by SSH-ing through a jump host (a VM you keep running just for SSH access), you’re paying for a VM that has one purpose and represents a persistent attack surface.

OCI Bastion Service provides managed, time-limited SSH sessions to private resources without requiring a running jump host VM. You create a bastion session, it’s valid for a configured time period (maximum 3 hours), and it’s gone. No persistent VM. Full audit trail.

bash

# Create a bastion session via OCI CLI
oci bastion session create-managed-ssh \
--bastion-id <bastion_ocid> \
--ssh-public-key-file ~/.ssh/id_rsa.pub \
--target-resource-id <db_system_node_ocid> \
--target-os-username opc \
--session-ttl-in-seconds 3600
# Connect using the session
ssh -i ~/.ssh/id_rsa -o ProxyCommand='...' opc@<db_node_private_ip>

Every bastion session is logged. Who created it, when, from which IP, to which target. That’s your audit trail without any additional tooling.


Oracle Data Safe — Enable It, Actually Use It

Data Safe is included with OCI at no additional cost for OCI-hosted databases. It provides security assessment, user assessment, data discovery, data masking, and activity auditing. Most teams enable it, look at the dashboard once, and forget it exists.

The two features I consider essential:

Security Assessment scans your database configuration against a baseline of security best practices and CIS Oracle benchmarks. It flags things like default passwords that haven’t been changed, excessive system privileges, users with DBA role who don’t need it, and database parameters that weaken security.

Run it on a new database before you put it into production. You will find things you missed.

User Assessment catalogs all database users, their privilege grants, and last login times. In production databases that have been running for years, I consistently find users that haven’t logged in for 12+ months with DBA or SYSDBA privilege. Those accounts should be locked or dropped.

sql

-- Manual equivalent: find users with DBA role, last login
SELECT grantee, admin_option,
(SELECT TO_CHAR(last_login, 'YYYY-MM-DD')
FROM dba_users u
WHERE u.username = rp.grantee) last_login
FROM dba_role_privs rp
WHERE granted_role = 'DBA'
ORDER BY last_login NULLS FIRST;

Any user with DBA privilege who hasn’t logged in for over 90 days is a risk. Lock them. If someone complains, unlock them — but the default should be locked.


Transparent Data Encryption — Default On, But Check Your Key Management

OCI DB Systems enable TDE by default. Your tablespaces are encrypted. Good. But default TDE uses Oracle-managed keys stored in the Oracle Wallet on the database server itself. This is encryption where the key lives next to the data — better than nothing, but not ideal.

For any database handling sensitive data (PII, financial data, health records), integrate TDE with OCI Vault for external key management:

sql

-- Check current TDE configuration
SELECT * FROM v$encryption_wallet;
-- For OCI-integrated key management, the wallet should show
-- STATUS = OPEN, WRL_TYPE = OKV or ORACLE_KEY_VAULT

With OCI Vault managing your TDE master keys, the encryption keys are stored separately from the database. Someone who gains access to your database storage can’t decrypt data without also compromising your key vault. This separation is what auditors look for in regulated environments.


Unified Auditing — Configure It Properly

Oracle 19c and 23ai use Unified Auditing. The default policy captures some activity but not everything you need for security monitoring. Review and customize:

sql

-- Check which audit policies are enabled
SELECT policy_name, enabled_option, entity_name
FROM audit_unified_enabled_policies
ORDER BY policy_name;
-- Create a custom policy for sensitive tables
CREATE AUDIT POLICY sensitive_data_access
ACTIONS SELECT, INSERT, UPDATE, DELETE
ON hr.employees, finance.payroll
WHEN 'SYS_CONTEXT(''USERENV'',''SESSION_USER'') != ''APP_USER'''
EVALUATE PER SESSION;
AUDIT POLICY sensitive_data_access;

The WHEN clause is powerful — it lets you audit only when the condition is true, filtering out expected application access and focusing on unexpected access patterns.

Store your audit data in a separate tablespace, or better, forward it to a centralized SIEM. Audit data sitting in the database it’s auditing is only somewhat useful — if someone compromises the database, they can manipulate the audit trail. External log forwarding addresses this.


Principle of Least Privilege — Review It Quarterly

The most reliable security control is also the most neglected: don’t give users privileges they don’t need.

sql

-- Find users with privileges they likely don't need
-- Users with CREATE ANY TABLE (dangerous)
SELECT grantee, privilege FROM dba_sys_privs
WHERE privilege IN ('CREATE ANY TABLE', 'DROP ANY TABLE',
'ALTER ANY TABLE', 'SELECT ANY TABLE',
'EXECUTE ANY PROCEDURE', 'CREATE ANY PROCEDURE')
AND grantee NOT IN ('SYS','SYSTEM','DBA')
ORDER BY grantee, privilege;
-- Find roles with excessive privileges
SELECT role, privilege FROM role_sys_privs
WHERE privilege LIKE 'ANY%'
ORDER BY role, privilege;

ANY privileges are broadly dangerous. SELECT ANY TABLE means the grantee can read any table in any schema. This is almost never needed for application users. Find these grants, understand why they were given, and revoke what isn’t necessary.

Schedule a quarterly privilege review. It’s boring, manual work. It’s also one of the most effective things you can do for database security.



Yorum bırakın