[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] remote service call authorization implemenation

On 10/05/2010 03:09 PM, Franky Bridelance wrote:
> Hi Scott, all,
> 
> I would like to add remote service method authorization on ECF remote
> services. The goal of this email is twofold : first I would like to have
> some comments on the way I want to use the existing API's and second I
> would like to have your opinion on some API extension to make the method
> invocation authorization possible.
>  
> Here's a description of what I would like to achieve:
> - Client connects to server with some credentials
> - Server authenticates the client with the given credentials, retrieves
> the authorization roles for the given credentials and links those
> authorization roles to the client container ID
> - For each remote service call done from the client, server checks if
> service method call is authorized for the given client container ID
> - Server cleans up relation between authorization roles and client
> container id when client disconnects (or user logs off)
> FYI: The real authentication and authorization wiill be done by spring
> security, ECF generic will be used to provide the information needed for
> authentication and authorization.
> 
> There's enough API in ECF to provide information for the authentication
> part:
>  
> - Client creates container
> - Get ISharedObjectContainerClient interface from the container.
> - Set an implementation of IConnectInitiatorPolicy on
> ISharedObjectContainerClient that will return the needed connect data to
> pass to the server
> - Create an implementation of IConnectContext containing the needed
> connect data
> - call connect method on container with the own IConnectContext
> implementation
> 
> - 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?
> 
> 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.
>  
> 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.
> 
> 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), 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);
> 
> The last thing to do would then be to implement the method
> setRemoteServiceCallPolicy on RegistrySharedObject class should then and
> Update the method RegistrySharedObject.executeRequest:
> try {
>    if (remoteSeviceCallPolicy != null) {
>       result =
> remoteServiceCallPolicy.callWithAuthorization(localregistration, call,
> responseTarget);
>    } else {
>       result = localRegistration.callService(call);
>    }
>    response = ...
> ...
> } catch...
> 
> 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.
> 
> 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;
> }
>  
> RegistrySharedObject.executeRequest method should then be changed to:
> try {
>    if (remoteServiceCallPolicy != null) {
>       remoteServiceCallPolicy.preInvocationHook(localregistration, call,
> responseTarget);
>    }
>    result = localRegistration.callService(call);
>    response = ...
> } catch ... {
> ...
> } finally {
>    if (remoteServiceCallPolicy != null) {
>       remoteServiceCallPolicy.postInvocationHook(localregistration,
> call, responseTarget);
>    }
> }
> 
> What's you opinion on this?
> 
> br,
> 
> Franky

Hi Franky,

thanks for your efforts. Do you happen to have a patch already that you
could share with us. Makes it a lot easier to understand the changes. :-)

Thanks
Markus