Tomcat 7 nesting CombinedRealm, LockoutRealm and DataSourceRealm

I am trying to embed Realms in Tomcat 7.0.32 (written here in pseudo-XML):

<CombinedRealm> <LockoutRealm> <DataSourceRealm/> </LockoutRealm> <UserDatabaseRealm/> </CombinedRealm> 

This doesn't seem to work - is it possible to embed Realms in Tomcat on more than two levels? I get a warning in the logs:

 No rules found matching 'Server/Service/Engine/Realm/Realm/Realm'. 

The idea is that there are some critical users in the web service that should not be blocked (like DOS for example) and some ordinary users who might have weaker passwords where lockoutRealm should be active. I am sure that other people have been in this situation.

If there is another way to achieve this (e.g. whitelist for LockoutRealm), let me know.

A single sign is also required.

I assume that expanding existing LockoutRealm code with a list of accounts that are never blocked will be an option, but I'm not very interested in writing my own Realm, I would rather not add my own code at Tomcat at this level, as this will complicate the setup for others, and with every Tomcat update it may break, etc.

Thanks for any help!

Here is the relevant part of server.xml in my test configuration:

 <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.CombinedRealm"> <!-- Lockout realm for the DB users --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- PRIMARY: DataSourceRealm with user DB --> <Realm className="org.apache.catalina.realm.DataSourceRealm" dataSourceName="jdbc/authority" userTable="user" userNameCol="username" userCredCol="password" digest="SHA" userRoleTable="user_role" roleNameCol="rolename" /> </Realm> <!-- FALLBACK: This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> </Engine> 
+7
source share
2 answers

New answer now:

Update to Tomcat 7.0.33 or later. Then it works great.

Christopher Schulz was so friendly as to send my question here to the Tomcat user list. The excellent Tomcat developers immediately fixed the problem and put it in the next version. Many thanks!

So now you can use a construct similar to the one in the question, or like this with a different order / "priority":

 ... <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.CombinedRealm"> <!-- PRIMARY: tomcat-users.xml with critical system users that should always work, DB independent and without lockout NOTE: If the wrong password is given, the secondary path with lockout is still attempted, so that a lockout on that path will still occur and be logged. Still the primary path is not locked for access by that happening. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> <!-- SECONDARY: DataSourceRealm with DB with lockout functionality --> <!-- (three level nesting of realms requires Tomcat >= 7.0.33) --> <Realm className="org.apache.catalina.realm.LockOutRealm" failureCount="5" lockOutTime="60" > <!-- note that when an account is locked correct password login is no longer possible (would otherwise defeat purpose of lockout), but also lockoutTime is still reset in each correct attempt --> <Realm className="org.apache.catalina.realm.DataSourceRealm" dataSourceName="jdbc/authority" userTable="user" userNameCol="username" userCredCol="password" digest="SHA" userRoleTable="user_role" roleNameCol="rolename" /> </Realm> </Realm> <Host > ... </Host> </Engine> ... 

Of course, you can also use other Realms and other combinations.

Please note that one thing can be misleading in the logs: in this design, if the wrong password is set for one of the critical users stored in the primary area, the primary area is denied access, then the secondary realm through the lockout area is checked and also denies access ultimately blocking the username. This is logged in the blocking area as a warning "An attempt was made to authenticate a blocked user ...". With the correct password, access continues to work through the main area, since it does not pass through the blocking area. That is, everything works as intended, only a log message can lead to confusion (of course, this cannot be avoided).

+3
source

Apache commons-digester is used to analyze configuration files, so I suspect that this particular use case was just not expected.

Tomcat org.apache.catalina.startup.RealmRuleSet.addRuleInstances seems to be falsified to go only 2 levels for Realm configuration. It seems simple enough to add another layer there.

I need to see how you can configure the digest to see if arbitrary levels can be supported, or if some subset needs to be configured manually.

Be sure to check the Tomcat user list to request such a change.

+3
source

All Articles