Skip to content

Commit

Permalink
Fixex 4256: Obfuscate JDBC Password in query.log: see trello card
Browse files Browse the repository at this point in the history
  • Loading branch information
gmarcostam committed Nov 29, 2024
1 parent c686650 commit a2561da
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
45 changes: 34 additions & 11 deletions extended/src/main/java/apoc/load/Jdbc.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,31 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneId;
import java.util.*;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.UUID;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static apoc.load.util.JdbcUtil.*;
import static apoc.load.util.JdbcUtil.getConnection;
import static apoc.load.util.JdbcUtil.getSqlOrKey;
import static apoc.load.util.JdbcUtil.getUrlOrKey;
import static apoc.load.util.JdbcUtil.obfuscateJdbcUrl;

/**
* @author mh
Expand Down Expand Up @@ -96,10 +111,7 @@ private Stream<RowResult> executeQuery(String urlOrKey, String tableOrSelect, Ma
throw sqle;
}
} catch (Exception e) {
log.error(String.format("Cannot execute SQL statement `%s`.%nError:%n%s", query, e.getMessage()),e);
String errorMessage = "Cannot execute SQL statement `%s`.%nError:%n%s";
if(e.getMessage().contains("No suitable driver")) errorMessage="Cannot execute SQL statement `%s`.%nError:%n%s%n%s";
throw new RuntimeException(String.format(errorMessage, query, e.getMessage(), "Please download and copy the JDBC driver into $NEO4J_HOME/plugins,more details at https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_load_jdbc_resources"), e);
throw customException(e, query, log);
}
}

Expand Down Expand Up @@ -134,13 +146,24 @@ private Stream<RowResult> executeUpdate(String urlOrKey, String query, Map<Strin
throw sqle;
}
} catch (Exception e) {
log.error(String.format("Cannot execute SQL statement `%s`.%nError:%n%s", query, e.getMessage()),e);
String errorMessage = "Cannot execute SQL statement `%s`.%nError:%n%s";
if(e.getMessage().contains("No suitable driver")) errorMessage="Cannot execute SQL statement `%s`.%nError:%n%s%n%s";
throw new RuntimeException(String.format(errorMessage, query, e.getMessage(), "Please download and copy the JDBC driver into $NEO4J_HOME/plugins,more details at https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_load_jdbc_resources"), e);
throw customException(e, query, log);
}
}

private static RuntimeException customException(Exception e, String query, Log log) {
String errorMessage = "Cannot execute SQL statement `%s`.%nError:%n%s";
String exceptionMsg = e.getMessage();

if(e.getMessage().contains("No suitable driver")) {
errorMessage = "Cannot execute SQL statement `%s`.%nError:%n%s%n%s";
exceptionMsg = obfuscateJdbcUrl(e.getMessage());
}

Exception ex = new Exception(exceptionMsg);
log.error(String.format("Cannot execute SQL statement `%s`.%nError:%n%s", query, exceptionMsg), ex);
return new RuntimeException(String.format(errorMessage, query, exceptionMsg, "Please download and copy the JDBC driver into $NEO4J_HOME/plugins, more details at https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_load_jdbc_resources"), ex);
}

static void closeIt(Log log, AutoCloseable...closeables) {
for (AutoCloseable c : closeables) {
try {
Expand Down
4 changes: 4 additions & 0 deletions extended/src/main/java/apoc/load/util/JdbcUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,8 @@ public static String getUrlOrKey(String urlOrKey) {
public static String getSqlOrKey(String sqlOrKey) {
return sqlOrKey.contains(" ") ? sqlOrKey : Util.getLoadUrlByConfigFile(LOAD_TYPE, sqlOrKey, "sql").orElse("SELECT * FROM " + sqlOrKey);
}

public static String obfuscateJdbcUrl(String query) {
return query.replaceAll("(jdbc:[^:]+://)([^\\s\\\"']+)", "$1*******");
}
}
18 changes: 17 additions & 1 deletion extended/src/test/java/apoc/load/JdbcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
import apoc.util.TestUtil;
import apoc.util.Util;
import apoc.util.collection.Iterators;
import org.junit.*;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.jupiter.api.AfterAll;
import org.junit.rules.ExpectedException;
import org.junit.rules.TestName;
Expand All @@ -27,8 +31,10 @@
import static apoc.ApocConfig.apocConfig;
import static apoc.util.MapUtil.map;
import static apoc.util.TestUtil.testCall;
import static apoc.util.TestUtil.testCallEmpty;
import static apoc.util.TestUtil.testResult;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class JdbcTest extends AbstractJdbcTest {

Expand Down Expand Up @@ -111,6 +117,16 @@ public void testLoadJdbcParams() throws Exception {
(row) -> assertResult(row));
}

@Test
public void testObfuscationUrlOnException() {
try {
testCallEmpty(db, "CALL apoc.load.jdbc('jdbc:ajeje://localhost:3306/data_mart?user=root&password=root','SELECT * FROM PERSON WHERE NAME = ?',['John'])", Map.of());
} catch (Exception e) {
assertTrue(e.getMessage().contains("No suitable driver found for jdbc:ajeje://*******"));
}

}

@Test
public void testLoadJdbcParamsWithConfigLocalDateTime() throws Exception {
testCall(db, "CALL apoc.load.jdbc('jdbc:derby:derbyDB','SELECT * FROM PERSON WHERE NAME = ?',['John'])",
Expand Down

0 comments on commit a2561da

Please sign in to comment.