tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Burch <br...@pingtoo.com>
Subject Re: problem using default Realm in new unit tests
Date Tue, 10 Jan 2012 03:21:23 GMT
Konstantin,

Thank you for your prompt and helpful response... at least I know I 
haven't overlooked something simple. With your encouragement, I'm happy 
to keep "fighting the alligators until I can get back to draining the 
swamp"!

On 10/01/12 02:56, Konstantin Kolinko wrote:
> 2012/1/9 Brian Burch<brian@pingtoo.com>:
>> On 06/01/12 11:47, Konstantin Kolinko wrote:
>>>
>>> 2012/1/6 Brian Burch<brian@pingtoo.com>:
>>>>
>>>> I am developing some new unit tests to validate SingleSignOn and
>>>> Authenticator logic. I have used this existing test class as my template:
>>>>
>>>> org.apache.catalina.authenticator.TestDigestAuthenticator
>>>>
>>>> .. which extends org.apache.catalina.startup.TomcatBaseTest.
>>>>
>>>> I noticed that TestDigestAuthenticator sets up its own MapRealm and
>>>> assigns
>>>> it to its single Context. I thought this logic was unnecessary, and so my
>>>> own initial test logic simply used the default RealmBase provided by the
>>>> underlying Tomcat instance. I add my test user and role to that. It
>>>> worked
>>>> fine with my simple cases, however...
>>>>
>>>> To test SSO, I need to set up two Contexts under the same Realm. I see
>>>> the
>>>> following message in the output log:
>>>>
>>>> INFO: The start() method was called on component [Realm[Simple]] after
>>>> start() had already been called. The second call will be ignored.
>>>>
>>>> I know it is an INFO message. I know the second start (and its associated
>>>> stop) are ignored and therefore are harmless. However, I am reluctant to
>>>> simply shrug and ignore it. My instincts tell me something isn't right.
>>>>
>>>> I have done quite a lot of investigating, but the underlying logic is
>>>> very
>>>> hard for me to follow. Here is what I am sure about:
>>>>
>>>> 1. The message is ONLY emitted in tests that create two Contexts and each
>>>> have the same Realm assigned with setRealm.
>>>>
>>>> 2. The message is NOT emitted at the time the Contexts are created and
>>>> defined (servlets, security constraints, etc).
>>>>
>>>> 3. The message IS emitted after the Tomcat.start method is called.
>>>>
>>>> 4. The message is emitted by one of the two threads which are started on
>>>> behalf of my two contexts. The messages are issued by the start and stop
>>>> methods in the abstract class org.apache.catalina.util.LifecycleBase.
>>>>
>>>> 5. org.apache.catalina.realm.RealmBase extends
>>>> org.apache.catalina.util.LifecycleMBeanBase which extends LifecycleBase.
>>>>
>>>> My currently unanswered questions are:
>>>>
>>>> 1. Is this message normal? (I don't see it when I start multiple contexts
>>>> under a real tomcat server, but perhaps the logging properties are
>>>> different).
>>>>
>>>> 2. Why isn't the redundant startup of the Realm detected earlier and
>>>> simply
>>>> avoided (maybe the Threads are intended to race to be first with startup
>>>> -
>>>> but then I think the message should be debug level and not sound so
>>>> scary).
>>>>
>>>>
>>>> Please don't waste your time investigating this for me. I am only asking
>>>> the
>>>> question because I don't want too get side-tracked if one of you already
>>>> knows the answers to my questions. I'd like to settle the matter quickly
>>>> and
>>>> get back to my original task!
>>>>
>>>> Thanks for listening,
>>>>
>>>
>>> The message is expected. I would say that the configuration is wrong,
>>> or at least unusual.
>>>
>>> If you look at the default server.xml file you will note that the
>>> <Realm>    element there belongs to Engine. That is why it is started
>>> once.
>>
>>
>> I agree, and this is what the TomcatBaseTest expects. If you "tickle" tomcat
>> with TomcatBaseTest.getTomcatInstance() and then with
>> Tomcat.getDefaultRealm(), a new default RealBase (memory) instance is
>> definitely created.
>>
>>
>>> When Contexts are created and their context.xml files are parsed, the
>>> Contexts always get distinct new Realm instances.
>>>
>>> Instead of assigning the same Realm instance to both Contexts you
>>> should assign it to an upper container (I have not looked at the API
>>> though).  Or maybe you can have different Realm instances, but which
>>> connect to the same backing storage?
>>
>>
>> When the StandardEngine (extending ContainerBase) thread starts, I would
>> expect percolating getRealm calls (from Context to Host to Engine) to
>> eventually arrive at the already-defined Tomcat default Realm. HOWEVER,
>> StandardEngine overrides the ContainerBase.getRealm method and ensures that
>> an unconfigured JAAS Realm is instantiated as the default for the Context,
>> because it cannot locate its parent (the field is certainly null, not
>> tomcat), so it decides to use this JAAS as the backstop.
>>
>> This looks to me as if some refactoring between tomcat 5 and 6 left the
>> Tomcat default memory realm orphaned from the StandardEngine, which now
>> operates independently and establishes a completely different default realm.
>> Perhaps the right hand no longer knows what the left hand is doing????
>>
>> Funny thing is that I googled this:
>>
>> http://tomcat.10.n6.nabble.com/default-realm-set-to-JAASRealm-in-StandardEngine-td2005479.html
>>
>> ... and your name (Konstantin) is all over it! Can you cast you mind back 4
>> months and try to give me a clue about the history of this change to the
>> logic?
>>
>> My feeling is that we need to stop StandardEngine from unilaterally creating
>> an unconfigured JAAS default Realm... and help the poor thing find its true
>> parent, i.e. tomcat, which has a perfectly serviceable default memory realm
>> just waiting to be used!
>
> Tomcat is not part of container hierarchy.
> Tomcat class is just a wrapper/factory that helps to launch standalone
> server instances. It is not used at all when you launch proper
> standalone Tomcat server.
>
> The hierarchy is what you see in server.xml starting with<Server>
> (StandardServer).
>
> (Well, truly speaking StandardServer is not a container, it does not
> implement Contaner interface).
>
> Also docs:
> http://tomcat.apache.org/tomcat-7.0-doc/config/realm.html
> - see where Realm has to be placed.

Yeah.. I've read that stuff forwards, backwards and sideways. I still 
don't feel completely confident relating what it says to what I see in 
the latest source, so please be patient if you think I'm asking about 
something that is already in the docs.

> Regarding Tomcat class behaviour - I created issue in Bugzilla:
> https://issues.apache.org/bugzilla/show_bug.cgi?id=52443

That WAS as surprise to me! Thanks - it confirms my suspicions, but I 
wasn't brave enough to call it a bug at this time.

> Regarding your use case:
> As of now I still think you should create two separate Realm for those
> web applications. (Another way is to assign one realm to Engine, but
> that does not play well with Tomcat#addWebapp(), as I mentioned in the
> above issue).

At the moment I don't see it like that. I feel the Realm should be 
shared between the Contexts that use it - in my case, which seems to be 
realistic, that means all webapps use the same Realm.

> Re: old thread
> I still think that that behaviour is not very good. At least it is bad
> that it is not documented. Anyway, some default Realm implementation
> is needed,

Agreed. Even if that default Realm implementation is not properly 
configured, it makes sense to let tomcat start "securely" and log an error.

> and I would prefer some other realm implementation as the
> default.
> But as I do not know any real problems with that JAASRealm, and I
> there is no other ready-to-use implementation that can be used as a
> replacement, the above alone is not enough to go with breaking the
> current behaviour. I suspect that removing JAASRealm is risky and can
> break some embedded Tomcat uses.

My main concern is the unit tests, but it should go without saying that 
I don't want to break a production system, even if we haven't yet got a 
unit test that locks in the existing (correct?) behaviour.

I wonder why the default was changed from MemoryRealm to JAASRealm? Was 
it because JAAS doesn't need any server.xml customisation - the config 
file is specified in the jvm startup options?

I have searched the latest source for uses of Tomcat.getDefaultRealm(), 
which instantiates the MemoryRealm in the case where a default realm has 
not yet been set. I find it is ONLY used in my new test classes in the 
org.apache.catalina.authenticator package. I haven't yet found a 
corresponding setdefaultRealm method in the class hierarchy, so at the 
moment I am assuming it doesn't exist.

That observation suggests to me the solution to my problem lies with 
making TomcatBasetest provide its default realm to StandardEngine, thus 
derailing instantiation of a default JAASRealm. If I can find a neat way 
to do this, then it will allow the unit tests to be elegant and 
minimalist, while leaving all production behaviour unchanged. I would 
prefer to do it programmatically, rather than build a server.xml for 
each unit test.

I'll look into this approach, bearing in mind that it might still lead 
me into trouble with Realm.start and stop problems down the track.

Brian

> Best regards,
> Konstantin Kolinko
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message