Extending BizTalk 2004: Create an Encryption Functoid
The last few weeks I’ve been pretty busy with BizTalk 2004 (those of you who are in my Messenger buddy list can whiteness that) and I must say it’s for a full 100% a product of the new Microsoft generation. What I mean by that is that everything is so extensible... You need to do something special in a receive pipeline? Just create the component in .NET and drop it in your receive pipeline. You need custom treatment of a message? Just create the component and drop it in an orchestration. And none of these customizations are rocket science, everyone with some decent knowledge of .NET can do it! To prove it, let’s create a custom Functoid that allows you to encrypt/decrypt values in your messages.
First of all: what the heck is a Functoid?
This is the definition from the glossary: An executable module that performs a specific calculation or data manipulation, and that is used graphically when constructing BizTalk Server maps to provide the basis for richer transformations than what is provided by XSLT on its own. (Btw: a updated set of the BizTalk documentation is coming on the second of April!). So it’s an tiny little component that you can use in the BizTalk Mapper when you transform a message to another message. There are quite a lot of Functoids already available out-of-the box in BizTalk 2004, going from simple string functions to more complex lookup’s in database tables. There are even Functoids in which you can type C# or VB.NET code that will be executed dynamically. Therefore the need for custom Functoids is in fact not very high, only in some cases where you need specific functionality repeatedly or you need the higher performance of compiled code, a custom Functoid can come in handy.
Imagine the following situation: you’re designing the EAI layer of a company that has to deal with credit card information of it’s customers. Probably you’re a little worried because you’ll be sending XML messages containing sensitive data to all sort of legacy systems. Of course you can use secure communication channels like HTTPS, but your manager really wants to have an extra layer of encryption for specific elements of your XML messages. So in the messages you’ll be receiving, the CreditCardNumber field will be encrypted, thus you’ll have to decrypt that field before you send it further. Let’s create some Functoids that can help us with the decryption and encryption!
Important note: the following example is meant to explain how to create a custom Functoid, it is not meant to illustrate a security best-practise!
You can create Functoids in a Class Library project in Visual Studio.NET, so let’s create one, and name it “SecurityFunctoids” for example. We’ll need a reference to the Microsoft.BizTalk.BaseFunctoids.dll assembly that is located in the Developer Tools directory of your BizTalk installtion (probably X:\Program Files\Microsoft BizTalk Server 2004\Developer Tools). This assembly contains the base Functoid class from which we’ll inherit. Since the assembly we’re creating will need to be deployed to the GAC, we’ll need to give it a strong name, so put the location of your public/private key pair in the AssemblyKeyFile attribute in the AssemblyInfo.cs file. Also in the AssemblyInfo.cs file add the Guid attribute, generate a new Guid for your Functoid (for VS.NET interoperability) and give you’re assembly a meaningful title:
[assembly: System.Runtime.InteropServices.Guid("2E345003-E2B0-47c3-89CB-3AC93A824064")]
[assembly: AssemblyTitle("SecurityFunctoids")]
Next we’ll need to add an Assembly Resource File to the project (Resources.resx for example) that will contain for each Functoid following items:
- Name
- Description
- ToolTip
- Bitmap (will be showed in the ToolBox)
I prefer to use the Resourcer tool to create resource files, it allows you to easily add various kinds of data (like text, bitmaps, …) to your resource file.
Now we’re ready to write some code! Add a new class to your project: DecryptionFunctoid, and use following code:
using System;
using Microsoft.BizTalk.BaseFunctoids;
using System.Reflection;
namespace SecurityFunctoids
{
public class DecryptionFunctoid: BaseFunctoid
{
public DecryptionFunctoid()
{
this.ID = 6002;
SetupResourceAssembly("SecurityFunctoids.Resources",
Assembly.GetExecutingAssembly());
SetName("ENCRYPTION_NAME");
SetTooltip("ENCRYPTION_TOOLTIP");
SetDescription("ENCRYPTION__DESCRIPTION");
SetBitmap("ENCRYPTION__BITMAP");
this.SetMinParams(2);
this.SetMaxParams(2);
SetExternalFunctionName(GetType().Assembly.FullName,
"SecurityFunctoids.EncryptionFunctoid", "DecryptString");
this.Category = FunctoidCategory.String;
this.OutputConnectionType = ConnectionType.AllExceptRecord;
// Parameter 1
AddInputConnectionType(ConnectionType.AllExceptRecord);
// Paramter 2
AddInputConnectionType(ConnectionType.AllExceptRecord);
}
public string DecryptString(string val1, string val2)
{
SymmetricEncryption enc = new SymmetricEncryption();
return enc.Decrypt(val1, val2);
}
}
}
As you can see, the class inherits from the BaseFunctoid. In the constructor there are a number of things set:
- Unique ID of the Functoid (start from 6000 for your own Functoids).
- Name, Tooltip, Description and Bitmap resource strings.
- The maximum and minimum number of parameters your Functoid will accept. In our case both are set to two. The first parameter will be the value to decrypt, the second parameter will be the key to use.
- The SetExternalFunctionName determines which function of the class will be used when the Functoid is invoked, in our case the DecryptString function.
- The category is specified by using the Category property.
- The parameters of the Functoid are configured.
Then the function that will do the work is written next: DecryptString. I’ve used a helper library for encryption and decryption of string values, so I won’t go into detail about encryption/decryption functionality. Finally build your project so we can use it in BizTalk. The deployment of a Functoid consist of three steps:
- Deploy it to the GAC
- Copy it to the X:\Program Files\Microsoft BizTalk Server 2004\Developer Tools\Mapper Extensions directory (So Visual Studio.NET can use it)
- Add it to the ToolBox in Visual Studio.NET (right click on the ToolBox, choose Add/Remove items, click the Functoids tab and browse to the SecurityFunctoids.dll file and make sure it’s checked.
If you’ve deployed your Functoid correctly you should be able to see it in the ToolBox:
To use the new Functoid you can create a similar orchestration as showed below:
The DecryptMessage Transform shape should contain String Decryption Functoid:
For samples of more advanced Functoids check out Scott Woodgate’s blog post.