Hi Franky,
First, I want to say...nice job! This will make a very nice addition to ECF remote services.
I should say though that we are approaching ECF 3.4 minor release (hopefully at the end of this month), and it may not be possible to get these API changes (and consequent changes to provider impls) decided upon and incorporated into the ECF 3.4 release. We've got to have an EF review and stuff like that as part of the release...so I just want to make sure you know that if we don't get this work into that release it's simply because of the mechanics of the releng process...and no reflection on the value of this work. I'm sure that we will be able to get it into later releases in some form.
With my comments below, I'm going to focus on the API additions rather than the implementation...i.e. to the org.eclipse.ecf.remoteservice package...rather than the specifics of the implementation. The reason for this is that I think that the API additions/changes are the most important to think carefully about...as API is forever :), while implementation bugs can be relatively easily fixed.
So...see further comments inline.
On 10/5/2010 6:09 AM, Franky Bridelance wrote:
Hi Scott, all,
<stuff deleted>
- Server creates container
- Get ISharedObjectContainerGroupManager interface from the container
- Set an implementation of IConnectHandlerPolicy on ISharedObjectContainerGroupManager that will
+ get the connect data
+ use this connect data to authenticate (via spring security)
+ if authentication fails throw an exception
+ if authentication succeeds: retrieve the authorization roles (via spring security) for the authenticated user and link this to the client container ID (fromID arg in IConnectHandlerPolicy.checkConnect) --> question: is the client container ID unique?
Yes.
For the authorization of remote service call there's as far as I know no API available, so I checked what is needed and came up with a proposal API. I tried to make the API generic enough to support several authorization implementations, provider independent and at the same time fitting ECF generic implementation and spring security integration.
This is great...exactly right about the need for generality and cross-provider support.
So what I need is a way to intercept the remote service call at the server side to do some authorization checking (or in my case to provide the needed information to spring security). It's important to have the interception "around" the remote service call such that authorization specific code can be performed before and after the remote service call (in my case some authorization info would be put before the service call for spring security and cleaned up after the call). In ECF generic implementation, what I think would be the right place (but here I'm maybe looking too much at how to integrate with spring security) is in RegistrySharedObject.executeRequest within the run method of the created IProgressRunnable around "localRegistration.callService(call)". I have three reasons to place the authorization interception there:
1. If an exception must be thrown because the call is not authorized the exception will be handled correctly.
2. We're sure not to have any thread context switching from this point to the local service method call (at least not in the ECF layer, you can still have thread context switching within the service method call but that's application specific).
3. It's the last method having all information needed for authorization: ID of the caller (client container), method call and service on which call is performed.
Yes, understood.
For the API, I was thinking to have a policy interface (like the IConnectInitiatorPolicy and IConnectHandlerPolicy) that can be set on IRemoteServiceContainerAdapter interface (question: is this the right place?
Because IRemoteServicecontainerAdapter looks more a client oriented interface while the IRemoteServiceCallPolicy is more a server thing),
Yes, it is the right place for this, I believe. IRemoteServiceContainerAdapter has both remote service 'host' (aka server), and 'consumer' (aka client) methods on it...as there isn't any assumed asymmetry in the remote service API (all just remote service api supporters...able to both register remote services and access the remote service).
for example:
public interface IRemoteServiceCallPolicy {
public Object callWithAuthorization(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID) throws Exception;
}
and on IRemoteServiceContainerAdapter there should be a new method:
public void setRemoteServiceCallPolicy(IRemoteServiceCallPolicy policy);
<stuff deleted>
There's one thing that bothers me with this solution: an implementation of the IRemoteServicecallPolicy.callWithAuthorization would need to have ECf generic internal knowledge to be able to call localRegistration.callService method because this method is not part of the IRemoteServiceRegistration interface.
Hmm. One possibility is that the IRemoteServiceRegistration interface be enhanced (i.e. to include a callService method).
Another (maybe better) solution could be to have an interface with a pre invocation hook and a post invocation hook. The preinvocation hook can then be used to authorize the service method call and the post invocation hook can be used to clean up authorization data that was set up at the preinvocation hook.
public interface IRemoteServiceCallPolicy {
public void preInvocationHook(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID) throws Exception;
public void postInocationHook(IRemoteServiceRegistration registration, IRemoteCall call, ID fromID) throws Exception;
}
<stuff deleted>
What's you opinion on this?
This second approach is interesting. It's perhaps a little more complex (two methods rather than one), but in some ways it's more similar to the approach taken in Java 2 security (i.e. the security manager).
My immediate inclination is to prefer the first one (for simplicity). But I would like to discuss with you (Franky) in public (i.e. here on the mailing list) a little bit about your use case...to try to understand which would work better for this and other use cases.
So if you don't mind me asking in public...what are you doing inside of IRemoteServiceCallPolicy for your use case? Is one of the two approaches you list above simpler in your use case? If so, which one?
Thanks again for doing this...and for considering contributing back to the ECF project. This will help all in the community.
Scott