Skip to content

Removing Event Handlers for Security Reasons

thofrey edited this page Apr 1, 2014 · 6 revisions

Table of Contents

  1. Introduction
  2. How We Are Going To Do It
  3. Using a Plugin
  4. In Closing

Introduction

Sometimes in your application you might create event-handlers that are used during development, but should not be available when your application is deployed to a production environment. Such events are commonly used to test pages, as development utilities, or as database quick view pages which do not have any security measures in place.

The simplest solution is to manually delete these event-handlers from your XML configuration file before deploying your application to your production environment, however this is an error prone and messy process. In this wiki entry, we will explore a programmatic solution that will remove the event-handlers you define using the Mach-II API, the [Simple Pattern Matcher][MachII18SpecificationToolkitEnhancements_SimplePatternMatchingwithSimplePatternMatcher.cfc] utility included in Mach-II 1.8+, the Environment Property included in Mach-II 1.8+, and a plugin we will write.

How We Are Going To Do It

Instead of manually commenting out the event-handlers we do not want to deploy to production, we are going to remove them programmatically from the Mach-II EventManager when the application is run on production. We're making full use of the EnvironmentProperty that is bundled with Mach-II 1.8+ so you may want to read that documentation before continuing here.

Another consideration is that in certain applications you may have many event-handlers to remove. Instead of listing each event-handler by name, we are going to use the Mach-II SimplePatternMatcher CFC which allows us to use the RegEx like wildcard character * (asterisk or star). If you've used a convention when naming your event-handlers, like test.this or test.that-- you can use a pattern like test.* to easily remove those events.

Lastly, we are going the use the API available to us in the EventManager to remove an event-handler from the application when Mach-II is loading the framework.

Using a Plugin

The example in this article shows the usage of a plugin to remove the event-handlers, but you could use a Property CFC as well if you prefer.

Configuring Our Plugin

Below is a plugin that we've defined in the XML configuration file. Notice that we are using an array of event-handler patterns that we want to remove when Mach-II is loaded. For example, the pattern preview.* will match any event-handler name that starts with preview. and due to the * wildcard -- any additional characters. Of course these are just examples, so you'll need to change the patterns to match the naming conventions used in your application.

    <plugin name="application" type="MyApplication.plugins.ApplicationPlugin">
        <parameters>
            <parameter name="removeEventHandlersOnProduction">
                <array>
                    <element value="preview.*"/>
                    <element value="test.*"/>
                </array>
            </parameter>
        </parameters>
    </plugin>

The Code Behind Our Plugin

Honestly, the code behind all of this is rather simple and straightforward. We only want to remove the event-handlers that match the patterns on our production environment group, so this code will only run if the application is deployed on a production environment as defined by the EnvironmentProperty.

If you don't have any environments setup, this code will run because the default environment group is production if you are not using the EnvironmentProperty. Setting up environments is a snap with the EnvironmentProperty so, again, you may want to read that documentation before proceeding.

Another work horse in this example is the Simple Pattern Matcher which makes matches by allowing you to use a simple * wildcard. This allows us to check our event name against an event name pattern that utilizes the * wildcard.

    <cfcomponent
        displayname="ApplicationPlugin"
        extends="MachII.framework.Plugin"
        output="false"
        hint="Performs application wide tasks.">

        <!---
        PROPERTIES
        --->
        <cfset variables.matcher = CreateObject("component", "MachII.util.SimplePatternMatcher").init() />

        <!---
        INITIALIZATION / CONFIGURATION
        --->
        <cffunction name="configure" access="public" returntype="void" output="false"
            hint="Configures the plugin.">

            <cfset var removeEventHandlersOnProduction = getParameter("removeEventHandlersOnProduction") />
            <cfset var eventManager = getAppManager().getEventManager() />
            <cfset var eventHandlerNames = eventManager.getEventNames() />
            <cfset var i = 0 />

            <!--- Remove events when in production environment group --->
            <cfif getAppManager().getEnvironmentGroup() EQ "production">
                <cfloop array="#eventHandlerNames#" index="i">
                    <cfif variables.matcher.match(removeEventHandlersOnProduction, i)>
                        <cfset eventManager.removeEvent(i) />
                    </cfif>
                </cfloop>
            </cfif>
        </cffunction>

    </cfcomponent>

Code Walk-Through

  • In the pseudo-constructor area, we are creating a simple pattern matcher object for us to use in the configure method. Remember, the configure method is only run once during the application life cycle (when the framework loads).
  • In the configure method, we need to grab the array of patterns (or concrete event-handler names -- it is not required they are patterns). Notice that the loop will only run when the application is in a production group. If you want to remove the events in other environment groups, you'll have to modify the code.
  • Lastly, we are going to loop through each event-handler name and ask the simple patter match if the current event-handler name matches any of the patterns we want to remove. If one of the supplied patterns matches, then we use the EventManager API to remove the event-handler by passing in the event-handler name. Notice we don't even have to loop over our array of patterns. The Simple Pattern Matcher accepts a single pattern or in this case an array of patterns to check against.

Voila! It's simple as that.

In Closing

As you can see, this somewhat complex task is easily accomplished using the Mach-II API, Mach-II supplied utilities, and just a few lines of code. Also, since we are using patterns, if you add another event-handler like test.thisCrazyThing to your application, it will be removed when you deploy your application to production because you used a pattern instead of defining a concrete event-handler name.

Clone this wiki locally