What about the case where a Module depends on another Module?

I'm guessing that was the intent.

Regards,

Peter.

Peter Firmstone wrote:
Edited slightly note: <edit-remove>for the Subject</edit-remove>

Peter Firmstone wrote:
Ok,

The ModuleServiceProvider adds a step:

  1. A ModuleServiceProvider is deserialized (reflective proxy only)
     (consider it a Module Factory, could rename it to that too).
  2. Deserialized ModuleServiceProvider is verified
  3. A Module cache is checked using the ModuleServiceProvider as a key
     (weakly referenced).
  4. If a Module exists in the cache, then that is used instead, goto 6.
5. If a Module doesn't exist in the cache <edit-remove>for the Subject</edit-remove> a new
     Module will be created using the ModuleServiceProvider
        1. CodeSource[] is obtained for the Module using the
           ModuleServiceProvider
        2. DownloadPermission is dynamically granted to all CodeSource
           in the array CodeSource[] only.
        3. DownloadPermission is only required to load the jar files
           for the Module, via overriding
           SecureClassLoader.getPermissions(CodeSource cs) as per
           PreferredClassLoader.
        4. The Module is deserialized, using the CodeSource[] URL's in
           a new ClassLoader instance.
        5. The Module is verified.
        6. The Module is granted GrantPermission(DownloadPermission)
        7. The Module knows which CodeSources require
           DownloadPermission and grant's these dynamically on an as
           needed basis.
        8. The Module needs a guard to check the caller has sufficient
           permission to use it, this would be created during module
           construction, we need to define a standard guard permissions
           for each method.
        9. The Module is stored in the cache associated with the
           ModuleServiceProvider.
  6. The Service Proxy is unmarshalled.
  7. The service is verified (it has to authenticate with the same
     Subject as the ModuleServiceProvider).
  8. The service is used. (Constraints ensure the service authenticates
     every method invocation).

Note: The ModuleServiceProvider has the same Subject as the Service Proxy.

Module needs an additional method:

ClassLoader getClassLoader(Subject s);

The Module needs to have a Subject parameter added to it's other methods too, the Module already know's the Codebase URL's, since this is it's responsibility, however it needs to ensure that different Subject's don't share ClassLoaders, in case multiple Subjects are using one Module with identical CodeSource, in the case where the Module Service provides for a number of Subjects.

The Module Service, knows which jar files, module / package versions are in use for the requested classes.

If Service Proxy's had OSGi embedded, they could be shutdown and reloaded with new Module versions, this would be synchronous with the Module Service.

Ordinary services might simply be stopped and re looked up with updated jar files and annotated with a new ModuleServiceProvider instance.

We can choose to limit other permission's also like SocketPermission's to particular domains.

Can we cache jar files somehow based on their URL?

I'm not certain if this is right, what do you think?

Cheers,

Peter.


Michal Kleczek wrote:
Thanks for the tips on using Guard and subclassing Permission - I will update the code.

But I am not completely sure I follow your idea of ModuleServiceProvider.

I'll try to explain why I think two permissions are needed.
Let's imagine a simple scenario:

1. A client gets a service proxy.
2. Before actually downloading any code and deserializing the proxy the client wants to verify a Module that it received as annotation. 3. After the proxy is deserialized the client wants to grant the proxy a permission to deserialize other objects that possibly will require other Modules to be downloaded.

So the following steps are performed:
1. A Module is deserialized
2. Deserialized Module is verified
3. A service proxy is deserialized
4. The service proxy is verified
5. DownloadPermission is granted to the proxy ClassLoader (note that it is a different ClassLoader than Module's ClassLoader)

But how can we implement conditional Module verification?
We can have a locally installed verifier that just checks if currently executing code has DownloadPermission and if that's the case consider any Module trusted. But - of course - the client itself has DownloadPermission, so this verifier would cause suppressing of Module verification alltogether. The idea is to have another permission that only the client has - the verifier would check that permission and if the calling code has it - consider Modules untrusted.
So now the sequence is as follows:
1. A Module is deserialized
2. DelegatedModuleTrustVerifier checks for SuppressModuleInstallPermission.
3. The client has it so DelegatedModuleTrustVerifier returns false
4. The Module is verified using standard ProxyTrustVerifier
5. A proxy is deserialized
6. The proxy is verified
7. The proxy is granted DownloadPermission
8. The proxy tries to deserialize a subsequent object (annotated with another Module)
9. A Module is desecialized
10. DelegatedModuleTrustVerifier checks for SuppressModuleInstallPermission. Calling code does not have it so DelegatedModuleTrustVerifier checks for DownloadPermission. Calling code does have DownloadPermission (see p. 7) so we consider this Module trusted
11. We're done :)

Michal


On Monday 11 of October 2010 13:06:18 Peter Firmstone wrote:
I don't completely follow, why do you need the additional permission?

Perhaps we could have ModuleServiceProvider that only allows a
reflective proxy?  We can authenticate a reflective proxy because
there's no downloaded code.

interface ModuleServiceProvider {
    CodeSource[] getModuleCodeSources();
    Module getModule();
}

Setting up the Module from the ModuleServiceProvider, we can obtain the
CodeSource URL and Certificate's before downloading any jar files for
the module and check if a Module ClassLoader has been registered for the
Subject.

We can then dynamically grant Permissions to that ClassLoader (using the
Module's class) with the Subject's Principals[], so it only has the
necessary Permission's when run as the Subject of the Service.

A marshalled smart proxy could be annotated with the
ModuleServiceProvider, which is authenticated, and has constraints set,
prior to instantiating a ClassLoader with the URL[]'s(if it doesn't
already exist), then deserialize the Module into it (by setting the
context ClassLoader) and use the new Module to provision the smart
proxy's jar archives.

Have a look at Gregg Wonderly's CodebaseAccessClassLoader too.

http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/net/jini/loader
/?pathrev=934258

Some Permission Tips:

   1. For simple Permission classes, extend Permission instead of
      BasicPermission if you can, if you don't need implement your own
      PermissionCollection, the Policy will provide an implementation
      for you (I provide a multi read PermissionCollection with my
      Policy Provider for better concurrency).
   2. Try using Guard installModule = new InstallModulePermission();
      Then instead of calling the AccessController or SecurityManager,
      call installModule.checkGuard() instead, it gets the security
      manager for you and checks the Permission, when I've got the
      InternetSecurityManager finished, this will speed up your
      permission check for repeated checks.

try {
    installModule.checkGuard(this);
    return true;
} catch (SecurityException ex) {
    return false;
}


Cheers,

Peter.

Michal Kleczek wrote:
Of course we need something more since the client has
InstallModulePermission it would suppress trust verification
alltogether. The simple fix is to have two permissions and suppress
trust verification only when we only have one of them. The client has
both, so we are going to verify trust.

class InstallModulePermission extends BasicPermission {
}

class SuppressInstallModulePermission extends BasicPermission {
}

public class DelegatedModuleTrustVerifier implements TrustVerifier {

    private static final InstallModulePermission
    INSTALL_MODULE_PERMISSION =
                new InstallModulePermission();
        private static final SuppressModuleTrustDelegationPermission
          SUPPRESS_MODULE_TRUST_DELEGATION_PERMISSION =
                  new SuppressModuleTrustDelegationPermission();
        @Override
    public boolean isTrustedObject(Object o, Context cntxt) {
            if (o instanceof Module) {
                    try {
AccessController.checkPermission(SUPPRESS_MODULE_TRUST_DE
                LEGATION_PERMISSION); return false;
                        }
            catch (SecurityException suppressEx) {
                            try {
AccessController.checkPermission(INSTALL_MODULE_PERMI
                    SSION); return true;
                                }
                catch (SecurityException installEx) {
                                    return false;
                                }
                        }
                }
                return false;
        }

}


Michal

On Monday 11 of October 2010 08:24:19 Michal Kleczek wrote:
On Monday 11 of October 2010 05:27:31 Peter Firmstone wrote:
Michal Kleczek wrote:
Some more thoughts.

There is one scenario that is not covered here:

I get an service, verify the module that loads its class using a
ModuleAuthority that I trust. This service in turn downloads some
other objects that it verified. There is no way I can delegate trust
verification to the service - I must trust Modules (actually
ModuleAuthorities) of those subsequent objects.

1. I have to have a way to allow or disallow module trust delegation
(looks like a case for dynamic permission grants)
Currently PreferredClassLoader uses DownloadPermission to prevent or
allow a CodeSource class loading, because the CodeSource hasn't yet
been loaded, we cannot dynamically grant DownloadPermission to a
CodeSource, using DynamicPolicy.
Thanks for the hint.
I think Module trust delegation can be achieved in a really simple way:

class InstallModulePermission extends Permission {
}

//this TrustVerifier is installed locally on the client
//so that delegation of Module trust verification can be done
//by granting a service InstallModulePermission

public class InstallModulePermissionVerifier implements TrustVerifier {

  private static final InstallModulePermission PERM =
      new InstallModulePermission()
    public boolean isTrustedObject(Object o, Context ctx) {
      try {
          if (o instanceof Module) {
              AccessController.checkPermission(PERM);
        return true;
            }
            return false;
        }
    catch (SecurityException e) {
          return false;
        }
    }

}

What do you think?

Michal






Reply via email to