NativeDBTraceLogTest.java
package org.sqlite.core;
import static org.assertj.core.api.Assertions.assertThat;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.slf4j.LoggerFactory;
public class NativeDBTraceLogTest {
@ParameterizedTest
@ValueSource(
strings = {
"pragma key = 'secret'",
"PRAGMA hexkey='secret'",
"pragma key = \"x'secret'\"",
"pragma rekey='sec''ret'",
"pragma main.key = 'secret'",
"pragma key('secret')",
"pragma textkey = secret",
"Pragma HexReKey = 'secret'",
"pragma textrekey = x'secret'"
})
public void redactSecretsHidesKeyValue(String sql) {
String redacted = NativeDB.redactSecrets(sql);
assertThat(redacted).doesNotContain("secret").doesNotContain("ret").contains("'***'");
}
@Test
public void redactSecretsHandlesVeryLongKey() {
String key = String.join("", java.util.Collections.nCopies(200_000, "a''b"));
assertThat(NativeDB.redactSecrets("pragma key = '" + key + "'"))
.isEqualTo("pragma key = '***'");
}
@Test
public void redactSecretsKeepsPragmaNameAndFollowingStatements() {
assertThat(NativeDB.redactSecrets("pragma key = 'secret'")).isEqualTo("pragma key = '***'");
assertThat(NativeDB.redactSecrets("pragma key('secret')")).isEqualTo("pragma key('***')");
assertThat(NativeDB.redactSecrets("pragma hexrekey = 'ab'; select 1"))
.isEqualTo("pragma hexrekey = '***'; select 1");
}
@ParameterizedTest
@ValueSource(
strings = {
"select key from t",
"pragma journal_mode = wal",
"pragma foreign_keys = on",
"select 1 from sqlite_schema"
})
public void redactSecretsLeavesOtherStatementsUnchanged(String sql) {
assertThat(NativeDB.redactSecrets(sql)).isEqualTo(sql);
}
@Test
public void redactSecretsHandlesNull() {
assertThat(NativeDB.redactSecrets(null)).isNull();
}
@Test
public void traceLogDoesNotContainPassword() throws Exception {
Logger logger = (Logger) LoggerFactory.getLogger(NativeDB.class);
Level previousLevel = logger.getLevel();
ListAppender<ILoggingEvent> appender = new ListAppender<>();
appender.start();
logger.addAppender(appender);
logger.setLevel(Level.TRACE);
try {
Properties props = new Properties();
props.setProperty("password", "supersecret");
try (Connection conn = DriverManager.getConnection("jdbc:sqlite::memory:", props);
Statement stat = conn.createStatement()) {
stat.execute("pragma rekey = 'othersecret'");
}
} finally {
logger.detachAppender(appender);
logger.setLevel(previousLevel);
appender.stop();
}
List<String> messages =
appender.list.stream()
.map(ILoggingEvent::getFormattedMessage)
.collect(Collectors.toList());
assertThat(messages).noneMatch(m -> m.contains("supersecret"));
assertThat(messages).noneMatch(m -> m.contains("othersecret"));
assertThat(messages).anyMatch(m -> m.contains("[SQLite EXEC] pragma key = '***'"));
assertThat(messages).anyMatch(m -> m.contains("[SQLite EXEC] pragma rekey = '***'"));
}
}