Security policy permissions for Grails in Tomcat

Here are the permissions I’ve used for Grails apps deployed to Tomcat running the Java security manager. The Grails 1.0.x permissions are for a simple CRUD app. So far the Grails 1.1 permissions are just for a Hello World app. They’re not cut-and-paste: some thought is required to apply to individual server setups and some duplication is present. The grants go in the conf/catalina.policy file and restarting Tomcat is required. Unfortunately, it seems impossible to completely isolate these per-webapp since the Groovy and Grails code presents itself in funny ways.

I’m using Tomcat 6.0.18 and used both JDK 1.6.0_12 and 1.6.0_13 running on some sort of Linux.

Common

These permissions are so common, not just for Groovy/Grails, that I gave up and allow them for all webapps.

grant {
    // jsp
    permission java.lang.RuntimePermission "defineClassInPackage.java.lang";
    permission java.lang.RuntimePermission "defineClassInPackage.org.apache.jasper.runtime";

    // jsp,struts,groovy,etc
    permission java.lang.RuntimePermission "accessDeclaredMembers";
    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina";
    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.coyote";

    // commons-beanutils, commons-digester, struts, and *every* jira and groovy/grails class
        // sigh, cf. https://www.securecoding.cert.org/confluence/display/java/SEC32-J.+Do+not+grant+ReflectPermission+with+action+suppressAccessChecks
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";

    // config
    permission java.util.PropertyPermission "catalina.base", "read";

    // logging
    permission java.util.PropertyPermission "log4j.*", "read";
    permission java.util.PropertyPermission "org.apache.commons.logging.*", "read";

    // dbcp,jdbc
    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.dbcp.dbcp";
    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.dbcp.pool";
    permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.dbcp.pool.impl";
    permission java.lang.RuntimePermission "accessClassInPackage.sun.jdbc.odbc";

    // we need to read web-app*.dtd at least from servlet-api.jar if not stuff from all the jars
    permission java.io.FilePermission "${catalina.home}${file.separator}lib${file.separator}-", "read";
    permission java.io.FilePermission "${catalina.base}${file.separator}lib${file.separator}-", "read";
};

Grails 1.0.x

This is needed if suppressAccessChecks is not allowed for everyone as above.

grant codeBase "file:/groovy/shell" {
   permission  java.lang.reflect.ReflectPermission "suppressAccessChecks";
};

General grant for Groovy:

grant codeBase "file:/groovy/script" {
   permission  java.lang.RuntimePermission "setContextClassLoader";
   permission  java.lang.reflect.ReflectPermission "suppressAccessChecks"; // if not allowed for all webapps above

    // database; adjust host/port
    permission java.net.SocketPermission "127.0.0.1:3306", "connect,resolve";
    permission java.net.SocketPermission "localhost", "resolve";
};

Per-webapp permissions:

grant codeBase "file:/PATH/TO/webapps/APPNAME/-" {
        // basic grails stuff incl. groovy magic
    permission groovy.security.GroovyCodeSourcePermission "/groovy/script";
    permission groovy.security.GroovyCodeSourcePermission "/groovy/shell";
    permission java.io.FilePermission "./grails-app/-", "read";
    permission java.io.FilePermission "/groovy/script", "read";
    permission java.io.FilePermission "/groovy/shell", "read";
    permission java.lang.RuntimePermission "accessClassInPackage.*";
    permission java.lang.RuntimePermission "createClassLoader";
    permission java.lang.RuntimePermission "defineClassInPackage.*";
    permission java.lang.RuntimePermission "getClassLoader";
    permission java.lang.RuntimePermission "getProtectionDomain";
    permission java.lang.RuntimePermission "setContextClassLoader";
    permission java.lang.RuntimePermission "shutdownHooks";
    permission java.util.PropertyPermission "*", "read,write";
};

These grants may be needed for Hibernate caching, and still might not be enough. If so, add them to the per-webapp section. Better is to re-configure the caching to use some other files, else they will be shared by multiple Grails webapps (which is bad). (Unfortunately that is difficult, especially to change the directory. Maybe another post will address it.)

        // grails 1.0.x broken hibernate ehcache
    //permission java.io.FilePermission "${catalina.base}${file.separator}temp", "read";
    //permission java.io.FilePermission "${catalina.base}${file.separator}temp${file.separator}org.hibernate.cache.StandardQueryCache.data", "read,write,delete";
    //permission java.io.FilePermission "${catalina.base}${file.separator}temp${file.separator}org.hibernate.cache.StandardQueryCache.index", "read,write,delete";
    //permission java.io.FilePermission "${catalina.base}${file.separator}temp${file.separator}org.hibernate.cache.UpdateTimestampsCache.data", "read,write,delete";
    //permission java.io.FilePermission "${catalina.base}${file.separator}temp${file.separator}org.hibernate.cache.UpdateTimestampsCache.index", "read,write,delete";

Grails 1.1

General grant needed for Groovy scripts:

// groovy scripts, e.g. grails
grant codeBase "file:/groovy/script" {
        // grails 1.1 + jdk 1.6.0_13
    permission java.lang.RuntimePermission "defineClassInPackage.java.io";
    permission java.lang.RuntimePermission "defineClassInPackage.java.lang";
    permission java.lang.RuntimePermission "defineClassInPackage.java.net";
    permission java.lang.RuntimePermission "defineClassInPackage.java.util";
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
    permission java.util.PropertyPermission "grails.env", "read";
};

Per-webapp grants:

grant codeBase "file:/PATH/TO/webapps/APPNAME/-" {
        // basic grails stuff incl. groovy magic
    permission groovy.security.GroovyCodeSourcePermission "/groovy/script";
    permission java.io.FilePermission "./grails-app/-", "read";
    permission java.io.FilePermission "/groovy/script", "read";
    permission java.lang.RuntimePermission "accessClassInPackage.*";
    permission java.lang.RuntimePermission "createClassLoader";
    permission java.lang.RuntimePermission "defineClassInPackage.*";
    permission java.lang.RuntimePermission "getClassLoader";
    permission java.lang.RuntimePermission "getProtectionDomain";
    permission java.lang.RuntimePermission "setContextClassLoader";
    permission java.lang.RuntimePermission "shutdownHooks";
    permission java.util.PropertyPermission "*", "read,write";

        // grails 1.1
    permission java.io.FilePermission "grails-app/-", "read";
    permission java.lang.RuntimePermission "setIO";

        // grails 1.1: various jars incl ant use /bin/env
    permission java.io.FilePermission "/bin/env", "read,execute";

        // jdk 1.6.0_13 + grails
    permission java.io.FilePermission "./plugins", "read";
};

Each webapp also needs an additional Groovy script grant:

grant codeBase "file:/groovy/script" {
        // grails 1.1 needs this for each webapp
    permission java.io.FilePermission "/PATH/TO/webapps/APPNAME/-", "read";
        // grails 1.1 + jdk 1.6.0_13 needs this for each webapp, sigh
    permission java.io.FilePermission "${catalina.base}/work/Catalina/HOSTNAME/APPNAME/-", "read";
};

Logging

For any version of Grails, logging needs additional permissions. Some are so common I add them separately:

// log4j
grant codeBase "file:${catalina.home}/lib/log4j-1.2.15.jar" {
    permission java.io.FilePermission "${catalina.base}${file.separator}logs", "read, write";
    permission java.io.FilePermission "${catalina.base}${file.separator}logs${file.separator}-", "read,write,delete";
};

// logging extra
grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {
        // for date-based filenames
    permission java.util.PropertyPermission "user.timezone", "read,write";
};

Each per-webapp section needs logging permissions which will vary based on your logging setup:

    // logs
    permission java.io.FilePermission "${catalina.base}/logs", "read";
    permission java.io.FilePermission "${catalina.base}/logs/APPNAME/-", "read,write,delete";

Database

The per-webapp grant also generally needs some database permissions. These are for mysql on localhost:

   permission  java.net.SocketPermission "127.0.0.1:3306", "connect,resolve";
   permission  java.net.SocketPermission "localhost", "resolve";




References

Mark Petrovic has written some nice articles and code about security profiling/monitoring, which I originally found via the Grails-user mailing list:

Download

Download the grants/permissions all together in one file:
grails-policy.txt

Tags: , ,

One Response to “Security policy permissions for Grails in Tomcat”

  1. [...] See the original post: Security policy permissions for Grails in Tomcat « haxx qua non [...]

Leave a Reply