Java LDAP connection pooling
Door Stefan Jansen / mrt 2015 / 1 Min
Door Avisi / / 2 min
At Avisi we maintain an application platform where the platform (VM's, databases, LDAP, etc.) is maintained by a third party. Modernizing our deployment processes, we obtained ownership of the platform's configuration. This brought up a practical issue: we don't know the passwords used by the applications to connect to the services provided by the platform (database, LDAP). In fact, we aren't allowed to know these passwords since that would break the SLA with the platform provider.
Before, the platform provider would set the required credentials but since we're automating our build & deployment cycle (in fact, we're moving to Continuous Delivery) a manual step is something we want to avoid. Thus, the problem is quite interesting: Storing configuration which's actual values you don't know.
The solution is quite simple: symmetric encryption, where the key (or passphrase) is only present at the target machine. Since we don't have access to the target machines (we just deliver our deployment package), we're unable to read the encryption key. Encrypt once, decrypt often:
The full implementation would span a few pages, so to prevent you from getting RSI due to all that scrolling the basic outline is below.
if the underlying driver hasn't been created yet create the underlying driver read the passphrase from the passphrase URL decrypt the supplied password using the passphrase delegate the properties and decrypted password to the underlying driver |
You don't have to implement it yourself since we were so kind to provide you with both the source and packaged JAR (see 'Resources' section at the bottom of this post).
Since this article is titled JDBC datasource password encryption in JBoss AS7, you'd expect us to tell you how to deploy it in JBoss AS7. Well, we will do so, in the snippet below. We're even so kind to provide you with a JBoss module which you can just extract and drop into your JBoss installation.
< datasource jta = "false" jndi-name = "java:/jdbc/my-datasource" pool-name = "myDs" enabled = "true" use-java-context = "true" > < connection-url >jdbc:some-url</ connection-url > <!-- URL from which the passphrase/key will be read --> < connection-property name = "passphrase-url" >file:/path/to/encryption/key.txt</ connection-property > <!-- Underlying JDBC driver class --> < connection-property name = "driver-class" >com.mysql.jdbc.Driver</ connection-property > < driver >encrypted</ driver > < pool > < min-pool-size >1</ min-pool-size > < max-pool-size >5</ max-pool-size > </ pool > < security > < user-name >my-user</ user-name > <!-- This password is encrypted --> < password >my-encrypted-password</ password > </ security > </ datasource > ... < drivers > <!-- Here you define your custom JDBC driver --> < driver name = "encrypted" module = "nl.avisi.jdbc:main" > < xa-datasource-class >nl.avisi.jdbc.EncryptedPasswordDriver</ xa-datasource-class > </ driver > ... </ drivers > |
Since this generic delegating JDBC driver doesn't know about its underlying driver until connect() is invoked, it won't be able to provide information regarding its version, JDBC compliance and supported JDBC URLs (which is required for using the DriverManager). Thus, a more refined version would implement driver-specific flavors which could delegate all invocations to its underlying driver, which might be required by your application of choice. That's up to you to implement.
$ openssl rand -base64 50
| Software Development
Door Avisi / okt 2024
Dan denken we dat dit ook wat voor jou is.