| <?xml version="1.0" encoding="UTF-8"?> |
| |
| <document> |
| <properties> |
| <author email="akarasulu">akarasulu</author> |
| <title>ApacheDS - Interceptor Interactions</title> |
| </properties> |
| <body> |
| <p> |
| Interceptors will perform operations on behalf of the user/context making calls |
| against the proxy. Interceptors will often need to access or alter the DIT. |
| Interceptors have several options for DIT |
| access/alteration.</p> |
| <ol nesting="0"> |
| <li> |
| operate directly against the |
| nexus</li> |
| <li> |
| operate against the nexus |
| proxy</li> |
| <li> |
| operate against the next Interceptor in the |
| chain</li> |
| <li> |
| operate against JNDI |
| interfaces</li> |
| <li> |
| operate against the nexus proxy with selective |
| bypass</li> |
| <li> |
| out of band support methods on |
| Interceptors</li> |
| </ol> |
| <p> |
| A combination of these approaches can be taken. Each one has side effects and |
| ramifications when used. We will discuss the ramifications of each option as it |
| relates to Interceptor interactions. Interceptor interactions (coupling) |
| undermine the overall goal of having orthogonal independent |
| services.</p> |
| <section heading="h2" name="Direct Operations Against the Nexus"> |
| <p> |
| Direct operations against the system nexus retrieves or alters raw entries |
| stored within partitions. Sometimes this is absolutely necessary and sometimes |
| it could lead to serious |
| problems.</p> |
| <subsection heading="h3" name="Direct operations on the nexus bypass the Interceptor Mechanism"> |
| <p> |
| Direct operations on the nexus bypass the Interceptor mechanism. No Invocation |
| object is pushed onto the InvocationStack, and no Interceptors intercept the |
| call. If the Interceptor code calling the nexus relies on pre or post |
| processing by any other Interceptor there will be a |
| problem.</p> |
| <p> |
| A good example is the reliance of upstream Interceptors on the Mitosis |
| replication Interceptor. Upstream Interceptors ironically don't even know of |
| the presence of the Mitosis Interceptor, nor that they rely on it. Mitosis does |
| not actually delete entries but marks them deleted. The Mitosis Interceptor |
| filters out deleted entries from searches and responds according with |
| NameNotFoundExceptions when other operations are performed on entries marked for |
| deletion. Interceptors before the Mitosis Interceptor don't have to worry about |
| whether or not an entry is deleted because this is handled already. This is not |
| the case for downstream Interceptors so positioning is critical. Direct access |
| to the nexus however bypasses the Mitosis Interceptor along with all others and |
| makes deleted entries |
| reappear.</p> |
| </subsection> |
| <subsection heading="h3" name="Raw access to partition entries may be required"> |
| <p> |
| Raw access to partition entries should be done with extreme caution. But at |
| times this access may be absolutely necessary. The Interceptor, it's position |
| and the effects of bypassing other possibly unknown Interceptors must be taking |
| into |
| consideration.</p> |
| </subsection> |
| </section> |
| <section heading="h2" name="Operations on the Nexus Proxy"> |
| <p> |
| Interceptors that have intercepted an operation, may use the proxy to perform |
| other operations. These other operations performed to satisfy the first |
| intercepted operation will also traverse the |
| InterceptorChain.</p> |
| <subsection heading="h3" name="There is a risk for infinate recursion"> |
| <p> |
| The danger here is an infinite recursion. Let's suppose the first intercepted |
| operation, Invocation *A*, performs operations *A'* (that's A prime) and *B* |
| against the nexus. Invocation *A'* by the way is the same operation as the |
| intercepted operation but with different parameters. The same operation does not |
| mean the same Invocation. In this case *A'* may incur another set of Invocation |
| *A"* and *B'* all invoked within the same Interceptor. This chain reaction |
| could continue unabated to blow out the stack without |
| regulation.</p> |
| <p> |
| A good example of an Interceptor prone to an infinite recursion is the |
| AuthorizationService. It needs to lookup and search for other other entries to |
| determine access rights to perform operations. Those lookup and search |
| operations in turn trigger the AuthorizationService again to issue another set |
| of lookup and search operations and so on. An infinate recursion is the |
| result.</p> |
| <p> |
| If the AuthorizationService could call lookup and search on the nexus proxy |
| while bypassing itself then the recursion can be avoided. This raises the |
| question of whether or not sub-operations excecuted by Interceptors are really |
| considered to be performed by the user of the intercepted |
| call.</p> |
| </subsection> |
| <subsection heading="h3" name="Effects on the InvocationStack"> |
| <p> |
| Calls against the nexus proxy are not presently possible. They can however be |
| enabled. The foreseeable mechanism would be to just call the proxy object of |
| the current intercepted operation. This could be done by peeking at the |
| InvocationStack to get a handle on the Invocation object for the current |
| operation. From there the calling Context can be accessed. An accessor in the |
| Context implementation can expose access to the nexus proxy |
| object.</p> |
| <p> |
| Calling this nexus proxy will push a new Invocation object on top of the current |
| operation's Invocation object. This is good even though the Context is used to |
| issue yet another Invocation. The key advantage though is that we can |
| diffentiate between the two Invocations even if the caller Context, operation |
| and the parameters are the |
| same.</p> |
| </subsection> |
| <subsection heading="h3" name="Identity Lock-in"> |
| <p> |
| Because the same Context object is used, the identity performing the operation |
| is the same. This may be good and |
| bad.</p> |
| <p> |
| It's good because we are associating the sub-operations with the user performing |
| the primary operation. Although if we peek onto the stack the bottom most |
| Invocation tells us who the original Invocation was issued by. Even if |
| sub-operations are performed as another user like the super-user we can tell who |
| the original user was that this sub-operation was issued on behalf |
| of.</p> |
| <p> |
| There will be situations when we want a setUid like mechanism to access |
| protected information on behalf of the current user. Even if the current user |
| does not have access to protected resources, the Interceptor should be able to |
| access these resources to satisfy the current intercepted operation. Meaning |
| the Interceptor will need to perform operations as if it were the admin user to |
| satisfy an operation on behalf of the current user. Doing this is no simple |
| matter: authentication must be bypassed to enable an operation as the admin |
| user. Otherwise we would need access to the admin's credentials. Plus |
| re-authentication as the admin is unnecesary since the Interceptor is trusted |
| with admin rights. If we trust the Interceptor and give it the ability to |
| access the DIT as the admin, we must be sure this is done without compromising |
| security.</p> |
| <p> |
| Another alternative to access protected resources would be to disable access |
| controls for select sub-operations performed by an Interceptor. Perhaps even if |
| an operation's associated identity is unchanged, another parameter can be used |
| to provide access as another user. This would be a special cue to the |
| Authorization |
| subsystem.</p> |
| <p> |
| These limitations just show us that we're missing something in the design of the |
| Interceptor Mechanism. Whether we need to handle sub-operations with special |
| authorization measures, selectively bypass or require specific Interceptors |
| something is |
| required.</p> |
| </subsection> |
| </section> |
| </body> |
| </document> |