This is an automated email from the ASF dual-hosted git repository.
marcuse pushed a commit to branch cassandra-4.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-4.0 by this push:
new aafb4d1944 Improve nodetool enable{audit,fullquery}log
aafb4d1944 is described below
commit aafb4d19448f12ce600dc4e84a5b181308825b32
Author: Marcus Eriksson <[email protected]>
AuthorDate: Wed Apr 12 09:17:50 2023 +0200
Improve nodetool enable{audit,fullquery}log
Patch by marcuse; reviewed by Dinesh Joshi and Mick Semb Wever for
CASSANDRA-18550
---
CHANGES.txt | 1 +
conf/cassandra.yaml | 2 ++
.../cassandra/config/DatabaseDescriptor.java | 5 ++++
.../apache/cassandra/service/StorageService.java | 2 ++
.../tools/nodetool/EnableFullQueryLog.java | 3 ++-
.../cassandra/utils/binlog/BinLogOptions.java | 7 ++++++
.../apache/cassandra/fql/FullQueryLoggerTest.java | 28 +++++++++++++++++++++-
7 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index b057a07f2a..4f873aa71c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.0.10
+ * Improve nodetool enable{audit,fullquery}log (CASSANDRA-18550)
* Report network cache info in nodetool (CASSANDRa-18400)
* Partial compaction can resurrect deleted data (CASSANDRA-18507)
* Allow internal address to change with reconnecting snitches
(CASSANDRA-16718)
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index 1b0871fcf1..3e4da52f5f 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -1360,6 +1360,8 @@ audit_logging_options:
# max_log_size: 17179869184 # 16 GiB
## archive command is "/path/to/script.sh %path" where %path is replaced
with the file being rolled:
# archive_command:
+ ## note that enabling this allows anyone with JMX/nodetool access to run
local shell commands as the user running cassandra
+ # allow_nodetool_archive_command: false
# max_archive_retries: 10
# validate tombstones on reads and compaction
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index f78a5b668a..8893f58e56 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -3140,6 +3140,11 @@ public class DatabaseDescriptor
return conf.full_query_logging_options;
}
+ public static void setFullQueryLogOptions(FullQueryLoggerOptions options)
+ {
+ conf.full_query_logging_options = options;
+ }
+
public static boolean getBlockForPeersInRemoteDatacenters()
{
return conf.block_for_peers_in_remote_dcs;
diff --git a/src/java/org/apache/cassandra/service/StorageService.java
b/src/java/org/apache/cassandra/service/StorageService.java
index 6a02b405af..b53467e81b 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -6081,6 +6081,8 @@ public class StorageService extends
NotificationBroadcasterSupport implements IE
blocking = blocking != null ? blocking : fqlOptions.block;
maxQueueWeight = maxQueueWeight != Integer.MIN_VALUE ? maxQueueWeight
: fqlOptions.max_queue_weight;
maxLogSize = maxLogSize != Long.MIN_VALUE ? maxLogSize :
fqlOptions.max_log_size;
+ if (archiveCommand != null &&
!fqlOptions.allow_nodetool_archive_command)
+ throw new ConfigurationException("Can't enable full query log
archiving via nodetool unless
full_query_logging_options.allow_nodetool_archive_command is set to true");
archiveCommand = archiveCommand != null ? archiveCommand :
fqlOptions.archive_command;
maxArchiveRetries = maxArchiveRetries != Integer.MIN_VALUE ?
maxArchiveRetries : fqlOptions.max_archive_retries;
diff --git
a/src/java/org/apache/cassandra/tools/nodetool/EnableFullQueryLog.java
b/src/java/org/apache/cassandra/tools/nodetool/EnableFullQueryLog.java
index 9873e5a01a..d78d5ae80f 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/EnableFullQueryLog.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/EnableFullQueryLog.java
@@ -42,7 +42,8 @@ public class EnableFullQueryLog extends NodeToolCmd
private String path = null;
@Option(title = "archive_command", name = {"--archive-command"},
description = "Command that will handle archiving rolled full query log files."
+
-
" Format is \"/path/to/script.sh %path\" where %path will be replaced with
the file to archive")
+
" Format is \"/path/to/script.sh %path\" where %path will be replaced with
the file to archive" +
+
" Enable this by setting the
full_query_logging_options.allow_nodetool_archive_command: true in the config.")
private String archiveCommand = null;
@Option(title = "archive_retries", name = {"--max-archive-retries"},
description = "Max number of archive retries.")
diff --git a/src/java/org/apache/cassandra/utils/binlog/BinLogOptions.java
b/src/java/org/apache/cassandra/utils/binlog/BinLogOptions.java
index 8005ca38ef..614d19031c 100644
--- a/src/java/org/apache/cassandra/utils/binlog/BinLogOptions.java
+++ b/src/java/org/apache/cassandra/utils/binlog/BinLogOptions.java
@@ -23,6 +23,13 @@ import org.apache.commons.lang3.StringUtils;
public class BinLogOptions
{
public String archive_command = StringUtils.EMPTY;
+
+ /**
+ * enable if a user should be able to set the archive command via
nodetool/jmx
+ *
+ * do not make this a hotprop.
+ */
+ public boolean allow_nodetool_archive_command = false;
/**
* How often to roll BinLog segments so they can potentially be reclaimed.
Available options are:
* MINUTELY, HOURLY, DAILY, LARGE_DAILY, XLARGE_DAILY, HUGE_DAILY.
diff --git a/test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java
b/test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java
index 73be0b493e..adb3ab67fd 100644
--- a/test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java
+++ b/test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java
@@ -32,7 +32,6 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
-import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -44,15 +43,18 @@ import net.openhft.chronicle.queue.RollCycles;
import net.openhft.chronicle.wire.ValueIn;
import net.openhft.chronicle.wire.WireOut;
import org.apache.cassandra.Util;
+import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.cql3.QueryOptions;
import org.apache.cassandra.cql3.statements.BatchStatement;
+import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.fql.FullQueryLogger.Query;
import org.apache.cassandra.fql.FullQueryLogger.Batch;
import org.apache.cassandra.cql3.statements.BatchStatement.Type;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.QueryState;
+import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.transport.ProtocolVersion;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.binlog.BinLogTest;
@@ -74,6 +76,7 @@ import static
org.apache.cassandra.fql.FullQueryLogger.SINGLE_QUERY;
import static org.apache.cassandra.fql.FullQueryLogger.TYPE;
import static org.apache.cassandra.fql.FullQueryLogger.VALUES;
import static org.apache.cassandra.fql.FullQueryLogger.VERSION;
+import static org.junit.Assert.fail;
public class FullQueryLoggerTest extends CQLTester
{
@@ -670,6 +673,29 @@ public class FullQueryLoggerTest extends CQLTester
logQuery("", QueryOptions.DEFAULT, queryState(), -1);
}
+ @Test
+ public void testJMXArchiveCommand()
+ {
+ FullQueryLoggerOptions options = new FullQueryLoggerOptions();
+
+ try
+ {
+ StorageService.instance.enableFullQueryLogger(options.log_dir,
options.roll_cycle, false, 1000, 1000, "/xyz/not/null", 0);
+ fail("not allowed");
+ }
+ catch (ConfigurationException e)
+ {
+ assertTrue(e.getMessage().contains("Can't enable full query log
archiving via nodetool"));
+ }
+
+ options.archive_command = "/xyz/not/null";
+ options.log_dir = "/tmp/abc";
+ DatabaseDescriptor.setFullQueryLogOptions(options);
+ StorageService.instance.enableFullQueryLogger(options.log_dir,
options.roll_cycle, false, 1000, 1000, null, 0);
+ assertTrue(FullQueryLogger.instance.isEnabled());
+ assertEquals("/xyz/not/null",
FullQueryLogger.instance.getFullQueryLoggerOptions().archive_command);
+ }
+
private static void compareQueryOptions(QueryOptions a, QueryOptions b)
{
assertEquals(a.getClass(), b.getClass());
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]