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]

Reply via email to