Groovy is integrated with the Java security model. Groovy scripts can be compiled and executed in the presence of a SecurityManager and a Policy that dictates what permissions are granted to the script.
In a typical java environment, permissions are granted to code according to its codeSource. A codeSource consists of a codebase (essentially, the URL the code was loaded from by the class loader) and optionally the certificates used to verify the code (when it is obtained from a signed jar file). Since groovy can produce java .class files which can be loaded by existing secure class loaders (e.g. URLClassLoader), the traditional mechanisms can be used to enforce security policies without doing anything special. Setting up and running java security can be a little tricky, so consider the following resources for more information:
- Java Security Tutorial
- Java Application Security
- Permissions in the Java 2 SDK
- Java 1.4 Security
- Java Security, 2nd Edition – O'Reilly
The last of these is a book which covers the Java security model in detail.
In a typical groovy environment, there are additional considerations – often groovy scripts are loaded dynamically from some filesystem and translated on the fly into java class files. In other cases, groovy scripts may be entered via an interactive shell, or retrieved from a database for dynamic translation.
Filesystem based Groovy scripts
In the case where the script is read from the filesystem, groovy uses a custom class loader GroovyClassLoader that searches the CLASSPATH for .groovy files and gives them a codeSource constructed from a codebase built from the source file URL. This class loader also supports signed .jar files containing .groovy scripts so that both codebase and certificates can be used to verify the source code. Once the groovy scripts are loaded as classes, they behave just like java classes with respect to security.
Non-URL based Groovy scripts
In the case where the script has no URL, there is not necessarily any definitive way for groovy to associate an appropriate codeSource with the script. In these cases, groovy allows a codebase to be specified for the script that is being compiled (by specifying a GroovyCodeSource), subject to the caller having permission to specify that specific codebase. This codebase takes the form of a URL, but need not refer to a physical file location.
To illustrate this more clearly, consider the case where some server system is responsible for fetching and loading scripts that will be executed on behalf of a client. Assume that the server is trusted (i.e. it has permission to do anything) while the client belongs to a class of restricted clients that only (for example) have permission to access the normally resricted property "file.encoding". For this simple example, assume that the security Policy in effect has been specified by the following policy file:
The groovy script to be executed on behalf of the client is:
When the client calls the server and passes this script for execution, the server can evaluate it, specifying a specific codebase:
In order for the server to be able to create a GroovyCodeSource with a specific codeBase, it must be granted permission by the Policy. The specific permission required is a GroovyCodeSourcePermission, which the server has by implication (the policy file grant of java.security.AllPermission).
The net effect of this is to compile the client script with the codeBase "/serverCodeBase/restrictedClient", and execute the compiled script. When executed, the policy file grant(s) for the codeBase "/serverCodeBase/restrictedClient" will be in effect.
For more information, check out the security test cases in the groovy source code distribution. These tests specify a custom policy file groovy.policy, which is located in the security directory under the groovy-core CVS module. The class SecurityTestSupport (located at src/test/groovy/security) activates this policy by specifying it in the system property "java.security.policy". Examining this policy file along with the test cases should detail the concepts discussed here.
Note that in a typical application environment, the policy would be located and activated either by using the default lookup mechanism (policy.url.<n> setting in JAVA_HOME/jre/lib/security/java.security) or as a VM argument: -Djava.security.policy=/my/policy/file.