How-to configure the Tomcat securitymanager file to allow Spring and Hibernate on your java secure webapp.
License : Copyright Emeric Nasi, some rights reserved
This work is licensed under a Creative Commons Attribution 4.0 International License.
I. Tomcat security manager.
The basis of Java security is to enable the security manager.
The security manager allows you to associate a given code (a webapp, a .class, a jar, etc) to one or more authorizations (ex. write on disk, connect to distant host, read properties, use reflection, etc).
The complete list can be found here
The problem with the Java security manager is that contrary to the C language, the Java language security is not on the front scene. Most Java developers don’t know anything about Java (real) security and it is very difficult to find some information about how to setup a security manager policy file.
On a Tomcat application server, the config file that is used by the security manager can be found at $TOMCAT_HOME/conf/catalina.policy.
I suggest you make a copy of this file before editing it, for example on a GNU Linux system :
cp ${CATALINA_HOME}/conf/catalina.policy ${CATALINA_HOME}/conf/catalina.policy.old
.
You can read more info related to Tomcat security manager here.
II. Permissions for Spring and Hibernate
The Spring and the Hibernate framework are widely used in modern J2SE and JEE applications. However it is very difficult to find some information related to "Wish permissions should be authorized for Spring or Hibernate?".
That is why I will give you the configurations I successfully tried.
To try the next code on Tomcat; you should edit your catalina.policy file and add the following lines at the end of the file (you do not need to modify default permissions).
II.1 System properties access
A particularity in the Hibernate code oblige us to give read and write access permissions to all system properties to the Hibernate and Spring jar.
// ---------------- Enable system properties access to spring and hibernate-------------
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/spring-X.X.X.jar" {
permission java.util.PropertyPermission "*", "read, write";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/hibernate-X.X.X.jar" {
permission java.util.PropertyPermission "*", "read, write";
};
II.2 Allow dependency injection.
Spring as well as Hibernate need access to the highly sensitive permissions that are reflection and runtime access to class members.
// ---------------- Enable reflection for spring and hibernate ------------
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/spring-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/hibernate-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/spring-modules-validation-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/commons-beanutils-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/commons-digester-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/commons-validator-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
// ----------------------- Enable reflection and runtime for implementation packages ---------------------- //
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/commons-lang-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.lang.RuntimePermission "accessDeclaredMembers";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/<my_webapp_hibernate_layer>-X.X.X.jar" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.lang.RuntimePermission "accessDeclaredMembers";
};
II.3 Allow aspect programming.
// ----------------- Grant permission needed for aspectj ---------------------------
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/spring-X.X.X.jar" {
// Access to aspectj properties
permission java.util.PropertyPermission "org.aspectj.tracing.debug", "read";
permission java.util.PropertyPermission "org.aspectj.tracing.factory", "read";
permission java.util.PropertyPermission "org.aspectj.weaver.Dump.exception", "read";
permission java.util.PropertyPermission "org.aspectj.weaver.Dump.condition", "read";
permission java.util.PropertyPermission "org.aspectj.dump.directory", "read";
// Enable some runtime features
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina";
permission java.lang.RuntimePermission "createClassLoader";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/aspectjweaver-X.X.X.jar" {
permission java.util.PropertyPermission "org.aspectj.tracing.debug", "read";
permission java.util.PropertyPermission "org.aspectj.tracing.factory", "read";
permission java.util.PropertyPermission "org.aspectj.weaver.Dump.exception", "read";
permission java.util.PropertyPermission "org.aspectj.weaver.Dump.condition", "read";
permission java.util.PropertyPermission "org.aspectj.dump.directory", "read";
// Enable some runtime features
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina";
permission java.lang.RuntimePermission "createClassLoader";
};
II.4 Enable database connexion.
Hibernate is compatible with most databases. To enable database connexion you need to enable a java.net.SocketPermission on the correct jars for the given host and port.
// ------------- Enable connection to database ----------------------------//
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/<jdatabase_driver>-X.X.X.jar" {
permission java.net.SocketPermission "<database_host>:<database_port>", "connect";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/hibernate-X.X.X.jar" {
permission java.net.SocketPermission"<database_host>:<database_port>", "connect";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/commons-dbcp-X.X.X.jar" {
permission java.net.SocketPermission "<database_host>:<database_port>", "connect";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/spring-X.X.X.jar" {
permission java.net.SocketPermission "<database_host>:<database_port>", "connect";
};
grant codeBase "file:${catalina.home}/webapps/my_webapp/WEB-INF/lib/commons-pool-X.X.X.jar" {
permission java.net.SocketPermission "<database_host>:<database_port>", "connect";
};
III. Finally...
Configuring a securitymanager is a basic important part when you set up security environment for Java. However it is not easy at all. When you try to fulfill this task, your first job is to find the permissions you need (which is quite easy, just look at the security exception log). Next, you need to find which jar needs which permissions and this is the difficult part, it requires you to have a careful look to the security exception stacktrace and to run a lot of tests!.
I hope this article will give you some hints when you will set up your own security manager.