I recently worked on a POC which had me spinning up an EDIFACT/AS2 exchange based on both BizTalk Server and MABS (Microsoft Azure BizTalk Server) and comparing the experiences. Seeing as this was my first time dealing with AS2 (EDIFACT was already an old friend) the very first thing I worked on was finding a means of sending messages to the AS2 onramps.
I found a few open source programs that would let me submit AS2 messages but I decided I wanted to do this programmatically instead via BizUnit 4.0 so I had easily repeatable scenarios, which I could easily re-test across BizTalk Server and MABS. Matt Frear has written a good post on how to send messages via AS2 using .NET, and I decided I was going to convert this into a BizUnit test step (with his blessing).
You can find the source code for the AS2SendTestStep here, or if you just want to download the assembly then you can do so here.
The test step support the below features.
- Supports BizTalk Server and MABS (and theoretically other AS2 server products, but I haven’t tested any others).
- Supports BizUnit data loaders which means that if you have many tests which require only slight variations to input messages then you don’t need to keep multiple copies of input files. You can just have a single base file and use a relevant DataLoader class to manipulate the stream as it is being read.
- Supports signing and encrypting outbound messages.
- Supports optional synchronous MDNs and allows you to validate them.
- Logs decrypted MDN messages to the test execution report.
Usage tips are below.
- You will need to reference the BizUnit.AS2TestSteps.dll assembly and the BizUnit.dll assembly provided by the BizUnit 4.0 framework.
- Select an input file directly by supplying the file name into the InputFileLocation property or supply a BizUnit DataLoader (which allows you to manipulate the file as you read it in) in the InputFileLoader property.
- Encrypt the outbound message – you will need a copy of the public key certificate and will need to supply the file path to it in the EncryptionCertificateFileLocation property.
- Sign the outbound message – you will need a copy of the private key certificate and will need to know the password. You will need to supply the path to the certificate to the SigningCertificateFileLocation property and the password to the SigningCertificatePassword property.
- Supports setting AS2From and AS2To headers via the As2From and As2To properties.
- Supports the use of a proxy server by setting appropriate values to the Ps property which allows you to supply the proxy server URL, and if required credentials as well.
- Allows you to set the subject HTTP header by setting the As2FileName property.
- Allows you to set the URL to post the request to by setting the Url property.
- Allows you to override the default timeout of 20 seconds by setting the TimeoutMilliseconds property.
- Allows you to run BizUnit substeps against the decrypted response message in case you want to validate it by suppying substeps into the SubSteps property.
An example test which sends an EDIFACT message to BizTalk Server (using a proxy server) and runs some regular expressions against the synchronous MDN response is below. Note that the RegexValidationStep in use here is not part of the BizUnit framework and is proprietary so sorry I can’t share that.
var testCase = new BizUnit.Xaml.TestCase();
var as2TestStep = new AS2SendTestStep();
as2TestStep.As2From = "FABRIKAM";
as2TestStep.As2To = "CONTOSO";
as2TestStep.EncryptionCertificateFileLocation = @"c:\host.cer";
as2TestStep.As2FileName = "EFACT_D95B_CODECO_output.txt";
as2TestStep.InputFileLocation = @"c:\temp\EFACT_D95B_CODECO_output.txt";
as2TestStep.SigningCertificateFileLocation = @"c:\fab.pfx";
as2TestStep.SigningCertificatePassword = "test";
as2TestStep.TimeoutMilliseconds = 20000;
as2TestStep.Url = "http://localhost/AS2Receive/BTSHTTPReceive.dll";
WebTestPlugins.AS2Helpers.ProxySettings ps = new WebTestPlugins.AS2Helpers.ProxySettings();
ps.Name = "http://proxyserver.test.co.nz";
as2TestStep.Ps = ps;
var regexValidationStep = new RegexValidationStep();
regexValidationStep._RegexDefintion.Add(new RegexDefinition("Content-Type: message/disposition-notification"));
regexValidationStep._RegexDefintion.Add(new RegexDefinition("Disposition: automatic-action/MDN-sent-automatically; processed"));
regexValidationStep._RegexDefintion.Add(new RegexDefinition("Final-Recipient: rfc822; CONTOSO"));
var bizUnitTest = new BizUnit.BizUnit(testCase);
And below is a screenshot of the test execution results. Note that the MDN text is logged here, and you can see the regular expressions being evaluated against the MDN as well.
You can of course take your own test steps much further by validating that BizTalk/MABS has consumed the file and written the message to its target destination, be it a SQL database or a file system folder etc… using the out of the box BizUnit test steps or your own custom ones.
The test step doesn’t currently support compression. If anyone can point me towards any good documentation on compressing AS2 messages in C# then I might try to include that.
Any other suggestions are welcome.
I’m pleased to announce that the White Paper titled “The A-Y of running BizTalk Server in Microsoft Azure” which I have been working on for the last two months is now available to download on the BizTalk 360 White Paper collection.
Writing this White Paper has been a momentous task, especially given that Microsoft Azure is an ever-changing entity (I’m pretty certain my synopsis on D-series VMs is already a bit dated since Microsoft have recently released new information stating that they sport faster CPUs, which I was previously unaware of, in addition to having SSDs) and I owe all the reviewers a big deal of thanks for their help.
This endeavour started out as a blog post (I just deleted the draft) and it quickly became apparent that the topic was well larger than anything I could cover within a single post and required a lot more attention to detail.
I hope the paper proves to be interesting and valuable to you, and as always welcome any feedback.
It will be nice to get back to blogging again 🙂
There is a ton of online documentation about Windows Azure VMs that advise that static IP addresses are not supported and that one must rely on dynamic IP addresses since Windows Azure VMs will hold onto those IP addresses for the lifetime of the VM. Take for example this article about deploying AD on a Windows Azure Virtual Network which advises to even use dynamic IP addresses on a domain controller.
This used to be true! Well, it kind of still is….in some cases…
Recently Microsoft released a fantastic new feature which makes Windows Azure VMs that much more compelling for developers in that when a VM is shut down from the Windows Azure Portal (not from the guest operating system which still continues the previous behaviour) it now actually gets deallocated and thus you are not charged for those compute units. This is very attractive for developers with MSDN accounts (who recently had some major price discounts applied on their compute units and on many other Azure services as well) as they can now consider scaling up their development machines to higher levels and still stay within their account limits by shutting down and deallocating their machines when they are not in use.
One by-product of this change is that when a machine has been deallocated its IP address is no longer reserved for that machine and is put back into the pool of available IP addresses and will be assigned to the next machine that is allocated. Shutting down the machine via the guest operating system doesn’t deallocate the machine and thus this problem isn’t seen then. This issue can have significant impact if you have a domain controller/DNS server running on your Azure virtual network which you shut down and deallocate to save money.
You can try to start up your deallocated machines in exactly the same order every single time to ensure that they get back the same IP address, or you can consider putting the domain controller/DNS server onto an isolated subnet of your virtual network so that there is no contention for its IP address.
If preserving an IP address if of major importance to you then you can either leave the Azure VMs running or always shut then down from the guest operating system rather than via the portal in which case the machine remains allocated and thus the IP address is preserved. Remember that even if the machine is shut down you will still be getting charged compute units if it isn’t deallocated.
Continuing my foray into the world of Azure I started playing with using my Azure VM as an ADFS server with the goal of using it as an identity provider in Windows Azure ACS for the appropriate candidate azure services. I followed the instructions on this fantastic step by step walkthrough by Haishi Bai (he sure does make it easy for those who are learning their way) but I ran into a problem when I tried to get the Identity and Access extension (on a side note make sure you have the WIF runtime installed on the server, then install the WIF SDK, and only then install the Identity and Access Visual Studio extension or you will face a null object reference type error when opening Visual Studio and the extension won’t load) in Visual Studio to use my Azure ACS namespace as an identity provider.
According to the instructions on this blog post and on many others one should browse to the Access Control Services management portal, click on the Management Service link, click on ManagementClient then symmetric key and take down the key value that is listed here.
Now to have Visual Studio connect to your ACS namespace you need to open the Identities and Access menu by right clicking on the project and selecting that item, choosing to use the Windows Azure Access Control Service and then pressing the configure link to choose an ACS namespace. Now the guidance says that you should place your ACS namespace in the first textbox and your symmetric key in the second.
Unfortunately you’ll find that chances are this wont work. You will be faced with a ID1113 error (you can see it by hovering over the red exclamation mark) which states that the combination of namespace and management key are invalid. Browsing around the internet (there are many places where this suggestion is made but it is probably worded best in this blog post) suggests that this is a common problem when you have created the ACS namespace in the new Azure Management Portal and have suggested that you should instead create the ACS namespace in the old portal instead (you can access the old portal by clicking on your name on the top right hand side of the portal screen and choosing previous portal).
What I have found however is that if I instead entered the ManagementClient password instead of the symmetric key then the extension seems to accept the combination and allows me to choose from the identity providers that I have configured in the ACS management portal. I do not know why the password is accepted while the symmetric key isn’t when that is apparently what is being asked for, but for others who are also stuck at this step use the password instead.
I hit an interesting problem today while trying to RDP to my Windows Azure VM using active directory credentials where I was getting an error message stating “An authentication error has occurred. The local security authority cannot be contacted.”.
This VM was connected to a domain, my domain controller also being an Azure VM. At some point I must have set the DNS settings on my VM to obtain the DNS server address automatically rather than explicitly point at my domain controller and this was the cause of my problem. The problem didn’t present itself till I rebooted the VM in question, and since a bit of time had passed in between the two actions it wasn’t immediately obvious what the cause of the problem was.
To fix the issue I had to swap the credentials I was using to remote into my VM to a local account (when you provisioned the VM you would have created a local account, if you don’t remember these credentials or any other local account details that have RDP access then you might be in some trouble) which allowed me to successfully remote into the VM, and then had to set the DNS server address to explicitly point at the IP address of my domain controller. Props to Kevin P. Sullivan who mentioned this solution on this discussion board.
My colleague Mark Brimble has also pointed out to me that he has seen the exact same error for a newly provisioned local user on an on premise VM for which the password had to be reset upon the first login, so take note that there might be other causes for this error message.
For those of you who aren’t very familiar with network settings hopefully the below screenshots should guide you (the highlights denote what you need to click/change).