diff --git a/CHANGES.txt b/CHANGES.txt index 5b811256d25f..e4a1d2078815 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -30,11 +30,11 @@ Merged from 5.0: * Fix ThreadLocalReadAheadBuffer#fill() to throw a CorruptBlockException if chunk metadata and file size are out of sync (CASSANDRA-21519) * Fix memtable on-heap accounting drift in BTree.update and BTreeRow.merge (CASSANDRA-21472) 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) * Validate authz before performing role check in LIST ROLES/PERMISSIONS (CASSANDRA-21560) * 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 7cf98d2892a3..4f5d81b3f1e8 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -209,6 +209,9 @@ Upgrading unchanged, and the datacenter and CIDR checks that ride along with them still run at least once per request. Auth cache request/hit/miss counts and the system_views.cidr_filtering_metrics_* counts and latencies will therefore report fewer events than before. (see CASSANDRA-21606) + - 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) Deprecation ----------- diff --git a/doc/modules/cassandra/pages/managing/operating/virtualtables.adoc b/doc/modules/cassandra/pages/managing/operating/virtualtables.adoc index 1ab7ddfd031d..68aef2e3d567 100644 --- a/doc/modules/cassandra/pages/managing/operating/virtualtables.adoc +++ b/doc/modules/cassandra/pages/managing/operating/virtualtables.adoc @@ -175,7 +175,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: [source, console] @@ -190,6 +190,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 @@ -205,6 +206,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 @@ -220,6 +222,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 @@ -235,6 +238,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 @@ -271,6 +275,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, @@ -668,10 +673,10 @@ results in: + [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) ---- \ No newline at end of file diff --git a/src/java/org/apache/cassandra/db/virtual/ClientsTable.java b/src/java/org/apache/cassandra/db/virtual/ClientsTable.java index ec8ef12c99c0..1c839e6b3f36 100644 --- a/src/java/org/apache/cassandra/db/virtual/ClientsTable.java +++ b/src/java/org/apache/cassandra/db/virtual/ClientsTable.java @@ -38,6 +38,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"; @@ -60,6 +61,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) @@ -86,6 +88,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, toLowerCaseLocalized(client.stage().toString())) .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 892cd97ee9b7..6a40b5565d4a 100644 --- a/src/java/org/apache/cassandra/db/virtual/GossipInfoTable.java +++ b/src/java/org/apache/cassandra/db/virtual/GossipInfoTable.java @@ -48,6 +48,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"; @@ -97,6 +98,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)); @@ -173,6 +175,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 81ba659b84dc..12360809810a 100644 --- a/test/unit/org/apache/cassandra/db/virtual/ClientsTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/ClientsTableTest.java @@ -70,7 +70,7 @@ public void testSelectAll() shouldUseEncryption(true); shouldUseClientCertificate(true); ResultSet result = executeNet("SELECT * FROM vts.clients"); - assertThat(result.getColumnDefinitions().size()).isEqualTo(15); + assertThat(result.getColumnDefinitions().size()).isEqualTo(16); for (Row r : result) { Assert.assertEquals(InetAddress.getLoopbackAddress(), r.getInet("address")); @@ -79,6 +79,7 @@ public void testSelectAll() 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 3493753fbe85..c1ea6ee7b190 100644 --- a/test/unit/org/apache/cassandra/db/virtual/GossipInfoTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/GossipInfoTableTest.java @@ -70,12 +70,13 @@ public void testSelectAllWithStateTransitions() throws Throwable assertThat(resultSet.size()).isEqualTo(1); UntypedResultSet.Row row = resultSet.one(); - assertThat(row.getColumns().size()).isEqualTo(65); + assertThat(row.getColumns().size()).isEqualTo(66); 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();