[Freeipa-devel] OTP Sync Client Design

Petr Vobornik pvoborni at redhat.com
Mon May 26 10:32:30 UTC 2014


On 26.5.2014 09:41, Martin Kosek wrote:
> 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.

It would be useful for `json_metadata` and `i18n` commands. Also I would 
like to see a global web ui configuration which could be read prior to 
authentication, e.g., to get allowed authentication methods( we have a 
ticket to disable forms-based auth).

>>
>> 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
>

 From long-term perspective, I'm for the refactoring. But if there is no 
time and if we want the feature, combination of Martin's #1 and #2 would 
a sufficient solution. Both could be just an interface for the same logic.

-- 
Petr Vobornik




More information about the Freeipa-devel mailing list