I'm using Tomcat 6.0.24, as packaged for Ubuntu Karmic. The default security policy of Ubuntu's Tomcat package is pretty stringent, but appears straightforward. In /var/lib/tomcat6/conf/policy.d, there are a variety of files that establish default policy.
Worth noting at the start:
I've not changed the stock tomcat install at all -- no new jars into its common lib directory(ies), no server.xml changes, etc. Putting the .war file in the webapps directory is the only deployment action.
the web application I'm deploying fails with thousands of access denials under this default policy (as reported to the log thanks to the -Djava.security.debug="access,stack,failure" system property).
turning off the security manager entirely results in no errors whatsoever, and proper app functionality
What I'd like to do is add an application-specific security policy file to the policy.d directory, which seems to be the recommended practice. I added this to policy.d/100myapp.policy (as a starting point -- I would like to eventually trim back the granted permissions to only what the app actually needs):
grant codeBase "file:${catalina.base}/webapps/ROOT.war" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/lib/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${catalina.base}/webapps/ROOT/WEB-INF/classes/-" {
permission java.security.AllPermission;
};
Note the thrashing around attempting to find the right codeBase declaration. I think that's likely my fundamental problem.
Anyway, the above (really only the first two grants appear to have any effect) almost works: the thousands of access denials are gone, and I'm left with just one. Relevant stack trace:
java.security.AccessControlException: access denied (java.io.FilePermission /var/lib/tomcat6/webapps/ROOT/WEB-INF/classes/com/foo/some-file-here.txt read)
java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
java.security.AccessController.checkPermission(AccessController.java:546)
java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
java.lang.SecurityManager.checkRead(SecurityManager.java:871)
java.io.File.exists(File.java:731)
org.apache.naming.resources.FileDirContext.file(FileDirContext.java:785)
org.apache.naming.resources.FileDirContext.lookup(FileDirContext.java:206)
org.apache.naming.resources.ProxyDirContext.lookup(ProxyDirContext.java:299)
org.apache.catalina.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:1937)
org.apache.catalina.loader.WebappClassLoader.findResource(WebappClassLoader.java:973)
org.apache.catalina.loader.WebappClassLoader.getResource(WebappClassLoader.java:1108)
java.lang.ClassLoader.getResource(ClassLoader.java:973)
I'm pretty convinced that the actual file that's triggering the denial is irrelevant -- it's just some properties file that we check for optional configuration parameters. What's interesting is that:
it doesn't exist in this context
the fact that the file doesn't exist ends up throwing a security exception, rather than java.io.File.exists() simply returning false (although I suppose that's just a matter of the semantics of the read permission).
Another workaround (besides just disabling the security manager in tomcat) is to add an open-ended permission to my policy file:
grant {
permission java.security.AllPermission;
};
I presume this is functionally equivalent to turning off the security manager.
I suppose I must be getting the codeBase declaration in my grants subtly wrong, but I'm not seeing it at the moment.