Archive

Posts Tagged ‘tomcat’
  • SSL your Tomcat 7

    One thing I’m doing very often and always searching on the Internet is how to obtain a self-signed SSL certificate and install it in both my client browsers and my local Tomcat.

    Sure enough there are enough resources available online, but since it’s a bore to go looking for the right one (yes, some do not work), I figured let’s do it right once and document it so that it will always be there.

    Create the keystore

    Keystores are, guess what, files where your store your keys. In our case, we need to create one that will be used by both Tomcat and for the certificat generation.

    The command-line is:

    >keytool -genkey -keyalg RSA -alias blog.frankel.ch -keystore keystore.jks -validity 999 -keysize 2048
    

    The parameters are as follow:

    Parameter Value Description
    -genkey   Requests the keytool to generate a key. For all provided features, type keytool -help
    -keyalg RSA Wanted algorithm. The specified algorithm must be made available by one of the registered cryptographic service providers
    -keysize 2048 Key size
    -validity  999 Validity in days
    -alias blog.frankel.ch Entry in the keystore
    -keystore keystore.jks Keystore. If the keystore doesn’t exist yet, it will be created and you’ll be prompted for a new password; otherwise, you’ll prompted for the current store’s password

    Configure Tomcat

    Tomcat’s SSL configuration is done in the ${TOMCAT_HOME}/conf/server.xml file. Locate the following snippet:

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

    Now, uncomment it and add the following attributes:

    • keystoreFile="/path/to/your/keystore.jks"
    • keystorePass="Your password"

    Note: if the store only contains a single entry, fine; otherwise, you’ll need to configure the entry’s name with keyAlias="blog.frankel.ch"

    Starting Tomcat and browsing to https://localhost:8443/ will show you Tomcat’s friendly face. Additionnaly, the logs will display:

    28 june 2011 20:25:14 org.apache.coyote.AbstractProtocolHandler init
    INFO: Initializing ProtocolHandler ["http-bio-8443"]
    

    Export the certificate

    The certificate is created from our previous entry in the keystore.

    The command-line is:

    >keytool -export -alias blog.frankel.ch -file blog.frankel.ch.crt -keystore keystore.jks
    

    Even simpler, we are challenged for the keystore’s password and that’s all. The newly created certificate is now available in the filesystem. We just have to distribute it to all browsers that will connect to Tomcat in order to bypass security warnings (since it’s a self-signed certificate).

    Spread the word

    The last step is to put the self-signed certificate in the list of trusted certificates in Firefox. For a quick and dirty way, import it in your own Firefox (Options -> Advanced -> Show certificates -> Import…) and distribute the %USER_HOME%"/Application Data/Mozilla/Firefox/Profiles/xzy.default/cert8.db file. It has to be copied to the %FIREFOX_HOME%/defaults/profile folder so that every single profile on the target machine is updated. Note that this way of doing will lose previously individually accepted certificates (in short, we’re overwriting the whole certificate database). For a more industrial process, look at the next section.

    To go further:

    Categories: JavaEE Tags: securityssltomcat
  • Tomcat 6 Developer's guide

    This review is about Tomcat 6 Developer’s guide by Damodar Chetty from Packt Publishing.

    Facts

    1. 11 chapters, 395 pages, 44$99
    2. This book covers how Tomcat works: Server,  Service, Connector, Valve, Pipeline, Engine, Host, Context, Wrapper and Manager won't hold any secrets anymore
    3. This book is intended for administrators that want to know how their product work and architects that need to bring additional functionnality into it

    Pros

    1. There's not much details on Tomcat's internals. The documentation on the site is enough for most uses, but sparse if one wants to really dive into the details. This book is a real wealth of information on how Tomcat really works.
    2. Most of Tomcat's oriented books talk about tuning or security. Very few detail how to create new components: this book is one of them
    3. Before each explanation into a configuration element, the book takes the time to remind the pertinent stuff of the Servlet specifications and to link it with the following explanation

    Cons

    1. The information is raw and dense. Since drawings and schemas take another route into our brain, more graphical sources of explanation would have been an asset

    Conclusion

    This book is reference documentation when you need to go beyond adding a data source to your application. If you use Tomcat in production, chances are you need to go further than that, for example to manage sessions in a cluster. In this case, Tomcat 6 developer’s guide will be a real asset.

    Categories: Bookreview Tags: tomcat
  • Clustering Tomcat

    In this article, I will show you how to use Apache/Tomcat in order to set up a load balancer. I know this has been done a zillion time before, but I will use this setup in my next article (teaser, teaser) so at least I will have it documented somewhere.

    Apache Tomcat is the reference JSP/container since its inception. Despite a lack of full JEE support, it certainly has its appeal. The reasons behind using a full-featured commercial JEE application server are not always technical ones. With lightweight frameworks such as Spring being mainstream, it is not unusual to think using Tomcat in a production environment. Some companies did it even before that.

    When thinking production, one usually think reliability and scalability. Luckily, both can be attained with Apache/Tomcat through the set up of a load-balancing cluster. Reliability is thus addressed so that if a Tomcat fails, following requests can be directed to a working Tomcat. Requests are dispatched to each Tomcat according to a predefined strategy. If the need be, more Tomcat can be added at will in order to scale.

    In the following example, I will set up the simplest clustering topology possible: an Apache front-end that balances 2 Tomcat instance on the same physical machine.

    Set up Apache

    The first step is to configure Apache to forward your requests to Tomcat. There are basically 2 options in order to do this (I ruled out the pre-shipped load-balancer webapp):

    • use mod_jk, the classic Apache/Tomcat module
    • use mod_proxy, another Apache module

    I’m not a system engineer, so I can’t decide on facts whether to use one or the other: I will use mod_jk since I’ve already used it before.

    • Download the mod_jk that is adapted to your Apache and Tomcat versions
    • Put it in the ‘modules’ folder of your Apache installation
    • Update your httpd.conf configuration to load it with Apache
    LoadModule jk_module modules/mod_jk-1.2.28-httpd-2.2.3.so
    
    • Configure Apache. Put these directive in the httpd.conf:
    JkWorkersFile	conf/worker.properties
    JkShmFile	logs/mod_jk.shm
    JkLogLevel	info
    JkLogFile logs/mod_jk.log
    JkMount		/servlets-examples/* lb
    

    This configuration example is minimal but needs some comments:

    Parameter Description
    JkWorkersFile Where to look for the module configuration file (see below)
    JkShmFile Where to put the shared memory file
    JkLogLevel Module log level (debug/error/info)
    JkLogFile Log file location. It is the default but declaring it avoid the Apache warning
    JkMount Which url pattern will be forwarded to which worker

    Since mod_jk can be used in non-clustered setups, there could be any JkMount, each forwarding to its own worker (see below). In our case, it means any request beginning with /servlets-examples/ (the trailing slash is needed) will be forwarded to the ‘lb’ worker.

    Configure the workers

    Workers are destination routes as viewed by Apache. They’re are referenced by an unique label in the httpd.conf and parameteirzed under the same label in the worker.properties file.

    My workers.properties is the following:

    worker.list=lb
    worker.worker1.port=8010
    worker.worker1.host=localhost
    worker.worker1.type=ajp13
    worker.worker2.port=8011
    worker.worker2.host=localhost
    worker.worker2.type=ajp13
    worker.lb.type=lb
    worker.lb.balance_workers=worker1,worker2
    

    I define 3 workers in this file: lb, worker1 and worker2. The ‘lb’ worker is the load-balancing worker: it is virtual and it balances the latter two. Both are configured to point to a real Tomcat instance.

    Now, with the Apache configuration in mind, we see that requests beginning with /servlets-examples/ will be managed by the load balancer worker which will in turn forward to a random worker.

    Note: one can also put weight on workers hosted by more powerful machines so that these are more heavily loaded than less powerful ones. In our case, both are hosted on the same machine so it has no importance whatsoever.

    Configure the Tomcat instances

    The last step consist of the configuration of Tomcat instances. In order to do so, I shamelessly copied entire Tomcat installations (I’m on Windows). While editing the server.xml of the Tomcat instances, three points are worth mentioning:

    • The Engine tag has a jvmRoute attribute. It’s value should be the same as the worker’s name used in both httpd.conf and worker.properties. Otherwise, sessions will be recreated for each request
    • Look out for duplicated port numbers if all Tomcat instances are on the same machine. For example, use an incremental rule to configure every stream on a different port
    • Be sure that the tcpListenPort attribute of the Receiver is unique across all Tomcat instances

    Use it!

    With the previous set up, one can now start both Tomcat and Apache, then browse to the servlet-examples webapp, and more precisely to the Session page. Look there for Tomcat 5.5 and there for Tomcat 6. The servlet-example page page displays the associated session ID:

    ID de Session: 324DAD12976045D197435033A67C025D.worker2
    Crée le: Tue Feb 23 23:15:13 CET 2010
    Dernier accès: Tue Feb 23 23:31:47 CET 2010
    

    Notice that on my Tomcat instance, the worker’s name is part of the session ID.

    If everything went fine, two interesting things should take place: first, when refreshing the page, the session ID should not change because of the sticky session (enabled by default). Morevoer, if I shutdown the Tomcat instance associated with the worker (the second in my case), and if I try to refresh the page, I still can access my application, but under a new session.

    Thus, I lose all the information I stored under my session! In my following article, I will study how on can try to remedy to this.

    To go further:

    Categories: JavaEE Tags: clustertomcat
  • Tomcat's Valve, an alternative to Filter

    native-to-filter/tomcat.gif

    In this article, I will show you how to replace filters declared in web.xml with unobtrusive mechanism in Tomcat.

    I’m a big friend of Apache Tomcat. In many cases, even enterprise applications can run with a simple JSP - servlet container and Tomcat has passed through all the evolutions of the standards with flying colors. This is not to say that other containers are bad (Jetty for instance, is very good at being embedded), only that I know enough about Tomcat to know it’s stable and bugfixes are regularly available: a condition for using a product in the enterprise. I am always amazed at why so few Tomcat run in production, compared to big fat application servers. Is it because it is too simple? Yet, it can be very powerful, as I will show with the Valve concept.

    Designers and architects know about the Intercepting Filter pattern: these filters intercept requests and responses and can be chained. The implementation of this pattern is the javax.servlet.Filter interface available since Servlet v2.3. Let’s take an example: suppose you have to get additional informations in a database (suche as name, ect.) when authentifying with a classical JAAS login. Since your application is not responsible for performing the check, it is impossible to get these infos at the right time. It is very simple when using a filter.

    First problem: you do not want your developers to write the database access code with each new application. You create the filter once, put it in the JAR and tell your teams to use this filter in their web.xml once and for all. Now your enterprise evolve and put information relative to people in a LDAP server (not really a bad idea). For newly created applications, you create another filter that access LDAP and use it from now on.

    Second problem: what do you do with your applications that use the legacy filter?

    1. You can run a batch that update the web.xml throughout your entire filesystem. Well, for me, that's too risky... I wouldn't want to get my production down in one big shot! And if the webapps run in non-exploded mode, it is impossible.
    2. You can still use the database and create a batch that synchronize data from the LDAP server to the database. Not risky at all. And 20 years latter, your information system is a big plate of spaghetti because information is duplicated everywhere. Not very urban.
    3. Finally, you can rely on our Tomcat friend from the beginning, remove the filter from applications at all and put a specific filter called a valve in Tomcat itself. A big disadvantage is that you now are coupled to Tomcat. This is not as bad as it sounds since the code is so isolated it can safely be migrated to another application server API real quick.

    I suppose mad dogs would go with option 1 and managers that change every 2 years would go with option 2. Of course, from my clearly subjective presentation of the solutions, you can guess i would go with option 3.

    "Valve is a request processing component associated with a particular Container. A series of Valves are generally associated with each other into a Pipeline."

    From Tomcat's Javadoc

    A valve is designed with a very generic interface org.apache.catalina.Valve. Tomcat also provides an abstract class org.apache.catalina.valves.ValveBase that can be safely extended. The main method of the latter is the invoke() method where you can access both request and response. Don’t forget to call the next valve in it or, like in filters, the chaining will stop.

    From this point, you are free to do as you choose: access the LDAP server, put a cookie, log performances, etc.

    You can find the Maven sources for 2 very simple examples here.

    To go further:

    Please note that the links point to the latest v6.0 version but the concepts exposed above are available in v5.5 and v4.1.

    Categories: JavaEE Tags: filtertomcatvalve
  • Custom LoginModule in Tomcat

    Tomcat manages application security through the concept of realm. A realm is a coherent package of name password pairs that identify valid users for a web application.

    Tomcat’s default realm is MemoryRealm. This realm reads the famous conf/tomcat-users.xml file and uses it check for name password pair validity. Tomcat also provides realms to check against pairs stored in a database, either through a direct connection, or through a configured datasource. The main disadvantage of these all these realms is that they force you to adopt Tomcat’ expected data structure. In most organizations, these constraints will be enough for the architect to rely upon custom or 3rd-party security components.

    In order to use your enterprise database structure, you would code a custom realm. Tomcat provides the org.apache.catalina.Realm interface. The drawback of implementing your own realm is that if you change your application server afterwards, all of your code would have been for naught. Yet, if you check Tomcat documentation thoroughly, you will see Tomcat also provides a JAASRealm. JAAS is the Java security feature and enable you to write custom security modules in a portable way. Tomcat’s JAASRealm performs as a adapter between realms and login modules so you only have to write a LoginModule and Tomcat will know how and when to call it.

    A LoginModule main method is login(). This is an example of a very basic module implementation:

    package ch.frankel.blog.loginmodule;
    
    import java.io.IOException;
    import java.util.Map;
    import javax.security.auth.Subject;
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.NameCallback;
    import javax.security.auth.callback.PasswordCallback;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import javax.security.auth.login.LoginException;
    import javax.security.auth.spi.LoginModule;
    
    /**
     * Login module that simply matches name and password to perform authentication.
     * If successful, set principal to name and credential to "admin".
     *
     * @author Nicolas Fränkel
     * @since 2 avr. 2009
     */
    public class PlainLoginModule implements LoginModule {
    
        /** Callback handler to store between initialization and authentication. */
        private CallbackHandler handler;
    
        /** Subject to store. */
        private Subject subject;
    
        /** Login name. */
        private String login;
    
        /**
         * This implementation always return false.
         *
         * @see javax.security.auth.spi.LoginModule#abort()
         */
        @Override
        public boolean abort() throws LoginException {
            return false;
        }
    
        /**
         * This is where, should the entire authentication process succeeds,
         * principal would be set.
         *
         * @see javax.security.auth.spi.LoginModule#commit()
         */
        @Override
        public boolean commit() throws LoginException {
    
            try {
                PlainUserPrincipal user = new PlainUserPrincipal(login);
                PlainRolePrincipal role = new PlainRolePrincipal("admin");
                subject.getPrincipals().add(user);
                subject.getPrincipals().add(role);
                return true;
            } catch (Exception e) {
                throw new LoginException(e.getMessage());
            }
        }
    
        /**
         * This implementation ignores both state and options.
         * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject,
         *      javax.security.auth.callback.CallbackHandler, java.util.Map,
         *      java.util.Map)
         */
        @Override
        public void initialize(Subject aSubject, CallbackHandler aCallbackHandler, Map aSharedState, Map aOptions) {
            handler = aCallbackHandler;
            subject = aSubject;
        }
    
        /**
         * This method checks whether the name and the password are the same.
         * @see javax.security.auth.spi.LoginModule#login()
         */
        @Override
        public boolean login() throws LoginException {
            Callback[] callbacks = new Callback[2];
            callbacks[0] = new NameCallback("login");
            callbacks[1] = new PasswordCallback("password", true);
            try {
                handler.handle(callbacks);
                String name = ((NameCallback) callbacks[0]).getName();
                String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());
                if (!name.equals(password)) {
                    throw new LoginException("Authentication failed");
                }
                login = name;
                return true;
            } catch (IOException e) {
                throw new LoginException(e.getMessage());
            } catch (UnsupportedCallbackException e) {
                throw new LoginException(e.getMessage());
            }
        }
    
        /**
         * Clears subject from principal and credentials.
         *
         * @see javax.security.auth.spi.LoginModule#logout()
         */
        @Override
        public boolean logout() throws LoginException {
            try {
                PlainUserPrincipal user = new PlainUserPrincipal(login);
                PlainRolePrincipal role = new PlainRolePrincipal("admin");
                subject.getPrincipals().remove(user);
                subject.getPrincipals().remove(role);
                return true;
            } catch (Exception e) {
                throw new LoginException(e.getMessage());
            }
        }
    }
    

    Once your login module is ready, you have to configure Tomcat to use it. JAASRealms, like any other realms can be configured for the whole Tomcat engine, for a specific virtual host or for a single web application. The simplest is to configure the realm for our application. It may happen in the Servers/Tomcat localhost config/server.xml if you work under Eclipse or in you /conf/.xml</code> if you cleanly deploy your web application but the following lines should be added between the Context tags:

    <Realm className="org.apache.catalina.realm.JAASRealm" appName="CustomLogin"
        userClassNames="ch.frankel.blog.loginmodule.PlainUserPrincipal"
        roleClassNames="ch.frankel.blog.loginmodule.PlainRolePrincipal"
    </Realm>
    

    Now that Tomcat knows it should use a JAASRealm, the final step is to configure JAAS itself. The first thing to do is to create a jaas.config file. This file has a very specific structure. Let’s take a look:

    CustomLogin {
        ch.frankel.blog.loginmodule.PlainLoginModule
        sufficient;
    };
    

    The first line references the login module class and corresponds to appName in the server.xml. The second line tells JAAS how to use this module. There are 4 acceptable values:

    Required
    This module must authenticate the user. But if it fails, the authentication nonetheless continues with the other login modules in the list.
    Requisite
    If the login fails then the control returns back to the application, and no other login modules will execute.
    Sufficient
    If the login succeeds then the overall login succeeds, and control returns to the application. If the login fails then it continues to execute the other login modules in the list.
    Optional
    The authentication process continues down the list of login modules irrespective of the success of this module.
    Now, you have to reference this file. Just launch Tomcat with this VM property: -Djava.security.auth.login.config=<JAAS_CONFIG>. From this point, if you correctly configure declarative security in you web application web.xml, it will use your login module. Of course, in a real-world case, you would check against a database, a LDAP server or a web-service to authentify your users but this small example provide you with the base to create such a complex code. Sources for this very basic example can be found here.
    Categories: JavaEE Tags: jaasloginmodulerealmsecuritytomcat