diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 0e2d79c3309..4737bfd7a70 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -121,6 +121,8 @@ New Features * 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 ---------------------- diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java index 2dfaae77c25..e1eabeb002b 100644 --- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java +++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/JdbcDataSource.java @@ -71,7 +71,7 @@ public class JdbcDataSource extends @Override public void init(Context context, Properties initProps) { - initProps = decryptPwd(initProps); + initProps = decryptPwd(context, initProps); Object o = initProps.get(CONVERT_TYPE); if (o != null) convertType = Boolean.parseBoolean(o.toString()); @@ -112,8 +112,8 @@ public class JdbcDataSource extends } } - private Properties decryptPwd(Properties initProps) { - String encryptionKey = initProps.getProperty("encryptKeyFile"); + private Properties decryptPwd(Context context, Properties initProps) { + String encryptionKey = context.replaceTokens(initProps.getProperty("encryptKeyFile")); if (initProps.getProperty("password") != null && encryptionKey != null) { // this means the password is encrypted and use the file to decode it try { diff --git a/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java index 08a936ae48c..3b1568f4892 100644 --- a/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java +++ b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestJdbcDataSource.java @@ -17,6 +17,7 @@ package org.apache.solr.handler.dataimport; import java.io.File; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.sql.Connection; @@ -136,15 +137,10 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase { @Test public void testRetrieveFromJndiWithCredentialsWithEncryptedPwd() throws Exception { 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("user", "Fred"); - props.put("encryptKeyFile", new File(tmpdir, "enckeyfile.txt").getAbsolutePath()); + props.put("encryptKeyFile", createEncryptionKeyFile()); props.put("password", "U2FsdGVkX18QMjY0yfCqlfBMvAB4d3XkwY96L7gfO2o="); props.put("holdability", "HOLD_CURSORS_OVER_COMMIT"); EasyMock.expect(dataSource.getConnection("Fred", "MyPassword")).andReturn( @@ -162,6 +158,32 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase { 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 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 public void testRetrieveFromJndiFailureNotHidden() throws Exception { @@ -403,7 +425,6 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase { DriverManager.deregisterDriver(driver); } } - @Test @Ignore("Needs a Mock database server to work") public void testBasic() throws Exception { @@ -442,4 +463,13 @@ public class TestJdbcDataSource extends AbstractDataImportHandlerTestCase { assertEquals(Float.class, msrp.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(); + } }