by community-syndication | Sep 4, 2013 | BizTalk Community Blogs via Syndication
A very powerful feature of BizTalk is Message Tracking. You can use the BizTalk Server Administration Console to enable message body and message property tracking. There you can also view the tracked message body and all the promoted properties for the message. There is only one but, Tracking a lot of data can be bad for the performance so Microsoft recommends that you should only enable the minimum tracking required for your application, as this will reduce the amount of data logged and lower the risk of tracking bottlenecks.
The BizTalk Performance Optimization Guide says the following about message body tracking:
Only use message body tracking if necessary. Depending on message throughput and message size, message body tracking can cause significant overhead. While BizTalk activity tracking has obvious benefits for debugging and auditing, it also has considerable performance and scalability implications. Therefore, you should track only data that is strictly necessary for debugging and security reasons, and avoids tracking redundant information.
So, it can be useful in a development- or test environment but you can’t use this feature in a production environment! But also in a Production environment you want to be able to track message bodies.
MongoDB could be a very good alternative to track message bodies because MongoDB is a web scale database, and doesn’t use SQL or JOINs, so it’s high-performance. An other advantage is that it is a document database. You can store the entire BizTalk message as a document in a collection but you can still search on specific items in the document.
Using MongoDB
MongoDB can be installed on many platforms such as Windows Azure but in this example I’m going to install it on the local machine.
Installing MongoDB on Windows is very simple. Download the archive, extract it and move the files to “C:\mongodb”. Also create the folder "C:\data\db". That is required to store the data files. Now you’re good to go! |
| |
| You can start MongoDB as a Windows Service but you can also start it from the Command Prompt: “C:\mongodb\bin\mongod.exe” |
|
| |
Creating a Custom Itinerary Messaging Service for Message Body Tracking
In the steps below I’m going to create an Itinerary Messaging Service that you can use inside an ESB to track message bodies. Notice that you can also use the code in a “regular” Orchestration or Pipeline Component!
| In a previous blog post I explained how to create a Custom Itinerary Messaging Service so in this post I’m focusing on the details! 😉 |
| |
| I’m using the officially supported C# Driver for MongoDB to insert a document in MongoDB. The C# Driver consists of two libraries: the BSON Library and the C# Driver. |
| |
| To add the necessary libraries to a Project in Visual Studio you can use NuGet Packages. |
|
| |
| Search on MongoDB and install the driver. |
|
| |
| You also need the Json.NET package because you have to serialize the XML to Json. Json.NET is a popular high-performance JSON framework for .NET |
|
| |
| Use JsonConvert.SerializeXmlNode to serialize a XmlDocument to Json. |
|
| |
| To insert a document in a collection in MongoDB create an object representing the document and call Insert. |
// This class serves as the root object for working with a MongoDB server.
MongoClient client = new MongoClient(connectionString);
var server = client.GetServer();
var mongoDbDatabase = server.GetDatabase(database);
var mongoDbCollection = mongoDbDatabase.GetCollection(collection);
// Parste the json to a BsonDocument (a collection of name/value pairs)
BsonDocument document = BsonDocument.Parse(jsonText);
// Insert the document in the collection
WriteConcernResult insertResult = mongoDbCollection.Insert(document);
// Result
ok = insertResult.Ok;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; } |
| |
| Add an entry in the itineraryServices section of the Esb.config file from the ESB Toolkit by adding an <itineraryService> element. |
<itineraryService id="1030" name="TrackingService" type="itHero.ESB.Services. TrackingService, itHero.ESB.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7f76ec21959e67b4" scope="Messaging" stage="All"/>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; } |
| |
| Now you can create an Itineray with the custom TrackingService: |
|
| |
| Before you can use the Itinerary Service in BizTalk you have to register all the assemblies in the Global Assembly Cache. You can use the Deployment Framework for BizTalk but you can also use Gacutil. |
|
| |
Testing
Once the itinerary is deployed to the Itinerary Store database and the Tracking Service is placed in the GAC, the solution is ready to be tested.
Create a Receive Port and a Receive Location with the BizTalk Administration Console and drop a message in it.
I’ve used the Trace class in System.Diagnostics to trace the steps but you can also use another component for it like ETW tracing.
| Run DebugView to watch the trace output. |
|
| |
| You can use the MongoVUE application for Windows to find the messages that are stored in MongoDB.
Notice that in the Message also the InterchangeID value is available to match the Message Body with an Tracking Event in BizTalk. |
|
| |
You can match the Message Body that is stored in MongoDB with a tracked Message in BizTalk.
1. Open the BizTalk Administrator and Search For: Tracked Message Events
2. Click on an Event and use the Message ID to match the Message in the Event to the Message Body in MongoDB. |
|
| |
Conclusion
The Tracking Service example showed that MongoDB is a really good alternative for tracking message bodies. I’ve always been a big fan of SQL Server so I was a bit skeptical about MongoDB but seeing is believing! It really is much faster than SQL Server and you can still search on individual items in a message.
You can download the sample Messaging Service with the source code here:
http://code.msdn.microsoft.com/Using-MongoDB-for-Message-a8e4ba4d
by community-syndication | Sep 1, 2013 | BizTalk Community Blogs via Syndication
In all fairness, this post relates to Azure Service Bus in general and not specifically to Windows Azure BizTalk Services (WABS).
When is this relevant?
Azure Service Bus and WABS both rely on Azure Access Control Service (ACS) to authenticate users before calling the service. This type of authentication is often referred to as Federated Security. In most samples of how to interact with Service Bus or WABS, the client first calls ACS (using user name and password) to receive a token, which is later used upon calling the actual service.
Using a ACS Service Identity (service user) makes sense when the client is a system, where you’d probably let each system have its own Service Identity.
-But what if the client is a user, such an employee or customer, perhaps calling in from a mobile unit?
In such cases, you’d have to keep the Service Identity stored on the device/application. Part from the security problems related to some evil person hacking the (Android) phone and then uses the credentials for evil purposes, you can’t do Authorization as every user is using the same credentials.
In such cases, you’d probably want to use some other directory than the one provided in ACS. In most cases Active Directory is likely to be the preferred choice.
Authentication
Token Based Authentication can be a bit hard to understand, so I’ll try to explain it using an analogy.
Imagine you’re going on a vacation to a different country, and upon facing the scary customs officer, you smile and give him your VISA card. Take my word for it, it won’t work, but the interesting part is why. Despite the anger he or she will direct towards you, i’s not about you at all. In fact, they will never trust YOU!
-The problem is that they don’t trust the VISA organization to vouch for your identity.
So we need to go to a trusted authority and ask them to vouch for our identity, in Sweden that would be the local police department. They won’t trust you either, and will ask for some other proof, but more on that later. Let’s just assume all goes well and they’ll issue you a passport.
The passport holds information about you, some information is public others may be hidden or encrypted, but more importantly it is signed by a trusted authority.
With a passport in our hand, the officer now trust your identity (Authentication), and he will now proceed to check your criminal records and ask a bunch of questions to determine if he will allow you to enter the country (Authorization).
Leaving the analogy and getting back to Federated Security. It’s pretty much the same thing. The Swedish Police department plays the role of the Issuer (ACS) the customs officer plays the role of the Relying Party Application (WABS or Service Bus), and the passport is of course the Token.
The difference between the analogy and Service Bus authentication, is that while the customs trust many different issuers, Windows Azure Service Bus ONLY TRUST ACS!
However, ACS can be configured to trust other issuers also referred to as Identity Providers. If we go back to the analogy, and the local Police department that issued the passport, -why did he trust you? There are actually a number of ways to prove your identity, but lets assume you’d use an ID. This is sometime referred to as a chain of trust.
This is how Active Directory come in play. Active Directory can be configured with Active Directory Federated Services (ADFS). ADFS is an issuer, and although Service Bus does not trust your ADFS, ACS can be trusted to do.
By adding your ADFS as an Identity Provider in ACS, you can authenticate yourself with ACS using a token provided by ADFS! ACS will then provide you with a new token which can be used to authenticate yourself with Service Bus.
Step 1: Ask ADFS to issue a token for ACS using Active Directory user name and password.
Step 2: Ask ACS to issue a token for SB, using a token issued by ADFS
Step 3: Call the service using the token provided by ACS.
Authorization
Although it won’t be sufficient for us, it’s worth pointing out that ACS provides some level of authorization which you can read more about here. ACS can however not provide authorization based on AD group membership, as the group membership claim comes as a comma separated string, with all groups:
Eg: CN=Sales,CN=Employees,,,,,,,,CN=Users,DC=MyDomain,DC=net
Before we dive into BizTalk Services I’d like to point out a couple “issues” you might encounter. In the case where your service is a REST service (such as with WABS), you’ll face two problems, one small and one big. Both problems relates to the fact that Service Bus will remove your token after the token has been verified by Service Bus. In other words, the token is not for you!
This little problem can be worked around, by adding the token twice. One using the “Authorization” header, and the other using a custom header.
The potentially bigger issue relates to the HTTP header it self, or rather its size. Using IIS 7 that limit is 16KB, but might differ depending on the version of IIS. By propagating the group membership claims from ADFS to the token issued by ACS, the token can get pretty big (depending of the number of groups the user is a member of). Adding the token twice, and you might pass the limit. The good news is that this limit is configurable, but the problem can be difficult to identify, as it might not occur for all users.
Anyway, by adding the token twice we can now evaluate group membership and authorize the user within our service (SB) or itinerary (WABS).
The Setup
The setup involves many steps, some of witch I’ll assume you have already done. For instance, it’s outside the scope of this post to set up ADFS and install the WABS SDK.
1. The Itinerary
As the overall sample is complicated enough, we’ll stick with a very simple itinerary .
The itinerary received the message using a One-Way bridge, and routs the message to either one of the queues, depending on if the user is part of any of the groups.
2. Extracting the HTTP Custom Header
As described earlier, we need to add the token twice. Once for the Service Bus to do Authentication, and the other for us to do Authorization. To do this, double-click the One-Way bridge to open the bridge configuration.
Select any of the two Enrish stages, and click the Property Definition in the Property Window. Add a new property definition, and set the values as following:
I will call my custom header “AUTH”, if you care to use a different name, just change the Identifier to what ever work for you.
3. Create a Message Inspector
Now that we have the token, we need to extract the group claim. To do this we’ll need to create a Message Inspector.
Follow these steps to create your project:http://msdn.microsoft.com/en-us/library/windowsazure/dn232389.aspx
Here is the code I used:
public class AuthorizationInspector : IMessageInspector
{
const string GROUPCLAIM = "http://schemas.xmlsoap.org/claims/Group";
/// <summary>
/// The name of the custom HTTP header, Eg. "AUTH"
/// </summary>
[PipelinePropertyAttribute(Name = "AuthToken")]
public string AuthToken { get; set; }
/// <summary>
/// A comma separated list of authorized groups, Eg. Sales, Marketing
/// </summary>
[PipelinePropertyAttribute(Name = "InGroups")]
public string InGroups { get; set; }
/// <summary>
/// Processesing the Message
/// </summary>
/// <param name="message"></param>
/// <param name="context"></param>
/// <returns></returns>
public Task Execute(IMessage message, IMessageInspectorContext context)
{
bool isInGroup;
try
{
// Get the incomming SWT token
var token = message.GetPromotedProperty(AuthToken);
if (token == null)
throw new Exception(AuthToken + " token is null");
var requestedGroups = InGroups.Split(',');
var claims = GetClaims(token.ToString());
var groups = (from c in claims[GROUPCLAIM].Split(',')
select new GroupEntry(c)).Where(g => g.Type == "CN");
var isingroup = groups.Where(g => requestedGroups.Count(r => r == g.Name) > 0);
return Task.Factory.StartNew(() =>
{
message.Promote("IsInGroup", isingroup.Count() > 0);
});
}
catch (Exception ex)
{
throw ex;
}
}
}
* The GetClaims method and the GroupEntry class is part of the downloadable sample
Compile your project. and go back to your Bridge configuration. Select the Enrich stage again (outer rim) and click the On Exit Inspector in the property window.
Type the FQN of your Inspector class in the Type field, Eg:
InspectorsLibrary.AuthorizationInspector, InspectorsLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a1cd373975c6a197
Our newly created Inspector had two properties:
- AuthToken – The name of the custom token we’ll use
- InGroups – The authorized groups Eg: Sales,Marketing,Finance
Build and deploy your bridge.
4. Configure ADFS to issue tokens for ACS
Open the Azure Management Portal, and browse to the Active directory. Select the namespace you’re using for WABS, and select Manage to open the ACS portal. At the bottom of the navigation field, click Application Integration, and copy the WS-Federation Metadata URI. This file includes the Realm(s) of the ACS along with public keys etc, needed to configure the Relying Party Trust in ADFS.
Next open the ADFS Manager, and browse to the Relying Party Trust node. Right click the node and select Add Relying Party Trust and click the Start button.
Keep the “Import data about” option, and paste in the ACS WS-Federation Metadata URI. Click Next *4 and Finish (leave the checkbox to open the claims configuration).
In the Edit Rule dialog, click Add Rule, and Next. Give it a name and set the Attribute Store to Active Directory.
Select the “Is-Member-Of-DL” attribute and map it to the Groups claim.
Click Ok.
In the ADFS Manager, browse to the “Endpoints” node. Make sure the usernamemixed endpoint is enabled. Also make a note of the URI together with the FederationMetadata URI.
5. Adding ADFS Identity Provider in ACS
Go back to the ACS portal, and click Identity Providers. Click Add and select WS-Federation identity provider and Next.
Give it a name and set the login text (although will never use it). Paste or type the URI to the ADFS FederationMetadata. I ran into some problems here, and needed to copy it locally, and add it using the Browse option. This file includes all configured claims from ADFS (among many other things).
In the Used By section, deselect all applications but your WABS application.
To propagate claims from the ADFS token to the ACS token, we need to do one more step. Click the Relying Party Application node, and select your WABS application. At the bottom of the page, click the selected Rule Group. Click the Generate button, and select your new Identity Provider. Click Save.
6. Try it out!
Kudos to you if you made it this far!
If you download the sample, you’ll find the MessageSender project which I originally got from here. I’ve made some modifications to make it work with ADFS. It generally comes down to two methods at the end of the MessageSender class.
- RequestSamlToken – Uses a WSTrust channel to get the SAML token from ADFS.
- RequestSwtWithSamlToken – Similar to the GetAcsToken method, but uses assertion to pass along the SAML token rather then username/password as with the GetAcsToken.
Related links:
Federated Authentication for Azure Service Bus
Azure Service Bus
BizTalk Services
Blog Post by: wmmihaa