diff --git a/CHANGES.txt b/CHANGES.txt index db88379acfe2..d70393e36dcd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,12 +1,12 @@ 4.1.13 Merged from 4.0: + * Avoid DNS lookup for hostname column in ClientsTable and GossipInfoTable (CASSANDRA-21539) * During streaming Bounds.getNonOverlappingBounds produces incorrect bounds leading to row/counter cache not invalidate correctly (CASSANDRA-21594) * Make runWithCompactionsDisabled return non-null on success (CASSANDRA-21527) * Validate authz before performing role check in LIST ROLES/PERMISSIONS (CASSANDRA-21560) * Ensure transferred_ranges reset on decommision re-attempt when pending ranges cannot be proven continous (CASSANDRA-16290) * Add validation to uncompressed length during decompression (CASSANDRA-21567) * Fix regression in PasswordObfuscator for dollar-quoted passwords (CASSANDRA-21559) - * Do not make DNS lookup when querying system_views.clients for hostname column by removing it (CASSANDRA-21539) * Fix memtable on-heap accounting drift in BTree.update and BTreeRow.merge (CASSANDRA-21472) * Include missing cassandra-jaas.config file in Debian package (CASSANDRA-19750) diff --git a/NEWS.txt b/NEWS.txt index 208e9ce9123e..c2b6b90ab5b5 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -59,6 +59,9 @@ Upgrading - This release addresses a security vulnerability in the LZ4 dependency, documented in CASSANDRA-21052. For users who did not use LZ4 native libraries, this will now fallback to a safer but less performant pure Java implementation. During startup, a warning will be logged if the LZ4 native library is not available. + - The hostname column in system_views.clients will no longer perform a reverse DNS lookup and will instead + return the same value as the address column. This avoids the risk of client connections overwhelming + DNS. (CASSANDRA-21539) 4.0.14 ====== diff --git a/doc/modules/cassandra/pages/new/virtualtables.adoc b/doc/modules/cassandra/pages/new/virtualtables.adoc index 6b402d1e6f9c..7a7a4befa792 100644 --- a/doc/modules/cassandra/pages/new/virtualtables.adoc +++ b/doc/modules/cassandra/pages/new/virtualtables.adoc @@ -112,7 +112,7 @@ We shall discuss some of the virtual tables in more detail next. The `clients` virtual table lists all active connections (connected clients) including their ip address, port, client_options, connection stage, driver -name, driver version, protocol version, request count, ssl +name, driver version, hostname, protocol version, request count, ssl enabled, ssl protocol and user name: .... @@ -128,6 +128,7 @@ cqlsh> SELECT * FROM system_views.clients; connection_stage | ready driver_name | DataStax Python Driver driver_version | 3.25.0 + hostname | localhost protocol_version | 5 request_count | 16 ssl_cipher_suite | null @@ -143,6 +144,7 @@ cqlsh> SELECT * FROM system_views.clients; connection_stage | ready driver_name | DataStax Python Driver driver_version | 3.25.0 + hostname | localhost protocol_version | 5 request_count | 4 ssl_cipher_suite | null @@ -158,6 +160,7 @@ cqlsh> SELECT * FROM system_views.clients; connection_stage | ready driver_name | DataStax Java driver for Apache Cassandra(R) driver_version | 4.13.0 + hostname | localhost protocol_version | 5 request_count | 18 ssl_cipher_suite | null @@ -173,6 +176,7 @@ cqlsh> SELECT * FROM system_views.clients; connection_stage | ready driver_name | DataStax Java driver for Apache Cassandra(R) driver_version | 4.13.0 + hostname | localhost protocol_version | 5 request_count | 7 ssl_cipher_suite | null @@ -209,6 +213,7 @@ VIRTUAL TABLE system_views.clients ( connection_stage text, driver_name text, driver_version text, + hostname text, protocol_version int, request_count bigint, ssl_cipher_suite text, @@ -503,10 +508,10 @@ cqlsh> SELECT * FROM clients LIMIT 2; [source, cql] ---- - address | port | connection_stage | driver_name | driver_version | protocol_version | request_count | ssl_cipher_suite | ssl_enabled | ssl_protocol | username ------------+-------+------------------+------------------------+----------------+------------------+---------------+------------------+-------------+--------------+----------- - 127.0.0.1 | 37308 | ready | DataStax Python Driver | 3.21.0.post0 | 4 | 17 | null | False | null | anonymous - 127.0.0.1 | 37310 | ready | DataStax Python Driver | 3.21.0.post0 | 4 | 8 | null | False | null | anonymous + address | port | connection_stage | driver_name | driver_version | hostname | protocol_version | request_count | ssl_cipher_suite | ssl_enabled | ssl_protocol | username +-----------+-------+------------------+------------------------+----------------+-----------+------------------+---------------+------------------+-------------+--------------+----------- + 127.0.0.1 | 37308 | ready | DataStax Python Driver | 3.21.0.post0 | localhost | 4 | 17 | null | False | null | anonymous + 127.0.0.1 | 37310 | ready | DataStax Python Driver | 3.21.0.post0 | localhost | 4 | 8 | null | False | null | anonymous (2 rows) ---- diff --git a/src/java/org/apache/cassandra/db/virtual/ClientsTable.java b/src/java/org/apache/cassandra/db/virtual/ClientsTable.java index ab796eaa4323..ee09d07425ed 100644 --- a/src/java/org/apache/cassandra/db/virtual/ClientsTable.java +++ b/src/java/org/apache/cassandra/db/virtual/ClientsTable.java @@ -29,6 +29,7 @@ final class ClientsTable extends AbstractVirtualTable { private static final String ADDRESS = "address"; private static final String PORT = "port"; + private static final String HOSTNAME = "hostname"; private static final String USERNAME = "username"; private static final String CONNECTION_STAGE = "connection_stage"; private static final String PROTOCOL_VERSION = "protocol_version"; @@ -48,6 +49,7 @@ final class ClientsTable extends AbstractVirtualTable .partitioner(new LocalPartitioner(InetAddressType.instance)) .addPartitionKeyColumn(ADDRESS, InetAddressType.instance) .addClusteringColumn(PORT, Int32Type.instance) + .addRegularColumn(HOSTNAME, UTF8Type.instance) .addRegularColumn(USERNAME, UTF8Type.instance) .addRegularColumn(CONNECTION_STAGE, UTF8Type.instance) .addRegularColumn(PROTOCOL_VERSION, Int32Type.instance) @@ -71,6 +73,7 @@ public DataSet data() InetSocketAddress remoteAddress = client.remoteAddress(); result.row(remoteAddress.getAddress(), remoteAddress.getPort()) + .column(HOSTNAME, remoteAddress.getHostString()) .column(USERNAME, client.username().orElse(null)) .column(CONNECTION_STAGE, client.stage().toString().toLowerCase()) .column(PROTOCOL_VERSION, client.protocolVersion()) diff --git a/src/java/org/apache/cassandra/db/virtual/GossipInfoTable.java b/src/java/org/apache/cassandra/db/virtual/GossipInfoTable.java index 228551aab45d..7d8bc593cc67 100644 --- a/src/java/org/apache/cassandra/db/virtual/GossipInfoTable.java +++ b/src/java/org/apache/cassandra/db/virtual/GossipInfoTable.java @@ -46,6 +46,7 @@ final class GossipInfoTable extends AbstractVirtualTable static final String ADDRESS = "address"; static final String PORT = "port"; + static final String HOSTNAME = "hostname"; static final String GENERATION = "generation"; static final String HEARTBEAT = "heartbeat"; @@ -95,6 +96,7 @@ public DataSet data() EndpointState localState = new EndpointState(entry.getValue()); SimpleDataSet dataSet = result.row(endpoint.getAddress(), endpoint.getPort()) + .column(HOSTNAME, endpoint.getHostString()) .column(GENERATION, getGeneration(localState)) .column(HEARTBEAT, getHeartBeat(localState)); @@ -171,6 +173,7 @@ private static TableMetadata buildTableMetadata(String keyspace) .partitioner(new LocalPartitioner(InetAddressType.instance)) .addPartitionKeyColumn(ADDRESS, InetAddressType.instance) .addClusteringColumn(PORT, Int32Type.instance) + .addRegularColumn(HOSTNAME, UTF8Type.instance) .addRegularColumn(GENERATION, Int32Type.instance) .addRegularColumn(HEARTBEAT, Int32Type.instance); diff --git a/test/unit/org/apache/cassandra/db/virtual/ClientsTableTest.java b/test/unit/org/apache/cassandra/db/virtual/ClientsTableTest.java index 1a9663d8d41c..219e55164064 100644 --- a/test/unit/org/apache/cassandra/db/virtual/ClientsTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/ClientsTableTest.java @@ -56,8 +56,8 @@ public void config() public void testSelectAll() throws Throwable { ResultSet result = executeNet("SELECT * FROM vts.clients"); - assertThat(result.getColumnDefinitions().size()).isEqualTo(12); - + assertThat(result.getColumnDefinitions().size()).isEqualTo(13); + for (Row r : result) { Assert.assertEquals(InetAddress.getLoopbackAddress(), r.getInet("address")); @@ -66,6 +66,7 @@ public void testSelectAll() throws Throwable Assert.assertNotNull(r.getMap("client_options", String.class, String.class)); Assert.assertTrue(r.getLong("request_count") > 0 ); // the following are questionable if they belong here + Assert.assertEquals(r.getInet("address").getHostAddress(), r.getString("hostname")); Assertions.assertThat(r.getMap("client_options", String.class, String.class)) .hasEntrySatisfying("DRIVER_VERSION", value -> assertThat(value.contains(r.getString("driver_name")))) .hasEntrySatisfying("DRIVER_VERSION", value -> assertThat(value.contains(r.getString("driver_version")))); diff --git a/test/unit/org/apache/cassandra/db/virtual/GossipInfoTableTest.java b/test/unit/org/apache/cassandra/db/virtual/GossipInfoTableTest.java index 4c1ab4d897aa..5c25d6ede51e 100644 --- a/test/unit/org/apache/cassandra/db/virtual/GossipInfoTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/GossipInfoTableTest.java @@ -77,12 +77,13 @@ public void testSelectAllWithStateTransitions() throws Throwable assertThat(resultSet.size()).isEqualTo(1); UntypedResultSet.Row row = resultSet.one(); - assertThat(row.getColumns().size()).isEqualTo(63); + assertThat(row.getColumns().size()).isEqualTo(64); assertThat(endpoint).isNotNull(); assertThat(localState).isNotNull(); assertThat(row.getInetAddress("address")).isEqualTo(endpoint.getAddress()); assertThat(row.getInt("port")).isEqualTo(endpoint.getPort()); + assertThat(row.getString("hostname")).isEqualTo(endpoint.getAddress().getHostAddress()); assertThat(row.getInt("generation")).isEqualTo(localState.getHeartBeatState().getGeneration()); assertThat(row.getInt("heartbeat")).isNotNull();