Disable scripted UDFs by default

patch by Robert Stupp; reviewed by Aleksey Yeschenko for CASSANDRA-9889
This commit is contained in:
Robert Stupp 2015-08-04 00:05:30 +02:00
parent fcece2dc2b
commit e37d577b6c
8 changed files with 52 additions and 6 deletions

View File

@ -1,4 +1,5 @@
3.0.0-beta1
* Disable scripted UDFs by default (CASSANDRA-9889)
* Add transparent data encryption core classes (CASSANDRA-9945)
* Bytecode inspection for Java-UDFs (CASSANDRA-9890)
Merged from 2.2:

View File

@ -887,6 +887,12 @@ tracetype_repair_ttl: 604800
# As of Cassandra 3.0 there is a sandbox in place that should prevent execution of evil code.
enable_user_defined_functions: false
# Enables scripted UDFs (JavaScript UDFs).
# Java UDFs are always enabled, if enable_user_defined_functions is true.
# Enable this option to be able to use UDFs with "language javascript" or any custom JSR-223 provider.
# This option has no effect, if enable_user_defined_functions is false.
enable_scripted_user_defined_functions: false
# The default Windows kernel timer and scheduling resolution is 15.6ms for power conservation.
# Lowering this value on Windows can provide much tighter latency and better throughput, however
# some virtualized environments may see a negative performance impact from changing this setting

View File

@ -266,6 +266,7 @@ public class Config
public int windows_timer_interval = 0;
public boolean enable_user_defined_functions = false;
public boolean enable_scripted_user_defined_functions = false;
/**
* Optionally disable asynchronous UDF execution.
* Disabling asynchronous UDF execution also implicitly disables the security-manager!

View File

@ -1754,6 +1754,16 @@ public class DatabaseDescriptor
return conf.enable_user_defined_functions;
}
public static boolean enableScriptedUserDefinedFunctions()
{
return conf.enable_scripted_user_defined_functions;
}
public static void enableScriptedUserDefinedFunctions(boolean enableScriptedUserDefinedFunctions)
{
conf.enable_scripted_user_defined_functions = enableScriptedUserDefinedFunctions;
}
public static boolean enableUserDefinedFunctionsThreads()
{
return conf.enable_user_defined_functions_threads;

View File

@ -209,8 +209,7 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
String language,
String body)
{
if (!DatabaseDescriptor.enableUserDefinedFunctions())
throw new InvalidRequestException("User-defined functions are disabled in cassandra.yaml - set enable_user_defined_functions=true to enable if you are aware of the security risks");
UDFunction.assertUdfsEnabled(language);
switch (language)
{
@ -258,8 +257,7 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
public final ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
{
if (!DatabaseDescriptor.enableUserDefinedFunctions())
throw new InvalidRequestException("User-defined-functions are disabled in cassandra.yaml - set enable_user_defined_functions=true to enable if you are aware of the security risks");
assertUdfsEnabled(language);
if (!isCallableWrtNullable(parameters))
return null;
@ -289,6 +287,14 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
}
}
public static void assertUdfsEnabled(String language)
{
if (!DatabaseDescriptor.enableUserDefinedFunctions())
throw new InvalidRequestException("User-defined functions are disabled in cassandra.yaml - set enable_user_defined_functions=true to enable");
if (!"java".equalsIgnoreCase(language) && !DatabaseDescriptor.enableScriptedUserDefinedFunctions())
throw new InvalidRequestException("Scripted user-defined functions are disabled in cassandra.yaml - set enable_scripted_user_defined_functions=true to enable if you are aware of the security risks");
}
private static final class ThreadIdAndCpuTime
{
long threadId;

View File

@ -131,8 +131,7 @@ public final class CreateFunctionStatement extends SchemaAlteringStatement
public void validate(ClientState state) throws InvalidRequestException
{
if (!DatabaseDescriptor.enableUserDefinedFunctions())
throw new InvalidRequestException("User-defined-functions are disabled in cassandra.yaml - set enable_user_defined_functions=true to enable if you are aware of the security risks");
UDFunction.assertUdfsEnabled(language);
if (ifNotExists && orReplace)
throw new InvalidRequestException("Cannot use both 'OR REPLACE' and 'IF NOT EXISTS' directives");

View File

@ -39,3 +39,4 @@ compaction_throughput_mb_per_sec: 0
row_cache_class_name: org.apache.cassandra.cache.OHCProvider
row_cache_size_in_mb: 16
enable_user_defined_functions: true
enable_scripted_user_defined_functions: true

View File

@ -35,6 +35,7 @@ import org.junit.Test;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TupleType;
import com.datastax.driver.core.TupleValue;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.cql3.functions.FunctionName;
@ -475,4 +476,25 @@ public class UFPureScriptTest extends CQLTester
row(1, expected1, expected2));
}
}
@Test
public void testJavascriptDisabled() throws Throwable
{
createTable("CREATE TABLE %s (key int primary key, val double)");
DatabaseDescriptor.enableScriptedUserDefinedFunctions(false);
try
{
assertInvalid("double",
"CREATE OR REPLACE FUNCTION " + KEYSPACE + ".assertNotEnabled(val double) " +
"RETURNS NULL ON NULL INPUT " +
"RETURNS double " +
"LANGUAGE javascript\n" +
"AS 'Math.sin(val);';");
}
finally
{
DatabaseDescriptor.enableScriptedUserDefinedFunctions(true);
}
}
}