1.4 - Interceptors
Interceptors are functional layers inside the DirectoryService. Each one of them are responsible for a specific task. They are ordered, and this order is not to be changed.
Each operation received by the DirectoryService will be processed by various interceptors, one after the other, down to the backend, and again when the result comes back to the caller. An interceptor can call the next interceptor, whcih will be determinated by the position it has in the chain of interceptors, or simply return. Note that calling the next interceptor does not require that you know which one will be called.
Some Interceptors can be disabled, some other can be enabled. It’s also possible to add some new one.
All in all, they will handle operations from a specific functional aspect.
Handled operations
Each Interceptor handles a subset of the possible operations, among those listed in the following table :
Operation | Description |
---|---|
add | Adds an entry in the backend |
bind | Binds on the DirectoryService |
compare | Compares the elements with the associated entry in the backend |
delete | Deletes the entry |
getRooDSE | Gets back the RootDSE entry |
hasEntry | Tells if an entry exists |
lookup | Fetches an entry |
modify | Modifies an entry |
move | Moves an entry |
moveAndRename | Moves and renames an entry |
rename | Renames an entry |
search | Searches for entries |
unbind | Unbinds from the DirectoryService |
It is important to understand that each operation will go through each Interceptor declared to handle the operation, down to the backend.
Existing interceptors
The following interceptors are already present in the server, even if they are not enabled. In this table, we list all the operations each interceptor is handling, and if the interceptor is enabled by default or not :
Interceptor | Enabled | add | bnd | cmp | del | DSE | has | lkp | mod | mov | m&r | ren | sea | ubd |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AciAuthorizationInterceptor | yes | X | - | X | X | - | X | X | X | X | X | X | X | - |
AdministrativePointInterceptor | yes | X | - | - | X | - | - | - | X | X | X | X | ? | - |
AuthenticationInterceptor | yes | X | X | X | X | X | X | X | X | X | X | X | X | X |
ChangeLogInterceptor | yes | X | - | - | X | - | - | - | X | X | X | X | - | |
CollectiveAttributeInterceptor | yes | X | - | - | - | - | - | X | X | - | - | - | X | - |
DefaultAuthorizationInterceptor | yes | - | - | - | X | - | - | X | X | X | X | X | X | - |
DelayInducingInterceptor | no | - | - | - | - | - | - | - | - | - | - | - | X | - |
EventInterceptor | yes | X | - | - | X | - | - | - | X | X | X | X | - | - |
ExceptionInterceptor | yes | X | - | - | X | - | - | - | X | X | X | X | - | - |
JournalInterceptor | yes | X | - | - | X | - | - | - | X | X | X | X | - | - |
KeyDerivationInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
NormalizationInterceptor | yes | X | X | X | X | - | X | X | X | X | X | X | X | - |
NumberIncrementInterceptor | yes | X | - | - | - | - | - | - | - | - | - | - | - | - |
OperationalAttributeInterceptor | yes | X | - | - | X | - | - | X | X | X | X | X | X | - |
PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
CryptPasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Md5PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Pkcs5s2PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Sha256PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Sha384PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Sha512PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
ShaPasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Smd5PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Ssha256PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Ssha384PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
Ssha512PasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
SshaPasswordHashingInterceptor | no | X | - | - | - | - | - | - | X | - | - | - | - | - |
ReferralInterceptor | yes | X | - | - | X | - | - | - | X | X | X | X | - | - |
SchemaInterceptor | yes | X | - | X | - | - | - | X | X | - | ? | X | X | - |
SubentryInterceptor | yes | X | - | - | X | - | - | ? | X | X | X | X | X | - |
TimerInterceptor | no | X | X | X | X | X | X | X | X | X | X | X | X | X |
TriggerInterceptor | yes | X | - | - | X | - | - | - | X | X | X | X | - | - |
The operations that are available are the operations for which we have some implementation in the interceptor class. For instance, the JournalInterceptor class implement the add, delete, modify, move, moveAndRename and rename methods.
Interceptors order
As we already said, the Interceptors order is significant : why would we proceed an Add operation through all the Interceptors if the user is simply denied the right to add an entry by the AciAuthorizationInterceptor ?
Currently, the following order is enforced :
Order | Interceptor |
---|---|
1 | NormalizationInterceptor |
2 | AuthenticationInterceptor |
3 | ReferralInterceptor |
4 | AciAuthorizationInterceptor |
5 | DefaultAuthorizationInterceptor |
6 | AdministrativePointInterceptor |
7 | ExceptionInterceptor |
8 | SchemaInterceptor |
9 | OperationalAttributeInterceptor |
10 | SubentryInterceptor |
11 | EventInterceptor |
12 | TriggerInterceptor |
13 | ChangeLogInterceptor |
14 | JournalInterceptor |
Example
Let’s consider the search operation. It will be processed successively by the following Interceptors, as it can be deduced by the two previous tables :
- NormalizationInterceptor
- AuthenticationInterceptor
- AciAuthorizationInterceptor
- DefaultAuthorizationInterceptor
- SchemaInterceptor
- OperationalAttributeInterceptor
- SubentryInterceptor
We can do the same exercise for each operation.
Processing
Basically, an Interceptor receives a request for an operation, does some pre-processing, calls the next Interceptor in the chain, does some post-processing, and returns a result.
Calling the next Interceptor is as simple as calling the next(OperationContext) method, which will compute the right Interceptor.
The pre-processing and post-processing are standard Java code, there is nothing special there.
Each operation is passed into an instance of a specific OperationContext, which contains all what is needed about the operation and the environment.