title: How to sanely configure security policy in Tomcat 6
body: <p>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 <code>/var/lib/tomcat6/conf/policy.d</code>, there are a variety of files that establish default policy.</p>
  
  <p>Worth noting at the start:</p>
  
  <ul>
  <li>I've not changed the stock tomcat install at all -- no new jars into its common lib directory(ies), no <code>server.xml</code> changes, etc.  Putting the .war file in the <code>webapps</code> directory is the only deployment action.</li>
  <li>the web application I'm deploying fails with thousands of access denials under this default policy (as reported to the log thanks to the <code>-Djava.security.debug="access,stack,failure"</code> system property).</li>
  <li>turning off the security manager entirely results in no errors whatsoever, and proper app functionality</li>
  </ul>
  
  <p>What I'd like to do is add an application-specific security policy file to the <code>policy.d</code> directory, which seems to be the recommended practice.  I added this to <code>policy.d/100myapp.policy</code> (as a starting point -- I would like to eventually trim back the granted permissions to only what the app actually needs):</p>
  
  <pre><code>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;
  };
  </code></pre>
  
  <p>Note the thrashing around attempting to find the right <code>codeBase</code> declaration.  I think that's likely my fundamental problem.</p>
  
  <p>Anyway, the above (really only the first two grants appear to have any effect) <em>almost</em> works: the thousands of access denials are gone, and I'm left with just one.  Relevant stack trace:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>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:</p>
  
  <ol>
  <li>it doesn't exist in this context</li>
  <li>the fact that the file doesn't exist ends up throwing a security exception, rather than <code>java.io.File.exists()</code> simply returning false (although I suppose that's just a matter of the semantics of the read permission).</li>
  </ol>
  
  <p>Another workaround (besides just disabling the security manager in tomcat) is to add an open-ended permission to my policy file:</p>
  
  <pre><code>grant {
    permission java.security.AllPermission;
  };
  </code></pre>
  
  <p>I presume this is functionally equivalent to turning off the security manager.</p>
  
  <p>I suppose I must be getting the <code>codeBase</code> declaration in my grants subtly wrong, but I'm not seeing it at the moment.</p>