Viewing Category: Mach-II  [clear category selection]

Mach-II Environment and CGI.SERVER_NAME

I'm running an instance of ColdFusion in a container that doesn't provide the original request hostname in the CGI.SERVER_NAME variable. That's a problem because I'm also using the Mach-II EnvironmentProperty, which rocks pretty hard, to match environment properties to the name of the server running the application. In my case, the server name is set in an HTTP header from the upstream Nginx server. So, what to do?

First, I created a drop dead simple component called EnvironmentHelperProperty that looks like this:

<cfcomponent extends="MachII.framework.Property" output="false">   <cffunction name="configure" returntype="void" access="public" output="false">     <cfset var serverPropertyName = getParameter("serverPropertyName", "serverName")/>     <cfset setProperty(serverPropertyName, getHttpRequestData().headers["X-Forwarding-ServerName"])/>   </cffunction> </cfcomponent>

Then I added the property to my Mach-II configuration before the existing EnvironmentProperty:

<property name="environmentHelperProperty" type="properties.EnvironmentHelperProperty">   <parameters>     <parameter name="serverPropertyName" value="serverName"/>   </parameters> </property> <property name="environment" type="">   <parameters>     <parameter name="defaultEnvironmentName" value="production"/>     <parameter name="serverPropertyName" value="serverName"/>     <!-- All the other stuff -->   </parameters> </property>

Finally, I made a tiny hack to the Mach-II EnvironmentProperty to honor an existing value in the serverName property, EnvironmentProperty.cfc.diff

Convenient Mach-II App Reload Link

Here's a Mach-II trick that might prove useful to some of you someday, perhaps in a somewhat bizarre set of circumstances*. It can be helpful to include a link somewhere on the page that allows for easy reloading of the framework. Of course, you wouldn't want such a link to be present in the production application. Using the awesome Mach-II Environment Property it's simple to place the link on the pages served only by the development servers. Consider that the Application.cfc (which is a subclass of MachII.mach-ii) contains the following code to reinitialize the application:

<cffunction name="reinit" returntype="void" access="private" output="false">   <cfset var argName = getProperty("applicationReinitKeyName", "undefined")/>   <cfset var argValue = getProperty("applicationReinitKeyValue")/>     <!--- The reload command isn't defined, possibly intentionally --->   <cfif argName eq "undefined">     <cfreturn/>   </cfif>     <cfif structKeyExists(url, argName) and url[argName] eq argValue>     <cftry>       <cfset reloadConfig()/>       <cfset structClear(session)/>       <!--- Perhaps some other things too. --->       <cfcatch>         <!--- Bummer! --->       </cfcatch>     </cftry>   </cfif> </cffunction>

The Mach-II configuration file just needs a pair of properties to define the reinitialize command, which of course could be different for each environment:

<property name="applicationReinitKeyName" value="foo"/> <property name="applicationReinitKeyValue" value="bar"/>

Finally, the view needs to place the special link on the page:

<cfif getAppManager().getEnvironmentGroup() eq "development">   <a href="#buildUrl('showHome', getProperty('applicationReinitKeyName') & '=' & getProperty('applicationReinitKeyValue'))#">Reload Application</a> </cfif>

*This is a reference to the Tom Lehrer Elements song. Yay chemistry!

Preventing SCCS Data Leaks

Many people, right or wrong, deploy CFML applications to the web server by performing a checkout a source code control system, such as Subversion or Git. This has the effect of placing repository information in directories with the rest of the files; ${APPROOT}/**/.svn and ${APPROOT}/.git, for example. It's possible that this repository information (containing the code in plain-text and configuration files) will be exposed by the web server. That would be bad.

Whether the repository data is visible to an HTTP client depends on several factors: the OS, the web server and configuration, the directory and file permissions and OS- and filesystem-specific attributes. Probably the two most common environments are Windows with IIS and Linux with Apache. In the first case, IIS by default is configured to hide files and directories with the NTFS hidden attribute. Since both Subversion and Git create their repository directories with this flag enabled, the default scenario on Windows/IIS is safe. However, the same is not true for Linux/Apache (or Apache on Windows, for that matter).

Apache has always shipped, to the best of my knowledge, with a server-wide directive to prevent disclosing .htaccess and .htpasswd files:

<FilesMatch "^\.ht"> Order allow,deny Deny from all Satisfy All </FilesMatch>

It's not enough, I'm afraid, to remove the "ht" from the regex. To properly secure the SCCS artifacts, I like to use the trusty mod_rewrite module:

RewriteRule /(\.svn|\.git)/.* - [L,F]

And while I'm on the topic of using mod_rewrite to secure an application, here are some rules I use to prevent any similar shenanigans:

RewriteRule ^/app/(config|filters|listeners|plugins|properties|views)/.* - [L,F] RewriteRule ^/(MachII|MachIIDashboard|coldspring|transfer|cfpayment)/.* - [L,F] RewriteRule ^/(db|gen|model|taglib)/.* - [L,F]

Please feel free to comment. Oh wait, I'm lame and haven't enable comments on this blog. I suppose you could send them to @jlamoree instead.

Quick and Dirty Configuration FIle Security

I follow the convention that XML configuration files for Mach-II, ColdSpring, and Transfer ORM go in the $WEBROOT/$APPROOT/config directory. This directory is web accessible, and unless otherwise protected, would leak information that could be compromising. There are many ways to secure this information, but a quick and dirty way to do it is add a .htaccess file to the source tree:

# /home/www/sites/ Order by allow,deny Deny from all

Of course, this will only work if Apache is configured with the default AccessFileName directive and the config directory is beneath a path with AllowOverride specifying (at least) Limit. For example:

# /etc/httpd/conf.d/ <Directory /home/www/sites/> AllowOverride Limit </Directory>

Another method that I use on sites with large sets of URL rewrite rules, is creating a rule to forbid access to matching URLs. For example:

# /etc/httpd/conf.d/ RewriteRule ^/app/config/.* / [L,F]

The rewrite has the same effect, but doesn't require the .htaccess file or AllowOverride directive.

Protecting Mach-II XML Files

Recently I've seen a buzz on some lists about preventing unauthorized downloads (or execution) of files composing a Mach-II web application. My preference is to use Apache mod_rewrite or a J2EE Servlet Filter. I don't like to write some clever CFML to do the job because that leaves all other files accessible.

Here are a batch of my mod_rewrite rules that live in an .htaccess file in the root of the web directory:

RewriteEngine on RewriteRUle ^/?$ /site/ [R,L] RewriteRule ^go/demo$ /site/index.cfm?event=content.demos [R,L] RewriteRule ^index\.cfm?(.*) /site/index.cfm?$1 [R,L] RewriteRule ^site/MachII?(.*) /site/index.cfm?$1 [NC,PT] RewriteRule ^site/(config|views)/? / [F]

The last rule is really the crux of the biscuit, with regard to securing the configuration files (XML) or calling any views outside of the controller's, um, control.