TDS Tutorial: Basic Tomcat and TDS Security

Tomcat (Server-Level) Configuration Files

About server.xml

Keep in mind

Tomcat's configuration files, including server.xml can be found in: $TOMCAT_HOME/conf

Important elements in server.xml

  1. Examine the Elements in server.xml.
  2. Move into the Tomcat conf/ directory and examine the server.xml file:

    $ cd $TOMCAT_HOME/conf
    $ less server.xml
    

    Reference the table below to see how the server.xml elements relate to configuring TDS (mouse-over the element for a description):

    Tag Name Instances How it relates to the TDS
    <Server>Description: The Server element represents the entire Catalina servlet container as a whole. It is the single outermost element in server.xml 1...1 Not modified unless you want to change the port number Tomcat listens for a SHUTDOWN command. (Enabled by default.)
    <GlobalNamingResources>Description: The GlobalNamingResources element defines the global Java Naming and Directory Interface (JNDI) resources for the Server. 0...* Needed to contain the UserDatabase that corresponds to the UserDatabaseRealm used to authenticate users. (Enabled by default.)
    <Resource>Description: The Resource element represents a static resource from which classes will be loaded and static files will be served. 0...* Editable user database (tomcat-users.xml) used by UserDatabaseRealm to authenticate users. (UserDatabaseRealm Resource Enabled by default.)
    <Service>Description: The Service element represents the combination of one or more Connector components that share a single Engine component for processing incoming requests. The top Tomcat service is named Catalina (hence the log file name of catalina.out). 1...* Not modified unless you wish to establish more than one service. (Catalina Service enabled by default.)
    <Connector>Description: The Connector element forward requests to the Engine using a specific protocol and returns the results to the requesting client. 1...* Used to establish HTTP and SSL connections. Also will communicate with an web server for proxying requests. (HTTP connector enabled by default on port 8080.)
    <Engine>Description: The Engine element represents the entire request processing machinery associated with a particular Catalina Service. 1...1 Not modified unless you specify a Host other than localhost. (Enabled by default.)
    <Realm>Description: The Realm element represents a "database" of usernames, passwords, and roles (groups) assigned to those users. 0...* The UserDatabaseRealm uses the UserDatabase configured in the global JNDI Resource. (UserDatabaseRealm enabled by default.)
    <Valve>Description: The Valve element represents a component that will be inserted into the request processing pipeline for the associated containing element. 0...* The RemoteAddrValve is used to filter access to the TDS based on IP address. (NOT enabled by default. You will need to add this if you want to use IP Filtering.)
    <Host>Description: The Host element represents a virtual host. 1...* Not modified unless you specify a Host other than localhost. (localhost enabled by default.)
    <Realm>Description: The Realm element represents a "database" of usernames, passwords, and roles (groups) assigned to those users. 0...* We use the MemoryRealm to configuring Tomcat to use digested passwords. (NOT enabled by default. You will need to add this if you want to use digested passwords.)
    <Valve>Description: The Valve element represents a component that will be inserted into the request processing pipeline for the associated containing element. 0...* We modify the AccessLogValve to customize the access logs generated by Tomcat. (NOT enabled by default. You will need to add this if you want to enable access logging.)

About tomcat-users.xml

Important elements in tomcat-users.xml

  1. Examine the Elements in tomcat-users.xml.
  2. Open the $TOMCAT_HOME/conf/tomcat-users.xml file:

    $ less $TOMCAT_HOME/conf/tomcat-users.xml
    

    Reference the table below to see how the tomcat-users.xml elements relate to configuring TDS (mouse-over the element for a description):

    Tag Name Instances How it relates to the TDS
    <tomcat-users>Description: The tomcat-users element represents the single outermost element in tomcat-users.xml 1...1 Not modified. (The only tag you get by default.)
    <role>Description: The role element defines one role or group a user can belong to. 1...* You will have at least two of these: one for the Tomcat manager application and one for the TDS. (You will need to add if you want to enable role-based authentication.)
    <user>Description: The user element represents one valid user. 1...* You will need to create an entry for each user who needs access to the Tomcat manager application and/or the restricted areas of the TDS. (You will need to add if you want to enable user authentication.)

Tomcat manager Application

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

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 $TOMCAT_HOME/conf should we edit to grant ourselves access to the manager application?

Granting access to the manager application

  1. Modify tomcat-users.xml to add role and user elements.
  2. Using your favorite editor, open $TOMCAT_HOME/conf/tomcat-users.xml:

    $ vi tomcat-users.xml
    

    Between the <tomcat-users> tags, add a role element and specify the rolename attribute as manager:

    <tomcat-users>
        <role rolename="manager"/>
    </tomcat-users>
    

    Now add a new user by adding a user element. Create a username and password for the new user and specify manager 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"/>
        <user name="admin" password="secret" roles="manager"/>   
    </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 $TOMCAT_HOME/logs/catalina.out.

Exercise One: Grant yourself access to the Tomcat manager application

  1. Using the steps outlined above, modify $TOMCAT_HOME/conf/tomcat-users.xml to grant yourself access to the Tomcat manager application.

Deploying the TDS using the manager application

  1. Use the manager application to undeploy the TDS.
  2. Find the TDS in the list of web application on the Applications page. Stop and then Undeploy the TDS:

    Undeploy the TDS

    List the contents of $TOMCAT_HOME/webapps/ to verify that both thredds.war and the unpacked thredds/ directory have been removed:

    $ cd $TOMCAT_HOME/webapps
    $ ls -l
    total 10284
    drwxr-xr-x 11 thredds workshop     4096 2009-05-13 17:15 docs
    drwxr-xr-x  5 thredds workshop     4096 2009-05-13 17:15 examples
    drwxr-xr-x  5 thredds workshop     4096 2009-05-13 17:15 host-manager
    drwxr-xr-x  5 thredds workshop     4096 2009-05-13 17:15 manager
    drwxr-xr-x  3 thredds workshop     4096 2009-05-13 17:15 ROOT
    
  3. Deploy the TDS using the manager application.
  4. Upload the TDS WAR file using the Deploy section of the manager application:

    Deploy the TDS

    Confirm the deployment went as planned by accessing the TDS using your browser: http://localhost:8080/thredds/

Exercise Two: Deploy the THREDDS Data Server using the manager application

  1. Using the steps outlined above, deploy the TDS using the manager application.

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

Due diligence

For added incentive to use encrypted passwords, read about the man-in-the-middle attack.

Configure Tomcat to use digested passwords

  1. First we need to enable digest passwords support in Tomcat by modifying server.xml.
  2. Open $TOMCAT_HOME/conf/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 flowing 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/thredds/apache-tomcat-6.0.20/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"/>
        <user name="admin" password="e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4" roles="manager"/>
    </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 $TOMCAT_HOME/logs/catalina.out.
    • 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 Three: 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. Create a self-signed certificate and store it in $TOMCAT_HOME/conf/keystore.
  2. Run the $JAVA_HOME/bin/keytool command:

    $ cd /home/thredds/jdk1.6.0_15/bin
    $ ./keytool -genkey -alias tomcat -keyalg RSA -keystore /home/thredds/apache-tomcat-6.0.20/conf/keystore
    

    Meaning of the keytool options:

    Command Purpose
    $JAVA_HOME/bin/keytool Java provides a tool, called keytool, that generates a self-signed certificate and puts in a keystore file.
    -genkey The -genkey option specifies that a key pair (private key and public key) needs to be created. This key pair will be enclosed in the self-signed certificate.
    -alias tomcat The -alias tomcat option creates an entry in the keystore file identified by the alias "tomcat" (which Tomcat will use to find your entry).
    -keyalg RSA The -keyalg RSA option specifies the algorithm (in this case is RSA) to be used for the creation the key pair.
    -keystore $TOMCAT_HOME/conf/keystore -keystore $TOMCAT_HOME/conf/keystore is location of where want to put our keystore. Otherwise, the default keystore is $user_home/.keystore.

    Create the self-signed certificate identity. While you are filling out the identity fields for your certificate, keep in mind:

    • Although it is not obvious, the first and last name, or CN, should be the host name
    • The keystore password (the first password you are prompted to enter) is always changeit
    • The last password (the key password) and keystore password need to be the same (changeit).
    Enter keystore password: changeit
    Re-enter new password: changeit
    What is your first and last name?
      [Unknown]:  localhost
    What is the name of your organizational unit?
      [Unknown]: THREDDS
    What is the name of your organization?
      [Unknown]:  Unidata
    What is the name of your City or Locality?
      [Unknown]:  Boulder
    What is the name of your State or Province?
      [Unknown]:  Colorado
    What is the two-letter country code for this unit?
      [Unknown]:  US
    Is CN=localhost, OU=THREDDS, O=Unidata, L=Boulder, ST=Colorado, C=US correct?
      [no]:  y
    
    Enter key password for 
            (RETURN if same as keystore password): 
    

    Verify the new keystore file has been generated in $TOMCAT_HOME/conf:

    $ cd /home/thredds/apache-tomcat-6.0.20/conf
    thredds@workshop03 conf]$ ls -l
    total 100
    drwxr-xr-x 3 thredds workshop  4096 2009-08-03 16:08 Catalina
    -rw------- 1 thredds workshop  8690 2009-05-13 17:15 catalina.policy
    -rw------- 1 thredds workshop  3665 2009-05-13 17:15 catalina.properties
    -rw------- 1 thredds workshop  1396 2009-05-13 17:15 context.xml
    -rw-r--r-- 1 thredds workshop  1360 2009-08-03 16:42 keystore
    -rw------- 1 thredds workshop  3257 2009-05-13 17:15 logging.properties
    -rw------- 1 thredds workshop  6576 2009-08-03 16:36 server.xml
    -rw------- 1 thredds workshop  1231 2009-08-03 16:37 tomcat-users.xml
    -rw------- 1 thredds workshop 50757 2009-05-13 17:15 web.xml
    
  3. Configure Tomcat to enable SSL and use the self-signed certificate.
  4. 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/thredds/apache-tomcat-6.0.20/conf/keystore" />
    

    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" />
    
  5. Verify SSL has been enabled.
  6. 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 name="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

  • This is specified in the web application deployment descriptor, aka web.xml.
  • Deployment descriptors are found in the WEB-INF directory of the web application: <application name>/WEB-INF/web.xml.
  • By convention, Tomcat and other servlet containers will read the web application deployment descriptors for initialization parameters and container-managed security constraints upon application deployment.
  • The TDS has been pre-configured to require that SSL encryption is enabled in order to access the remote management tool.

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/thredds/apache-tomcat-6.0.20/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/thredds/apache-tomcat-6.0.20/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 step 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.

THREDDS This document is maintained by Unidata. Send comments to THREDDS support.