Author: rmannibucau
Date: Wed Oct 24 09:31:44 2012
New Revision: 1401596
URL: http://svn.apache.org/viewvc?rev=1401596&view=rev
Log:
TOMEE-500 password cipher for tomcat-jdbc
Added:
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolCipherPasswordTest.java
- copied, changed from r1401234,
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolTest.java
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/META-INF/
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/META-INF/org.apache.openejb.resource.jdbc.cipher.PasswordCipher/
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/META-INF/org.apache.openejb.resource.jdbc.cipher.PasswordCipher/Mock
Modified:
openejb/trunk/openejb/rat.xml
openejb/trunk/openejb/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
Modified: openejb/trunk/openejb/rat.xml
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/rat.xml?rev=1401596&r1=1401595&r2=1401596&view=diff
==============================================================================
--- openejb/trunk/openejb/rat.xml (original)
+++ openejb/trunk/openejb/rat.xml Wed Oct 24 09:31:44 2012
@@ -74,6 +74,7 @@
<exclude
name="tomee/tomee-myfaces/src/main/resources/META-INF/services/org.apache.myfaces.spi.FacesConfigResourceProviderFactory"/>
<exclude
name="tomee/tomee-webapp/src/main/webapp/js/jquery/jquery-1.7.1.js"/>
<exclude
name="tomee/tomee-mojarra/src/main/resources/META-INF/services/com.sun.faces.spi.injectionprovider"
/>
+ <exclude
name="tomee/tomee-jdbc/src/test/resources/META-INF/org.apache.openejb.resource.jdbc.cipher.PasswordCipher/Mock"
/>
<exclude
name="tomee/tomee-webapp/src/main/webapp/lib/jquery/jquery-1.7.2.min.js" />
<!-- minimize so ignored -->
<!-- user-owned config files. see httpds default.httpd.conf for
precident -->
Modified:
openejb/trunk/openejb/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java?rev=1401596&r1=1401595&r2=1401596&view=diff
==============================================================================
---
openejb/trunk/openejb/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
(original)
+++
openejb/trunk/openejb/tomee/tomee-jdbc/src/main/java/org/apache/tomee/jdbc/TomEEDataSourceCreator.java
Wed Oct 24 09:31:44 2012
@@ -21,6 +21,7 @@ import org.apache.juli.logging.LogFactor
import org.apache.openejb.monitoring.LocalMBeanServer;
import org.apache.openejb.monitoring.ObjectNameBuilder;
import org.apache.openejb.resource.jdbc.BasicDataSourceUtil;
+import org.apache.openejb.resource.jdbc.cipher.PasswordCipher;
import org.apache.openejb.resource.jdbc.plugin.DataSourcePlugin;
import org.apache.openejb.resource.jdbc.pool.PoolDataSourceCreator;
import org.apache.openejb.util.Duration;
@@ -109,13 +110,31 @@ public class TomEEDataSourceCreator exte
if (properties.containsKey("minEvictableIdleTime") &&
!properties.containsKey("minEvictableIdleTimeMillis")) {
converted.setProperty("minEvictableIdleTimeMillis", minEvict);
}
+
+ final String passwordCipher = properties.getProperty("PasswordCipher");
+ if (passwordCipher != null && "PlainText".equals(passwordCipher)) { //
no need to warn about it
+ properties.remove("PasswordCipher");
+ } else {
+ String password = properties.getProperty("Password");
+ if (passwordCipher != null) {
+ try {
+ final PasswordCipher cipher =
BasicDataSourceUtil.getPasswordCipher(passwordCipher);
+ final String plainPwd =
cipher.decrypt(password.toCharArray());
+ converted.setProperty("password", plainPwd);
+
+ // all went fine so remove it to avoid errors later
+ properties.remove("PasswordCipher");
+ properties.remove("Password");
+ } catch (SQLException e) {
+ LOGGER.error("Can't decrypt password", e);
+ }
+ }
+ }
+
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
final String key = entry.getKey().toString();
final String value = entry.getValue().toString().trim();
if (!value.isEmpty() && !converted.containsKey(key)) {
- if ("PasswordCipher".equals(key) && "PlainText".equals(value))
{ // no need to warn about it
- continue;
- }
if ("MaxOpenPreparedStatements".equalsIgnoreCase(key) ||
"PoolPreparedStatements".equalsIgnoreCase(key)) {
String interceptors =
properties.getProperty("jdbcInterceptors");
if (interceptors == null ||
!interceptors.contains("StatementCache")) {
@@ -164,15 +183,26 @@ public class TomEEDataSourceCreator exte
public static class TomEEDataSource extends
org.apache.tomcat.jdbc.pool.DataSource {
private static final Log LOGGER =
LogFactory.getLog(TomEEDataSource.class);
+ private static final Class<?>[] CONNECTION_POOL_CLASS = new Class<?>[]
{ PoolConfiguration.class };
private ObjectName internalOn = null;
public TomEEDataSource(final PoolConfiguration properties, final
ConnectionPool pool, final String name) {
- super(properties);
+ super(readOnly(properties));
this.pool = pool;
initJmx(name);
}
+ public TomEEDataSource(final PoolConfiguration poolConfiguration,
final String name) {
+ super(readOnly(poolConfiguration));
+ try { // just to force the pool to be created and be able to
register the mbean
+ createPool();
+ initJmx(name);
+ } catch (Throwable ignored) {
+ // no-op
+ }
+ }
+
@Override
public ConnectionPool createPool() throws SQLException {
if (pool != null) {
@@ -183,14 +213,8 @@ public class TomEEDataSourceCreator exte
}
}
- public TomEEDataSource(final PoolConfiguration poolConfiguration,
final String name) {
- super(poolConfiguration);
- try { // just to force the pool to be created and be able to
register the mbean
- createPool();
- initJmx(name);
- } catch (Throwable ignored) {
- // no-op
- }
+ private static PoolConfiguration readOnly(final PoolConfiguration
pool) {
+ return (PoolConfiguration)
Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
CONNECTION_POOL_CLASS, new ReadOnlyConnectionpool(pool));
}
private void initJmx(final String name) {
@@ -233,6 +257,22 @@ public class TomEEDataSourceCreator exte
}
}
+ private static class ReadOnlyConnectionpool implements InvocationHandler {
+ private final PoolConfiguration delegate;
+
+ public ReadOnlyConnectionpool(final PoolConfiguration pool) {
+ delegate = pool;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final
Object[] args) throws Throwable {
+ if (!(method.getName().startsWith("set") && args != null &&
args.length == 1 && Void.TYPE.equals(method.getReturnType()))) {
+ return method.invoke(delegate, args);
+ }
+ return null;
+ }
+ }
+
private static class TomEEConnectionPool extends ConnectionPool {
public TomEEConnectionPool(final PoolConfiguration poolProperties)
throws SQLException {
super(poolProperties);
Copied:
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolCipherPasswordTest.java
(from r1401234,
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolTest.java)
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolCipherPasswordTest.java?p2=openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolCipherPasswordTest.java&p1=openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolTest.java&r1=1401234&r2=1401596&rev=1401596&view=diff
==============================================================================
---
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolTest.java
(original)
+++
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/java/org/apache/tomee/jdbc/TomcatPoolCipherPasswordTest.java
Wed Oct 24 09:31:44 2012
@@ -17,46 +17,47 @@
package org.apache.tomee.jdbc;
import org.apache.openejb.jee.EjbJar;
-import org.apache.openejb.jee.SingletonBean;
import org.apache.openejb.junit.ApplicationComposer;
import org.apache.openejb.junit.Configuration;
import org.apache.openejb.junit.Module;
-import org.apache.openejb.resource.jdbc.managed.local.ManagedConnection;
-import org.junit.After;
+import org.apache.openejb.resource.jdbc.cipher.PasswordCipher;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.annotation.Resource;
-import javax.ejb.EJB;
-import javax.ejb.EJBContext;
-import javax.ejb.LocalBean;
-import javax.ejb.Singleton;
-import javax.ejb.TransactionAttribute;
-import javax.ejb.TransactionAttributeType;
import javax.sql.DataSource;
-import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
-import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
-import java.util.Map;
import java.util.Properties;
+import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
@RunWith(ApplicationComposer.class)
-public class TomcatPoolTest {
- private static final String URL =
"jdbc:hsqldb:mem:managed;hsqldb.tx=MVCC"; // mvcc otherwise multiple
transaction tests will fail
+public class TomcatPoolCipherPasswordTest {
+ private static final String URL = "jdbc:hsqldb:mem:cipher;hsqldb.tx=MVCC";
private static final String USER = "sa";
- private static final String PASSWORD = "";
+ private static final String PASSWORD = "this one will be overriden if it
works";
private static final String TABLE = "PUBLIC.MANAGED_DATASOURCE_TEST";
- @EJB
- private Persister persistManager;
+ @Resource(name = "ciphered")
+ private DataSource ds;
+
+ public static class MockCipher implements PasswordCipher {
+ @Override
+ public char[] encrypt(final String plainPassword) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String decrypt(final char[] encryptedPassword) {
+ return "";
+ }
+ }
@BeforeClass
public static void createTable() throws SQLException,
ClassNotFoundException {
@@ -75,157 +76,26 @@ public class TomcatPoolTest {
final Properties p = new Properties();
p.put("openejb.jdbc.datasource-creator",
TomEEDataSourceCreator.class.getName());
- p.put("managed", "new://Resource?type=DataSource");
- p.put("managed.JdbcDriver", "org.hsqldb.jdbcDriver");
- p.put("managed.JdbcUrl", URL);
- p.put("managed.UserName", USER);
- p.put("managed.Password", PASSWORD);
- p.put("managed.JtaManaged", "true");
- p.put("managed.JdbcInterceptors", "StatementCache(prepared=true)");
+ p.put("ciphered", "new://Resource?type=DataSource");
+ p.put("ciphered.JdbcDriver", "org.hsqldb.jdbcDriver");
+ p.put("ciphered.JdbcUrl", URL);
+ p.put("ciphered.UserName", USER);
+ p.put("ciphered.Password", PASSWORD);
+ p.put("ciphered.PasswordCipher", "Mock");
+ p.put("ciphered.JtaManaged", "false");
+ p.put("ciphered.JdbcInterceptors", "StatementCache(prepared=true)");
return p;
}
@Module
public EjbJar app() throws Exception {
- return new EjbJar()
- .enterpriseBean(new SingletonBean(Persister.class).localBean())
- .enterpriseBean(new
SingletonBean(OtherPersister.class).localBean());
- }
-
- @LocalBean
- @Singleton
- @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public static class OtherPersister {
- @Resource(name = "managed")
- private DataSource ds;
-
- @Resource
- private EJBContext context;
-
- public void save() throws SQLException {
- TomcatPoolTest.save(ds, 10);
- }
-
- public void saveAndRollback() throws SQLException {
- TomcatPoolTest.save(ds, 11);
- context.setRollbackOnly();
- }
- }
-
- @LocalBean
- @Singleton
- public static class Persister {
- @Resource(name = "managed")
- private DataSource ds;
-
- @Resource
- private EJBContext context;
-
- @EJB
- private OtherPersister other;
-
- public void save() throws SQLException {
- TomcatPoolTest.save(ds, 1);
- }
-
- public void saveAndRollback() throws SQLException {
- TomcatPoolTest.save(ds, 2);
- context.setRollbackOnly();
- }
-
- public void saveTwice() throws SQLException {
- TomcatPoolTest.save(ds, 3);
- TomcatPoolTest.save(ds, 4);
- }
-
- public void rollbackMultipleSave() throws SQLException {
- TomcatPoolTest.save(ds, 5);
- TomcatPoolTest.save(ds, 6);
- context.setRollbackOnly();
- }
-
- public void saveInThisTxAndAnotherOne() throws SQLException {
- TomcatPoolTest.save(ds, 7);
- other.save();
- }
-
- public void saveInThisTxAndRollbackInAnotherOne() throws SQLException {
- TomcatPoolTest.save(ds, 8);
- other.saveAndRollback();
- }
+ return new EjbJar();
}
@Test
- public void commit() throws SQLException {
- persistManager.save();
- assertTrue(exists(1));
- }
-
- @Test
- public void rollback() throws SQLException {
- persistManager.saveAndRollback();
- assertFalse(exists(2));
- }
-
- @Test
- public void commit2() throws SQLException {
- persistManager.saveTwice();
- assertTrue(exists(3));
- assertTrue(exists(4));
- }
-
- @Test
- public void rollback2() throws SQLException {
- persistManager.rollbackMultipleSave();
- assertFalse(exists(5));
- assertFalse(exists(6));
- }
-
- @Test
- public void saveDifferentTx() throws SQLException {
- persistManager.saveInThisTxAndAnotherOne();
- assertTrue(exists(7));
- assertTrue(exists(10));
- }
-
- @Test
- public void saveRollbackDifferentTx() throws SQLException {
- persistManager.saveInThisTxAndRollbackInAnotherOne();
- assertTrue(exists(8));
- assertFalse(exists(12));
- }
-
- @After
- public void checkTxMapIsEmpty() throws Exception { // avoid memory leak
- final Field map =
ManagedConnection.class.getDeclaredField("CONNECTION_BY_TX");
- map.setAccessible(true);
- final Map<?, ?> instance = (Map<?, ?>) map.get(null);
- assertEquals(0, instance.size());
- }
-
- private static boolean exists(int id) throws SQLException {
- final Connection connection = DriverManager.getConnection(URL, USER,
PASSWORD);
- final Statement statement = connection.createStatement();
- final ResultSet result = statement.executeQuery("SELECT count(*) AS NB
FROM " + TABLE + " WHERE ID = " + id);
- try {
- assertTrue(result.next());
- return result.getInt(1) == 1;
- } finally {
- statement.close();
- connection.close();
- }
- }
-
- private static void save(final DataSource ds, int id) throws SQLException {
- execute(ds, "INSERT INTO " + TABLE + "(ID) VALUES(" + id + ")");
- }
-
- private static void execute(final DataSource ds, final String sql) throws
SQLException {
- final Connection connection = ds.getConnection();
- final Statement statement = connection.createStatement();
- statement.executeUpdate(sql);
- statement.close();
- connection.close();
+ public void validConfig() throws SQLException {
+ assertThat(ds,
instanceOf(TomEEDataSourceCreator.TomEEDataSource.class));
+ assertEquals(new MockCipher().decrypt(null),
((TomEEDataSourceCreator.TomEEDataSource)
ds).getPoolProperties().getPassword());
}
}
Added:
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/META-INF/org.apache.openejb.resource.jdbc.cipher.PasswordCipher/Mock
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/META-INF/org.apache.openejb.resource.jdbc.cipher.PasswordCipher/Mock?rev=1401596&view=auto
==============================================================================
---
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/META-INF/org.apache.openejb.resource.jdbc.cipher.PasswordCipher/Mock
(added)
+++
openejb/trunk/openejb/tomee/tomee-jdbc/src/test/resources/META-INF/org.apache.openejb.resource.jdbc.cipher.PasswordCipher/Mock
Wed Oct 24 09:31:44 2012
@@ -0,0 +1 @@
+org.apache.tomee.jdbc.TomcatPoolCipherPasswordTest$MockCipher