tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Glenn Nielsen <>
Subject Re: Tomcat 4.1-dev web application management current design &proposal for improvements
Date Mon, 04 Mar 2002 02:19:28 GMT
Thanks for the comments Craig.  

Before I continue further it might help if I put my proposal in context 
by showing how customers are being virtual hosted.

The goal is to have each customer in their own sandbox so that nothing
the customer does can compromise the security of the server, nor compromise
another customer's security.  In addition, we need to empower the customers
as much as possible so that they can administer their web site and applications
without system administrators having to babysit the server or its configuration.  

>From our sys admin point of view, these customers for which we host 
websites and applications are untrusted users.


There is an apache server which hosts 1..N customer webistes.
Apache uses mod_jk and Ajp13 to pass requests to Tocmat as needed,
the webapps directory below is mapped into the apache document space
using an Alias.

Each customer has their own directory which they have FTP access to.
But the customers are in a sandbox, they can't see other customer website
data using FTP.  Customers do not have shell accounts, their only access
for modifying files below is via FTP or using the Tomcat manager for
web application management.  Customers are not allowed to use CGI, PHP, etc.
but SSI is enabled.

Here is the directory structure and the file r/w access allowed.

www (r/w)       - Apache document root
logs (r)        - Apache access and error logs, plus other data we export to customer
webapps (r/w)   - appBase for Tomcat Host
tomcat/logs (r) - directory for Tomcat Host and Context logs
tomcat/work (r) - Tomcat work directory for Host, so they can see java source for compiled
JSP pages


There are 1..N servers hosting Tomcat for customer virtual hosts.
The server running Tomcat has the /export/home/web directory on
the Apache server NFS mounted so Tomcat can access each virtual
hosts webapps directory, work, and logs directory.

Customers have no access at all to the server running Tomcat except
via the Tomcat manager and thier web applications.  Tomcat is running 
with the SecurityManager enabled with a very strict security policy.

Here is an example customer Tomcat Host configuration.

      <Host name="" debug="0"
            autoDeploy="true" unpackWARs="true">

        <Realm  className="org.apache.catalina.realm.JDBCRealm" debug="0"
                connectionName="customer1wac" connectionPassword="password"
                userTable="users" userNameCol="user_name" userCredCol="user_pass"
                userRoleTable="user_roles" roleNameCol="role_name" digest="MD5" />

        <Logger className="org.apache.catalina.logger.FileLogger"
                prefix="tomcat_log-" suffix=".txt"

        <DefaultContext debug="0" reloadable="false">
          <!-- JND DataSource for sending email -->
          <Resource name="mail/send" auth="CONTAINER"
          <ResourceParams name="mail/send">
          <!-- JNDI JDBC DataSource Resource for using MySQL dB -->
          <Resource name="jdbc/data" auth="CONTAINER"
          <ResourceParams name="jdbc/data">

        <!-- Tomcat manager application, can be IP restricted if customer desires -->
        <Context path="/manager"
                 debug="0" privileged="true">
          <!-- Uncomment and add IP addresses if customer requests IP restrictions
          <Valve className="org.apache.catalina.valves.RemoteAddrValve"
                 allow=""/> -->


There is a dB server which provides databases for customer Realm based
authentication and customer data.  Each customer has their own db and
are in thier own dB sandbox.  They do have remote access to administer
their database which can be IP restricted if the customer desires.


The changes I would like to see for how Tomcat manages applications and
how the manager works is all based on requirements for virtual hosting
untrusted customers.  These customers need the ability to put new apps
into production, remove apps permanently, update them, and update indiviual
JSP files using FTP if needed.  Yet, not allow them out of their sandbox
and keep from having sys admins constantly fixing things or changing configs.

This is a long term goal that is getting very close to realization.  The 
last two pieces of the puzzle are web application management and the new 
SecurityManager design I proposed a few weeks ago.

And I am willing to do alot or all of the work required to make these changes.
It's my itch, so they say.

Followup comments intermixed below with yours.

"Craig R. McClanahan" wrote:
> See intermixed.
> On Sat, 2 Mar 2002, Glenn Nielsen wrote:
> > Date: Sat, 02 Mar 2002 10:06:59 -0600
> > From: Glenn Nielsen <>
> > Reply-To: Tomcat Developers List <>
> > To:
> > Subject: Tomcat 4.1-dev web application management current design &
> >     proposal for  improvements
> >
> >   Tomcat 4.1-dev HEAD web app management current design and proposal for
> > improvements
> >
> > Current Behaviour
> > =================
> >
> > Here is a stab at documenting how the Tomcat 4.1 dev HEAD CVS branch
> > manages web applications based on reviewing user documentation, code,
> > and testing.  Please review and add corrections if needed.
> >
> > Tomcat Startup
> > --------------
> >
> > Context's configured in server.xml deployed.
> >
> For people who haven't found it yet, this functionality is in
> org.apache.catalina.startup.HostConfig.
> > if( autoDeploy == true )
> >
> >   Deploys Context configurations found in appBase/*.xml.
> >     calls host.install() with a file URL to Context xml config file.
> >     The Context *.xml file can specify any directory on the server
> >     as the docBase and it will be instantiated as a Context, as long
> >     as the SecurityManager doesn't prevent access.
> >
> >   Deploys *.war files found in appBase/*.xml
> >     if( unpackWARs == true )
> >        calls host.install() with a file: URL after expanding the war file.
> >     if( unpackWARs == false )
> >         calls host.install() with a jar:file: URL to war.
> >
> >   Deploys directories found in appBase.
> >     calls host.install() with a file URL to directory.
> >
> > Tomcat runtime AutoDeploy
> > -------------------------
> >
> > A background thread is started.
> >
> > if( autoDeploy == true )
> >    the actions above for autoDeploy are taken each 15 seconds.
> >
> > Contexts are checked for a modified web.xml, if detected the
> > Context is stopped then started again.
> >
> > Tomcat Manager
> > --------------
> >
> > - deploy ** Not available via HTMLManagerServlet
> >
> I don't personally believe in HTMLManagerServlet.  Manager was designed to
> be scriptable by tools, and an HTML UI for managing Tomcat needs to do a
> lot more than just this, like the admin tool will do.

I agree. The best approach would be to make any necessary changes to
Tomcat first, then the manager servlet and ant task, then finally
a rewritten HTMLManagerServlet.

> > Installs a web application using a war file sent via an HTTP PUT.
> > The deployed application does not persist if Tomcat is restarted.
> >
> Ultimately, persistence should be handled by mechanisms to update
> server.xml -- but this is really an all-or-nothing thing.
> Currently, deploy doesn't support sending a context configuration XML file
> along with the WAR -- it will need this for webapps that have JNDI
> resource references that need to be configured (either as absolute values
> or as links to global JNDI resources>, or custom logger/manager
> configurations, or ....

For my purposes as you can tell from the example Tomcat Host config,
I will use a standard host config that creates the sandbox they use
to deploy their applications in.  We will not let the customer configure
anything within their Host or Context.

I'm sure use of Context xml config snippets are of benefit to many,
but these are not a high priority for me.  Whatever you and others
thinks is best is fine with me, as long as I can disable it.

> > - install
> >
> > Installs a web application using a remote Context config xml
> > file and a war file or directory located on the server.
> > You can specifiy any file URL as long as the SecurityManager
> > doesn't prevent access. Such as "file:/". And the Context config
> > xml file can specify any docBase.  The installed application does
> > not persist if Tomcat is restarted unless the directory or war
> > file existed in the Host's appBase.
> >
> You can install a config file, a WAR (or unpacked directory), or both.  In
> the latter case, the "docBase" provided in the config file is ignored.  (I
> would expect we'd implement this the same way when deploy knows how to do
> a multipart upload.

Yeah, maybe once we have that code setup in jakarta-commons-sandbox for
multipart mime uploads. So many good ideas, so little time.  Sigh...

> Note that install works only if Tomcat is on the same machine, whereas
> deploy can be executed remotely.  On the other hand, it's faster because
> the WAR does not need to be copied.
> Persistence issues here are similar to that for deploy.
> > - start
> >
> > Starts the Context if it exists and is currently stopped.
> >
> > - reload
> >
> > Reloads Context if it is a directory, does not reload if
> > it is running from a war file. A reload does not reload
> > the web applications web.xml. So if you make configuration
> > changes to the web.xml file you need to do a stop/start.
> >
> I'm not sure that stop/start actually does the right thing currently
> (haven't ever looked at that scenario), because it doesn't remove anything
> that was configured by the "old" web.xml file.

Ok, I guess this needs further investigation.

> > - stop
> >
> > Stops the Context if it exists
> >
> > - remove
> >
> > Removes the Context from a running instance of Tomcat and
> > stops it.  Does not remove any files.
> >
> > - undeploy ** Not available via HTMLManagerServlet
> >
> > Removes Context from host, delete's app directory or war file.
> > Does not delete work dir.
> >
> Deleting the work dir is something to think about.  It takes time, but
> guarantees the app a clean slate if it is redeployed.

There has to be a mechanism to say this web app needs to be permanently
removed from the server.  This has to include the workDir.  What if the
customer then deployed a completely different application with the same
context path but the old workDir still existed?   And by the Servlet spec, 
the workDir isn't even guaranteed to survive servlet container restarts.  
The only manager task at this moment which can do that is undeploy.

> > - list
> >
> > Lists information on existing contexts.
> >
> > - sessions
> >
> > Lists information on the number of sessions for Context
> >
> > Tomcat Shutdown
> > ---------------
> >
> > Each Context is removed using Host.remove(contextpath).
> > This removes the Context object from the Host container
> > and performs a Context stop().
> >
> Therefore, anything we change in the remove command (such as possibly
> removing the work dir here as well) would also be done at Tomcat shutdown
> unless we special case it.  In particular, this would interfere with one
> Tomcat feature that is popular among some groups of developers - saving
> the current sessions and reloading them at the next startup (which also
> works across the reload command above).

Yes, this is a special case, the workDir should only be removed when 
undeploying an application or updating an application (if update gets added).  
I wouldn't want Tomcat to have to recompile JSP pages that were previously 
compiled just because Tomcat was restarted, or lose Session data.

> >
> > *********************************************************************
> >
> >
> >
> > Here is a proposal for improving how Tomcat manages web applications.
> > My goals in creating this were to address security concerns and to
> > improve the ability for virtual hosted customers to manager their
> > own applications. Please review.
> >
> > core/
> > ======================
> >
> > Suggestions for improvement
> > ---------------------------
> >
> > The install and deploy manager tasks along with the autoDeploy
> > of a Context *.xml in a Host's appBase make it possible for
> > someone who has access to the manager or write file access to
> > the appBase directory on the server to specify a docBase any
> > where on the server Tomcat is running on.  When virtual hosting
> > customers sites this is a big security problem.
> >
> > Restrict instantiation of Contexts to a directory or war
> > file located in the Host's appBase. If this is too restrictive
> > for some, then add a Host attribute of globalDeploy=(true|false)
> > with a default of false.  If globalDeploy is true an application
> > can be deployed using a file or war from outside of the Host's
> > appBase.
> >
> For deploy, we've got total control over where the WAR is placed.
> If/when the ability to deploy a config file as well is supported (Glenn,
> how do you currently deal with vhost customers that need JNDI resources?),
> we can do the same thing about ignoring the docBase in the config file,
> and controlling where the config file and the corresponding WAR or
> directory is placed.

Good.  :-)

> For install, restricting the directory to be under appBase would interfere
> with the ability to do webapp development local to my user home directory
> (by installing the app, doing edits in place, reloading as necesary).  It
> would also remove a capability that many production applications rely on,
> to *not* require all webapps to be installed in a common subdirectory.

Per my VH config setup above, we use multiple webapps directories by setting
the Host appBase.

> You also could not implement the "user home directories" feature like
> Apache does (http://localhost:8080/~craigmcc), which is currently
> supported.
> One alternative might be to parameterize Manager to turn off support for
> install completely.  After all, you can accomplish what you want by
> setting autoDeploy to true and then just dropping the WAR or directory
> into the "appBase" directory for that host.

On a production system used for virtual hosting I prefer having liveDeploy==false.
I don't want the overhead of a thread that runs every 15 seconds scanning all
the webapps directories and using synchronized methods. I want the customer to 
explicetly deploy/undeploy apps.

That is if the customer has access to write files to their webapps directory. 
When the manager can support complete remote adminstration, we may decide to
not allow our customers access to their webapps directory at all.  Force them
to use a web based mangement tool solely.

> > startup/
> > =======================
> >
> > Here are some inconsistencies in the HostConfig
> > -----------------------------------------------
> >
> > A background thread is always started.  From the comments
> > for the thread methods it isn't clear what it does.
> >
> > In some places the comments talk about session timeouts,
> > in other places checking for modified classes, and in other places
> > it mentions checking for shutdown, and the checkInterval variable
> > says check periodically for web app deployment.
> >
> > Looking at the code, this is what it does.
> >
> > Every 15 seconds it wakes up.
> >
> >   if autoDeploy=true, it checks for new web apps to deploy.
> >
> >   Then it checks each context to see if the web.xml has changed.
> >   If it has changed it does a stop, then start of the Context.
> >
> > Suggested improvements
> > ----------------------
> >
> > Cleanup the misleading comments.
> >
> > There is only one flag used for determining if you want
> > autoDeploy which applies both at startup and runtime interval
> > deployment.
> >
> > These two should be separate.  It is very likely that you would
> > want autoDeploy at Tomcat startup, but not checks at 15 second
> > intervals. Remove the autoDeploy attribute and add the following:
> >
> > startupAutoDeploy=(true|false) default = true
> > intervalAutoDeploy=(true|false) default = false
> >
> Agree with two flags.  However, I'd rather leave one of them named
> "autoDeploy" so we don't break all current server.xml files.  Maybe:
>     startupAutoDeploy --> autoDeploy
>     intervalAutoDeploy --> liveDeploy
> or something like that?  Defaults would be true for both to mimic current
> behavior.

Good suggestion.

> > The checks for a modified web.xml which stop then start a Context
> > should only be done if intervalAutoDeploy=true. I haven't found any
> > user documentation about Context start/stop if the web.xml is modified,
> > document this feature.
> >
> Per above, I don't think it works correctly, either.
> > Only start the background thread if intervalAutoDeploy=true.
> >
> Yep.


> > Deploying applications using a Context *.xml file located in the
> > Host's appBase or via the manager servlet is a security problem.
> > Instantiation of a new Context runs with the SecurityManager permissions
> > granted to catalina.  This allows anyone with write access to the
> > appBase directory for a Host or access to the manager servlet to configure
> > directories and war files anywhere catalina has file read permission.
> > This affects the docBase, workDir, and loggers.
> >
> > Add an attribute to disable it:
> >
> > deployXML=(true|false) default=false
> >
> I'm ok with an option, but suggest the default is true.  When you are not
> in a "hosting customers" environment, it is very valuable to be able to
> configure anything you can put in a <Context> element, without having to
> mess with server.xml and restarting Tomcat to d it.

I can live with that. :-)

> >
> > servlets/
> > ============================
> >
> > Questions
> > ---------
> >
> > The install task used to support any URL, now it only
> > supports URL's for local files on the server.  But
> > HTTP PUT was implemented for the deploy task. Was this
> > changed to get around the JVM bug related remote access
> > to and reading of a JAR (zip)? I checked the CVS log
> > for the ManagerServlet and it wasn't mentioned.
> >
> I could never get jar:http:..... URLs to work right, so it didn't seem
> reasonable to allow the user to try and get frustrated.  In addition, the
> advent of the deploy command provided a better way to deal with remote
> JARs (and the performance of the installed webapp will be better as well,
> because the WAR is uploaded).

I agree, just wanted to verify the reasoning.

> > Suggested improvements
> > ----------------------
> >
> > - deploy
> >
> > Currently war files deployed do not persist past a Tomcat restart.
> > That makes this pretty useless for someone to use for managing their
> > applications on a production system.
> >
> This is true for install as well, unless you happen to have installed an
> app in the appBase directory and autoDeploy is true.  It's also a bigger
> issue than just new apps being deployed, since the admin app will let you
> adjust basically every property on every component of a running Tomcat
> server, and you want to be able to save all of that as well.

Whatever you think is best.  I may use the admin app, but we won't allow
our customers access to it.  They may use it on their local systems when
doing application development.

> I've got some ideas for how to deal with this globally that are not ready
> for prime time yet, but I'd prefer *not* to try to deal with just part of
> the problem.
> > If the Host unpackWARs==true
> >   Install the war file in the Host's appBase as {context-path}.war.
> >   (The war is required to exist in order to perform the new update task)
> >   Expand the war file into a directory named {context-path} in the
> >   Host's appBase.  If the directory or war file already exist in the
> >   Host's appBase, the deploy should fail.
> >
> I'm ok with respecting unpackWARs on a deploy (but not on an install --
> because install already gives you the choice of installing a directory or
> a WAR, but deploy doesn't).

I can live with that.  As long as I can restrict install to only allow
directories or war files which exist in the Host's appBase.

> Where to put the WAR or directory is an issue that is affected by the
> persistence of the entire Tomcat configuration, so it should be dealt with
> holistically.

>From a vh perspective, it gets put in whatever their Host has defined as an

> > If the Host unpackWARs==false
> >   Install the war file in the Host's appBase as {context-path}.war.
> >   If the war exists in the Host's appBase, the deploy should fail.
> >
> > - install
> >
> > Change the name to "add", install implies you are putting
> > something on the server.  And "add" is the counterpart to remove.
> > So "add" would add a Context configuration, "remove" removes a Context
> > configuration.
> >
> I do not like gratuitously breaking backwards compatibility.

I'm ok with leaving it alone.

> > Make it easier to specify a war or directory within the Host's
> > appBase.  If the URL is not a file URL create a file URL relative to
> > the Host's appBase.
> >
> I don't get why you need to use *any* manager command if this is what you
> want?  Just drop in the WAR or directory, turn on intervalAutoDeploy (or
> whatever it is called), and the app is "installed".

This is just a convenience item in case you want liveDeploy disabled on
a production system.  Keeps the customer from having to know and type in
the complete path.  If you are really dead set against it, its ok.
Just let me know.

> > - start
> >
> StandardContext.start(), among other things, processes the web.xml file.
> But, I don't think we're currently cleaning out the
> servlets/filters/listeners/etc. set up previously, so that needs to be
> added in order to make "stop/start" do the expected thing.

As mentioned above, needs further code review.

> > - reload
> If we make stop/start work correctly, it might be worth re-implementing
> reload in terms of that instead of the special case it currently is.  On
> the down side, this would make reloads slower if all you did was recompile
> a bean class.

Reload can be problematic in a number of ways.  What happens to session data?
What if classes serialized out to disk change?  What if the web.xml has filters
or listeners configured.  Perhaps a stop/start is the safest solution.  Less
prone to problems, easier to document.  With the warning to users about changes
to classes which get stored as Session data breaking those sessions.

> >
> > - update
> >
> > Add a new task called update.  Requires a context path for an
> > existing Context and performs an HTTP PUT of a new war file.
> >
> > Some applications need to exist in a context directory because they
> > need to manage data files stored within the context directory.  An
> > update allows for the web application resources to be updated without
> > removing any existing data generated by an application.
> >
> IMHO, this is a poor architecture choice for deployed production
> applications ... but lots of people do it.

There isn't any other choice for a self contained application.  You can't
use the workDir (tempdir) because by the spec it doesn't have to survive
a restart.  So you aren't left with any other choice but the webapps
own directory.  Perhaps this is something that could be looked at for the 
next Servlet spec, a standard place for application generated data to live.

> > if the Host unpackWARs==false
> >   Stop the Context, remove the War file, remove the Context workDir.
> >   Install the new war in the Host's appBase and start the context.
> >   Kind of a one step undeploy/deploy.
> >
> > if the Host unpackWARs==true
> >   If the context doesn't exist, fail.  If the context directory or
> >   the war file doesn't exist, fail.
> >
> >   Stop the Context. Remove any files in the Context directory which
> >   exist in the old war file.  Remove the old war file. Remove the
> >   Context workDir.
> >
> >   Install the war file in the Host's appBase as {context-path}.war.
> >   (The war is required to exist in order to perform the new update task)
> >   Expand the war file into a directory named {context-path} in the
> >   Host's appBase.
> >
> You might be better off with a "patch" command that accepts a JAR (instead
> of a WAR -- so you can only replace what you want to and don't need a
> complete webapp) that does:  stop, replace/add files from the JAR, start.

We are encouraging customers to use a local version of Tomcat to develop
and test applications so that they don't do this on the production system.
>From my perspective its easier to create a war of the app from your local
system and deploy that than try to create a jar with just those things
that changed.

Perhaps both an update and a patch. I can see where a patch would be
nice if the application war was very large.

> Removing the work dir means you give up saving sessions across this
> operation, which is not always what you want -- it should be optional (or
> we need to change where SESSIONS.ser is kept so that it's not affected).

I would be fine with removing everything from the Context's workDir except
for SESSIONS.ser on an update or patch.  The same caveat from above applies, 
if they changed any classes that get serialized as session data, it breaks 
the session.

> > - stop
> >
> > - remove
> >
> > - undeploy
> >
> > Delete workDir in addition to deleting Context directory or
> > war file when undeploying a Context. Per the Servlet spec
> > the workDir isn't required to be maintained across container
> > restarts, so there should be no problem removing it when an
> > application is undeployed.
> >
> As mentioned above, this would currently disable the "save sessions across
> restart" feature, but that can be dealt with in a different way.

There needs to be a way to permanently remove an application from
the server.  The only task I see being able to do that is undeploy.
If the customer doesn't want to completely remove the app they can
use stop or remove.

> > - list
> >
> > - sessions
> >
> > Add the ability to track session creation by the request URI
> > which created the session.  I haven't looked into how hard this
> > would be to implement.  A web application which handles alot of
> > unique visitors can end up creating 1000's of sessions.  This eats
> > up JVM memory and affects performance. The default behaviour of a
> > JSP page is to create a session. Listing what request URI
> > created a Session and how many will make it much easier to find
> > and fix those JSP pages, etc. which are creating unnecessary sessions.
> >
> The simplest technique for this would be to write a Filter that overrides
> the getSession() method and keeps track of when a new session is actually
> created (session.isNew()).  Such a filter could be non-invasively added to
> any webapp (on any 2.3 based container) without having to be a Tomcat
> feature.
> Inside Tomcat, the current APIs don't really lend themselves to tracking
> this -- the Manager.createSession() method doesn't accept any argument to
> specify the related request (indeed, Tomcat doesn't care if you create a
> session *outside* the context of a particular request), so you'd have to
> go track down the places that this is called and instrument them.  But, if
> you wanted, you could create a Valve that did the same thing inside Tomcat
> that the Filter suggested above does at the application level.

Thanks for the suggestions, I'll look into it further.

> > servlets/
> > ================================
> >
> > Suggested improvements
> > ----------------------
> >
> > Add the deploy task.
> >
> > Add the undeploy task. This should include a confirmation page
> > before actually undeploying the context path.
> >
> > Add the update task.  This should include a confirmation page
> > before actually performing the web application update.
> >
> > Increase the font size for the context information, using Netscape 4.7
> > I can barely read it.
> >
> Or just get rid of the thing ...

Or completely rewrite it.

> > ant/
> > ===================
> >
> > Create a new ant task for performing updates.
> >
> or patch ...

or both.

> > *********************************************************************
> >

Thanks for all the good feedback.  I will put up a revised proposal
once I get your follow up and any other comments.



Glenn Nielsen    | /* Spelin donut madder    |
MOREnet System Programming               |  * if iz ina coment.      |
Missouri Research and Education Network  |  */                       |

To unsubscribe, e-mail:   <>
For additional commands, e-mail: <>

View raw message