Configuring the Oracle JDBC Security Policy File

August 13, 2019 | 5 minute read
Text Size 100%:

Java Security Model

Java Security Manager provides additional protection for resources running in a JVM; It uses the Java security policy file to enforce a set of permissions granted to the code base. For example to use the NLS feature, application needs to give java.io.FilePermission "${oracle.jdbc.policy.ORAI18N}", "read"; permission. Please refer to the section below with the header "JDBC driver features and the required permissions" for more details.
You must enable the security manager to use the policy file.  One way to enable the security manager using the -Djava.security.manager option. Application servers such as Web Logic Server, Tomcat, JBoss, etc. have different ways to specify the policy file.

Please refer to the following link for more details about the Java Security Manager: https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-specTOC.fm.html

Policy File Strategy

Grant the least permissions as possible.
  • Start with the sample ojbc.policy file, described in the next section. Then run the application.
  • Check the thrown security exception. Add the smallest-grained permission possible in the file that fixes exception.
  • Repeat this until application run without exception.
  • Regularly review security policy files to accommodate any updates in the application.

Review all *.policy files. Check the policy files precedence order. Remove unused grants. Add extra permissions to applications or modules that require them, not all applications. Put comments in the file to track  your changes. To debug any issue use –Djava.security.debug=all to troubleshoot security failures.

 

ojdbc.policy File

This is a sample Oracle JDBC Driver Security Policy File. If you enable a SecurityManager, you must grant Oracle JDBC certain permissions. You need to use the Oracle JDBC security policy file in your application such as -Djava.security.policy=ojdbc.policy. This file can be downloaded from the JDBC OTN website. e.g.

http://download.oracle.com/otn/utilities_drivers/jdbc/193/ojdbc.policy

If you don’t use the policy file, then the JDBC driver won’t work when the security manager is enabled. E.g. you can get an exception like

Copied to Clipboard
Error: Could not Copy
Copied to Clipboard
Error: Could not Copy
[java] java.security.AccessControlException: access denied (javax.management.MBeanTrustPermission register)

When you use the policy file, it protects critical internal resources. No privileged access to external resources. This way one cannot use the Thin driver for a DoS (denial-of-service) attack.

The ojdbc.policy file is parameterized. You must define certain system properties to use it.

 e.g. -Doracle.jdbc.policy.JDBC_CODE_BASE=$ORACLE_HOME/lib/ojdbc8.jar

Here are the few samples of policy file:

Sample-1: Application uses a  Thin driver connection and queries a table

I have a Select.java which connects to a database and then select from a table (e.g. DUAL) in that database. Here is the code snippet for it:


OracleDataSource ds = new OracleDataSource();
String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=myhost)(PORT=myport))(CONNECT_DATA=(SERVICE_NAME=myservicename)))";
ds.setURL(url);

Connection conn = ds.getConnection();
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery(“SELECT * FROM dual”);

You can run this sample to use the file using the following command:

java -Doracle.jdbc.policy.CLIENT_HOST=myclienthost -Doracle.jdbc.policy.DBMS_HOST=myserverhost -Doracle.jdbc.policy.DBMS_PORT=myport -Doracle.jdbc.policy.JDBC_CODE_BASE=$ORACLE_HOME/lib/ojdbc8.jar -Doracle.jdbc.policy.USER_CODE_BASE=/myhome/application/- -Doracle.jdbc.policy.CONFIG_FILE=$TNS_ADMIN/ojdbc.properties -Djava.security.manager -Djava.security.policy=myojdbc.policy Select

Please update above command with your actual host, port, application directory, etc.

myojdbc.policy file looks as shown below:

grant codeBase "file:${oracle.jdbc.policy.JDBC_CODE_BASE}" {
/* Always needed */
permission java.sql.SQLPermission "deregisterDriver", "";
permission java.util.PropertyPermission "user.name", "read";
permission java.util.PropertyPermission "oracle.jdbc.*", "read";
permission java.util.PropertyPermission "database", "read";
permission java.util.PropertyPermission "oracle.net.*", "read";
permission java.util.PropertyPermission "javax.net.ssl.*", "read";
permission java.lang.management.ManagementPermission "control";
permission javax.management.MBeanServerPermission "createMBeanServer";
permission javax.management.MBeanPermission "oracle.jdbc.driver.OracleDiagnosabilityMBean#[com.oracle.jdbc:type=diagnosability,*]", "registerMBean";
permission javax.management.MBeanTrustPermission "register";
permission java.lang.RuntimePermission "getenv.TNS_ADMIN";
permission java.util.PropertyPermission "TNS_ADMIN", "read";
permission java.io.FilePermission "${oracle.jdbc.policy.CONFIG_FILE}", "read";
permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.util.PropertyPermission "java.util.logging.config.file", "read";
/* Needed only if you use the Thin driver */ permission java.net.SocketPermission "${oracle.jdbc.policy.CLIENT_HOST}", "connect,resolve";
permission java.net.SocketPermission "${oracle.jdbc.policy.DBMS_HOST}:${oracle.jdbc.policy.DBMS_PORT}", "connect,resolve";
/* Allow the JDBC driver to auto-resolve and instantiate the Oracle PKI * Provider (For SSL with Oracle Wallets). Not needed if the Oracle PKI * provider is registered with Java security. */
permission java.util.PropertyPermission "oracle.pki.*", "read";
permission java.security.SecurityPermission "putProviderProperty.OraclePKI";
/* Allow the driver to obtain all key stores from Key Store Service */
permission oracle.security.jps.service.keystore.KeyStoreAccessPermission "stripeName=*,keystoreName=*,alias=*", "read"; };

grant codeBase "file:${oracle.jdbc.policy.USER_CODE_BASE}" {
permission java.io.FilePermission "${oracle.jdbc.policy.USER_CODE_BASE}","read,write";
permission java.io.FilePermission "${oracle.jdbc.policy.ORAI18N}", "read";
permission javax.management.MBeanServerPermission "createMBeanServer";
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.util.PropertyPermission "oracle.jdbc.*", "read";
/* Needed only if you use the Thin driver */
permission java.net.SocketPermission "${oracle.jdbc.policy.DBMS_HOST}:${oracle.jdbc.policy.DBMS_PORT}", "connect,resolve";
permission java.net.SocketPermission "${oracle.jdbc.policy.CLIENT_HOST}", "connect,resolve";
/* Needed only if you use Key Store Service. Replace the * to limit access. */
permission oracle.security.jps.service.keystore.KeyStoreAccessPermission "stripeName=*,keystoreName=*,alias=*", "read"; };

If you use the Thick driver then, you need to add more permissions in the myojdbc.policy file as shown below:

grant codeBase "file:${oracle.jdbc.policy.JDBC_CODE_BASE}" { …
/* Needed only if you use the OCI driver */
permission java.lang.RuntimePermission "loadLibrary.ocijdbc19"; }

Sample-2: Application uses a Universal Connection Pool and query a table

I have a UCPSelect.java which connects to a database and then select from a table (e.g. DUAL) in that database. This time it uses the Universal Connection Pool. Here is the code snippet for it:


PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=myhost)(PORT=myport))(CONNECT_DATA=(SERVICE_NAME=myservicename)))";
pds.setURL(url);
pds.setConnectionFactoryClassName(OracleDataSource.class.getName());

Connection conn = pds.getConnection();
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery(“SELECT * FROM dual”);

You can run this sample to use the file using the following command:

java -Doracle.jdbc.policy.CLIENT_HOST=myclienthost -Doracle.jdbc.policy.DBMS_HOST=myserverhost -Doracle.jdbc.policy.DBMS_PORT=myport -Doracle.jdbc.policy.JDBC_CODE_BASE=$ORACLE_HOME/lib/ojdbc8.jar -Doracle.jdbc.policy.CONNECTION_POOL_CODE_BASE=$ORACLE_HOME/lib/ucp.jar -Doracle.jdbc.policy.USER_CODE_BASE=/myhome/application/- -Doracle.jdbc.policy.CONFIG_FILE=$TNS_ADMIN/ojdbc.properties -Djava.security.manager -Djava.security.policy=myojdbc.policy UCPSelect

Please update above command with your actual host, port, application directory, etc.

You need to add more permissions in the myojdbc.policy file as shown below:

/* Needed only if you use connection pool. */
grant codeBase "file:${oracle.jdbc.policy.CONNECTION_POOL_CODE_BASE}" {
/* Always needed */
permission java.util.PropertyPermission "oracle.ucp.*", "read";
permission java.util.PropertyPermission "oracle.jdbc.*", "read";
permission java.util.PropertyPermission "oracle.jdbc.fanEnabled", "write";
permission java.util.PropertyPermission "oracle.jdbc.beginRequestAtConnectionCreation", "write";
permission java.util.PropertyPermission "java.util.logging.config.file", "read";
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.lang.RuntimePermission "shutdownHooks";
permission java.lang.RuntimePermission "modifyThread";
permission javax.management.MBeanServerPermission "createMBeanServer";
permission javax.management.MBeanPermission "oracle.ucp.admin.UniversalConnectionPoolManagerMBean#-[oracle.ucp.admin:name=UniversalConnectionPoolManagerMBean(*),*]", "registerMBean";
permission javax.management.MBeanPermission "oracle.ucp.admin.JDBCUniversalConnectionPoolMBeanImpl#-[oracle.ucp.admin.UniversalConnectionPoolMBean:name=*]", "registerMBean";
/* Needed only if you use the Thin driver */ permission java.net.SocketPermission "${oracle.jdbc.policy.CLIENT_HOST}", "connect,resolve";
permission java.net.SocketPermission "${oracle.jdbc.policy.DBMS_HOST}:${oracle.jdbc.policy.DBMS_PORT}", "connect,resolve"; };

The JDBC driver features and the required permissions

Only define the system properties required by the JDBC features you use. Many permissions based on a feature in use such as DMS, XA, XDB, AQ, NLS, etc.

Here is the table showing features and related permissions to grant in the policy file for the ojdbc??.jar codebase:

Feature

Permissions

Remark

NLS

java.io.FilePermission "${oracle.jdbc.policy.ORAI18N}", "read";

Put orai18n.jar in your classpath

AQ or DCN

java.net.SocketPermission "${oracle.jdbc.policy.DBMS_HOST}", "accept";

 

DMS

java.util.PropertyPermission "oracle.dms.console.DMSConsole", "read";
java.util.PropertyPermission "oracle.dms.mount", "read";
java.util.PropertyPermission "oracle.dms.property.file", "read";
java.util.PropertyPermission "oracle.dms.clock", "read";
java.util.PropertyPermission "oracle.dms.clock.units", "read";
java.util.PropertyPermission "oracle.dms.publisher.classes", "read";

 

XA

java.util.PropertyPermission "oracle.jserver.version", "read";

 

XML

java.util.PropertyPermission "oracle.xdkjava.compatibility.version", "read";

 

Fast Connection Failover

oracle.ons.CreatePermission "ONSUser";
oracle.ons.SubscribePermission "ONSUser";
java.io.FilePermission "${oracle.jdbc.policy.OPMN_CONFIG}", "read";
java.util.PropertyPermission "oracle.ons.*", "read";
java.net.SocketPermission "${oracle.jdbc.policy.REMOTE_ONS_HOST1}:${oracle.jdbc.policy.REMOTE_ONS_PORT1}", "connect,resolve";
java.net.SocketPermission "localhost", "connect,resolve";

Remote ONS host:port

 

The sample ojdbc.policy file contains comments for permissions needed for each feature and codebase. Please read it and make the necessary changes for your application requirement.

There may be a small performance penalty when you use the policy file. It only applies when an application attempts some activity that requires permission checks. Most operations that require permission checks are expensive operations (IO, Network access, etc.) so the overhead of security checks will be a pretty low percentage of total runtime. Benchmark your application to determine performance overhead.

Resources

  • Policy File Syntax:

http://docs.oracle.com/javase/8/docs/technotes/guides/security/PolicyFiles.html#FileSyntax

  • Permissions in JDK:

http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html

  • JDBC Download:

http://www.oracle.com/technetwork/database/features/jdbc/jdbc-ucp-122-3110062.html

ILESH GARISH


Previous Post

Oracle Functions: Invoking Functions Automatically With Cloud Events

Todd Sharp | 5 min read

Next Post


Oracle Functions: Using Key Management To Encrypt And Decrypt Configuration Variables

Todd Sharp | 6 min read
Oracle Chatbot
Disconnected