Monday, June 18, 2012

Centralized SSO Application Configuration Data Store

Reading application configuration data from a Single Sign-On database is a well-known concept within the BizTalk community. There are other means of retrieving application configuration data for BizTalk, yet retrieving them from SSO is the most powerful one. Microsoft has built an SSO Application Configuration Snap-In that provides a good user experience maintaining custom configuration data. With the Snap-In you will also get code for a .NET Helper Class to support retrieval of application configuration data in BizTalk. This approach has some major benefits. Your application configuration data is cached, has a built in refresh mechanism (ESSO Service) and is secure.
What if you have a requirement that to remotely (from a non-BizTalk machine) retrieve application configuration data, because you like to benefit from SSO Config Store?
Consider the following diagram
In this scenario a mapping is implemented using a Functoid based on a shared helper class that reads the connectionstring information from SSO. Why all this trouble, well….BizTalk is not the only product that can do transformations, -and it’s worthy to write another post on when to use what product- but let’s say that this helper class is designed with in mind that the functionality will re-used by other interfaces which are developed using Sql Server Integration Services (SSIS) interfacing.
The implementation forces us to enable the machine that runs SSIS to access the SSO Database, that is, using the SSO API.
Business scenario
We use the BizTalk Deployment Framework (BTDF) to create an SSO Application, the BTDF uses the BizTalk Configuration to determine the location of the SSO. This works fairly easy since the Enterprise Single Sign On service is available on the BizTalk machine and all the required components.
However an SSIS machine….has no BizTalk, no Enterprise Single Sign on Service, no SSO Client…
Why is the SSIS arrow in red….well…getting this scenario to work is not what you call ‘a walk in the park’.
Steps to implement this scenario, what can go wrong
· Installing the SSOClient (I used the setup from BizTalk and only installed the administration components)
o Configure the SSO Server
Note: SSO Affiliate Applications are visible
· SSOAdministration MMC Snap-in
o Verified that the server is available
· Program Files\Common Files\Enterprise Single Sign On
o Verified using ssomanage –listapps that REMOTE applications are visible/shown
· DTC Ping
Performed a ping on the client/server
· Create a test client with different SSO Interop dlls
o Unhandled Exception:
System.Runtime.InteropServices.COMException: Could not contact the SSO server '<Server>'. Check that SSO is configured and that the SSO  service is running on that server.

(RPC: 0x800706D9: There are no more endpoints available from the endpoint mapper.)
at Microsoft.BizTalk.SSOClient.Interop.ISSOConfigStore.GetConfigInfo(String applicationName, String identifier, Int32 flags, IPropertyBag properties)
at SSOSettingsFileManager.SSOSettingsFileReader.Read(String affiliateApplication)
at SSOSettingsFileManager.SSOSettingsFileReader.ReadString(String affiliateApplication, String valueName
at SSOSettingsFileReader.ReadString(String affiliateApplication, String valueName) at CheckSSOSetting.Program.Main(String[] args)

How to solve this
To implement this scenario you would have to create a custom SSO client (or make some minor modifications).
· In our case the BTDF created the SSO Application using a specific GUID, ensure that when you read settings from an SSO Application, that the same GUID is used for reading settings

public static string InfoIdentifier = "{56D74464-67EA-464d-A9D4-3EBBA4090010}";
· Use the correct SSO Flag
//SSOFlag.SSO_FLAG_RUNTIME does not work from a remote machine
private const int SSOFLagsToUse = SSOFlag.SSO_FLAG_NONE; 

The SSO Client code
To be able to communicate with the SSO Server from a non-BizTalk machine the client code that works for SSO Application created with the BTDF is listed below;

public static string InfoIdentifier = "{56D74464-67EA-464d-A9D4-3EBBA4090010}";

//SSOFlag.SSO_FLAG_RUNTIME does not work from a remote machine
private const int SSOFLagsToUse = SSOFlag.SSO_FLAG_NONE; 
ISSOConfigStore configStore = (ISSOConfigStore)new SSOConfigStore();
SSOPropertyBag bag = new SSOPropertyBag();
configStore.GetConfigInfo(affiliateApplication, SSOHelper.InfoIdentifier, SSOFLagsToUse, bag); 
bag.Read(SSOHelper.PropName, out propertyValue, 0);
public void SaveConfigInfo(SSOPropertyBag bag, string affiliateApplication)
ISSOConfigStore configStore = (ISSOConfigStore)new SSOConfigStore();
configStore.SetConfigInfo(affiliateApplication, SSOHelper.InfoIdentifier, bag);
public void DeleteConfigInfo(string affiliateApplication)
ISSOConfigStore configStore = (ISSOConfigStore)new SSOConfigStore();
configStore.DeleteConfigInfo(affiliateApplication, SSOHelper.InfoIdentifier);

And voila…

Thanks to my colleagues from Microsoft Nico Stokman and Dick Dijkstra for their never ending enthusiasm to solve a problem where you didn’t wish you would have to go the extra mile to resolve it and Steef-Jan for his input and suggestions on this blog subject.


1 comment:

Steve Culshaw said...

Excellent post