Enable Java Security Manager in API Manager 2.5.0

Image for post
Image for post

Why Java Security Manager

Every time this API is invoked, the API Manager will shut down. It can be prevented by using the Java Security Manager.

Here is to provide the mechanism on enabling Java Security Manager in any WSO2 Product, and I hereby take the example of WSO2 API Manager 2.5.0.

Product: WSO2 API Manager 2.5.0

JDK: jdk1.8.0_144.jdk

  1. Download WSO2 API Manager 2.5.0 from https://wso2.com/api-management/. It’s <product-pack>
  2. A key is needed to sign the jars in the product. Generate it using the keytool command as follows:
keytool -genkey -alias signFiles -keyalg RSA -keystore signkeystore.jks -validity 3650 -dname "CN=Isuru,OU=Engineering, O=WSO2, L=Colombo, ST=Western, C=LK"

3. Import the signFiles public key certificate which was created in step2 to wso2carbon.jks.

keytool -export -keystore signkeystore.jks -alias signFiles -file sign-cert.cerkeytool -import -alias signFiles -file sign-cert.cer -keystore <product_pack>/repository/resources/security/wso2carbon.jks

4. Prepare the script(signallJars.sh) to sign the JARs and grant them the required permission. Please provide your key store password to ‘keypass’ you provided in step 2–3. Please note that here we are using the signing algorithm as SHA256withRSA. Since JDK 1.8 does not accept weak algorithms we need to use this. Products which are compatible with jdk1.7 may use MD5withRSA as the signing algorithm. But JDK 1.8 does not accept that and you get errors in the step of signing the jars.

signallJars.sh

#!/bin/bash
set -e
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH

root=$1
keyname="signkeystore.jks"
keyalias="signFiles"
keypass=""
#keystore=$1/repository/resources/security/$keyname
keystore=$keyname

echo "JAVA HOME Set to : $JAVA_HOME"

for i in `find $1 -iname "*.jar"`
do
echo $i
echo $(jarsigner -sigalg SHA256withRSA -digestalg SHA1 -keystore $keystore -storepass $keypass $i $keyalias) | awk '{print $1 " " $2}'
echo $(jarsigner -verify -keystore $keystore -storepass $keypass $i $keyalias) | awk '{print $1 " " $2}'
done

5. Execute the following commands to sign the JARs in your product.

/signallJars.sh <product_pack>

You will be getting a sample output as below.

JAVA HOME Set to : /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
wso2am-2.5.0/repository/components/dropins/org.wso2.securevault_1.0.0_wso2v2_1.0.0.jar
jar signed.
jar verified.
wso2am-2.5.0/repository/components/dropins/encoder_1.1_1.0.0.jar
jar signed.
jar verified.
wso2am-2.5.0/repository/components/dropins/httpmime_4.3.6_1.0.0.jar
jar signed.

6. Add the following to the startup script of the product pack. (product_pack/bin/wso2server.sh) Add them before the org.wso2.carbon.bootstrap.Bootstrap $* line.

-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 \

7. Create a sec.policy file and add it to product_pack/repository/conf folder. Make sure you provide following permission to sec.policy file.

chmod +x sec.policy

sec.policy

keystore "file:${user.dir}/repository/resources/security/wso2carbon.jks", "JKS";
// ========== SYSTEM CODE PERMISSIONS =========================================
// These permissions apply to javac
grant codeBase "file:${java.home}/lib/-" {
permission java.security.AllPermission;
};
// These permissions apply to all shared system extensions
grant codeBase "file:${java.home}/jre/lib/ext/-" {
permission java.security.AllPermission;
};
// These permissions apply to javac when ${java.home] points at $JAVA_HOME/jre
grant codeBase "file:${java.home}/../lib/-" {
permission java.security.AllPermission;
};
// These permissions apply to all shared system extensions when
// ${java.home} points at $JAVA_HOME/jre
grant codeBase "file:${java.home}/lib/ext/-" {
permission java.security.AllPermission;
};
// ========= Carbon Cloud Server Permissions ===================================
grant {
permission java.net.SocketPermission "*:1-65535", "connect,resolve";
permission java.util.PropertyPermission "http.proxyHost", "read";
permission java.util.PropertyPermission "http.nonProxyHosts", "read";
permission java.util.PropertyPermission "adb.converterutil", "read";
// permission java.io.FilePermission "${carbon.home}/repository/deployment/server/jaggeryapps/publisher/-", "read,write";
// permission java.io.FilePermission "${carbon.home}/repository/deployment/server/jaggeryapps/store/-", "read,write";
permission java.lang.RuntimePermission "accessClassInPackage.org.wso2.carbon.context";
permission java.lang.RuntimePermission "accessClassInPackage.org.wso2.carbon.registry.api";
permission java.lang.RuntimePermission "accessClassInPackage.org.wso2.carbon.registry.core";
permission java.lang.RuntimePermission "accessClassInPackage.org.wso2.carbon.user.api";
permission java.lang.RuntimePermission "accessClassInPackage.org.wso2.carbon.user.core";
permission java.lang.RuntimePermission "accessClassInPackage.org.wso2.carbon.authenticator.stub";
permission java.lang.RuntimePermission "accessClassInPackage.org.wso2.carbon.core.common";
permission java.lang.management.ManagementPermission "control";
permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "setContextClassLoader";
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.util.PropertyPermission "*", "read";
permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
};
grant signedBy "signFiles" {
permission java.security.AllPermission;
};
// Trust all super tenant deployed artifacts
grant codeBase "file:${carbon.home}/modules/-" {
permission java.security.AllPermission;
};

grant CodeBase "file:${user.dir}/repository/deployment/server/-" {
permission java.security.AllPermission;
};
grant CodeBase "file:${user.dir}/lib/core/-" {
permission java.security.AllPermission;
};

8. Start the server and it should be started successfully.

./wso2server.sh

Test if Java Security Manager is successfully enabled over API Manager.

  1. Login to API Publisher and create an API with following details.

https://localhost:9443/publisher

Name: APItest
Context: /apitest
version: 1.0.0
API Definition: GET /*

2. In the Implement tab, select ‘Prototyped API’ and select Implementation method as ‘Inline”.

3. Expand the ‘GET’ resource and use the following script as in the screenshot.

java.lang.System.exit(0);
Image for post
Image for post

4. Publish the API and go to API Store.

5. Invoke the API as below.

Image for post
Image for post

Expected: You should get the following exception. And the server should not shut down.

Caused by: org.mozilla.javascript.WrappedException: Wrapped java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "exitVM.0") (<Unknown Source>#3)
at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1754)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:148)
at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:225)
at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)
at org.mozilla.javascript.gen._Unknown_Source__133._c_script_0(<Unknown Source>:3)
at org.mozilla.javascript.gen._Unknown_Source__133.call(<Unknown Source>)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:394)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3091)
at org.mozilla.javascript.gen._Unknown_Source__133.call(<Unknown Source>)
at org.mozilla.javascript.gen._Unknown_Source__133.exec(<Unknown Source>)
at com.sun.phobos.script.javascript.RhinoCompiledScript.eval(RhinoCompiledScript.java:55)

Troubleshooting

A fatal error has been detected by the Java Runtime Environment:

#

# Internal Error (exceptions.cpp:427), pid=27389, tid=0x0000000000002303

# fatal error: ExceptionMark destructor expects no pending exceptions

#

# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)

# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode bsd-amd64 compressed oops)

# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try “ulimit -c unlimited” before starting Java again

#

# An error report file with more information is saved as:

# /Users/IsuruUyanage/Desktop/Support/Rotation2/CGRSUB-3/new3/wso2am-2.5.0/hs_err_pid27389.log

#

# If you would like to submit a bug report, please visit:

# http://bugreport.java.com/bugreport/crash.jsp

#

./wso2server.sh: line 323: 27389 Abort trap: 6 $JAVACMD -Xbootclasspath/a:”$CARBON_XBOOTCLASSPATH” $JVM_MEM_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=”$CARBON_HOME/repository/logs/heap-dump.hprof” $JAVA_OPTS -Dcom.sun.management.jmxremote -classpath “$CARBON_CLASSPATH” -Djava.endorsed.dirs=”$JAVA_ENDORSED_DIRS” -Djava.io.tmpdir=”$CARBON_HOME/tmp” -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 -Dcatalina.base=”$CARBON_HOME/lib/tomcat” -Dwso2.server.standalone=true -Dcarbon.registry.root=/ -Djava.command=”$JAVACMD” -Dcarbon.home=”$CARBON_HOME” -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dcarbon.config.dir.path=”$CARBON_HOME/repository/conf” -Djava.util.logging.config.file=”$CARBON_HOME/repository/conf/etc/logging-bridge.properties” -Dcomponents.repo=”$CARBON_HOME/repository/components/plugins” -Dconf.location=”$CARBON_HOME/repository/conf” -Dcom.atomikos.icatch.file=”$CARBON_HOME/lib/transactions.properties” -Dcom.atomikos.icatch.hide_init_file_path=true -Dorg.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING=false -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true -Dcom.sun.jndi.ldap.connect.pool.authentication=simple -Dcom.sun.jndi.ldap.connect.pool.timeout=3000 -Dorg.terracotta.quartz.skipUpdateCheck=true -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 -Djava.net.preferIPv4Stack=true -Dcom.ibm.cacheLocalHost=true -DworkerNode=false -Dhttpclient.hostnameVerifier=”DefaultAndLocalhost” org.wso2.carbon.bootstrap.Bootstrap $*

2. Once you login to the Publisher, you will get the following exception. It is because some permission is missing in the sec.policy file.

caused by: org.mozilla.javascript.WrappedException: Wrapped java.lang.NullPointerException (<carbon>/scripts/server/osgi.js#8)

at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1754)

at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:148)

at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:225)

at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)

at org.jaggeryjs.rhino.<carbon>.scripts.server.c0._c_anonymous_2(<carbon>/scripts/server/osgi.js:8)

at org.jaggeryjs.rhino.<carbon>.scripts.server.c0.call(<carbon>/scripts/server/osgi.js)

at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)

at org.jaggeryjs.rhino.<carbon>.scripts.server.c0._c_anonymous_1(<carbon>/scripts/server/tenant.js:2)

at org.jaggeryjs.rhino.<carbon>.scripts.server.c0.call(<carbon>/scripts/server/tenant.js)

at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)

at org.jaggeryjs.rhino.<carbon>.scripts.server.c0._c_script_0(<carbon>/scripts/server/tenant.js:1)

at org.jaggeryjs.rhino.<carbon>.scripts.server.c0.call(<carbon>/scripts/server/tenant.js)

at org.jaggeryjs.rhino.<carbon>.scripts.server.c0.exec(<carbon>/scripts/server/tenant.js)

at org.jaggeryjs.jaggery.core.manager.CommonManager.exposeModule(CommonManager.java:274)

at org.jaggeryjs.jaggery.core.manager.CommonManager.require(CommonManager.java:259)

at org.jaggeryjs.jaggery.core.manager.WebAppManager.require(WebAppManager.java:347)

at sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:126)

at org.mozilla.javascript.FunctionObject.call(FunctionObject.java:386)

at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:63)

at org.jaggeryjs.rhino.publisher.modules.api.c3._c_anonymous_34(/publisher/modules/api/add.jag:800)

Written by

Senior Software Engineer — QA at WSO2

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store