SOLR-8610: Resolve variables in encryptKeyFile of DIH's JdbcDataSource

This commit is contained in:
Mikhail Khludnev 2016-06-02 23:32:01 +03:00
parent 59b4fc0bb0
commit c2aea1b803
3 changed files with 42 additions and 10 deletions

View File

@ -150,6 +150,8 @@ New Features
* SOLR-7123: '/update/json/docs' path supports nested documents (noble) * SOLR-7123: '/update/json/docs' path supports nested documents (noble)
* SOLR-8610: Resolve variables in encryptKeyFile of DIH's JdbcDataSource (Kristine Jetzke via Mikhail Khludnev)
Bug Fixes Bug Fixes
---------------------- ----------------------

View File

@ -71,7 +71,7 @@ public class JdbcDataSource extends
@Override @Override
public void init(Context context, Properties initProps) { public void init(Context context, Properties initProps) {
initProps = decryptPwd(initProps); initProps = decryptPwd(context, initProps);
Object o = initProps.get(CONVERT_TYPE); Object o = initProps.get(CONVERT_TYPE);
if (o != null) if (o != null)
convertType = Boolean.parseBoolean(o.toString()); convertType = Boolean.parseBoolean(o.toString());
@ -112,8 +112,8 @@ public class JdbcDataSource extends
} }
} }
private Properties decryptPwd(Properties initProps) { private Properties decryptPwd(Context context, Properties initProps) {
String encryptionKey = initProps.getProperty("encryptKeyFile"); String encryptionKey = context.replaceTokens(initProps.getProperty("encryptKeyFile"));
if (initProps.getProperty("password") != null && encryptionKey != null) { if (initProps.getProperty("password") != null && encryptionKey != null) {
// this means the password is encrypted and use the file to decode it // this means the password is encrypted and use the file to decode it
try { try {

View File

@ -17,6 +17,7 @@
package org.apache.solr.handler.dataimport; package org.apache.solr.handler.dataimport;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.sql.Connection; import java.sql.Connection;
@ -136,15 +137,10 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase {
@Test @Test
public void testRetrieveFromJndiWithCredentialsWithEncryptedPwd() throws Exception { public void testRetrieveFromJndiWithCredentialsWithEncryptedPwd() throws Exception {
MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource); MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource);
File tmpdir = File.createTempFile("test", "tmp", createTempDir().toFile());
Files.delete(tmpdir.toPath());
tmpdir.mkdir();
byte[] content = "secret".getBytes(StandardCharsets.UTF_8);
createFile(tmpdir, "enckeyfile.txt", content, false);
props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB"); props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB");
props.put("user", "Fred"); props.put("user", "Fred");
props.put("encryptKeyFile", new File(tmpdir, "enckeyfile.txt").getAbsolutePath()); props.put("encryptKeyFile", createEncryptionKeyFile());
props.put("password", "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o="); props.put("password", "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o=");
props.put("holdability", "HOLD_CURSORS_OVER_COMMIT"); props.put("holdability", "HOLD_CURSORS_OVER_COMMIT");
EasyMock.expect(dataSource.getConnection("Fred", "MyPassword")).andReturn( EasyMock.expect(dataSource.getConnection("Fred", "MyPassword")).andReturn(
@ -162,6 +158,32 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase {
assertSame("connection", conn, connection); assertSame("connection", conn, connection);
} }
@Test
public void testRetrieveFromJndiWithCredentialsWithEncryptedAndResolvedPwd() throws Exception {
MockInitialContextFactory.bind("java:comp/env/jdbc/JndiDB", dataSource);
props.put(JdbcDataSource.JNDI_NAME, "java:comp/env/jdbc/JndiDB");
props.put("user", "Fred");
props.put("encryptKeyFile", "${foo.bar}");
props.put("password", "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o=");
EasyMock.expect(dataSource.getConnection("Fred", "MyPassword")).andReturn(
connection);
Map<String,Object> values = new HashMap<>();
values.put("bar", createEncryptionKeyFile());
context.getVariableResolver().addNamespace("foo", values);
jdbcDataSource.init(context, props);
connection.setAutoCommit(false);
mockControl.replay();
jdbcDataSource.getConnection();
mockControl.verify();
}
@Test @Test
public void testRetrieveFromJndiFailureNotHidden() throws Exception { public void testRetrieveFromJndiFailureNotHidden() throws Exception {
@ -403,7 +425,6 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase {
DriverManager.deregisterDriver(driver); DriverManager.deregisterDriver(driver);
} }
} }
@Test @Test
@Ignore("Needs a Mock database server to work") @Ignore("Needs a Mock database server to work")
public void testBasic() throws Exception { public void testBasic() throws Exception {
@ -442,4 +463,13 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase {
assertEquals(Float.class, msrp.getClass()); assertEquals(Float.class, msrp.getClass());
assertEquals(Long.class, trim_id.getClass()); assertEquals(Long.class, trim_id.getClass());
} }
private String createEncryptionKeyFile() throws IOException {
File tmpdir = File.createTempFile("test", "tmp", createTempDir().toFile());
Files.delete(tmpdir.toPath());
tmpdir.mkdir();
byte[] content = "secret".getBytes(StandardCharsets.UTF_8);
createFile(tmpdir, "enckeyfile.txt", content, false);
return new File(tmpdir, "enckeyfile.txt").getAbsolutePath();
}
} }