A Brief evolution of java.security.Policy providers and Jini Security, please correct me where necessary.

Prior to Jini 2.0 security was left up to implementing developers, the standard tools available in Java 1.2 were insufficient. You had to implement your own SecurityManager. Or you could define Security policy's in policy files. The AccessController still consulted the ProtectionDomain, but the ProtectionDomain Permission's were static and unchanging. You could implement your own policy provider for java.security.Policy, by there was no way you could guarantee updates to the ProtectionDomain with any changes, the ProtectionDomain used the Policy.getPermissions(ProtectionDomain) call to obtain the PermissionCollection from the Policy.

To enable the Jini 2.0 Security infrastructure, Sun made changes to Java itself, in Java 1.4 ProtectionDomain's were given a new constructor that enabled the ProtectionDomain to consult an external Policy Provider, and the java.security.Policy gained the implies(ProtectionDomain, Permission) method, allowing the ProtectionDomain to consult the Policy, Jini 2.0 took advantage of this with the DynamicPolicyProvider. This Policy system is a permissive system, that is security was only ever relaxed, it cannot be tightened without restarting the JVM.

Now we have taken a new evolutionary step, inspired by Sun's Neuromancer Research Project's additional security needs, for a distributed object registry, we now have a RevokeableDynamicPolicy interface.

RevokeableDynamicPolicy wouldn't be possible to implement without the changes to Java 1.4 Security that were prompted by Jini 2.0.

A RevokeableDynamicPolicy relies on the following features inherent in Java:

   * ProtectionDomain's new dynamic 4 parameter constructor support for
     dynamic Policy's, supplied with a null PermissionCollection. Added
     in Java 1.4
   * Not returning any PermissionCollection's belonging to dynamic
     grants via either of Policy.getPermissions(*) methods. Only those
     belonging to underlying static Policy providers will be returned.
   * Total reliance on Policy.implies(ProtectionDomain, Permission)
     added in Java 1.4

A RevokeableDynamicPolicy supports the addition or removal of PermissionGrant's

   * PermissionGrant.implies(ProtectionDomain), is the main feature of
     the RevokeableDynamicPolicy.
   * PermissionGrant is an interface.
   * A PermissionGrant can be implemented by anyone, but the
     implementing codebase must have a RuntimePermission for
     "getProtectionDomain" and GrantPermission for the Permission's it
     will grant.
   * A PermissionGrant can use any means it can to determine if it
     implies a ProtectionDomain, if it does the RevokeableDynamicPolicy
     will add Permission's to the PermissionCollection cached for that
     ProtectionDomain by calling PermissionGrant.getPermissions();
   * To remove a PermissionGrant, you must have RevokePermission.

What I discovered when implementing a Concurrent version of RevokeableDynamicPolicy:

   * PermissionCollection.elements() returned an
     Enumeration<Permission> that would throw a
     ConcurrentModificationException, when Permission's were added to
     the backing PermissionCollection.
   * java.security.Permissions is a heterogeneous PermissionCollection
     implementation, it's a point of contention for threads.  It needed
     a concurrent replacement.
   * The replacement,
     org.apache.river.imp.security.policy.ConcurrentPermissions
     implements a threadsafe alternative for Permissions that prevents
     Enumeration<Permission> from throwing
     ConcurrentModificationException by caching.
   * Now it is possible for Policy.implies(ProtectionDomain,
     Permission) calls to occur concurrently during adding or removal
     of PermissionGrant's.  Policy.elements() Enumeration<Permission>
     can also be enumerated during adding or removal of
     PermissionGrant's or implies() calls.
   * UmbrellaGrantPermission's have been added to
     org.apache.river.imp.security.policy.DynamicConcurrentPolicyProvider,
     so you can minimise the size of Policy files for GrantPermission's.
   * This implementation passes all the existing qa harness and jtreg
     tests for DynamicPolicy.
   * Please feel free to assist by creating new tests for Concurrency
     (many threads, hammer all methods).

What's next:

   * Adding new methods to net.jini.security.Security to provide
     support for PermissionGrant's and RevokeableDynamicPolicy.
   * Creating an Entry that provides PermissionGrantBuilder's to assist
     the client to restrict the Permission's to those that are
     acceptable to the client and only those needed by the Service.
   * Utilising the new org.apache.river.imp.util.PolicyParser interface
     (this may be added to the api at a later date), standard java
     policy file syntax can be parsed by the provided
     DefaultPolicyParser (courtesy Apache Harmony) and will return
     PermissionGrant's, the PermissionGrant's can return
     PermissionGrantBuilder's that can be used in Entry's
   * We can add standard java policy files to our downloadable jar
     archives, we just need a utility class that generates the
     PermissionGrantBuilder Entry's for us.
   * The new PolicyParser allows parsing of URL based policy files.
   * A Distributed Object Registry, inspired by Project Neuromancer,
     utilising distributed hash tables to track the location of objects.

The bigger picture, A Future Roadmap:

   * Standardise the use of a Parent ClassLoader in the ClassLoader
     hierarchy (tree) above all client and service implementation and
     proxy ClassLoader's so that the implementations can all
     communicate using COMMON SERVICE INTERFACES.
   * Standardise jar file naming to assist ClassLoader layout, see
     https://issues.apache.org/jira/browse/RIVER-341
   * Create a new ServiceStarter / ClientStarter to setup the
     ClassLoader tree based on the new naming scheme.
   * Codebase Entry's and Client Codebase Provisioning.
   * jeri Endpoint implementations to traverse firewalls.
   * DNS-SD for Internet Unicast Discovery.
   * StreamServiceRegistrar - for the Internet with delayed
     Unmarshalling of Service Proxy's
   * A new URL Handler for CodeBase's with Version information for
     Provisioning.

RevokeableDynamicPolicy and StreamServiceRegistrar lookup filter chaining makes it possible to:

   * Lookup Services by common Codebase Entry's
   * Process ResultStream using chained and nested ServiceItemFilters:

        1. ServiceItemFilter at the client by comparison of Entry
           contents < > =.
        2. ServiceItemFilter to Unmarshall Proxy, Provision CodeSource
        3. ServiceItemFilter to check Method Constraints
        4. ServiceItemFilter to Dynamically Grant Permission's based on
           Entry as deemed acceptable.
        5. ServiceItemFilter to Perform operation on Proxy
        6. ServiceItemFilter to Dynamically Revoke Permission's based.
        7. ServiceItemFilter to Throw away Proxy reference
        8. While next, Goto 2 repeat process, can utilise same
           ClassLoader as previous Service Proxy for speed, no need to
           downlaod, reload and re verify bytecodes for CodeSource.

   * ResultStream's are like an Enumeration, but are concurrent, used
     like a stream, a null result indicates end of ResultStream.

Best Regards,

Peter Firmstone.

Reply via email to