WCF Hooks Extensions

Version Information

Library cPanel.Core.Hooks.dll
Status BETA
Version 0.1
Compatible Enkompass Version 2.0

Contents

Introduction

The hook system allows you to receive and process messages sent to Enkompass WCF Server's API. Advanced aspects of the system can allow you to cancel or alter API call messages while they are processed.

Information provided in this document corresponds to version BETA 0.1 of the cPanel.Core.Hooks library. Because this is beta software, we reserve the right to change the systems definition until it is no longer in beta. We will attempt to make these changes backwards-compatible; however, we cannot guarantee that changes that we make from release to release will not break some of your customizations.

Changes will be documented in Enkompass' change log.

Configuring hooks

Hooks are an optional component of the Enkompass WCF processing architecture. To enable the hooks system, you must add a configuration file to the hooks application path.

You can find your hooks application path by looking in your server's registry:

$cPanelApplicationPath$ = HKLM:SOFTWARE\cPanel, Inc.\cPanel\ApplicationPath

Once you have this value, combine the path listed above with the following:

$cPanelApplicationPath$\Common\Hooks\HookConfiguration.config

For example:

\\fileserver\e\ApplicationPath\Common\Hooks\HookConfiguration.config

The configuration file

The HookConfiguration.config configuration file should resemble the following:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="hookLoaderConfiguration" 
             type="cPanel.Core.Hooks.HookLoaderConfigurationSection,cPanel.Core.Hooks" />
  </configSections>
  <hookLoaderConfiguration>
    <hookItems>
    ...
    </hookItems>
  </hookLoaderConfiguration>
</configuration>


You may configure a few parameters in this file.

The <hookLoaderConfiguration> tag

You can configure the following attributes of the <hookLoaderConfiguration> tag:

Name Values Optional Default Notes
debug true
false
yes false Enables additional logging in the message processing layers. This logging will slow down processing for WCF calls significantly. You should either not include this attribute in the configuration file or make sure to set its value to =false in most cases. You should only enable this feature when you are trying to diagnose a problem with the hooks system.
logAll true
false
yes false Enables verbose logging of unmonitored messages, including the output of their SOAP messages. Enabling this attribute may be useful to developers trying to understand the format of the action names and details of a SOAP message's header or body.

The <hookItems> tag

The <hookItems> tag is contained in within the <hookLoaderConfiguration> tag. This tag contains the collection of hooks to install on the system. Each hook is added into the <hookItems> tag using an <add> tag like so:

<add name="UrlHooks" 
      type="cPanel.Core.Hooks.UrlHookBehaviour, cPanel.Core.Hooks" 
      externalConfigurationPath="\\10.1.15.101\e\ApplicationPath\Common\Hooks\UrlHookConfiguration.config" /> <add> 

The <add> tag

You can use the <add> tag to add a single hook behavior to the Enkompass WCF pipeline. Each behavior represents a complete and independent way that hooks are processed. This <add> tag has the following attributes:

Name Values Optional Default Notes
name $string no N/A A unique name for the hook.
enable true
false
yes true Selects whether to enable or disable the corresponding hook.
type $fully-qualified-type no N/A The .NET object type that implements the hook behavior. The type may be in any format recognizable the Microsoft .NET framework.
For more information, review Microsoft's type documentation.
path $path yes N/A If provided, this parameter will load the DLL from the specified path instead of the default location. This allows you to install DLLs for hooks outside of Enkompass, but load them into the Enkompass WCF services process.
ALERT! Warning:We have not yet tested this parameter.
externalConfigurationPath $path no N/A The full path to the configuration file for this hook behavior.

Types of hooks

Type Description
Filter Hooks A type of hook that includes a specific set of messages to be processed.
Broadcast Hooks A type of hook that processes all the messages passed through the system.

Available Hooks

There are 2 hook behavior libraries released with this beta. They are the CommandHook and the UrlHook. These hooks are considered filter hooks because you must specify specific messages you want the hook to process.

Command hooks

A command hook allows you to send specific WCF messages to an executable program. This program can be any type of executable on the Enkompass server or any executable available in the same domain as the Enkompass server. For a command hook to work, the Enkompass WCF service account must be able to execute the executable file.

A sample configuration file is shown below:


<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="commandHookConfiguration" 
             type="cPanel.Core.Hooks.CommandHookConfigurationSection,cPanel.Core.Hooks" />
  </configSections>
  <commandHookConfiguration enable="true" >
    <handledMessages>
      <add name="BeforeAmIAlive" 
           action="http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive" 
           actionType="Before" command="C:\logger\log.exe" args=" -before '{0}'" />
      <add name="AfterAmIAlive"  
           action="http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive" 
           actionType="After" command="C:\logger\log.exe" args=" -after '{0}'" />
    </handledMessages>
  </commandHookConfiguration>
</configuration>

The <commandHookConfiguration> tag

The <commandHookConfiguration> tag has the following attributes:

Name Values Optional Default Notes
enabled true
false
yes true Turns the entire hook behavior on or off. You must restart the WCF service for changes to this attribute to take effect.

The <handledMessages> tag

This tag contains a list of the messages that will be processed by the command hook behavior. Each message must be specified by an <add> tag.

The <add> tag

This tag configures the command hook for a single message. Each message you want to process should include an <add> tag.

The <add> tag has the following attributes:

Name Values Optional Default Notes
name $string no N/A The unique name of the message to process. This is something you make up to describe the message you are processing.
action $string no N/A The internal representation for the WCF message you want to process. This value should be formatted like so:
http://www.cpanel.net/schemas/2008/03/<ServiceInterface>/<MessageName>
Where <ServiceInterface> is one of the following:
  • IServerAdministratorService — Methods for SAI
  • IWebSiteOwnerService — Methods for WSOI
  • IMailOwnerService — Methods for MOI

The <MessageName> tag is the name of the method to call to the API.
actionType Before
After
yes After This value indicates when the hook should be used, either before or after the API call is processed.
note Note: Before action types can cancel the API call; After action types cannot.
command $string no N/A The command to call when the message is received. The command can include optional substitution parameters using {#} syntax. The following are valid substitution parameters.
  • {0} - Message Name
  • {1} - Stage
args $string yes N/A The arguments to pass to the command. Arguments can include optional substitution parameters using {#} syntax. The following are valid substitution parameters:
  • {0} - Message Name
stripSoapEnvelope true
false
yes true WCF processes all messages as SOAP calls. The hook has code to strip out SOAP headers if this is attribute is set to true. When set to =false, the message is passed to the command as-is.
transform $XSLT yes N/A A valid XSLT transform definition to apply to the message sent to the command.
note Note: If stripSoapEnvelope is enabled, the SOAP headers are stripped before this transform is called.

The command, called by the command hook, should expect the incoming message data on standard input. It should send output to standard output and errors to standard error.

For hooks with action Type = Before, the input message format is as follows:


Log.exe Information: 0 : [ ] 2011-06-07 17:23:45Z [INFO : ] - Command Hook Application - Main - Before 'http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive'
Message ID: f9fdae87-eb37-4a54-afa9-665691706297
Action: http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive
Stage: BeforeDispatch
Request:
<AmIAlive xmlns="http://www.cpanel.net/schemas/2008/03/" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" />

For hooks with action Type = After, the input message format is as follows:


Log.exe Information: 0 : [ ] 2011-06-07 17:23:45Z [INFO : ] - Command Hook Application - Main - After 'http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive'
Message ID: 27d2a629-8101-4338-bc5a-202fe40ccfd6
Action: http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive
Stage: AfterDispatch
Request:
<AmIAlive xmlns="http://www.cpanel.net/schemas/2008/03/" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" />
Response:
<AmIAliveResponse xmlns="http://www.cpanel.net/schemas/2008/03/" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
 <AmIAliveResult>true</AmIAliveResult>
</AmIAliveResponse>

Writing a command

When designing the command to process the hooked event, the process will pass the event name on the command line.

The command should expect the following keys to identify parts of the message:

Key Value Description
Message ID $GUID The unique identifier for the message in the processing chain.
Action $URL The unique name of the event in URL format.
Stage BeforeDispatch
AfterDispatch
Indicates whether the hook event is sent before or after the core API is called. BeforeDispatch indicates that the command can be canceled by the hook, as the the hook event is taking place before the API call. =AfterDispatch indicates that the hook is called after the core API call is run.
Request:/r/n URL-encoded XML The request tag is on a line by itself. The request body is on the next line and is URL-encoded.
Response:/rn URL-encoded XML The response tag is on a line by itself. The response body is on the next line and is URL-encoded. The response is sent only if the Stage is set to AfterDispatch.
/r/n/r/n $EOF Two consecutive empty lines indicate the end of the file.

Sample log


Before http://tempuri.org/ICalculator/Divide
Message ID: edbf2452-36db-4acd-a8ad-96f9f40b30aa
Action: http://tempuri.org/ICalculator/Divide
Stage: BeforeDispatch
Request:
<Divide>
  <i>6</i>
  <j>9</j>
</Divide>
After http://tempuri.org/ICalculator/Divide
Message ID: fc7ac19d-5fe5-4942-b12d-360411760ea7
Action: http://tempuri.org/ICalculator/Divide
Stage: AfterDispatch
Request:
<Divide>
  <i>6</i>
  <j>9</j>
</Divide>
Response:
<DivideResponse>
  <DivideResult>0</DivideResult>
</DivideResponse>

URL hooks

URL hooks allow you to send WCF messages to a URL to be processed. The URL should use standard HTTP requests and response mechanisms.

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="urlHookConfiguration" 
             type="cPanel.Core.Hooks.UrlHookConfigurationSection,cPanel.Core.Hooks" />
  </configSections>
  <urlHookConfiguration enable="true" baseUrl="http://10.1.15.102:2086/logmessage.aspx" >
    <handledMessages>
     ...
    </handledMessages>
  </urlHookConfiguration>
</configuration>

The <urlHookConfiguration> tag

Name Values Optional Default Notes
enabled true
false
yes true Enables or disables the hook behavior. You must restart the WCF service for this to take effect.
baseUrl $URL yes N/A This attribute allows you to define the message URLs as relative to the base URL.

The <add> tag

This tag configures the URL hook for a single message. Each message you want to process should include an <add> tag.

Name Values Optional Default Notes
name $string no N/A The unique name of the message to process. This is something you make up to describe the message you are processing.
action $string no N/A The internal representation for the WCF message you want to process. This value should be formatted like so:
http://www.cpanel.net/schemas/2008/03/<ServiceInterface>/<MessageName>
Where <ServiceInterface> is one of the following:
  • IServerAdministratorService — Methods for SAI
  • IWebSiteOwnerService — Methods for WSOI
  • IMailOwnerService — Methods for MOI
The <MessageName> tag is the name of the method to call to the API.
actionType Before
After
yes After This value indicates when the hook should be used: either before or after the API call is processed.
note Note: Before action types can cancel the API call; =After action types cannot.
url $string no N/A The URL to call when the message is received. The URL can include optional substitution parameters using {#} syntax. The following are valid substitution parameters:
  • {0} - Message Name
  • {1} - Stage
isRelativeUrl true
false
yes false If true, the URL indicated above is a relative URL and will be combined with =baseUrl above. If false, then the above URL is a fully qualified URL.
stripSoapEnvelope true
false
yes true WCF processes all messages as SOAP calls. The hook has code to strip out SOAP headers if this attribute is set to true. When set to =false, the message is passed to the command as-is.
transform $XSLT yes N/A A valid XSLT transform definition to apply to the message sent to the command.
note Note: If stripSoapEnvelope is enabled, the SOAP headers are stripped before this transform is called.

The URL called by the command hook should expect incoming message data as part of the HTTP request body and should return data via the HTTP response body.

For hooks with actionType = Before, the input message format is as follows:


cPanel.Web Information: 0 : [ ] 2011-06-07 17:43:06Z [INFO : ] - Test - LogMessage - http://10.1.15.102:2086/logger/logmessage.aspx?action=Before&message=http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive
cPanel.Web Information: 0 : [ ] 2011-06-07 17:43:06Z [INFO : ] - Test - LogMessage - Message ID: dd26771a-63f1-4e3c-bd89-0ab38310c21a
Action: http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive
Stage: BeforeDispatch
Request:
<AmIAlive xmlns="http://www.cpanel.net/schemas/2008/03/" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" />

For hooks with actionType = After, the input message format is as follows:


cPanel.Web Information: 0 : [ ] 2011-06-07 17:43:06Z [INFO : ] - Test - LogMessage - http://10.1.15.102:2086/logger/logmessage.aspx?stage=After&message=http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive
cPanel.Web Information: 0 : [ ] 2011-06-07 17:43:06Z [INFO : ] - Test - LogMessage - Message ID: b2cf36ce-8e6c-4b71-981a-f4faeed51f52
Action: http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive
Stage: AfterDispatch
Request:
<AmIAlive xmlns="http://www.cpanel.net/schemas/2008/03/" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" />
Response:
<AmIAliveResponse xmlns="http://www.cpanel.net/schemas/2008/03/" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
 <AmIAliveResult>true</AmIAliveResult>
</AmIAliveResponse>

The URL hook should return one of the following HTTP status codes. You may use some of these codes to modify the message's processing cycle.

HTTP Status Code Cancels Operation
Ok 200 No
Created 201 No
Accepted 202 No
Unauthorized 402 Yes*
Forbidden 403 Yes*

note Note: Canceling only occurs if the hook took place before the API function was called.

Hook configuration samples

The following is an example of HookConfiguration.config:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="hookLoaderConfiguration" type="cPanel.Core.Hooks.HookLoaderConfigurationSection,cPanel.Core.Hooks" />
  </configSections>
  <hookLoaderConfiguration debug="true">
    <hookItems>
      <add name="UrlHooks" type="cPanel.Core.Hooks.UrlHookBehaviour, cPanel.Core.Hooks" 
           externalConfigurationPath="\\10.1.15.101\e\ApplicationPath\Common\Hooks\UrlHookConfiguration.config" />
      <add name="CommandHooks" type="cPanel.Core.Hooks.CommandHookBehaviour, cPanel.Core.Hooks" 
           externalConfigurationPath="\\10.1.15.101\e\ApplicationPath\Common\Hooks\CommandHookConfiguration.config" />
    </hookItems>
  </hookLoaderConfiguration>
</configuration>


The following is an example of CommandHookConfiguration.config:


<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="commandHookConfiguration" type="cPanel.Core.Hooks.CommandHookConfigurationSection,cPanel.Core.Hooks" />
  </configSections>
  <commandHookConfiguration enable="true" >
    <handledMessages>
      <add name="BeforeAmIAlive" 
           action="http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive" 
           actionType="Before" command="C:\logger\log.exe" args=" -before '{0}'" />
      <add name="AfterAmIAlive"  
           action="http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive" 
           actionType="After" command="C:\logger\log.exe" args=" -after '{0}'" />
    </handledMessages>
  </commandHookConfiguration>
</configuration>


The following zip files are examples for TestCommand and CommandHook:


The following is an example of UrlHookConfiguration.config:


<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="urlHookConfiguration" type="cPanel.Core.Hooks.UrlHookConfigurationSection,cPanel.Core.Hooks" />
  </configSections>
  <urlHookConfiguration enable="true" baseUrl="http://10.1.15.102:2086/logmessage.aspx" >
    <handledMessages>
      <add name="BeforeAmIAlive" 
           action="http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive" 
           actionType="Before" url="?action=Before&amp;message={0}" isRelativeUrl="true" />
      <add name="AfterAmIAlive"  
           action="http://www.cpanel.net/schemas/2008/03/IServerAdministratorService/AmIAlive" 
           actionType="After" url="?stage=After&amp;message={0}" isRelativeUrl="true"  />
    </handledMessages>
  </urlHookConfiguration>
</configuration>


The following zip file is an example of a test page for UrlHook:

To make the logger above record information to your SAI log file, you must change system.diagnostics in your SAI web.config to:

<system.diagnostics>
    <trace autoflush="true" indentsize="4" />
    <sources>
      <source name="cPanel.Web" switchValue="Verbose">
    <listeners>
      <add name="textListener"/>
    </listeners>
      </source>
      <source name="cPanel.Web.Build" switchValue="Error">
        <listeners>
          <add name="textBuildListener"/>
        </listeners>
      </source>
    </sources>
    <switches>
        <add name="cPanel.EntryType" value="All"/>
    </switches>
    <sharedListeners>
      <add type="System.Diagnostics.ConsoleTraceListener"
           name="consoleListener"
           traceOutputOptions="None"/>
      <add type="cPanel.Web.Logging.RollingTextWriterTraceListener, cPanel.Web.Logging, Culture=neutral"
           initializeData="fsailog.txt"
           name="textListener"
           traceOutputOptions="None"/>
      <add type="cPanel.Web.Logging.RollingTextWriterTraceListener, cPanel.Web.Logging, Culture=neutral"
           initializeData="fbsailog.txt"
           name="textBuildListener"
           traceOutputOptions="None"/>
    </sharedListeners>
  </system.diagnostics>

Extending hooks

The command and URL hooks classes were designed to allow developers to extend functionality to support the integration scenario beyond our current implementation. There are many extension points in both of these classes.

Command Hook Classes

The command hook contains three main groups of classes:

The CommandHook class Summary
The CommandHook class summary

The first class is the CommandHook class, which is derived from the hook class:

The CommandHook class
The CommandHook class

The command hook, as described above, provides a way to map a message received by the WCF API to an external, executable command. Out of the box, this class comes with fairly limited command and argument formatting. However, the FormatCommand() and FormatArguments() methods are virtual methods. This means that if the services provided by the class are inadequate, you can create your own CommandHook-derived class as seen below.

Additionally, if you do not like the current way the command hook writes messages to the input stream or processes the command response, you can override WriteMessage() or ProcessCommandResponse(). A sample custom implementation is shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cPanel.Core.Hooks;

namespace Sample
{
    public class CustomCommandHook : CommandHook
    {
        protected override string FormatCommand(string command, HookExtension call, Stage stage, CommandHookMessage config)
        {
            // Do what you want here to create the command call string
            return base.FormatCommand(command, call, stage, config);
        }

        protected override string FormatArguments(string arguments, HookExtension call, Stage stage, CommandHookMessage config)
        {
            // Do what you want here to create the command arguments string
            return base.FormatArguments(arguments, call, stage, config);
        }        
    }
}

If you create a custom implementation class, you must also create a set of installer classes for the new CustomCommandHook. Standard installers are defined in the CommandHookOperationBehaviorAttribute and CommandHookBehavior classes.

To implement your own custom versions of these classes, you can use the generic installer types like so:

public class CustomCommandHookBehavior : HookBehaviour<CustomCommandHook>
    {
    }

    public class CustomCOmmandHookBehaviorAttribute : HookOperationBehaviorAttribute<CustomCommandHook>
    {
    }

With these three classes, you have a complete extension solution for the command hook. You can now add your custom hooks to your $cPanelApplicationPath$\Common\Hooks\HookConfiguration.config file, as you did with the hooks that we provided.

<add name="CustomCommandHooks" type="Sample.UrlHookBehaviour, Sample" externalConfigurationPath="\\10.1.15.101\e\ApplicationPath\Common\Hooks\CommandHookConfiguration.config" /> 

Topic revision: r7 - 23 Jun 2011 - 12:26:29 - MelanieSeibert
AllDocumentation/EnkompassDocs.WcfHookExtensions moved from Sandbox.WcfHookExtensions on 17 Jun 2011 - 17:34 by Main.JustinSchaefer - put it back