Skip to main content

Enabling Java Security Manager for WSO2 products

Why Java Security Manager is needed?


In Java, the Security Manager is available for applications to have various security policies. The Security Manager helps to prevent untrusted code from doing malicious actions on the system. 

You need to enable Security Manager, if you plan to host any untrusted user applications in WSO2 products, especially in products like WSO2 Application Server.

The security policies should explicitly allow actions performed by the code base. If any of the actions are not allowed by the security policy, there will be a SecurityException

For more information on this, you can refer Java SE 7 Security Documentation.

Security Policy Guidelines for WSO2 Products


When enabling Security Manager for WSO2 products, it is recommended to give all permissions to all jars inside WSO2 product. For that, we plan to sign all jars using a common key and grant all permissions to the signed code by using "signedBy" grant as follows.

grant signedBy "<signer>" {
permission java.security.AllPermission;
};

We also recommend to allow all property reads and WSO2 has a customized Carbon Security Manager to deny certain system properties.

One of the main reasons is that in Java Security Policy, we need to explicitly mention which properties are allowed and if there are various user applications, we cannot have a pre-defined list of System Properties. Therefore Carbon Security Manager's approach is to define a list of denied properties using the System Property "denied.system.properties". This approach basically changes Java Security Manager's rule of "Deny all, allow specified" to "Allow all, deny specified".

There is another system property named "restricted.packages" to control the package access. However this "restricted.packages" system property is not working in latest Carbon and I have created CARBON-14967 JIRA to fix that properly in a future Carbon release.

Signing all JARs inside WSO2 product.


To sign the jars, we need a key. We can use the keytool command to generate a key.

$ keytool -genkey -alias signFiles -keyalg RSA -keystore signkeystore.jks -validity 3650 -dname "CN=Isuru,OU=Engineering, O=WSO2, L=Colombo, ST=Western, C=LK"
Enter keystore password:
Re-enter new password:
Enter key password for
(RETURN if same as keystore password):

Above keytool command creates a new keystore file. If you omit -dname argument, all key details will be prompted.

Now extract the WSO2 product. I will be taking WSO2 Application Server as an example.

$ unzip -q  ~/wso2-packs/wso2as-5.2.1.zip


Let's create two scripts to sign the jars. First script will find all jars and the second script will be used to sign a jar using the keystore we created earlier.

signJars.sh script:

#!/bin/bash
if [[ ! -d $1 ]]; then
echo "Please specify a target directory"
exit 1
fi
for jarfile in `find . -type f -iname \*.jar`
do
./signJar.sh $jarfile
done


signJar.sh script:

#!/bin/bash

set -e

jarfile=$1

keystore_file="signkeystore.jks"
keystore_keyalias='signFiles'
keystore_storepass='wso2123'
keystore_keypass='wso2123'

signjar="$JAVA_HOME/bin/jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore $keystore_file -storepass $keystore_storepass -keypass $keystore_keypass"
verifyjar="$JAVA_HOME/bin/jarsigner -keystore $keystore_file -verify"

echo "Signing $jarfile"
$signjar $jarfile $keystore_keyalias

echo "Verifying $jarfile"
$verifyjar $jarfile

# Check whether the verification is successful.
if [ $? -eq 1 ]
then
echo "Verification failed for $jarfile"
fi


Now we can see following files.

$ ls -l
-rwxrwxr-x 1 isuru isuru 602 Dec 9 13:05 signJar.sh
-rwxrwxr-x 1 isuru isuru 174 Dec 9 12:56 signJars.sh
-rw-rw-r-- 1 isuru isuru 2235 Dec 9 12:58 signkeystore.jks
drwxr-xr-x 11 isuru isuru 4096 Dec 6 2013 wso2as-5.2.1

When we run signJars.sh, all JARs found inside WSO2 Application Server will be signed using the "signFiles" key.

$ ./signJars.sh wso2as-5.2.1/ > log

Configuring WSO2 Product to use Java Security Manager


To configure Java Security Manager, we need to pass few arguments to the main Java process. 

Java Security Manager can be enabled by using "java.security.manager" system property. We will specify the WSO2 Carbon Security Manager using this argument.

We also need to specify the security policy file using "java.security.policy" system property.

As I mentioned earlier, we will also set "restricted.packages" & "denied.system.properties" system properties.

Following is the recommended set of values to be used in wso2server.sh (Edit the startup script and add following lines just before the line " org.wso2.carbon.bootstrap.Bootstrap $*"


    -Djava.security.manager=org.wso2.carbon.bootstrap.CarbonSecurityManager \
-Djava.security.policy=$CARBON_HOME/repository/conf/sec.policy \
-Drestricted.packages=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,org.wso2.carbon. \
-Ddenied.system.properties=javax.net.ssl.trustStore,javax.net.ssl.trustStorePassword,denied.system.properties \


Exporting signFiles public key certificate and importing it to wso2carbon.jks


We need to import the signFiles public key certificate to the wso2carbon.jks as the security policy file will be referring the signFiles signer certificate from the wso2carbon.jks (as specified by the first line).

$ keytool -export -keystore signkeystore.jks -alias signFiles -file sign-cert.cer
$ keytool -import -alias signFiles -file sign-cert.cer -keystore wso2as-5.2.1/repository/resources/security/wso2carbon.jks

Note: wso2carbon.jks' keystore password is "wso2carbon".

The Security Policy File


As specified in the system property "java.security.policy", we will keep the security policy file at $CARBON_HOME/repository/conf/sec.policy

Following policy file should be enough for starting up WSO2 Application Server and deploying a sample JSF & CXF webapps.


keystore "file:${user.dir}/repository/resources/security/wso2carbon.jks", "JKS";

// ========= Carbon Server Permissions ===================================
grant {
// Allow socket connections for any host
permission java.net.SocketPermission "*:1-65535", "connect,resolve";

// Allow to read all properties. Use -Ddenied.system.properties in wso2server.sh to restrict properties
permission java.util.PropertyPermission "*", "read";

permission java.lang.RuntimePermission "getClassLoader";

// CarbonContext APIs require this permission
permission java.lang.management.ManagementPermission "control";

// Required by any component reading XMLs. For example: org.wso2.carbon.databridge.agent.thrift:4.2.1.
permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.bind.v2.runtime.reflect";

// Required by org.wso2.carbon.ndatasource.core:4.2.0. This is only necessary after adding above permission.
permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.bind";
};

// ========= Platform signed code permissions ===========================
grant signedBy "signFiles" {
permission java.security.AllPermission;
};

// ========= Granting permissions to webapps ============================
grant codeBase "file:${carbon.home}/repository/deployment/server/webapps/-" {

// Required by webapps. For example JSF apps.
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";

// Required by webapps. For example JSF apps require this to initialize com.sun.faces.config.ConfigureListener
permission java.lang.RuntimePermission "setContextClassLoader";

// Required by webapps to make HttpsURLConnection etc.
permission java.lang.RuntimePermission "modifyThreadGroup";

// Required by webapps. For example JSF apps need to invoke annotated methods like @PreDestroy
permission java.lang.RuntimePermission "accessDeclaredMembers";

// Required by webapps. For example JSF apps
permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.compiler";

// Required by webapps. For example JSF EL
permission java.lang.RuntimePermission "getClassLoader";

// Required by CXF app. Needed when invoking services
permission javax.xml.bind.JAXBPermission "setDatatypeConverter";

// File reads required by JSF (Sun Mojarra & MyFaces require these)
// MyFaces has a fix https://issues.apache.org/jira/browse/MYFACES-3590
permission java.io.FilePermission "/META-INF", "read";
permission java.io.FilePermission "/META-INF/-", "read";

// OSGi permissions are requied to resolve bundles. Required by JSF
permission org.osgi.framework.AdminPermission "*", "resolve,resource";
};

The security policies may vary depending on your requirements. I recommend to test your application thoroughly in a development environment.

NOTE: There are risks in allowing some Runtime Permissions. Please look at the java docs for RuntimePermission. See Concerns below.

Troubleshooting Java Security


Java provides the "java.security.debug" system property to set various debugging options and monitor security access.

I recommend to add following line to wso2server.sh whenever you need to troubleshoot some issue with Java Security.

    -Djava.security.debug="access,failure"

After adding that line, all the debug information will be printed to standard output. To check the logs, we can start the server using nohup.

$ nohup ./wso2server.sh &

Then we can grep the nohup.out and look for access denied messages.

$ tailf nohup.out | grep denied

Concerns with Java Security Policy


There are few concerns with current permission model in WSO2 products.

  • Use of ManagementPermission instead of Carbon specific permissions. The real ManagementPermission is used for a different purpose. I created CARBON-14966 jira to fix that.
  • Ideally the permission 'java.lang.management.ManagementPermission "control"' should not be specified in policy file as it is only required for privileged actions in Carbon. However due to indirect usage of such privileged actions within Carbon code, we need to specify that permission. This also needs to be fixed.
  • In above policy file, the JSF webapps etc require some risky runtime permissions. I recommend to use a Custom Runtime Environment (CRE) in WSO2 Application Server for JSF webapps etc and sign the jars inside CRE. You can also grant permissions based on the jar names (Use grant codeBase). However signing jars and using a CRE is a better approach with WSO2 AS.
If you also encounter any issues when using Java Security Manager, please discuss those issues in our developer mailing list.




Comments

Popular posts from this blog

Finding how many processors

I wanted to find out the processor details in my laptop and I found out that there are several ways to check. For example, see The RedHat community discussion on  Figuring out CPUs and Sockets . In this blog post, I'm listing few commands to find out details about CPUs. I'm using Ubuntu in my Lenovo ThinkPad T530 laptop and following commands should be working any Linux system. Display information about CPU architecture $ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 2 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 58 Model name: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz Stepping: 9 CPU MHz: 1199.988 CPU max MHz: 3600.0000 CPU min MHz: 1200.0000 BogoMIPS: 5787.1...

Java Mission Control & Java Flight Recorder

Last year, I got two opportunities to talk about Java Mission Control & Java Flight Recorder. I first talked about " Using Java Mission Control & Java Flight Recorder " as an internal tech talk at WSO2 . I must thank Srinath for giving me that opportunity. After that, Prabath also invited me to do a talk at Java Colombo Meetup . Prabath, Thank you for inviting me and giving me the opportunity to talk at the Java Colombo Meetup! I'm also very excited to see that Marcus Hirt , the Team Lead for Java Mission Control has mentioned about the Java Colombo Meetup in his blog post: " My Favourite JMC Quotes ". It's so nice to see "Sri Lanka" was mentioned in his blog post! :) From Marcus' Blog Here are the slides used at the meetup. Java Colombo Meetup: Java Mission Control & Java Flight Recorder from Isuru Perera Marcus Hirt's blog posts really helped me to understand JMC & JFR concepts and his tutorials were very helpful...

Flame Graphs with Java Flight Recordings

Flame Graphs Brendon D. Gregg , who is a computer performance analyst , has created  Flame Graphs to visualize stack traces in an interactive way. You must watch his talk at USENIX/LISA13 , titled Blazing Performance with Flame Graphs , which explains Flame Graphs in detail. There can be different types of flame graphs and I'm focusing on  CPU Flame Graphs  with Java in this blog post. Please look at the Flame Graphs Description  to understand the Flame Graph visualization. CPU Flame Graphs and Java Stack Traces As  Brendon  mentioned in his talk, understanding why CPUs are busy is very important when analyzing performance.  CPU Flame Graphs  is a good way to identify hot methods from sampled stack traces. In order to generate CPU Flame Graphs for Java Stack Traces , we need a way to get sample stack traces. Brendon has given examples to use jstack  and Google's lightweight-java-profiler . Please refer to his perl program on g...