Tomcat 7 nesting CombinedRealm, LockoutRealm and DataSourceRealm - java

I'm trying to nest Realms as follows 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 nest Realms in Tomcat by more than two levels? I get a warning in the logs:
No rules found matching 'Server/Service/Engine/Realm/Realm/Realm'.
The idea behind is that the web service has some critical users that must not be locked out (e.g. as a DOS) and some normal users, which may have weaker passwords, where the lockoutRealm should be active. I'm sure other people have been in this situation.
If there is another way to achieve this (e.g. a whitelist for the LockoutRealm), please let me know.
Single sign on is also needed.
I guess extending the existing LockoutRealm code with a list of accounts never to lock out would be an option, but I'm not so keen on writing my own Realm, I would rather not add custom code on that level to Tomcat, as this will complicate setup for others and with every Tomcat update it might break etc.
Thanks for any help!
Here is the relevant part of server.xml of my test config:
<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 "%r" %s %b" />
</Host>
</Engine>

Apache commons-digester is used to parse the configuration files, so I suspect this particular use case simply wasn't expected.
Tomcat's org.apache.catalina.startup.RealmRuleSet.addRuleInstances seems rigged to only go 2-levels deep for Realm configuration. Seems simple enough to add another layer in there.
I'd have to look at how the digester can be configured to see if arbitrary levels could be supported, or if some subset would have to be manually configured.
Feel free to head over to the Tomcat users' list to request such a change.

The new answer is now:
Update to Tomcat 7.0.33 or later. Then it works perfectly.
Christopher Schultz was so friendly to forward my question here to the Tomcat user list. The great Tomcat developers have immediately addressed the issue and put this in the next release. Thanks a lot!
So you can now use a construction like the one in the question or like this with different order / "priorities":
...
<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 may also use other Realms and other combinations.
Note that one thing can be misleading in the logs: In this construction, if a wrong password is given for one of the critical users stored in the primary realm, the primary realm denies access, then the secondary realm via the lockout realm is tried and also denies access eventually locking out the username. This is logged by the lockout realm as a warning "An attempt was made to authenticate the locked user ...". Still with correct password, access keeps working via the primary realm, as it does not go via the lockout realm. I.e. all works as intended, just the log message could lead to confusion (of course this is impossible to avoid).

Related

DataSourceRealm not working since changing from JDBCRealm in Tomcat

I am attempting to upgrade an existing web application to run on Tomcat 10.1 from Tomcat 9.0 where it works fine. My web application currently uses JDBCRealm but this appears to now be deprecated with Tomcat 10.1 and are now advised to use DataSourceRealm instead.
I have attempted to follow the instructions on the Apache website to use the DataSourceRealm instead and upgraded both my context.xml and server.xml however my authentication isn't now working.
Here is my context.xml file:
<Context path="/TASSU"> <Realm className="org.apache.catalina.realm.DataSourceRealm" connectionName="root" connectionPassword="sesame"
connectionURL="jdbc:mysql://localhost:3306/login_details" debug="99" driverName="com.mysql.jdbc.Driver"
roleNameCol="Rolename" userCredCol="Password" userNameCol="Username" userRoleTable="userrole" userTable="userpass"/>
And here is the realm information within my server.xml file:
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
<Realm className="org.apache.catalina.realm.DataSourceRealm" connectionName="root" connectionPassword="sesame"
connectionURL="jdbc:mysql://localhost:3306/login_details" debug="99" driverName="com.mysql.jdbc.Driver"
roleNameCol="Rolename" userCredCol="Password" userNameCol="Username" userRoleTable="userrole" userTable="userpass"/>
Here is the error that is being displayed in the logs:
25-Jan-2023 10:13:50.699 SEVERE [http-nio-8080-exec-23] org.apache.catalina.realm.DataSourceRealm.open Exception performing authentication
Can anyone see at first glance what the issue could be here? Have I set these two files up correctly?

Need to deploy the same app to multiple contexts, each with a different database Tomcat7

How to deploy the same application to multiple contexts, each with a different database.
Using Tomcat7.0.54. We have 3 different environments like Development, Quality, Production. All the 3 environments have 3 different database configurations.
Normally apache-tomcat-7.0.54\conf\context.xml file. Sample D config.
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
<Resource name="java:jboss/datasources/letterDatasource"
auth="Container"
type="javax.sql.DataSource"
username="admin"
password="admin"
driverClassName="oracle.jdbc.OracleDriver"
url="xxx xxxx xxxxx xx"
maxActive="8"
maxIdle="4"/>
How to do the above programmatically or efficiently instead of changing in every server context.xml file.?
i am not using spring. just normal web application using seam 2.3 with jsf and richfaces.
Thank you.
Keep your data base properties in an environment.property file, which will be different for each stage. Specified environment will take their specific environmental properties.

Tomcat generates empty access log file

Since I need the runtime information of every request processed by Tomcat, I've configured the access log output for Tomcat in the file {$CATALINA_HOME}/conf/server.xml as following. But when running the application, the access log file just stays empty. Anybody knows the reasons? Thanks a lot!
<Host name="localhost" appBase="deploy"
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="/home/admin/shopcenter/logs/"
prefix="localhost_access_log"
suffix=".log"
buffered="false"
encoding="GB18030"
pattern="common"/>
</Host>

tomcat realm set user roles dynamically

I am using tomcat security for my application:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
<!--This is only applicable for Tomcat 8.5 and higher version with SQL server authentication-->
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionURL="jdbc:sqlserver://xxx.xx.xxx.xxx:1433;databaseName=xxxxx" connectionName="xxxx" connectionPassword="xxxx" roleNameCol="role_name" userCredCol="user_pass" userNameCol="user_name" userRoleTable="user_roles" userTable="users">
<CredentialHandler algorithm="MD5" className="org.apache.catalina.realm.MessageDigestCredentialHandler"/>
</Realm>
</Realm>
Now I want to be able to dynamically set new roles to the logged-in user from within the application whatever the authentication datasource may be. I need this to be deployed in an application and the client won't let us have the authentication database details and would prefer to themselves set the realm details. So it should work for all server/database types and hence be generic to the extent as possible.

Setting property 'source' to 'org.eclipse.jst.jee.server:GestorContenidoWS' did not find a matching property. Try all the solutions

This is my first post here (but not the first time that I visit the page, I found a lot of solutions here), first of all, sorry for my english I will try to explain myself as best I can.
This question appears another time in this page, but I tried all the solutions that the people post and I still with this problem, well here we go.
I made a project on Eclipse(indigo) for launch like a WebService (I did it before with succes, is not my first time) and when I Run on Server(Tomcat7) all seems fine and the appears this Warning.
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:GestorContenidoWS' did not find a matching property.
Then appear in the Web perspective of Eclipse the page "HTTP 404". I'm telling this because I read in other post that this Warning is not a problem, but seems that it is for me (The project is also vinculated with a JPA Persistence).
.I found two solutions for make dissappear this Warning. First, go to Server Overview and select the option 'Publish module contexts to separate XML files' and then try to Run on server again, but didn't work.
The other option was, remove the project from the server from the Server View. Then run the project under the same server for recreated server.xml, but didn't work also.
Anybody can help me? Maybe the problem of this "HTTP 404 requested resource (/GestorContenidoWS/) is not available." is in another part or its because this Warning?"
The code of my server.xml (without comments) is this:
<?xml version="1.0" encoding="UTF-8"?>
--><Server port="8005" shutdown="SHUTDOWN">
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory"name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1"redirectPort="8443"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/>
</Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log." suffix=".txt"/>
<Context docBase="GestorContenidoWS" path="/GestorContenidoWS" reloadable="true" source="org.eclipse.jst.jee.server:GestorContenidoWS"/></Host>
</Engine>
</Service>
Thank you
First of all this is a warning and not an error. So there is no need to worry too much about it. Basically it means, that Tomcat does not know what to do with the source attribute from context.
This source attribute is set by Eclipse (or to be more specific the Eclipse Web Tools Platform) to the server.xml file of Tomcat to match the running application to a project in workspace.
Tomcat generates a warning for every unknown markup in the server.xml (i.e. the source attribute) and this is the source of the warning. You can safely ignore it.
This is a warning and can be safely ignored. Tomcat or the Web container does not understand what to do with the property set by Eclipse
set contex-root
<property name="context-root" value="path" />
and http://localhost:8080/path
show your index file
Find server.xml. For example "C:\Dev\apache-tomcat-8.5.23\conf\server.xml"
Find your application in server.xml
<Context docBase="C:\Dev\apache-tomcat-8.5.23\wtpwebapps\SpringRestExample" path="/spring" reloadable="true" source="org.eclipse.jst.jee.server:SpringRestExample"/></Host>
Expected url http://localhost:8080/SpringRestExample/rest/emp/9999
But (path="/spring") instead (path="/SpringRestExample")
Therefore current url http://localhost:8080/spring/rest/emp/9999

Categories