river-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Firmstone <j...@zeus.net.au>
Subject Learnings from a RevokeableDynamicPolicy & A Future Roadmap
Date Sun, 01 Aug 2010 03:53:30 GMT
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.


Mime
View raw message