Monday, November 25, 2013

Where has your LDAP connection pool gone?



You have deployed Oracle BPM and decided to run some load tests against it. You're concerned, among other things, about the behavior of your backend LDAP server under peak times, whether it's going to be able to handle the load or not. You check the security providers settings in Weblogic Server and see you have an LDAP Authenticator (or some specialization, like OVD Authenticator, for instance) with an ldap pool size set to 50 connections. But your test reveals that many more than 50 connections gets open in your LDAP server. You change that number, redo your tests, but the behavior doesn't change at all. Then you get worried about the LDAP connection handling performed by the Weblogic authenticator.

This post is to tell you, as far this scenario goes, there's nothing wrong with it. In fact, for this specific scenario, you're looking at the wrong place for your connection pool settings.

Oracle BPM, as well as SOA, WebCenter, UCM (Universal Content Management), IPM (Imaging Processing Management) and others use something called User/Role API to communicate with LDAP stores. Whenever these components need to assert a user identity or query user/group/attribute information, they go through User/Role API. It is an abstraction built on top of JNDI to ease the access to Directory servers. You can connect to any LDAP server supported by WLS authenticators and use the very same set of APIs to retrieve and write data without having to resort on JNDI, regardless of the LDAP server you connect to.


User/Role API has a strict design. This blog post  clarifies some important aspects you need to know about it. And here comes something I haven't mentioned there. User/Role API doesn't leverage the connection pool settings defined in WLS authenticators. Instead, it uses one of these two options:

a) User/Role API own connection pool

b) JDK's JNDI connection pool

You figure out which one is being used by looking at the idstore.ldap service instance in jps-config.xml:

You are with User/Role API own connection pool if you have

<serviceInstance name="idstore.ldap" provider="idstore.ldap.provider">
    ...
    <property name="CONNECTION_POOL_CLASS" value="oracle.security.idm.providers.stdldap.LDConnectionPool"/>
    ...
</serviceInstance>

In this case, the following properties are applicable for configuring the pool:

connection.pool.authentication
connection.pool.max.size
connection.pool.min.size
connection.pool.protocol
connection.pool.provider.type
connection.pool.timeout
oracle.security.jps.ldap.max.retry

You find their descriptions and possible values in this document.

They are specified in the idstore.ldap service instance as name/value pairs, like, for instance:

<property name="connection.pool.max.size" value="20"/>


You are with JDK's JNDI connection pool if:

<serviceInstance name="idstore.ldap" provider="idstore.ldap.provider">
    ...
    <property name="CONNECTION_POOL_CLASS" value="oracle.security.idm.providers.stdldap.JNDIPool"/>
    ...
</serviceInstance>

And in this case the relevant properties are the following:

com.sun.jndi.ldap.connect.pool.debug
com.sun.jndi.ldap.connect.pool.initsize
com.sun.jndi.ldap.connect.pool.prefsize
com.sun.jndi.ldap.connect.pool.maxsize
com.sun.jndi.ldap.connect.pool.protocol
com.sun.jndi.ldap.connect.pool.timeout

Please look at this document for their complete description and possible values.

These are system properties. As such, they can be set in the setDomainEnv.sh script and applied to all the servers in a given Weblogic server domain. Just add them to the variable EXTRA_JAVA_PROPERTIES using the -D switch and restart your servers.

Whenever possible, go with JNDI connection pool.

Are LDAP SSL connections pooled?


Now, if the LDAP Authenticator connects through SSL, there's one vital detail, a direct consequence of what's stated in the JNDI documentation above, transcripted here:

"There are a couple of environment properties that automatically disqualify a Context instance from using a pooled connection. A Context instance cannot use a pooled connection if it has its "java.naming.ldap.factory.socket" property set to a custom socket factory class, or its "java.naming.security.sasl.callback" property set to a custom callback handler class, or its "com.sun.jndi.ldap.trace.ber" property set to enable protocol tracing."

Guess what? User/Role API does use a custom socket factory for LDAP connections over SSL. Therefore, no connections are pooled if SSL is on, no matter which connection pool. Unless...

In order to get User/Role API pooling LDAP SSL connections, you need to make sure of 3 things:

1) LDAP server SSL mode is server auth
2) LDAP server's certificate has been imported into Weblogic truststore
3) User/Role API uses JDK's default SSL socket factory: javax.net.ssl.SSLSocketFactory. And that must be set for idstore.ldap service instance in jps-config.xml, as per:

<serviceInstance name="idstore.ldap" provider="idstore.ldap.provider">
...
<property name="java.naming.ldap.factory.socket" value="javax.net.ssl.SSLSocketFactory"/>
...
</serviceInstance>


What if LibOVD is on?


And what if virtualize=true flag is enabled, meaning libOVD is active? For an introduction to libOVD, look here.

In this case, User/Role API no longer plays. LibOVD has its own connection pool and that is managed in adapters.os_xml. By default, you find this file under $MW_HOME/user_projects/domains/$DOMAIN_NAME/config/fmwconfig/ovd/default. Notice that connection pool parameters are specific to each adapter.

For each adapter, you'd have something like:

<ldap id="OIDAuthenticator" version="0">
...
<heartBeatInterval>60</heartBeatInterval>
<timeout>120000</timeout>
<maxPoolSize>10</maxPoolSize>
<maxPoolWait>1000</maxPoolWait>
<maxPoolChecks>10</maxPoolChecks>
...
</ldap>


Finally...


All this naturally begs the question: when are the connection pool settings in Weblogic authenticators used?

Mostly at authentication times in applications that makes use of container-based authentication. For example, ADF applications, who delegates authentication to the container. However, keep in mind there's nothing preventing applications to employ User/Role API internally. And there's also nothing preventing administrators to activate libOVD. So yeah, there might be occasions where you'll need to tune the connection pool in JNDI/User Role API and Weblogic, or in LibOVD and Weblogic.


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.