I have a plain Java app that launches an embedded instance of Jetty which, in turn, launches several instances of the Equinox Servlet Bridge.
I am attempting to restrict the use of reflection in my application. To do this I have implemented a custom SecurityManager and set it via System.setSecurityManager() in my top level java application.
This seems to have the effect of enabling the Security Admin in Equinox which is causing my bundles to not resolve due to missing permissions.
I believe that I can work around this by including a permission file in my OSGI-INF directory of my bundles but this seems to be tedious. Is there any way I can set the default permission set on the top level of the bridge to allow full permissions on all bundles so that I do not have to include the permission file in all of my bundles?
By default the Security Admin in Equinox should be granting AllPermission to the protection domains of the bundles installed in the framework. The idea is you have to lock down the system by adding your own rules using the ConditionalPermissionAdmin service. So it sounds like something strange is going on with your custom security manager that is overriding what is granted by the protection domains the OSGI framework is setting up. Also, the framework implementation will not work properly unless it is granted AllPermission. Not sure if you are doing that in your custom security manager.
The permission.perm files in theOSGI-INF folder are not going to help you here because that file is only used to indicate to the framework a superset of permissions to allow a particular bundle. So adding PackagePermission to your permission.perm files is not going to actually grant the bundles that permission unless your custom security manager is granting the permission also.
The security manager I have implemented only overrides the checkPermission() methods and will only act on Permissions of the type ReflectPermission allowing all other permissions.
I attempted to do some output debugging in my security manager and it seems as if the permission that initially throws the error does not ever hit my security manager. Here is the error I am getting. Probably should have attached this in the first place.
!ENTRY org.eclipse.equinox.common 4 0 2013-03-08 14:36:53.933
!MESSAGE FrameworkEvent ERROR
!STACK 0
org.osgi.framework.BundleException: The bundle "org.eclipse.equinox.common_3.6.0.v20110523 [62013]" could not be resolved. Reason: Missing Permission: ("org.osgi.framework.PackagePermission" "org.eclipse.equinox.log" "exportonly"), Missing Constraint: Import-Package: org.eclipse.equinox.log; version="[1.0.0,2.0.0)"
at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolverError(AbstractBundle.java:1327)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolutionFailureException(AbstractBundle.java:1311)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:323)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:389)
at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1130)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:559)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:544)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:457)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:243)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:438)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:1)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)
I am wondering if this error is not actually due to an actual permission check but some other check. I have tried to locate the piece of the code in org.eclipse.osgi that actually sets the error but this has proved rather difficult as the stack trace is reporting an error that was stored during the bundle resolution phase.
I was able to resolve my issue. The problem seems to be that I was not setting up my policy correctly. I created the following class based on the Permission collection in the servlet bridge FrameworkLauncher class.
public class AllPolicy extends Policy {
/**
* Pulled from the servlet bridge FrameworkLauncher class
*/
static final PermissionCollection allPermissions = new PermissionCollection() {
private static final long serialVersionUID = 482874725021998286L;
// The AllPermission permission
Permission allPermission = new AllPermission();
// A simple PermissionCollection that only has AllPermission
public void add(Permission permission) {
// do nothing
}
public boolean implies(Permission permission) {
return true;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Enumeration elements() {
return new Enumeration() {
int cur = 0;
public boolean hasMoreElements() {
return cur < 1;
}
public Object nextElement() {
if (cur == 0) {
cur = 1;
return allPermission;
}
throw new NoSuchElementException();
}
};
}
};
/* (non-Javadoc)
* @see java.security.Policy#getPermissions(java.security.CodeSource)
*/
@Override
public PermissionCollection getPermissions(CodeSource codesource) {
return allPermissions;
}
}
Then I set this as my policy using
Policy.setPolicy(new AllPolicy());
I am still not entierly sure why this is needed but it seems to have resolve my issues.