This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Middleware

1 - Tomcat

1.1 -

Why do we put something in front of tomcat? Do we need it? I’ll quote the apache docs.

When using a single server, the performance when using a native webserver in front of the Tomcat instance is most of the time significantly worse than a standalone Tomcat with its default HTTP connector, even if a large part of the web application is made of static files.

Of course, this changes when we need a load balancer….or do we?

Tomcat 5 provides load balancing in three different ways: using the JK native connector, using Apache 2 with mod_proxy and mod_rewrite, or using the balancer web app.

The balancer web app is for tomcat native load balancing and provides useful features such as cluster wide sessions that the apache solutions (and hardware based ones) do not.

Below are some links on using tomcat native clustering.

http://www.onjava.com/pub/a/onjava/2004/03/31/clustering.html

http://www.onjava.com/pub/a/onjava/2004/04/14/clustering.html

And of course:

http://tomcat.apache.org/tomcat-5.5-doc/cluster-howto.html

Note: I imported this from a pot I wrote 20 years ago! Does anyone use Java anymore? I haven’t since 2016. But I like the thought.

1.2 - AD Auth

Note: Some very old info on tomcat container auth

Background

The conventional approach when connecting Java Servlets to Active Directory is to use the Java Naming and Directory Interface (JNDI) built into the Web or Servlet Container. This is done by configuring a security realm in the Container, making it available to all servlets inside.

Servlets such as the Tomcat Manager Application, which use the security-restraint mechanism, can immediately take advantage of this interface. Other servlets can be converted to use container based relatively easily. Configuration of both the Manager App and an example of a servlet with form-based login are detailed below. Directory Prep

In order for an application to talk to Active Directory, the service must have an account. This is known as a service account. Contact your AD Org Unit Administrator and ask to have a development account and groups created for your system. Alternatively, use your favorite tool and follow the procedure Creating Tomcat Resources in AD, For Development

Tomcat Configuration

Server Config

Configuring tomcat means editing the server.xml file. This is usually found in [tomcat home]/conf/server.xml, tomcat home being where you installed tomcat at.

Tomcat ships with the JNDI resource “UserDatabase” in the server.xml. This is a connection to a flat text file. By substituting our own JNDI resource, we can take advantage of Active Directory.

Note: We use the service account “OIT-tomcat-boss4” in the Org Unit Folder “Ohio/OIT/OIT-SysOps/Service Accounts”. Yours will be what your OUAdmin gives you, or what you create.

Comment out:

And then right below it Add

 <Realm className="org.apache.catalina.realm.JNDIRealm"		
	connectionName="CN=jjjjj,OU=Service Accounts,OU=jjjjj"
	connectionPassword="SomePassWord"
	connectionURL="ldap://jjjjj:389"
	userRoleName="member"
	userBase="CN=jjjjj"
	userPattern="CN={0},OU=jjjjjj"
	roleBase="ou=Groups,ou=jjjjj"
	roleName="cn"
    	roleSearch="(member={0})"              
	roleSubtree="false"
     	userSubtree="false"
   />

Note: This is a ‘un-encrypted’ connection to AD via the LDAP protocol. The problem isn’t passwords, they are one-way hashed during the bind process. What is at risk is the data. Who is in what group is passing in plain text. This is in most cases marginally OK. However, if group membership is deemed to be a security risk you can implement LDAPS. (How To Needed)

It is also possible to use MD5 passwords and SASL mechanisms. (How To Needed)

Tomcat Manager

[tomcat home]/webapps/manager/WEB-INF/web.xml

Web App Side Config

The webapp requires a two-part change;

  • a change to your form (if you’re reusing your exiting form)
  • an edit to your web.xml.

The Form

To use this with an existing webapp, that has a form (that you don’t want to change) simply change the details of your form so it uses the same method, action and names as the following.

<form method="POST" action="j_security_check">
    <input type="text" name="j_username">
    <input type="password" name="j_password">
</form>

Tomcat will take these values and pass them to the JNDI module, which will check against Active Directory.

The Web.xml

You add the controls you want by creating rolls and limiting what Resources and Methods that role can access.

If a user is not in the “AD Dev Portal” they will not be able to edit, rename, upload, etc. (see the pages and access listed in the security constraints).

Note that the data constraints are commented out because we have this on the inside network and aren’t using SSL. See Section above on SSL implementation.

<!-- This application has two basic areas;                                      -->
<!--    the webroot of the application accessed by all users(/MyWebApp)         -->
<!--    and the admin pages (/MyWebApp/Admin)                                   -->
<!-- We assign the role-name 'Users' to first, and 'Admin' to the second        -->

    <security-constraint>
        <display-name>All Users</display-name>
        <web-resource-collection>
            <web-resource-name>All Users</web-resource-name>
            <url-pattern>/MyWebApp</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>Users</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <display-name>Admin Users</display-name>
        <web-resource-collection>
            <web-resource-name>Admin Users</web-resource-name>
            <url-pattern>/MyWebApp/Admin</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>Admins</role-name>
        </auth-constraint>
    </security-constraint>


<!-- And here we map the User and Admin roles to the corresponding Active Directory groups -->

    <security-role>
        <description>CBW Webapp Admins</description>
        <role-name>Admin</role-name>
        <group-name>CBW-WebappAdmin</group-name>
    </security-role>

    <security-role>
        <description>CBW Webapp Users</description>
        <role-name>User</role-name>
        <group-name>CBW-WebappUser</group-name>
    </security-role>


<!-- We can also specify how to handle log in -->

   <login-config>
       <auth-method>FORM</auth-method>
           <form-login-config>/MyWebApp/login.jsp</form-login-config>
           <form-error-page>/MyWebApp/error_login.jsp</form-error-page>
   </login-config>

More web.xml

The previous example did not seem to work, but here is another possible configuration. In the web.xml for the application (Tomcat manager, lambda probe, etc), add a security-role for your Active Directory group. Then add references to that role along side any references to other security-roles that came with the application. In this way you extend the original configuration rather than alter it.

For example, within the Tomcat Manager web.xml file:

  <!-- Define a Security Constraint on this Application -->
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>HTMLManger and Manager command</web-resource-name>
      <url-pattern>/jmxproxy/*</url-pattern>
      <url-pattern>/html/*</url-pattern>
      <url-pattern>/list</url-pattern>
      <url-pattern>/expire</url-pattern>
      <url-pattern>/sessions</url-pattern>
      <url-pattern>/start</url-pattern>
      <url-pattern>/stop</url-pattern>
      <url-pattern>/install</url-pattern>
      <url-pattern>/remove</url-pattern>
      <url-pattern>/deploy</url-pattern>
      <url-pattern>/undeploy</url-pattern>
      <url-pattern>/reload</url-pattern>
      <url-pattern>/save</url-pattern>
      <url-pattern>/serverinfo</url-pattern>
      <url-pattern>/status/*</url-pattern>
      <url-pattern>/roles</url-pattern>
      <url-pattern>/resources</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <!-- NOTE:  This role is not present in the default users file -->
       <!-- Ohio University: Added the OIT-Tomcat-Admin AD group with same privs as a manager. -->
       <role-name>manager</role-name>
       <role-name>OIT-Tomcat-Admin</role-name>
    </auth-constraint>
  </security-constraint>

  <!-- Define the Login Configuration for this Application -->
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Tomcat Manager Application</realm-name>
  </login-config>

  <!-- Security roles referenced by this web application -->
  <security-role>
    <description>The role that is required to log in to the Manager Application</description>
    <role-name>manager</role-name>
  </security-role>

  <!-- Ohio University: Added the OIT-Tomcat-Admin Active Directory Group. -->
  <security-role>
    <description>Declares an OIT AD Group to the Tomcat Manager Application</description>
    <role-name>OIT-Tomcat-Admin</role-name>
  </security-role>

Notes

Setting up LDAPS

Adding the AD CA to the keystore that tomcat is configured to use, similar to how we add the Geotrust CA, should do the trick

In the webapp, you can ensure transport security by adding a constraint as below - if - you have setup LDAPS on the server

    <security-constraint>
        <display-name>All Users</display-name>
        <web-resource-collection>
            <web-resource-name>All Users</web-resource-name>
            <url-pattern>/MyWebApp</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>Users</role-name>
        </auth-constraint>

        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>

    </security-constraint>

Example of ldap to role mapping: https://jazz.net/learn/LearnItem.jsp?href=content/tech-notes/jazz-team-server-1_0-user-management-in-tomcat/index.html

1.3 - LocalPort Forwarding

Note: Circa 2008

The best way to have tomcat run on port 80, but not be root, is to use iptables.

One can change the tomcat connector, but since non root processes don’t have access to ports under 1024, nothing will happen. Since iptables is part of the kernel and already running on most servers, it’s a relatively short jump to turn on forward from port 80 to 8080, tomcat’s native port.

The iptables command is:

iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j REDIRECT --to-port 8080

To make this happen with SuSE, you need to tag into the SuSEfirewall2 system ( this is a series of scripts that do all the heavy lifting of iptables in SuSE so you don’t have to)

You could edit the /etc/sysconfig/SuSEfirewall2 config file, but since we already have the iptables command we can simply insert it into the /etc/sysconfig/scripts/SuSEfirewall2-custom config file.

Don’t forget to activate the custom-config file in your main config file. (/etc/sysconfig/SuSEfirewall2 section 25)

My thanks to Ramon Casha whose article the iptables command and idea is pulled from http://linux.org.mt/article/tomcat-ports

Most of the instructions on how to do this are at http://jakarta.apache.org/tomcat/tomcat-5.0-doc/ssl-howto.html

However, there are some peculiarities to using the IBM jre as opposed to the sun.

In the tomcat connector, one has to use algorithm=“IbmX509” and sslProtocol=“SSL”

If you don’t use the right algorithm, you’ll see it in your tomcat log. The second item IExplorer doesn’t work with.

As with the port 80 instructions, you’ll need to add a hook in the custom firewall rules (it’s detailed in the other inst)