Scripting and sandboxing in Java applications part 1

It’s a very common situation when an application needs some runtime customization, but it’s impossible via settings and you are too lazy to change source code, or you just cannot update your application too often. In that case you may use different script engines in order to change application behavior in runtime. Moreover, the developer doesn’t have to do changes themself. It may be the duty of administrators, analysts, etc

 

So, I want to describe the way of one java application, from the simplest script engine up to engines with secured sandboxes.

The first approach – javascript engine

We just needed to preprocess input strings – just filter them, trim and normalize. There was nothing interesting there. In this case a javascript engine was the most suitable solution. So  out choise was Nashorn.  With this interpreter you are able to:

  • Make some code on javascript of course
  • Implement your own javascript functions
  • Access to Java classes
  • Invoke Java methods from javascript
  • Invoke javascript methods from Java
  • Implement a sandbox
  • etc

It’s a part of JDK and there is even a console interpreter.

jjs
jjs> print (‘giggity’)
giggity

Integration is also very simple:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("print('giggity');");

You may find more examples here or here. This solution was acceptable for that time, but requirements had changed over time

The next step – Groovy engine

The code base was growing and we needed something more serious than a JavaScript engine. In addition, the whole team is JVM-based, so the next choice was the Groovy engine.

Binding binding = new Binding();
GroovyShell shell = new GroovyShell(binding);
Script scrpt = shell.parse(new File("app.groovy"));
binding.setVariable("foo", "bar");
shell.evaluate("println(foo)")

So we had the full power of a Java Virtual Machine. Since that point our application was going to production usage. A little bit about the app – it contains a huge amount of very sensitive data. Also, there are complex ACLs, rules and so on, which are protecting data from unauthorized access. In this stage we were faced with big security issues. As I mentioned before, we had the full power of JVM and user-script had access to reflection API, internal classes, bean, processes and so on. The first thing that we tried was the sandbox by Kohsuke Kawaguchi. For the first try it was ok, but it works only as a whitelist model. It became incompatible with our requirements. In my next post I will describe how we’ve built sandbox for paranoid.

 

Leave a Reply

Your email address will not be published. Required fields are marked *