diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java index 2792991b871f..9e40aaa3db5a 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java @@ -41,6 +41,7 @@ import com.google.cloud.bigquery.storage.v1.BigQueryWriteClient; import com.google.cloud.bigquery.storage.v1.BigQueryWriteSettings; import com.google.cloud.http.HttpTransportOptions; +import com.google.common.collect.ImmutableSortedSet; import java.io.IOException; import java.io.InputStream; import java.sql.CallableStatement; @@ -76,6 +77,70 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { private final String connectionId; private static final String DEFAULT_JDBC_TOKEN_VALUE = "Google-BigQuery-JDBC-Driver"; private static final String DEFAULT_VERSION = "0.0.0"; + private static final Set SAFE_TO_LOG_PROPERTIES = + ImmutableSortedSet.orderedBy(String.CASE_INSENSITIVE_ORDER) + .add( + BigQueryJdbcUrlUtility.PROJECT_ID_PROPERTY_NAME, + BigQueryJdbcUrlUtility.DEFAULT_DATASET_PROPERTY_NAME, + BigQueryJdbcUrlUtility.LOCATION_PROPERTY_NAME, + BigQueryJdbcUrlUtility.ENABLE_HTAPI_PROPERTY_NAME, + BigQueryJdbcUrlUtility.UNSUPPORTED_HTAPI_FALLBACK_PROPERTY_NAME, + BigQueryJdbcUrlUtility.HTAPI_MIN_TABLE_SIZE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.HTAPI_ACTIVATION_RATIO_PROPERTY_NAME, + BigQueryJdbcUrlUtility.KMS_KEY_NAME_PROPERTY_NAME, + BigQueryJdbcUrlUtility.QUERY_PROPERTIES_NAME, + BigQueryJdbcUrlUtility.ENABLE_SESSION_PROPERTY_NAME, + BigQueryJdbcUrlUtility.LOG_LEVEL_PROPERTY_NAME, + BigQueryJdbcUrlUtility.LOG_PATH_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_TYPE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_ACCESS_TOKEN_READONLY_PROPERTY_NAME, + BigQueryJdbcUrlUtility.USE_QUERY_CACHE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.QUERY_DIALECT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.ALLOW_LARGE_RESULTS_PROPERTY_NAME, + BigQueryJdbcUrlUtility.LARGE_RESULTS_TABLE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.LARGE_RESULTS_DATASET_PROPERTY_NAME, + BigQueryJdbcUrlUtility.DESTINATION_DATASET_EXPIRATION_TIME_PROPERTY_NAME, + BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.PROXY_HOST_PROPERTY_NAME, + BigQueryJdbcUrlUtility.PROXY_PORT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.JOB_CREATION_MODE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.MAX_RESULTS_PROPERTY_NAME, + BigQueryJdbcUrlUtility.PARTNER_TOKEN_PROPERTY_NAME, + BigQueryJdbcUrlUtility.ENDPOINT_OVERRIDES_PROPERTY_NAME, + BigQueryJdbcUrlUtility.PRIVATE_SERVICE_CONNECT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.METADATA_FETCH_THREAD_COUNT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.RETRY_TIMEOUT_IN_SECS_PROPERTY_NAME, + BigQueryJdbcUrlUtility.JOB_TIMEOUT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.RETRY_INITIAL_DELAY_PROPERTY_NAME, + BigQueryJdbcUrlUtility.RETRY_MAX_DELAY_PROPERTY_NAME, + BigQueryJdbcUrlUtility.ADDITIONAL_PROJECTS_PROPERTY_NAME, + BigQueryJdbcUrlUtility.CONNECTION_POOL_SIZE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.LISTENER_POOL_SIZE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.ENABLE_WRITE_API_PROPERTY_NAME, + BigQueryJdbcUrlUtility.SWA_APPEND_ROW_COUNT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.SWA_ACTIVATION_ROW_COUNT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.FILTER_TABLES_ON_DEFAULT_DATASET_PROPERTY_NAME, + BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.SSL_TRUST_STORE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.MAX_BYTES_BILLED_PROPERTY_NAME, + BigQueryJdbcUrlUtility.LABELS_PROPERTY_NAME, + BigQueryJdbcUrlUtility.REQUEST_REASON_PROPERTY_NAME, + BigQueryJdbcUrlUtility.HTTP_CONNECT_TIMEOUT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.HTTP_READ_TIMEOUT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.BYOID_AUDIENCE_URI_PROPERTY_NAME, + BigQueryJdbcUrlUtility.BYOID_CREDENTIAL_SOURCE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.BYOID_POOL_USER_PROJECT_PROPERTY_NAME, + BigQueryJdbcUrlUtility.BYOID_SA_IMPERSONATION_URI_PROPERTY_NAME, + BigQueryJdbcUrlUtility.BYOID_SUBJECT_TOKEN_TYPE_PROPERTY_NAME, + BigQueryJdbcUrlUtility.BYOID_TOKEN_URI_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_EMAIL_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_CHAIN_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_TOKEN_LIFETIME_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_SA_EMAIL_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_PVT_KEY_PATH_PROPERTY_NAME, + BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME) + .build(); private HeaderProvider headerProvider; BigQueryReadClient bigQueryReadClient = null; BigQueryWriteClient bigQueryWriteClient = null; @@ -152,6 +217,18 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { this.connectionId = UUID.randomUUID().toString(); try (BigQueryJdbcMdc.MdcCloseable mdc = BigQueryJdbcMdc.registerInstance(this.connectionId)) { this.connectionUrl = url; + if (LOG.isLoggable(java.util.logging.Level.CONFIG)) { + Properties connectionProps = ds.createProperties(); + Properties maskedProps = new Properties(); + for (String name : connectionProps.stringPropertyNames()) { + String value = connectionProps.getProperty(name); + if (!SAFE_TO_LOG_PROPERTIES.contains(name)) { + value = "*****"; + } + maskedProps.setProperty(name, value); + } + LOG.config("Connection properties: %s", maskedProps.toString()); + } this.openStatements = ConcurrentHashMap.newKeySet(); this.autoCommit = true; this.sqlWarnings = new ArrayList<>(); diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java index 82c14a41fbdb..4ad4e094338c 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java @@ -392,7 +392,7 @@ public Connection getConnection() throws SQLException { return DriverManager.getConnection(getURL(), createProperties()); } - private Properties createProperties() { + Properties createProperties() { Properties connectionProperties = new Properties(); if (this.projectId != null) { connectionProperties.setProperty( diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java index dd6ceb0deceb..252d252588bc 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java @@ -29,13 +29,17 @@ import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; +import java.util.Optional; import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -public class BigQueryConnectionTest { +public class BigQueryConnectionTest extends BigQueryJdbcLoggingBaseTest { private static final String DEFAULT_VERSION = "0.0.0"; private static final String DEFAULT_JDBC_TOKEN_VALUE = "Google-BigQuery-JDBC-Driver"; @@ -456,4 +460,36 @@ public void testIsReadOnlyTokenProvided(String readonlyProp, boolean expectedIsR assertEquals(expectedIsReadOnly, connection.isReadOnlyTokenUsed()); } } + + @Test + public void testConnectionPropertiesLoggingAndMasking() throws IOException, SQLException { + Logger rootLogger = BigQueryJdbcRootLogger.getRootLogger(); + Level originalLevel = rootLogger.getLevel(); + rootLogger.setLevel(Level.CONFIG); + + try { + String url = + "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" + + "OAuthType=2;ProjectId=MyTestProjectId;" + + "OAuthAccessToken=secretAccessToken;Location=US;"; + try (BigQueryConnection connection = new BigQueryConnection(url)) { + // Just trigger the constructor + } + + Optional connectionPropertiesLog = + capturedLogs.stream() + .filter(r -> r.getMessage().contains("Connection properties:")) + .findFirst(); + assertTrue( + connectionPropertiesLog.isPresent(), + "Log message about Connection properties was not found"); + String logMessage = connectionPropertiesLog.get().getMessage(); + assertTrue(logMessage.contains("ProjectId=MyTestProjectId")); + assertTrue(logMessage.contains("Location=US")); + assertTrue(logMessage.contains("OAuthAccessToken=*****")); + assertFalse(logMessage.contains("secretAccessToken")); + } finally { + rootLogger.setLevel(originalLevel); + } + } }