Permissions in OSGi
In a previous post, we looked at implementing a sandbox for Java applications in which we can securely run mobile code.
This post looks at how to do the same in an OSGi environment.
OSGi
The OSGi specification defines a dynamic module system for Java. As such, it’s a perfect candidate for implementing the kind of plugin system that would enable your application to dynamically add mobile code.
Security in OSGi builds on the Java 2 security architecture that we discussed earlier, so you can re-use your knowledge about code signing, etc.
OSGi goes a couple of steps further, however.
Revoking Permissions
One of the weaknesses in the Java permissions model is that you can only explicitly grant permissions, not revoke them. There are many cases where you want to allow everything except a particular special case.
There is no way to do that with standard Java permissions, but, luckily, OSGi introduces a solution.
The downside is that OSGi introduces its own syntax for specifying policies.
The following example shows how to deny PackagePermission
for subpackages of com.acme.secret
:
DENY { ( ..PackagePermission "com.acme.secret.*" "import,exportonly" ) } "denyExample"
(In this and following examples, I give the simple name of permission classes instead of the fully qualified name. I hint at that by prefixing the simple name with ..
)
PackagePermission
is a permission defined by OSGi for authorization of package imports and exports. Your application could use a policy like this to make sure that mobile code can’t call the classes in a given package, for instance to limit direct access to the database.
Extensible Conditions on Permissions
The second improvement that OSGi brings is that the conditions under which a permission are granted can be dynamically evaluated at runtime.
The following example shows how to conditionally grant ServicePermission
:
ALLOW { [ ..BundleSignerCondition "* ; o=ACME" ] ( ..ServicePermission "..ManagedService" "register" ) } "conditionalExample"
ServicePermission
is an OSGi defined permission that restricts access to OSGi services.
The condition is the part between square brackets. OSGi defines two conditions, which correspond to the signedBy
and codeBase
constructs in regular Java policies.
You can also define your own conditions. The specification gives detailed instructions on implementing conditions, especially with regard to performance.
Different Types of Permissions
The final innovation that OSGi brings to the Java permissions model, is that there are different types of permissions.
Bundles can specify their own permissions. This doesn’t mean that bundles can grant themselves permissions, but rather that they can specify the maximum privileges that they need to function. These permissions are called local permissions.
The OSGi framework ensures that the bundle will never have more permissions than the local permissions, thus implementing the principle of least privilege.
Actually, that statement is not entirely accurate. Every bundle will have certain permissions that they need to function in an OSGi environment, like being able to read the org.osgi.framework.*
system properties.
These permissions are called implicit permissions, since every bundle will have them, whether the permissions are explicitly granted to the bundle or not.
The final type of permissions are the system permissions. These are the permissions that are granted to the bundle.
The effective permissions are the set of permissions that are checked at runtime:
effective = (local ∩ system) ∪ implicit
Local permissions enable auditing. Before installing a bundle into your OSGi environment, you can inspect the Bundle Permission Resource in OSGI-INF/permissions.perm
to see what permissions the bundle requires.
If you are not comfortable with granting the bundle these permissions, you can decide to not install the bundle. The point is that you can know all of this without running the bundle and without having access to its source code.
Integration into the Java Permissions Model
The OSGi framework integrates their extended permissions model into the standard Java permissions model by subclassing ProtectionDomain
.
Each bundle gets a BundleProtectionDomainImpl
for this purpose.
This approach allows OSGi to tap into the standard Java permissions model that you have come to know, so you can re-use most of your skills in this area. The only thing you’ll have to re-learn, is how to write policies.
Comparison of Permission Models
To put the OSGi permission model into perspective, consider the following comparison table, which uses terminology from the XACML specification:
Permission Models | Standard Java | OSGi |
---|---|---|
Effects | permit | permit, deny |
Target, Condition | codeBase, signedBy | codeBase, signedBy, custom conditions |
Combining Algorithms | first-applicable | first-applicable, local/system/implicit |
From this table you can see that the OSGi model is quite a bit more expressive than the standard Java permission model, although not as expressive as XACML.
Reference: Permissions in OSGi from our JCG partner Remon Sinnema at the Secure Software Development blog.