Skip to content

Commit 0fa189b

Browse files
committed
Ensure queries in system.runtime.queries are redacted
1 parent 76ec66f commit 0fa189b

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.google.common.collect.ImmutableList;
1717
import com.google.common.collect.ImmutableMap;
1818
import com.google.common.collect.ImmutableSet;
19+
import com.google.common.collect.Sets;
1920
import io.trino.spi.connector.AggregateFunction;
2021
import io.trino.spi.connector.AggregationApplicationResult;
2122
import io.trino.spi.connector.CatalogSchemaTableName;
@@ -138,6 +139,7 @@ public class MockConnectorFactory
138139
private final Supplier<List<PropertyMetadata<?>>> columnProperties;
139140
private final Optional<ConnectorNodePartitioningProvider> partitioningProvider;
140141
private final Function<ConnectorTableFunctionHandle, ConnectorSplitSource> tableFunctionSplitsSources;
142+
private final Set<String> securitySensitivePropertyNames;
141143

142144
// access control
143145
private final ListRoleGrants roleGrants;
@@ -193,6 +195,7 @@ private MockConnectorFactory(
193195
Supplier<List<PropertyMetadata<?>>> tableProperties,
194196
Supplier<List<PropertyMetadata<?>>> columnProperties,
195197
Optional<ConnectorNodePartitioningProvider> partitioningProvider,
198+
Set<String> securitySensitivePropertyNames,
196199
ListRoleGrants roleGrants,
197200
Optional<ConnectorAccessControl> accessControl,
198201
boolean allowMissingColumnsOnInsert,
@@ -240,6 +243,7 @@ private MockConnectorFactory(
240243
this.tableProperties = requireNonNull(tableProperties, "tableProperties is null");
241244
this.columnProperties = requireNonNull(columnProperties, "columnProperties is null");
242245
this.partitioningProvider = requireNonNull(partitioningProvider, "partitioningProvider is null");
246+
this.securitySensitivePropertyNames = requireNonNull(securitySensitivePropertyNames, "securitySensitivePropertyNames is null");
243247
this.roleGrants = requireNonNull(roleGrants, "roleGrants is null");
244248
this.accessControl = requireNonNull(accessControl, "accessControl is null");
245249
this.data = requireNonNull(data, "data is null");
@@ -320,6 +324,12 @@ public Connector create(String catalogName, Map<String, String> config, Connecto
320324
allowSplittingReadIntoMultipleSubQueries);
321325
}
322326

327+
@Override
328+
public Set<String> getSecuritySensitivePropertyNames(String catalogName, Map<String, String> config, ConnectorContext context)
329+
{
330+
return Sets.intersection(securitySensitivePropertyNames, config.keySet());
331+
}
332+
323333
public static MockConnectorFactory create()
324334
{
325335
return builder().build();
@@ -459,6 +469,7 @@ public static final class Builder
459469
private Supplier<List<PropertyMetadata<?>>> columnProperties = ImmutableList::of;
460470
private Optional<ConnectorNodePartitioningProvider> partitioningProvider = Optional.empty();
461471
private Function<ConnectorTableFunctionHandle, ConnectorSplitSource> tableFunctionSplitsSources = handle -> null;
472+
private Set<String> securitySensitivePropertyNames = ImmutableSet.of();
462473

463474
// access control
464475
private boolean provideAccessControl;
@@ -822,6 +833,12 @@ public Builder withAllowSplittingReadIntoMultipleSubQueries(boolean allowSplitti
822833
return this;
823834
}
824835

836+
public Builder withSecuritySensitivePropertyNames(Set<String> securitySensitivePropertyNames)
837+
{
838+
this.securitySensitivePropertyNames = securitySensitivePropertyNames;
839+
return this;
840+
}
841+
825842
public MockConnectorFactory build()
826843
{
827844
Optional<ConnectorAccessControl> accessControl = Optional.empty();
@@ -872,6 +889,7 @@ public MockConnectorFactory build()
872889
tableProperties,
873890
columnProperties,
874891
partitioningProvider,
892+
securitySensitivePropertyNames,
875893
roleGrants,
876894
accessControl,
877895
allowMissingColumnsOnInsert,

testing/trino-tests/src/test/java/io/trino/connector/system/runtime/TestSystemRuntimeConnector.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import com.google.common.collect.ImmutableList;
1717
import com.google.common.collect.ImmutableMap;
18+
import com.google.common.collect.ImmutableSet;
1819
import com.google.common.collect.Iterables;
1920
import com.google.common.util.concurrent.SettableFuture;
2021
import io.airlift.units.Duration;
@@ -48,6 +49,7 @@
4849
import static io.airlift.concurrent.Threads.threadsNamed;
4950
import static io.trino.spi.type.BigintType.BIGINT;
5051
import static io.trino.spi.type.VarcharType.VARCHAR;
52+
import static io.trino.testing.TestingNames.randomNameSuffix;
5153
import static io.trino.testing.TestingSession.testSessionBuilder;
5254
import static io.trino.testing.assertions.Assert.assertEventually;
5355
import static java.lang.String.format;
@@ -89,6 +91,7 @@ public Iterable<ConnectorFactory> getConnectorFactories()
8991
.withGetViews((session, schemaTablePrefix) -> ImmutableMap.of())
9092
.withListTables((session, s) -> ImmutableList.of("test_table"))
9193
.withGetColumns(tableName -> getColumns.apply(tableName))
94+
.withSecuritySensitivePropertyNames(ImmutableSet.of("password"))
9295
.build();
9396
return ImmutableList.of(connectorFactory);
9497
}
@@ -299,6 +302,75 @@ public void testTasksTable()
299302
getQueryRunner().execute("SELECT * FROM system.runtime.tasks");
300303
}
301304

305+
@Test
306+
public void testRedactedCreateCatalog()
307+
{
308+
String catalog = "catalog_" + randomNameSuffix();
309+
getQueryRunner().execute(
310+
"""
311+
CREATE CATALOG %s USING mock
312+
WITH (
313+
"user" = 'bob',
314+
"password" = '1234'
315+
)
316+
""".formatted(catalog));
317+
318+
assertQuery(
319+
format("SELECT query FROM system.runtime.queries WHERE query LIKE '%%%s%%' AND query NOT LIKE '%%system.runtime.queries%%'", catalog),
320+
"""
321+
VALUES 'CREATE CATALOG %s USING mock
322+
WITH (
323+
"user" = ''bob'',
324+
"password" = ''***''
325+
)'
326+
""".formatted(catalog));
327+
}
328+
329+
@Test
330+
public void testRedactedPrepareCreateCatalog()
331+
{
332+
String catalog = "catalog_" + randomNameSuffix();
333+
getQueryRunner().execute(
334+
"""
335+
PREPARE create_catalog FROM
336+
CREATE CATALOG %s USING mock
337+
WITH (
338+
"user" = 'bob',
339+
"password" = '1234'
340+
)
341+
""".formatted(catalog));
342+
343+
assertQuery(
344+
format("SELECT query FROM system.runtime.queries WHERE query LIKE '%%%s%%' AND query NOT LIKE '%%system.runtime.queries%%'", catalog),
345+
"""
346+
VALUES 'PREPARE create_catalog FROM
347+
CREATE CATALOG %s USING mock
348+
WITH (
349+
"user" = ''bob'',
350+
"password" = ''***''
351+
)'
352+
""".formatted(catalog));
353+
354+
Session executeSession = testSessionBuilder()
355+
.setCatalog("mock")
356+
.setSchema("default")
357+
.addPreparedStatement(
358+
"create_catalog",
359+
"""
360+
CREATE CATALOG %s USING mock
361+
WITH (
362+
"user" = 'bob',
363+
"password" = '1234'
364+
)
365+
""".formatted(catalog))
366+
.build();
367+
getQueryRunner().execute(executeSession, "EXECUTE create_catalog");
368+
369+
assertQuery(
370+
"SELECT query FROM system.runtime.queries WHERE query LIKE '%%EXECUTE create_catalog%%' AND query NOT LIKE '%%system.runtime.queries%%'",
371+
"VALUES 'EXECUTE create_catalog'");
372+
}
373+
302374
private static void run(int repetitions, double successRate, Runnable test)
303375
{
304376
AssertionError lastError = null;

0 commit comments

Comments
 (0)