You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fortress@directory.apache.org by Jan Sindberg <js...@autorola.com> on 2016/01/06 15:00:08 UTC

Handling missing connection to LDAP

If there is no connection to the LDAP, then it is no longer possible to create an AccessMgrFactory. 

First we get:
org.apache.directory.fortress.core.CfgRuntimeException: static init: Error loading from cfg file: [fortress.properties] SecurityException=org.apache.directory.fortress.core.FinderException: getConfig dn [cn=DEFAULT,ou=Config,dc=example,dc=com] caught LdapException=INVALID_CREDENTIALS: Bind failed: ERR_316 Directory service is not started., errCode=127

On subsequent calls we get:
java.lang.NoClassDefFoundError: Could not initialize class org.apache.directory.fortress.core.AccessMgrFactory

Is there a way to handle this and make the Fortress core api reconnect later?

// Jan Sindberg

Re: Handling missing connection to LDAP

Posted by Shawn McKinney <sm...@apache.org>.
> On Jan 6, 2016, at 9:07 AM, Jan Sindberg <js...@autorola.com> wrote:
> 
> The no-go of a local cache is that security is always about the least priviliges. We don't want to let users continue for "too long" when we chance their permissions on the fly - all because of a network or server problem. Then it is better to not give access at all. 
> 
> But the problem I encounter here is that fortress will never again be able to connect if the first connection fails. I guess it has something to do with classloader? The subsequent java.lang.NoClassDefFoundError comes even when the LDAP is running again. This means that we will have to restart the whole web application in order to get it working again - and that is not a viable option because it will affect many other users.

Agree with your least priv notion.  And yes it is a classloader issue of sorts - the initialization happens inside static code blocks inside the config and pool classes and that happens the first time each class is loaded.  There is no retry once that initialization has failed.  This is a solvable problem if not an easy one to fix.  

Need to think more about it.  (Open to ideas)

Shawn


SV: Handling missing connection to LDAP

Posted by Jan Sindberg <js...@autorola.com>.
> From : Shawn McKinney [mailto:smckinney@apache.org]
> Sendt: 6. januar 2016 16:06
> Til: fortress@directory.apache.org
> Emne: Re: Handling missing connection to LDAP
> 
> 
> > On Jan 6, 2016, at 8:52 AM, Emmanuel Lécharny <el...@gmail.com>
> wrote:
> >
> > Le 06/01/16 15:00, Jan Sindberg a écrit :
> >> If there is no connection to the LDAP, then it is no longer possible to
> create an AccessMgrFactory.
> >>
> >> First we get:
> >> org.apache.directory.fortress.core.CfgRuntimeException: static init:
> >> Error loading from cfg file: [fortress.properties]
> >> SecurityException=org.apache.directory.fortress.core.FinderException:
> >> getConfig dn [cn=DEFAULT,ou=Config,dc=example,dc=com] caught
> >> LdapException=INVALID_CREDENTIALS: Bind failed: ERR_316 Directory
> >> service is not started., errCode=127
> >>
> >> On subsequent calls we get:
> >> java.lang.NoClassDefFoundError: Could not initialize class
> >> org.apache.directory.fortress.core.AccessMgrFactory
> >>
> >> Is there a way to handle this and make the Fortress core api reconnect
> later?
> >
> > Complicated...
> >
> > Fortress is storing all the Authz information in a remote server, and
> > if it's not reachable, then you won't be able to make any decision.
> >
> > AFAIR, we had internal discussion about setting up a local cache
> > within the API to allow Fortress to keep going even if the remote LDAP
> > server is down. I'm not sure it's in Fortress atm, and I'm not sure we
> > decided anything about such an addition...
> >
> > Shawn ?
> 
> I think it would be a lot of work to satisfy a corner case.  But you might
> wonder why instantiating a manager component is hitting the remote server
> in the first place.  The reason is fortress stores much of its parameters on the
> remote server itself in a configuration node.
> 
> For explanation check out this writeup:
> https://github.com/apache/directory-fortress-core/blob/master/README-
> CONFIG.md
> 
> The runtime is in the process of pulling back that config info when it gets the
> connection error and gives up.
> 
> There might be a case where we want to delay hitting that server, or maybe
> allow it to retry later, i.e. at regular intervals.  Not as complicated as caching
> the information, but tricky.  It would require rewiring how the configuration
> subsystem and ldap pooling mechanisms work.  Worth considering, but we
> need to be careful here, no guarantees against overcomplicating or creating
> new problems.
> 
> Shawn

The no-go of a local cache is that security is always about the least priviliges. We don't want to let users continue for "too long" when we chance their permissions on the fly - all because of a network or server problem. Then it is better to not give access at all. 

But the problem I encounter here is that fortress will never again be able to connect if the first connection fails. I guess it has something to do with classloader? The subsequent java.lang.NoClassDefFoundError comes even when the LDAP is running again. This means that we will have to restart the whole web application in order to get it working again - and that is not a viable option because it will affect many other users.

// Jan

Re: Handling missing connection to LDAP

Posted by Emmanuel Lécharny <el...@gmail.com>.
Le 06/01/16 16:44, Shawn McKinney a écrit :
>> On Jan 6, 2016, at 9:23 AM, Emmanuel Lécharny <el...@gmail.com> wrote:
>>
>> AFAIR, when we had this conversation (probably 2 years ago), we talked
>> about using an embedded ApacheDS server in the Fortress API, server that
>> would be synced with the remote LDAP server.
>>
>> This is far from being a simple architecture...
> Ah yes I remember now.  In that scenario the runtime would always use the cache, in this case embedded ldap server.  
Yep. And as you can have ApacheDS using a in-memory backend, you won't
have any data stored on disk (but you might also have the data on disk,
if for instance you are using an application on a laptop that is not
likely to be connected to the network all the time).


> Worth considering down the road…
Fortress 2.0 ?

Re: SV: Handling missing connection to LDAP

Posted by Emmanuel Lécharny <el...@gmail.com>.
Le 07/01/16 12:36, Jan Sindberg a écrit :
>> Fra: Shawn McKinney [mailto:smckinney@apache.org]
>> Sendt: 6. januar 2016 16:44
>> Til: fortress@directory.apache.org
>> Emne: Re: Handling missing connection to LDAP
>>
>>
>>> On Jan 6, 2016, at 9:23 AM, Emmanuel Lécharny <el...@gmail.com>
>> wrote:
>>> AFAIR, when we had this conversation (probably 2 years ago), we talked
>>> about using an embedded ApacheDS server in the Fortress API, server
>>> that would be synced with the remote LDAP server.
>>>
>>> This is far from being a simple architecture...
>> Ah yes I remember now.  In that scenario the runtime would always use the
>> cache, in this case embedded ldap server.  Worth considering down the
>> road…
>>
>> Shawn
> I like the idea of an in-memory ApacheDS in slave mode. They are still reachable by apache directory studio and most likely also from a Fortress Commander - could be used to emergency changes in case of network failures. It doesn't sound too difficult (if jar-hell can be handled ...  ;-).  - This is however more about network related performance and resilience - It does not change the current situation that the LDAP must be running and fully synchronized before anyone tries to use fortress core.

Which is a non issue, if you don't have millions of entries. If you
assume that when you initialized Fortress for the very first time, it
was able to access data from the remote server, then every update made
on the main LDAP server will be propagated to the client in a matter of ms.
>
> A quick search found 18 static initializer blocks in fortress core. And then there is stuff like this:
> private static final String SAFE_TEXT_PATTERN_STRING = Config.getProperty( GlobalIds.REG_EX_SAFE_TEXT );

We can also change that. One idea, *if* we use an embedded ApacheDS,
would be to store the config in LDAP too. No more statc initializers...


SV: Handling missing connection to LDAP

Posted by Jan Sindberg <js...@autorola.com>.
> Fra: Shawn McKinney [mailto:smckinney@apache.org]
> Sendt: 6. januar 2016 16:44
> Til: fortress@directory.apache.org
> Emne: Re: Handling missing connection to LDAP
> 
> 
> > On Jan 6, 2016, at 9:23 AM, Emmanuel Lécharny <el...@gmail.com>
> wrote:
> >
> > AFAIR, when we had this conversation (probably 2 years ago), we talked
> > about using an embedded ApacheDS server in the Fortress API, server
> > that would be synced with the remote LDAP server.
> >
> > This is far from being a simple architecture...
> 
> Ah yes I remember now.  In that scenario the runtime would always use the
> cache, in this case embedded ldap server.  Worth considering down the
> road…
> 
> Shawn

I like the idea of an in-memory ApacheDS in slave mode. They are still reachable by apache directory studio and most likely also from a Fortress Commander - could be used to emergency changes in case of network failures. It doesn't sound too difficult (if jar-hell can be handled ...  ;-).  - This is however more about network related performance and resilience - It does not change the current situation that the LDAP must be running and fully synchronized before anyone tries to use fortress core.

A quick search found 18 static initializer blocks in fortress core. And then there is stuff like this:
private static final String SAFE_TEXT_PATTERN_STRING = Config.getProperty( GlobalIds.REG_EX_SAFE_TEXT );

It would be nice to create some other form of initialization but it might then require keeping a state of completeness of initialization and connection and throwing appropriate exceptions. The benefit could be that configuration can be changed at runtime?

In the end we all have to prioritize, and since our application have so many other dependencies of the order of running services, one more or less doesn't really matter. I definitely see the convenience of utility classes and static initializers :-)

// Jan


Re: Handling missing connection to LDAP

Posted by Shawn McKinney <sm...@apache.org>.
> On Jan 6, 2016, at 9:23 AM, Emmanuel Lécharny <el...@gmail.com> wrote:
> 
> AFAIR, when we had this conversation (probably 2 years ago), we talked
> about using an embedded ApacheDS server in the Fortress API, server that
> would be synced with the remote LDAP server.
> 
> This is far from being a simple architecture...

Ah yes I remember now.  In that scenario the runtime would always use the cache, in this case embedded ldap server.  Worth considering down the road…

Shawn

Re: Handling missing connection to LDAP

Posted by Emmanuel Lécharny <el...@gmail.com>.
Le 06/01/16 16:05, Shawn McKinney a écrit :
>> On Jan 6, 2016, at 8:52 AM, Emmanuel Lécharny <el...@gmail.com> wrote:
>>
>> Le 06/01/16 15:00, Jan Sindberg a écrit :
>>> If there is no connection to the LDAP, then it is no longer possible to create an AccessMgrFactory. 
>>>
>>> First we get:
>>> org.apache.directory.fortress.core.CfgRuntimeException: static init: Error loading from cfg file: [fortress.properties] SecurityException=org.apache.directory.fortress.core.FinderException: getConfig dn [cn=DEFAULT,ou=Config,dc=example,dc=com] caught LdapException=INVALID_CREDENTIALS: Bind failed: ERR_316 Directory service is not started., errCode=127
>>>
>>> On subsequent calls we get:
>>> java.lang.NoClassDefFoundError: Could not initialize class org.apache.directory.fortress.core.AccessMgrFactory
>>>
>>> Is there a way to handle this and make the Fortress core api reconnect later?
>> Complicated...
>>
>> Fortress is storing all the Authz information in a remote server, and if
>> it's not reachable, then you won't be able to make any decision.
>>
>> AFAIR, we had internal discussion about setting up a local cache within
>> the API to allow Fortress to keep going even if the remote LDAP server
>> is down. I'm not sure it's in Fortress atm, and I'm not sure we decided
>> anything about such an addition...
>>
>> Shawn ?
> I think it would be a lot of work to satisfy a corner case.  But you might wonder why instantiating a manager component is hitting the remote server in the first place.  The reason is fortress stores much of its parameters on the remote server itself in a configuration node.  
>
> For explanation check out this writeup:
> https://github.com/apache/directory-fortress-core/blob/master/README-CONFIG.md
>
> The runtime is in the process of pulling back that config info when it gets the connection error and gives up.  
>
> There might be a case where we want to delay hitting that server, or maybe allow it to retry later, i.e. at regular intervals.  Not as complicated as caching the information, but tricky.  It would require rewiring how the configuration subsystem and ldap pooling mechanisms work.  Worth considering, but we need to be careful here, no guarantees against overcomplicating or creating new problems.
>
> Shawn
AFAIR, when we had this conversation (probably 2 years ago), we talked
about using an embedded ApacheDS server in the Fortress API, server that
would be synced with the remote LDAP server.

This is far from being a simple architecture...


Re: Handling missing connection to LDAP

Posted by Shawn McKinney <sm...@apache.org>.
> On Jan 6, 2016, at 8:52 AM, Emmanuel Lécharny <el...@gmail.com> wrote:
> 
> Le 06/01/16 15:00, Jan Sindberg a écrit :
>> If there is no connection to the LDAP, then it is no longer possible to create an AccessMgrFactory. 
>> 
>> First we get:
>> org.apache.directory.fortress.core.CfgRuntimeException: static init: Error loading from cfg file: [fortress.properties] SecurityException=org.apache.directory.fortress.core.FinderException: getConfig dn [cn=DEFAULT,ou=Config,dc=example,dc=com] caught LdapException=INVALID_CREDENTIALS: Bind failed: ERR_316 Directory service is not started., errCode=127
>> 
>> On subsequent calls we get:
>> java.lang.NoClassDefFoundError: Could not initialize class org.apache.directory.fortress.core.AccessMgrFactory
>> 
>> Is there a way to handle this and make the Fortress core api reconnect later?
> 
> Complicated...
> 
> Fortress is storing all the Authz information in a remote server, and if
> it's not reachable, then you won't be able to make any decision.
> 
> AFAIR, we had internal discussion about setting up a local cache within
> the API to allow Fortress to keep going even if the remote LDAP server
> is down. I'm not sure it's in Fortress atm, and I'm not sure we decided
> anything about such an addition...
> 
> Shawn ?

I think it would be a lot of work to satisfy a corner case.  But you might wonder why instantiating a manager component is hitting the remote server in the first place.  The reason is fortress stores much of its parameters on the remote server itself in a configuration node.  

For explanation check out this writeup:
https://github.com/apache/directory-fortress-core/blob/master/README-CONFIG.md

The runtime is in the process of pulling back that config info when it gets the connection error and gives up.  

There might be a case where we want to delay hitting that server, or maybe allow it to retry later, i.e. at regular intervals.  Not as complicated as caching the information, but tricky.  It would require rewiring how the configuration subsystem and ldap pooling mechanisms work.  Worth considering, but we need to be careful here, no guarantees against overcomplicating or creating new problems.

Shawn

Re: Handling missing connection to LDAP

Posted by Emmanuel Lécharny <el...@gmail.com>.
Le 06/01/16 15:00, Jan Sindberg a écrit :
> If there is no connection to the LDAP, then it is no longer possible to create an AccessMgrFactory. 
>
> First we get:
> org.apache.directory.fortress.core.CfgRuntimeException: static init: Error loading from cfg file: [fortress.properties] SecurityException=org.apache.directory.fortress.core.FinderException: getConfig dn [cn=DEFAULT,ou=Config,dc=example,dc=com] caught LdapException=INVALID_CREDENTIALS: Bind failed: ERR_316 Directory service is not started., errCode=127
>
> On subsequent calls we get:
> java.lang.NoClassDefFoundError: Could not initialize class org.apache.directory.fortress.core.AccessMgrFactory
>
> Is there a way to handle this and make the Fortress core api reconnect later?

Complicated...

Fortress is storing all the Authz information in a remote server, and if
it's not reachable, then you won't be able to make any decision.

AFAIR, we had internal discussion about setting up a local cache within
the API to allow Fortress to keep going even if the remote LDAP server
is down. I'm not sure it's in Fortress atm, and I'm not sure we decided
anything about such an addition...

Shawn ?