Data Source Security Part 3
By Steve Felts-Oracle on Oct 12, 2012
In part one, I introduced the security features and talked about the default behavior. In part two, I defined the two major approaches to security credentials: directly using database credentials and mapping WLS user credentials to database credentials. Now it's time to get down to a couple of the security options (each of which can use database credentials or WLS credentials).
Set Client Identifier on Connection
When "Set Client Identifier" is enabled on the data source, a client property is associated with the connection. The underlying SQL user remains unchanged for the life of the connection but the client value can change. This information can be used for accounting, auditing, or debugging. The client property is based on either the WebLogic user mapped to a database user using the credential map or is the database user parameter directly from the getConnection() method, based on the “use database credentials” setting described earlier.
To enable this feature, select “Set Client ID On Connection” in the Console. See "Enable Set Client ID On Connection for a JDBC data source" http://docs.oracle.com/cd/E24329_01/apirefs.1211/e24401/taskhelp/jdbc/jdbc_datasources/EnableCredentialMapping.html in Oracle WebLogic Server Administration Console Help.
The Set Client Identifier feature is only available for use with the Oracle thin driver and the IBM DB2 driver, based on the following interfaces.
For pre-Oracle 12c, oracle.jdbc.driver.OracleConnection.setClientIdentifier(client) is used. See http://docs.oracle.com/cd/B28359_01/network.111/b28531/authentication.htm#i1009003 for more information about how to use this for auditing and debugging. You can get the value using getClientIdentifier() from the driver. To get back the value from the database as part of a SQL query, use a statement like the following.
“select sys_context('USERENV','CLIENT_IDENTIFIER') from DUAL”.
Starting in Oracle 12c, java.sql.Connection.setClientInfo(“OCSID.CLIENTID", client) is used. This is a JDBC standard API, although the property values are proprietary. A problem with setClientIdentifier usage is that there are pieces of the Oracle technology stack that set and depend on this value. If application code also sets this value, it can cause problems. This has been addressed with setClientInfo by making use of this method a privileged operation. A well-managed container can restrict the Java security policy grants to specific namespaces and code bases, and protect the container from out-of-control user code. When running with the Java security manager, permission must be granted in the Java security policy file for
permission "oracle.jdbc.OracleSQLPermission" "clientInfo.OCSID.CLIENTID";
Using the name “OCSID.CLIENTID" allows for upward compatible use of
“select sys_context('USERENV','CLIENT_IDENTIFIER') from DUAL”
or use the JDBC standard API java.sql.getClientInfo(“OCSID.CLIENTID") to retrieve the value.
This value in the Oracle USERENV context can be used to drive the Oracle Virtual Private Database (VPD) feature to create security policies to control database access at the row and column level. Essentially, Oracle Virtual Private Database adds a dynamic WHERE clause to a SQL statement that is issued against the table, view, or synonym to which an Oracle Virtual Private Database security policy was applied. See Using Oracle Virtual Private Database to Control Data Access http://docs.oracle.com/cd/B28359_01/network.111/b28531/vpd.htm for more information about VPD. Using this data source feature means that no programming is needed on the WLS side to set this context; it is set and cleared by the WLS data source code.
For the IBM DB2 driver, com.ibm.db2.jcc.DB2Connection.setDB2ClientUser(client) is used for older releases (prior to version 9.5). This specifies the current client user name for the connection. Note that the current client user name can change during a connection (unlike the user). This value is also available in the CURRENT CLIENT_USERID special register. You can select it using a statement like
“select CURRENT CLIENT_USERID from SYSIBM.SYSTABLES”.
When running the IBM DB2 driver with JDBC 4.0 (starting with version 9.5), java.sql.Connection.setClientInfo(“ClientUser”, client) is used. You can retrieve the value using java.sql.Connection.getClientInfo(“ClientUser”) instead of the DB2 proprietary API (even if set setDB2ClientUser()).
Oracle Proxy Session
Oracle proxy authentication allows one JDBC connection to act as a proxy for multiple (serial) light-weight user connections to an Oracle database with the thin driver. You can configure a WebLogic data source to allow a client to connect to a database through an application server as a proxy user. The client authenticates with the application server and the application server authenticates with the Oracle database. This allows the client's user name to be maintained on the connection with the database.
Use the following steps to configure proxy authentication on a connection to an Oracle database.
1. If you have not yet done so, create the necessary database users.
2. On the Oracle database, provide CONNECT THROUGH privileges. For example:
SQL> ALTER USER connectionuser GRANT CONNECT THROUGH dbuser;
where “connectionuser” is the name of the application user to be authenticated and “dbuser” is an Oracle database user.
3. Create a generic or GridLink data source and set the user to the value of dbuser.
4a. To use WLS credentials, create an entry in the credential map that maps the value of wlsuser to the value of dbuser, as described earlier.
4b. To use database credentials, enable “Use Database Credentials”, as described earlier.
5. Enable Oracle Proxy Authentication, see "Configure Oracle parameters" in Oracle WebLogic Server Administration Console Help.
6. Log on to a WebLogic Server instance using the value of wlsuser or dbuser.
6. Get a connection using getConnection(username, password). The credentials are based on either the WebLogic user that is mapped to a database user or the database user directly, based on the “use database credentials” setting.
You can see the current user and proxy user by executing:
“select user, sys_context('USERENV','PROXY_USER') from DUAL".
Note: getConnection fails if “Use Database Credentials” is not enabled and the value of the user/password is not valid for a WebLogic Server user. Conversely, it fails if “Use Database Credentials” is enabled and the value of the user/password is not valid for a database user.
A proxy session is opened on the connection based on the user each time a connection request is made on the pool. The proxy session is closed when the connection is returned to the pool. Opening or closing a proxy session has the following impact on JDBC objects.
- Closes any existing statements (including result sets) from the original connection.
- Clears the WebLogic Server statement cache.
- Clears the client identifier, if set.
-The WebLogic Server test statement for a connection is recreated for every proxy session.
These behaviors may impact applications that share a connection across instances and expect some state to be associated with the connection.
Oracle proxy session is also implicitly enabled when use-database-credentials is enabled and getConnection(user, password) is called,starting in WLS Release 10.3.6. Remember that this only works when using the Oracle thin driver.
To summarize, the definition of oracle-proxy-session is as follows.
- If proxy authentication is enabled and identity based pooling is also enabled, it is an error.
- If a user is specified on getConnection() and identity-based-connection-pooling-enabled is false, then oracle-proxy-session is treated as true implicitly (it can also be explicitly true).
- If a user is specified on getConnection() and identity-based-connection-pooling-enabled is true, then oracle-proxy-session is treated as false.