TDS Tutorial: Basic Tomcat and TDS Security

Notice: This section is out of date with respect to recent version of Tomcat

For a more up-to-date version of this content, please follow the TDS 5.0 guide

Tomcat manager Application: A Word Of Caution

About the manager application

More about manager

For more information about the Tomcat manager application, see the Tomcat Manager App HOW-TO documentation.

Accessing the Tomcat manager application

Changes to the manager application

The manager application URLs and roles has been re-structured. See the Tomcat Migration guide for more information.

Attempt to access the Tomcat manager application in your browser: http://localhost:8080/manager/html/. You will be prompted to login via BASIC authentication, which will end in failure since we do not yet have permission to access the manager application:

Manager app with 401 response code

Based on what we know about Tomcat configuration, which file in the Tomcat conf/ directory should we edit to grant ourselves access to the manager application?

Granting access to the manager application

  1. Modify tomcat-users.xml to add a user element.
  2. Using your favorite editor, open ${tomcat_home}/conf/tomcat-users.xml :

    $ vi tomcat-users.xml
    

    The roles of "manager-gui", "manager-status", "manager-script", and "manager-jmx" are pre-defined in Tomcat 7.

    Now add a new user by adding a user element. Create a username and password for the new user and specify manager-gui as one of the roles (in this example we are creating a user called 'admin' with a corresponding password of 'secret'):

    <tomcat-users>
        <role rolename="manager-gui"/>
        <user username="admin" password="secret" roles="manager-gui"/>   
    </tomcat-users>
    
  3. Restart Tomcat and log into the manager application.
  4. Keep in mind

    Changes to tomcat-users.xml do not take effect until Tomcat is restarted.

    Attempt to access the manager application again (http://localhost:8080/manager/html/), this time logging in using the name and password specified in tomcat-users.xml :

    Tomcat manager application

    Thinking ahead

    To gain access to restricted parts of the TDS, you will perform the same steps you used to grant yourself access to the manager application.

    Voilà! You should have access to the manager application.

Troubleshooting tips

  • Check the XML syntax in tomcat-users.xml to make sure it is well-formed and without error.
  • Did you restart Tomcat after you made your changes to tomcat-users.xml ?
  • Any errors will be reported in the Tomcat logs/catalina.out file.

Caveat of the manager application

PermGen info

For a really good description of the issue, see this series of three articles:

The dreaded java.lang.OutOfMemoryError: PermGen space failure error:

Using Digested Passwords

The problem of passwords in clear text

Tomcat Realms

The Tomcat documentation contains a wealth of information about the different Tomcat Realms.

Configure Tomcat to use digested passwords

  1. First we need to enable digest passwords support in Tomcat by modifying a couple of Tomcat Realms in the server.xml file in the Tomcat conf/ directory.
  2. A Tomcat Realm represents a "database" of usernames, passwords, and roles assigned to tomcat users.

    Realm Name Purpose
    UserDatabaseRealm The UserDatabaseRealm is enabled by default and reads clear text user password information stored in tomcat-users.xml.
    MemoryRealm The MemoryRealm reads the user password information stored in the tomcat-users.xml in a specified encrypted format.

    Open the server.xml with your favorite editor:

    $ vi server.xml
    

    Locate the UserDatabaseRealm (right above the Host element) and comment it out:

    <!-- 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"/>
    -->
    <!-- Define the default virtual host
         Note: XML Schema validation will not work with Xerces 2.2.
    -->
    <Host name="localhost"  appBase="webapps"
          unpackWARs="true" autoDeploy="true"
          xmlValidation="false" xmlNamespaceAware="false">
    

    Now add the following MemoryRealm information inside the Host element:

    <!-- 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"/>
    -->
    <!-- Define the default virtual host
         Note: XML Schema validation will not work with Xerces 2.2.
    -->
    <Host name="localhost"  appBase="webapps"
          unpackWARs="true" autoDeploy="true"
          xmlValidation="false" xmlNamespaceAware="false">
    
        <Realm className="org.apache.catalina.realm.MemoryRealm"
          digest="SHA" />
    
  3. Create a SHA encrypted version of your password.
  4. Tomcat provides a script ( ${tomcat_home}/bin/digest.sh ) that will encrypt a password string according to the algorithm specified. Use this script as follows with the password you made for yourself previously:

    $ /home/tds/apache-tomcat-6.0.32/bin/digest.sh -a SHA secret
    secret:e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4
    
  5. Update tomcat-users.xml.
  6. Replace your clear-text password in tomcat-users.xml with the encrypted version:

    <tomcat-users>
        <role rolename="manager-gui"/>
        <user username="admin" password="e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4" roles="manager-gui"/>
    </tomcat-users>
    
  7. Verify digest passwords have been successfully enabled in Tomcat.
  8. BASIC authentication

    Since we are using BASIC authentication, you will need to clear any authenticated sessions in your browser to test whether digested passwords have been enabled.

    Restart Tomcat and verify digest passwords have been successfully enabled by logging into the Tomcat manager application using your password in clear text: http://localhost:8080/manager/html/

    Troubleshooting tips

    • Check the XML syntax in tomcat-users.xml and server.xml to make sure it is well-formed and without error.
    • Did you restart Tomcat after you made your changes to tomcat-users.xml and server.xml ?
    • Any errors will be reported in the catalina.out file in the Tomcat logs/ directory.
    • You do not need to type the encrypted version of your password into the browser (the browser auto-magically encrypts your password for you before it transmits it to the server).

Exercise One: Configure Tomcat to use digested passwords

  1. Using the steps outlined above, enable digested passwords in Tomcat.

Enabling SSL Encryption

About Secure Sockets Layer (SSL)

How SSL works

For more information on how SSL works, Wikipedia details the steps involved during an SSL transaction.

SSL certificates

Accessing the TDS remote management tool

Other than the compelling security reasons, you will want to enable SSL to take advantage of the TDS remote management tool which (out-of-the-box) requires SSL in order to access: http://localhost:8080/thredds/admin/debug

  1. Configure Tomcat to enable SSL and use the self-signed certificate.
  2. Based on what we know about Tomcat configuration, which file in ${tomcat_home}/conf should we edit to to enable SSL?

    Open ${tomcat_home}/conf/server.xml with your favorite editor:

    $ vi server.xml
    

    Locate the Java HTTP/1.1 Connector listening on port 8080 and verify it is redirecting SSL traffic to port 8443:

    <Connector port="8080" protocol="HTTP/1.1"
                  connectionTimeout="20000"
                  redirectPort="8443" />
    

    Find and uncomment the SSL HTTP/1.1 Connector listening on port 8443 to activate this connector:

    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
                  maxThreads="150" scheme="https" secure="true"
                  clientAuth="false" sslProtocol="TLS" />
    

    Add a keystoreFile attribute to the SSL HTTP/1.1 Connector to tell Tomcat where to find the keystore:

    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
                  maxThreads="150" scheme="https" secure="true"
                  clientAuth="false" sslProtocol="TLS" keystoreFile="/home/tds/tds/apache-tomcat-6.0.32/conf/keystore" />
    

    Since we opted to not use the default keystore password , we need to specify the new password so Tomcat can open the file:

    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
                  maxThreads="150" scheme="https" secure="true"
                  clientAuth="false" sslProtocol="TLS" keystoreFile="/home/tds/tds/apache-tomcat-6.0.32/conf/keystore" keystorePass="foobar" />
    

    Finally, verify the AprLifecycleListener is uncommented (found near the top of the file):

    <!--APR library loader. Documentation at /docs/apr.html -->
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    
  3. Verify SSL has been enabled.
  4. Restart Tomcat:

    $ ${tomcat_home}/bin/shutdown.sh
    $ ${tomcat_home}/bin/startup.sh
    

    Verify Tomcat is listening on port 8443 by running the netstat command:

    $ netstat -an | grep tcp
    

    man netstat

    Run man netstat in your terminal window to learn more about this command.

    netstat (short for network statistics) is available on Unix, Unix-like, and Windows NT-based operating systems. It is a command-line tool that displays:

    • network connections (both incoming and outgoing)
    • routing tables
    • and a number of network interface statistics

    Look for the following in the output:

    tcp        0      0 127.0.0.1:8443               0.0.0.0:*                   LISTEN
    

    Troubleshooting tips

    • Check the XML syntax in server.xml to make sure it is well-formed and without error.
    • When generating the self-signed certificate, the last password (the key password ) and keystore password should be the same ( changeit ). If they differ, Tomcat cannot open the keystore and you will get this error: java.io.IOException: Cannot recover key .
    • Did you restart Tomcat after you made your changes to server.xml ?
    • Did you specify the full path to the keystore file in server.xml ?

Exercise Four: Grant yourself access to the TDS remote management tool

  1. Using the steps outlined above, create a self-signed certificate and enable SSL in Tomcat.
  2. Modify ${tomcat_home}/conf/tomcat-users.xml to add a new role with the rolename attribute of tdsConfig , and add this role to your list of roles:
  3. <tomcat-users>
        <role rolename="manager"/>
        <role rolename="tdsConfig"/>
        <user username="admin" password="e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4" roles="manager,tdsConfig"/>
    </tomcat-users>
    
  4. Restart Tomcat and try to access the TDS remote management tool: http://localhost:8080/thredds/admin/debug/
  5. SSL warning for self-signed certificate

Configuring web applications for SSL

How did Tomcat know to use SSL for the TDS remote management tool?

Where, in any of the configuration changes you made to ${tomcat_home}/conf/server.xml or ${tomcat_home}/conf/tomcat-users.xml , did you explicitly specify that TDS remote management tool must be accessed via SSL?

The missing piece: /WEB-INF/web.xml

Looking at the TDS deployment descriptor

  1. Have a look at the deployment descriptor that comes with the TDS.
  2. Navigate to the unpacked thredds directory in ${tomcat_home}/webapps , and view the file:

    $ cd /home/tds/tds/apache-tomcat-6.0.32/webapps/thredds
    $ less WEB-INF/web.xml
    
  3. Look for a reference to the TDS remote management tool's URL ( /admin/debug ).
  4. Near the bottom of the deployment descriptor you will find this entry:

      <!-- This allows "remote configuration":
        /thredds/admin/debug gives access to various debug and status info.
        /thredds/admin/content/ -> "{tomcat_home}/content/thredds/"
        /thredds/admin/root/ -> "{tomcat_home}/webapps/thredds/" DISABLED
        /thredds/admin/dataDir/path -> "{dataRoot(path)}/webapps/thredds/"  DISABLED
       -->
      <security-constraint>
        <web-resource-collection>
          <web-resource-name>sensitive read access</web-resource-name>
          <url-pattern>/admin/*</url-pattern>
          <http-method>GET</http-method>
          <!-- http-method>PUT</http-method -->
        </web-resource-collection>
        <auth-constraint>
          <role-name>tdsConfig</role-name>
        </auth-constraint>
        <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
          </user-data-constraint>
      </security-constraint>
    

    Configuration help

    For more information on how to configure security requirements for a web application in a deployment descriptor, see: Defining Security Requirements for Web Applications.

    • The <user-data-constraint> establishes a requirement that the constrained requests be received over a protected transport layer connection. This guarantees how the data will be transported between client and server.
    • <transport-guarantee> choices for type of transport guarantee include NONE , INTEGRAL , and CONFIDENTIAL :
      1. Specify CONFIDENTIAL when the application requires that data be transmitted so as to prevent other entities from observing the contents of the transmission. (E.g., via SSL.)
      2. Specify INTEGRAL when the application requires that the data be sent between client and server in such a way that it cannot be changed in transit.
      3. Specify NONE to indicate that the container must accept the constrained requests on any connection, including an unprotected one.

Enabling SSL for the Tomcat manager application

  1. Modify the deployment descriptor of the Tomcat manager application.
  2. Using your favorite editor, open the deployment descriptor for the Tomcat manager application:

    $ vi /home/tds/tds/apache-tomcat-6.0.32/webapps/manager/WEB-INF/web.xml
    

    Locate the <security-constraint> element (near the bottom of the 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 -->
           <role-name>manager</role-name>
        </auth-constraint>
      </security-constraint>
    

    The comment in the <auth-constraint> element is no longer correct:

    <!-- NOTE: This role is not present in the default users file -->

    (Since we've already added the role of manager to the tomcat-users.xml file, we might as well remove the comment.)

    Add a <user-data-constraint> with a <transport-guarantee> of CONFIDENTIAL to enable port-forwarding to port 8443:

      <!-- 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>
           <role-name>manager</role-name>
        </auth-constraint>
        <user-data-constraint>
         <transport-guarantee>CONFIDENTIAL</transport-guarantee>
         </user-data-constraint>
      </security-constraint>
    
  3. Verify SSL has been enabled for the Tomcat manager application.
  4. Restart Tomcat and verify SSL has been enabled for the Tomcat manager application: http://localhost:8080/manager/html/

    Tomcat manager authentication prompt

    Troubleshooting tips

    • Check the XML syntax in web.xml to make sure it is well-formed and without error.
    • Did you specify a <transport-guarantee> of CONFIDENTIAL ?
    • Did you restart Tomcat after you made your changes to web.xml ?

Exercise Five: Enable SSL for the Tomcat manager application.

  1. Using the steps outlined above, enable SSL for the Tomcat manager application.

Additional Security Configuration

Additional resources

We have compiled a list of a few additional steps you should take to help secure Tomcat and your TDS server. This is not a complete laundry list of security fixes! Please use it as a starting point when securing your server.


THREDDSThis document is maintained by Unidata staff. Please send comments to THREDDS support.