[Freeipa-devel] OTP Sync Client Design

Martin Kosek mkosek at redhat.com
Mon May 26 07:41:32 UTC 2014


On 05/23/2014 11:19 PM, Nathaniel McCallum wrote:
> On Wed, 2014-05-14 at 14:08 -0400, Nathaniel McCallum wrote:
>> Occasionally OTP tokens get out of sync with the server. When this
>> happens, the user or an admin need to synchronize the token. To this
>> end, we landed server-side synchronization support, which is a simple
>> bind with a custom control. This all works with my sample test script.
>>
>> Client support is proving a bit more difficult. In the ideal world, the
>> client would contact LDAP directly and perform the operation. This would
>> make a man in the middle attack difficult and we can ensure encryption
>> over the entire operation.
>>
>> However, browsers, without server-side assistance, cannot perform this
>> operation from javascript. This means that, in this case, the first
>> factor and two second factors must be transmitted to the FreeIPA server
>> and then proxied to 389. Is this an acceptable compromise?
>>
>> This command also needs to be accessible *without* an existing user
>> login since, if a user's token is out of sync, the user can't login. Is
>> it possible to expose such an API? If so, how? Both "ipa env" and "ipa
>> ping" seem to require kinit, so I don't see any obvious examples.
> 
> Thanks everyone for your feedback. This particular feature is proving
> difficult to implement, even with our agreed upon design. To reiterate
> this design: there will be an HTTP method by which to synchronize
> tokens.
> 
> There are two assumptions in the code which are making this difficult:
> 1. All cli commands are Command subclasses.
> 2. All Command subclasses create authenticated server methods.
> 
> There are thus two ways to tackle this problem.
> 
> First, I can create a standard POST method in rpcserver.py. This is not
> very modular. But the biggest problem is that there is no way to create
> the cli-side command to call it (assumption #1).
> 
> Second, I can create a Command subclass, similar to the passwd plugin.
> This will create both the client- and server-side components. However,
> there is no way to disable the server-side authentication.
> 
> I think that solving the second of these problems is the most reusable.
> Just as an example, the ping command currently requires authentication
> but does not need to do so. The passwd Command too shouldn't need to
> authenticate before executing the command because the command
> authenticates itself.
> 
> I think it very likely that we are going to have need for other Command
> subclasses in the future which do not require authentication.
> 
> However, implementing this approach is rather difficult as it will
> require a refactoring of rpcserver.py. The code in rpcserver.py contains
> many layering violations and the class structure is rather unclear
> (look, for instance, at the different orders in which xmlrpc and jsonrpc
> classes inherit from their parent classes).
> 
> The current problem forcing this refactoring is that authentication
> appears to happen across several different layers, but always before the
> command to be executed is unmarshalled. We need to invert this order:
> the command needs to be unmarshalled first in order to determine whether
> or not authentication is necessary. I don't think that switching this
> order is practical without constraining authentication to a single layer
> (or two: session and krb5) late in the request process.
> 
> Git tells me that lots of people have touched this code, so I'm hoping
> for good feedback! ;)
> 
> Alternatively, we could create a way to inject cli commands without
> having Command subclasses. Isolating these concerns is itself probably a
> good design choice. Ideally we'd have a structure where the Command
> class itself inherits from a CLICommand class and a ServerMethod class.
> But this too will be a massive refactoring, perhaps even bigger than the
> rpcserver.py refactoring.
> 
> So, which assumption should we break: #1 or #2? And who wants to help me
> do it? Also, I am all ears for easier solutions for this feature.
> 
> Nathaniel

Hi Nathaniel,

These are all good ideas, it is true that we are sometimes hitting framework
limitations which will force to rewrite some parts, Petr Viktorin already have
couple of wished refactorings in mind.

What you are suggesting sounds as a pretty massive refactorings touching basic
framework parts that have not been touched for long years. Refactorings of
this scale would take months of planning and execution.

Question is, does this use case warrants such big change? AFAIK, we need to
solve following use cases:

1) Admin wants to manipulate user's token via Web UI/CLI - easy to do, admin is
authenticated and can run any commands

2) User wants to re-synchronize token via Web UI: easy to do, create POST
callback and a Web UI page. IMO, Web UI will be the most used synchronization
interface for users, it is usually not very frequent operation so Web UI can
guide user through the procedure (as compared to plain CLI).

3) User wants to re-synchronize a token via CLI: given the framework is not
ready for this kind of unauthenticated operation and refactorings would take
massive amount of time, can we simply avoid using the framework and provide a
standalone CLI utility "ipa-token-resync" and deploy it in freeipa-client
package? The utility can then call the LDAP operation directly and wrap it in a
nice CLI interface for the user.

Martin




More information about the Freeipa-devel mailing list