package eu.esdihumboldt.util.groovy.sandbox.test.internal; import static org.junit.Assert.fail; import java.util.Collections; import org.codehaus.groovy.control.CompilerConfiguration; import org.junit.Before; import org.junit.Test; import org.kohsuke.groovy.sandbox.SandboxTransformer; import eu.esdihumboldt.util.groovy.sandbox.internal.RestrictiveGroovyInterceptor; import eu.esdihumboldt.util.groovy.sandbox.internal.RestrictiveGroovyInterceptor.AllowedPrefix; import groovy.lang.GroovyShell; /** * Test for Groovy sandboxing. * * @author Kai Schwierczek */ @SuppressWarnings("restriction") public class GroovySandboxTest { private RestrictiveGroovyInterceptor interceptor; private GroovyShell shell; /** * Sets up the Groovy shell and interceptor. */ @Before public void setUp() { CompilerConfiguration cc = new CompilerConfiguration(); cc.addCompilationCustomizers(new SandboxTransformer()); shell = new GroovyShell(cc); interceptor = new RestrictiveGroovyInterceptor(Collections.<Class<?>> emptySet(), Collections.<Class<?>> emptySet(), Collections.<AllowedPrefix> emptyList()); } /** * Tests that the basic classes are allowed with their defined methods. */ @Test public void basicClassesAllowed() { interceptor.register(); shell.evaluate("new String().toString()"); shell.evaluate("new Integer(5).intValue(); Integer.MAX_VALUE"); shell.evaluate("Math.random()"); shell.evaluate("new Date().getTime()"); shell.evaluate("\"${new Date()}.toString()\""); shell.evaluate("['foo', 'bar', 'list'].size()"); shell.evaluate("['foo':'bar', 'map':'value'].size()"); shell.evaluate("[1..3].size()"); interceptor.unregister(); } private void assertDisallowed(String script) { boolean caught = false; try { shell.evaluate(script); } catch (Exception e) { caught = true; } finally { if (!caught) fail("script was not intercepted correctly! " + script); } } /** * Tests, that access to not allowed classes is disallowed. */ @Test public void notAllowedClassesDisallowed() { interceptor.register(); // some exemplary tests assertDisallowed("System.exit(0)"); assertDisallowed("''.getClass().forName('java.lang.System')"); interceptor.unregister(); } /** * Tests, that certain Groovy methods, properties cannot be accessed. */ @Test public void groovyStuffDisallowed() { interceptor.register(); assertDisallowed("\"${new Date()}\".invokeMethod('blafoo', null)"); assertDisallowed("metaClass = null"); assertDisallowed("setMetaClass(null)"); assertDisallowed("setProperty(null, null)"); interceptor.unregister(); } /** * Tests, that certain Closure methods, properties cannot be accessed. */ @Test public void closureStuffDisallowed() { interceptor.register(); assertDisallowed("{->}.delegate = null"); assertDisallowed("{->}.setDelegate(null)"); assertDisallowed("{->}.directive = 0"); assertDisallowed("{->}.setDirective(0)"); assertDisallowed("{->}.resolveStrategy = 0"); assertDisallowed("{->}.setResolveStrategy(0)"); assertDisallowed("{->}.rehydrate(0, 1, 2)"); // test one pair from within closure assertDisallowed("{-> resolveStrategy = 0}()"); assertDisallowed("{-> setResolveStrategy(0)}()"); interceptor.unregister(); } /** * Tests, that expressions inside GStrings are intercepted, too. */ @Test public void gstringIntercepted() { interceptor.register(); assertDisallowed("\"${->System.exit(0)}\".toString()"); assertDisallowed("\"${out -> out << 'foo'}\".toString()"); assertDisallowed("\"${new File('foo')}\".toString()"); interceptor.unregister(); } }