Some usecases have a requirement to enable and disable bundles based on a notion of a trusted bundle. One way to establish trust is to sign a bundle with a trusted certificate. Configuring this usecase with the current signed bundle support is awkward and likely unmanageable.
The Equinox Framework (version 3.3) supports signed bundles in the following ways:
- Verification of signer certificates. Does basic parsing of the certificates used to sign a bundle and associates the certificates with an installed bundle.
- Verification of certificate trust. Determines if a certificate should be trusted. Trust authorities can be registered with the Framework to effect the trust policy.
- Verification of content at runtime. Determines if the bundle content has been tampered with at runtime.
- Assign Java 2 permissions based on certificates used to sign a bundle. The ConditionalPermissionAdmin service and the BundleSignerCondition can be used to assign bundles permissions when a security manager is used.
Using the signed bundle support a framework could be configured to enable and disable bundles based on a notion of trusted signer certificates. To do this with the current implementation the Framework needs to be started with a security manager. Then the ConditionalPermissionAdmin and BundleSignerCondition can be used to assign AllPermissions to all bundles which are signed by a trusted certificate. Bundles which are not signed by a trusted certificate would not be granted any permissions. The OSGi specification defines ImportPackagePermission and BundlePermission permissions which must be granted to a bundle before they are allowed to access a package or bundle constraint. Bundles which have constraints (i.e. Import-Package, Require-Bundle, Fragment-Host etc.) would only be allowed to resolve if they have the permissions to access their constraints. If a bundle is not resolved then it cannot run code, export packages, contribute to the service registry or the eclipse extension registry etc.
In this case trusted bundles are granted AllPermissions and therefore would be able to resolve. Note that bundles which define no constraints would still be allowed to resolve even if they had no permissions. Using this approach a management agent can implement a policy to grant AllPermissions to only a trusted set of signers, but this approach has the following disadvantages.
- Requires a security manager.
- All bundles must be security aware. This involves defining the correct permissions and implementing the proper doPriv calls to protect clients from the unnecessary permission checks.
- Running with a security manager impacts performance significantly because of the extra overhead to perform permission checks.
- Bundles with no constraints would still be able to resolve. This may be a very small percentage of bundles but could be used to contribute bad extensions to the eclipse extension registry.
Running Eclipse with a security manager is currently not very attractive. Even if the performance was not an issue there are 10000s lines of code that need to be evaluated to security enable all the code in the Eclipse RCP downloads. This would not be a one time effort either. All of the eclipse committers will need to be educated on the issues of writing secure code and would have to maintain security for all new code contributed to Eclipse. This is a good long-term goal, bug can not be achieved in the short-term. Any short-term or mid-term solution should support not running with a security manager.
Bug 153847 has been opened to track a solution to this requirement.
- Design with below goals in mind
- RCP app can be configured such as untrusted bundles will be prevented from loading/resolving.
- Provide a point where code can plug in custom load time policy handler
- Dynamically allow bundles to be disable/enable at runtime
- Allowing a load time policy to be configured in a way such that alert pop up will come up if signed bundle are not trusted or classes are being tampered at runtime.
- Honors the policy state changes at runtime
- Changeing load time policy is possible through some config UI...
- Comparison of two verification approaches
Installed -> Resolved approach
Prevent the bundle from entering the RESOLVED state if it is not signed by a "good" or "trusted" signer. This way no code could be run or from the non-trusted bundle. One disadvantage with this approach is that ALL the bundles will go through the parsing and checking of certs part that is very expensive. One way to mitigate the problem is by having some caching of certificate parsing, however, it will get tricker when if bundles are signed w/ timestamps.
Resolved -> Active approach
Checking the trust bundles when they go from resolved to active state. This approach does not have parsing ALL bundles part as Installed->Resolved approach. However, this approach has below problems:
- Packages can be exported/imported
- Code can be executed from the bundle (unless the bundle has a lazy activation policy). Remember the BundleActivator is only one entry execution entry point for a bundle. Any package exported from the bundle can provide execution entry points which other bundles can call.
- The bundle can contribute extension points and extensions to the extension registry.
We will take the Installed -> Resolved approach for our prototypes. It will leverage lots of exiting support of signed bundle in Eclipse 3.3. A user will be able to configure the load time security policy though a property file.
- User Experiences
Verifying the bundles that changes the state from Installed to Resolved will not be able to display a warning dialog to the user if the bundles are not trusted according to the load time security policy. Therefore, the bundles that were not resolved due to security reason will be 'held' in memory and displayed to the user when the UI is available.
An alternative is port a trimmed down version of SWT into the load time security bundle or fragment. However, this would require big effort to do so.
- Load time verification
The load time security involves three basic steps
- Parsing the certificate from the bundles
- Validating the certificates
- Making sure resources/bundles are not tampered
In order to mitigate the performance hit of this feature, the above steps will be done at different stage. For example, step 1 and step 2 will be done at the Install Time. Step 3 will execute as resources/classes are loaded from the bundle.
- Install bundles
When bundles are installed, the certificates that are used to signed bundles are parsed at installed time and cached for later use. Additionally, the result of validating certificates and whether the certificates are valid w/ timestamps, valid w/o timestamps, or invalid.
- Load time security policy
The load time security policy is configurable through some properties. The policy will be something like this
- Unsigned (Allow, deny, prompt)
- Expired Certs (Allow, deny, prompt)
- Signed w/ trusted signers ( passes by default)
- Signed w/ untrusted signers (Allow, deny, prompt)
- Tampered contents (Fail by default)