fps
fps

Reputation: 34460

Elasticsearch 2.0.0 security manager with groovy script

I'm using brand new Elasticsearch 2.0.0 from a Java application.

When calling the prepareUpdate() method with an inline groovy script that has the following code:

import org.elasticsearch.common.logging.*
import groovy.json.*

ESLogger logger = ESLoggerFactory.getLogger('events-sequence.groovy')

def TOKEN_SEPARATOR = "###"
def flow = [ ]

try {
    ctx._source.events.reverseEach { e ->
        def context = e.tuplenized_context ? JsonOutput.toJson(e.tuplenized_context) : "[]"
        flow << (e.name.toLowerCase() + TOKEN_SEPARATOR + context.toLowerCase())
    }
    ctx._source.flow = flow.join(TOKEN_SEPARATOR)

} catch (Throwable t) {
    logger.error("Error applying derivation", t)
    throw t
}

I'm receiving the following exception:

    java.security.AccessControlException: access denied ("java.util.PropertyPermission" "groovy.json.faststringutils.write.to.final.fields" "read")

According to the stacktrace, this happens when calling the JsonOutput.toJson() method:

java.lang.ExceptionInInitializerError
        at groovy.json.internal.CharBuf.addJsonFieldName(CharBuf.java:516)
        at groovy.json.JsonOutput.writeMap(JsonOutput.java:423)
        at groovy.json.JsonOutput.writeObject(JsonOutput.java:267)
        at groovy.json.JsonOutput.writeIterator(JsonOutput.java:441)
        at groovy.json.JsonOutput.writeObject(JsonOutput.java:269)
        at groovy.json.JsonOutput.toJson(JsonOutput.java:187)
        at groovy.json.JsonOutput$toJson.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
        at 3974cbb354b454f7c665982a3a8f854ede6125fb$_run_closure1.doCall(3974cbb354b454f7c665982a3a8f854ede6125fb:18)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1019)
        at groovy.lang.Closure.call(Closure.java:426)
        at groovy.lang.Closure.call(Closure.java:442)
        at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2030)
        at org.codehaus.groovy.runtime.DefaultGroovyMethods.reverseEach(DefaultGroovyMethods.java:2172)
        at org.codehaus.groovy.runtime.dgm$532.invoke(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:274)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
        at 3974cbb354b454f7c665982a3a8f854ede6125fb.run(3974cbb354b454f7c665982a3a8f854ede6125fb:17)
        at org.elasticsearch.script.groovy.GroovyScriptEngineService$GroovyScript.run(GroovyScriptEngineService.java:248)
        at org.elasticsearch.action.update.UpdateHelper.executeScript(UpdateHelper.java:251)
        at org.elasticsearch.action.update.UpdateHelper.prepare(UpdateHelper.java:196)
        at org.elasticsearch.action.update.UpdateHelper.prepare(UpdateHelper.java:79)
        at org.elasticsearch.action.bulk.TransportShardBulkAction.shardUpdateOperation(TransportShardBulkAction.java:408)
        at org.elasticsearch.action.bulk.TransportShardBulkAction.shardOperationOnPrimary(TransportShardBulkAction.java:203)
        at org.elasticsearch.action.support.replication.TransportReplicationAction$PrimaryPhase.performOnPrimary(TransportReplicationAction.java:579)
        at org.elasticsearch.action.support.replication.TransportReplicationAction$PrimaryPhase$1.doRun(TransportReplicationAction.java:452)
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    Caused by: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "groovy.json.faststringutils.write.to.final.fields" "read")
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
        at java.security.AccessController.checkPermission(AccessController.java:884)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
        at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294)
        at java.lang.System.getProperty(System.java:753)
        at groovy.json.internal.FastStringUtils.<clinit>(FastStringUtils.java:37)
        ... 42 more

In my elasticsearch.yml config file, I've added these 2 lines:

script.inline: on 
script.indexed: on

Is there anything else I need to configure so that I can serialize an object to JSON within a groovy script?

EDIT: I've also tried to initialize Elasticsearch setting the following option:

export ES_JAVA_OPTS=-Dgroovy.json.faststringutils.write.to.final.fields\=true

But had no luck, since the problem seems to be that there are no permissions to access the groovy.json.faststringutils.write.to.final.fields system property, whatever its value is.


EDIT 2: All modifying the default java.policy file, specifying a new policy file with the -Djava.security.manager and -Djava.security.policy=file:///my.policy options and disabling the security manager via the -Dsecurity.manager.enabled=false option didn't work.

I've reported this as an issue to the Elasticsearch guys, and they've already fixed it. Actually, here's the commit, but it won't be available until version 2.1.

Is there any workaround or configuration option to make it work now?

Upvotes: 1

Views: 1427

Answers (3)

Andrew White
Andrew White

Reputation: 53496

None of the other suggestions here worked for me either, but I did find that I could disable the ES security manager by adding the following to my elasticsearch.yml file...

security.manager.enabled: false

Note that this is deprecated as of 2.2.0 and will likely be removed soon. This is not a best practice and should be avoided when dynamic scripts are allowed.

Upvotes: 2

Mohit
Mohit

Reputation: 1755

A better way of implementing it is to define your script under /config/scripts. As your script is static, you gain following advantages out of it:

  1. No inline scripting required which makes your application safe.
  2. Script is compiled once and used again. This gives you performance gain.
  3. No need to change any java security policy.

Upvotes: 0

Ori Dar
Ori Dar

Reputation: 19000

You will have to update your policy file with the system property read permission.

Add: permission java.util.PropertyPermission "groovy.json.faststringutils.write.to.final.fields", "read" to the grant block.

The default policy file (java.policy) resides under $JAVA_HOME/lib/security, unless specified otherwise using java.security.policy system property.

Alternatively, run the JVM without a security manager with -Dsecurity.manager.enabled=false

Upvotes: 0

Related Questions