In my previous post on Different JVM settings for different Tomcat instances, I briefly touched on using tomcat-users.xml to allow access to the the Server Status page. This page, along with the Tomcat Manager application (amongst others), are installed by default when you deploy Tomcat. Access to them is controlled via the tomcat-users.xml file.
As we saw in the previous article, we can enable access by defining a role, and subsequently a user who is part of that role.
Why doesn't Tomcat ship with a default account?: Simple. It's a security issue. Instead of providing that default account, Tomcat is locked down completely, and it's up to us to enable access.
Let's try accessing the Tomcat Manager without having any users defined in tomcat-users.xml.
As you can see, access is restricted. However, what it does do is tell us (some of) the types of roles available to us.
Let's look at our tomcat-users.xml file again. Now, based on what you see in the file, and what we added in the previous article, I'm hoping most (if not all) of you are a little concerned by the fact passwords are stored in plain text.
Thankfully this file isn't directly accessible from a web browser, however it can be read by anyone who has access to the server.
Tomcat Realms are simply a way of "storing" usernames, passwords and roles. The default out of the box realm used is "UserDatabaseRealm". This particular realm reads clear text passwords out of tomcat-users.xml
We're going to look at a couple of alternative realms, namely: MemoryRealm and JDBCRealm. There are other realms available to you, and if your interested, you can read up on them at: http://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html
What we're going to do is change the realm to "MemoryRealm", which whilst still reading the user details out of tomcat-users.xml, will now do so using a specified encrypted format: SHA, MD2 or MD5.
The algorithm must be supported by the java.security.MessageDigest class
Open up CATALINA_HOME/instance/conf/server.xml
Find "UserDatabaseRealm", as below, and comment it out.
Next, add the following Realm inside the Host block, which is just below the section you commented out.
Save the file, and exit.
We now need to create a SHA encrypted version of the password you want to use. Tomcat is useful here as it provides a script to do just that. Inside CATALINA_HOME/bin, run the following:
As a proper example:
You now want to replace your password (in tomcat-users.xml) with the encrypted version.
<user username="admin" password="d033e22ae348aeb5660fc2140aec35850c4da997" roles="manager-gui"/>
Now restart Tomcat and you should be able to login.
To configure the JDBCRealm, we need to do a couple of things first:
- Create tables and columns in your database of choice (we're going to use MySQL in this scenario)
- Configure a 'tomcat' user to allow Tomcat to talk to MySQL
- Drop the MySQL connector JAR file into place
- Set up our Realm
Use the following scripts to create your tables:
(I've created a dedicated database called TomcatAuthentication)
user_name varchar(15) not null primary key,
user_pass varchar(50) not null
create table user_roles (
user_name varchar(15) not null,
role_name varchar(15) not null,
primary key (user_name, role_name) );
We need to populate our tables with data, so now run the following:
insert into user_roles values('admin','manager-gui');
We now need to grant a 'tomcat' user read access to these tables, so run the following from your favourite MySQL client tool:
The next thing we need to do is get a hold of the MySQL JDBC driver, which we can download from: http://dev.mysql.com/downloads/connector/j/
Download the file, extract the contents, and then copy the JAR file (in my case mysql-connector-java-5.1.20-bin.jar) to CATALINA_HOME/lib
Now we want to add a Realm to our servers.xml file to support JDBC.
Add the following to our
userTable="users" userNameCol="user_name" userCredCol="user_pass"
I've already replace the appropriate entries above to those we're using in this article.
Now you can restart Tomcat, and when you try to access the Tomcat Manager or Service Status page, authentication will now take place against MySQL.
You can obviously harden your password further by using SSL, and locking down access to internal IPs or even just localhost, and we'll look at this in a future article.