Azure BizTalk Rules Alternatives

 

All Preview API Apps including BizTalk Rules V1 API App was deprecated from Azure since Jan 18th, 2017. The migration path is to redeploy the V1 API App as App Service but this is not possible for built in BizTalk Rues API App.

Here are few alternatives of BizTalk Rules V1 API App:

Option 1: On-Premises BizTalk Rules Engine

we can use BizTalk BRE to define Rules in Rules Editor, deploy them on a BizTalk Server installation and write a Web API App to execute the policy through code, and we access the Web API App from Azure through a Hybrid Connection. The Logic Apps does not support Hybrid Connections yet, therefore we have to create a Relay Web App in Azure which take HTTP requests from the Logic App and pass it on to On-premises Rules Web API App.

 

Logic App –> App Service | Azure Hosted Relay Web API [Relay request and Cache Rules Result] –> Hybrid Connection –> On-Premises Web API –> BizTalk BRE Call

 

With this approach, we have access to full capabilities of BizTalk Rules Engine to create and execute complex Rules, and store and retrieve facts from on-premises SQL Server database. However, we need to have a BizTalk 2010+ installation on any on-premises server or on an Azure VM.

 

Option 2: CodeEffects Rules Engine

CodeEffects Rules Engine provide a web based Rules editing and testing platform, and we can choose this option if we don’t have a BizTalk Server installation, yet we want a UI based Rule editor and complex rules processing.

Logic App –> App Service | Azure Hosted Relay Web API [Relay request and Cache Rules Result] –> Hybrid Connection –> Code Effects Rule Engine

Option 3: Azure Functions as Rules Engine

 

Azure Functions is a solution for easily running small pieces of code in the cloud. The Code can be edited and deployed within Azure Portal. The idea is to use Azure Functions to defined and execute the Rules Logic and the Functions are invoked over an HTTP call from Logic Apps or Web Apps.

 

Logic App | Web App –> HTTP call to Azure Function –> Azure Function implementation

 

Option/Feature

Rules Authoring

Rules Complexity

Dependency

1: BizTalk Rules Engine

UI

Complex

BizTalk installation

2: CodeEffects

UI

Complex

CodeEffects Rules License/Free version

3: Azure Functions

Code

Custom Code

No

Posted in Azure, BizTalk, C#. Tags: . Leave a Comment »

Azure Service Bus: Securing message content

When working with web services published over Internet, it is immensely important to secure the data sent and received from the web services. To provide data security at transport level, we can use Secure Socket Layer/TLS. Secure Sockets Layer (SSL) provides encryption and signing the contents of the packets sent over TCP which makes data securely transmitted over network layer.
But this is not enough when the data being sent is of sensitive nature and no one except the receiver should be able to read it. We also need to consider data archiving or tracking at intermediate storage or message data security of inflight messages between the two systems. In such scenarios, it is very important to have message level security as well along with transport level security (SSL) in order to keep the data safe and secure.

In order to implement message level security, the data should be encrypted before sending over wire to the web service and when it reaches the destination, it should be decrypted. RSA and AES algorithms are the most commonly used modern times cryptosystems.

AES Advanced Encryption Standard is a symmetric cryptosystem widely used to encrypt large amount of data. AES makes use of a password and a salt to encrypt and decrypt data.

While RSA is an asymmetric cryptographic algorithm which means two keys are generated, one as public key which is used to encrypt the data and the other as private key used to decrypt the data. Unlike AES the RSA has a maximum data size limitation. The maximum size of data which can be encrypted using RSA with 2048 bits key is 256 bytes. This is the reason why we used RSA for encryption of small piece of data i.e. password and salt. Whereas for larger piece of data we used AES algorithm for encryption.

Using only RSA would have a negative impact on overall performance. As stated earlier the RSA can only encrypt and decrypt data of limited size, so we would have to partition data into several chunks with each not exceeding the maximum of 256 bytes including the padding size. Then applying encryption on each piece of chunk and after encryption, chaining these chunks together in a sequence which they were in before applying partitioning. The same strategy would have also needed to be applied at the time of decryption at the cost of performance degradation. All this would have added as a huge overhead to overall complexity and performance of encryption and decryption.

We used RSA to encrypt and decrypt small piece of data i.e. password and salt used in AES encryption and used AES encryption and decryption for the data payload.

Scenario

In our scenario there is a producer console application which picks up a HL7 Eligibility EDI file stored in a local folder, encrypts the data and posts it to a Logic App hosted in Azure.

The Logic App then stores the encrypted data in a Blob storage for archiving and sends the encrypted data to the Service Bus queue.

The consumer is an on premises web application which picks data from the Service Bus queue, decrypts it on premises and displays it on the screen.

clip_image001

We created a self-signed certificate and generated .cer that holds the public key to be used for encryption and .pfx that stores both private and public keys which is used for decryption.

The producer console application used public key to encrypt and the consumer web application used private key to decrypt.

Implementation Steps

1. We used AES cryptosystem to encrypt data using a randomly generated password and a Salt.

2. Then we encrypted randomly generated password and the Salt using RSA cryptosystem with the public key stored in a self-signed public certificate. (.cer file)

3. After getting all three pieces of information encrypted, a JSON message is created for sending encrypted content, encrypted password and encrypted salt to the Logic app. The data was base64 encoded before putting it in the JSON message

Example:

{

"content":"dz921W/64+ArEyrlE/2OI5CdAVvKXFlnIF43Y+zkrgftKiffLpy0a9Ei2YG4JGRqcH4I3wSI7H1vuC91sLHCgbyM0bIpR7G….JzL",

"password":"OwQQfWcCsuNNYo…==",

"salt":"GnmIBuy1rdK9cILpUc…1w=="

}

4. Once message is received at the Logic App, it stores it in a blob storage and sends it to a Service Bus queue.

clip_image003

5. A consumer web app get the encrypted message from Service Bus queue and decrypts encrypted password and SALT using the private key stored in a certificate which carries a private key along with public key and has the .pfx extension. Then using these decrypted password and Salt, decrypts the AES encrypted data and displays it on the screen.

clip_image005

How to Generate Self Signed certificate

There are multiple ways to generate a self -signed certificate but we used IIS Manager to generate one for our demo.

1. Open IIS Manager

clip_image007

2. Scroll down to IIS pane and double click icon ‘Server Certificates’

clip_image009

3. A new window will open, click Create Self-Signed Certificate on the right under the ‘Action’ pane

clip_image011

4. Give any name to the new certificate and create

clip_image013

5. Select newly created certificate and click on export from the right pane

clip_image015

6. Set a password and press Ok. This password is required when you are loading the certificate in the code or importing it to the certificate store.

Posted in Azure, C#. 1 Comment »

BizTalk EDI: Creating batching configuration in code

For outbound EDI batching, we have to create Batch Configuration in Party Configuration and set Filter Criteria about what messages should constitute one batch. But what if Filter Criteria is dynamic or we have too many batches to configure

here is code snippet to create batch configuration through API

 var builder = new SqlConnectionStringBuilder("DATA SOURCE="BTSSQLServer;Initial Catalog=BizTalkMgmtDb;
Integrated Security=SSPI;");
            using (var tmpCtx = TpmContext.Create(builder))
            {
                var agreement = (from p in tmpCtx.Agreements where p.Name == AgreementName select p).FirstOrDefault();
                if (agreement == null)//create agreement if does not exist.
                {
                    string Sender = ConfigurationManager.AppSettings["Sender"] ?? "SenderPartyName";
                    string Receiver = ConfigurationManager.AppSettings["Receiver"] ?? "ReceiverPartyName";
                    var OneWayAgreement = agreement.GetOnewayAgreement(Sender, Receiver); 
                    var firstBatch = OneWayAgreement.GetBatches()[0]; // first batch config is used as template
                    var newBatch = OneWayAgreement.CreateBatch(BatchName);
                    FilterPredicate predicate = firstBatch.GetFilterPredicate();
                    predicate.Groups[0].Statements[0].Value = "FilterRHS";
                    newBatch.SetFilterPredicate(predicate);
                    newBatch.SetReleaseCriteria(firstBatch.GetReleaseCriteria());
                    tmpCtx.AddToBatchDescriptions(newBatch);
                    tmpCtx.SaveChanges();
// this SQL insert is required to Activate the batch config
                    using (var cmd = new SqlCommand(@" INSERT INTO [dbo].[PAM_Control]
                                                                       ([EdiMessageType]
                                                                       ,[ActionType]
                                                                       ,[ActionDateTime]
                                                                       ,[UsedOnce]
                                                                       ,[BatchId]
                                                                       ,[BatchName]
                                                                       ,[SenderPartyName], ReceiverPartyName, AgreementName)
                                                                    SELECT 0 as EDIMessageType
                                                                  ,'EdiBatchActivate' as 'ActionType'
                                                                  ,GetDate() as 'ActionDateTime'
                                                                  ,0 as 'UsedOnce' 
                                                                  ," + newBatch.Id + @" as [BatchId]
                                                                  ,'" + BatchName + @"' as [BatchName], '"+ Sender +@"', '"+
 Receiver +@"', '" + AgreementName + "'", new SqlConnection(builder.ConnectionString)))
                    {
                        cmd.ExecuteNonQuery();
                    }
                }
                tmpCtx.Dispose();
Posted in BizTalk, C#. Tags: , . Leave a Comment »

.NET Integration with HSM

Recently had a scenario where we need to encrypt Card PIN code with keys provided by HSM. In our case, HSM was using TripleDES symmetric key algorithm for encryption and decryption. First, I tried with .NET Framework TripleDESCryptoServiceProvider, but that was not working.

After lots of trial and error, the solution was using Thales Simulator Library. Following is sample code for encrypting PIN with ZPK (Zone Private Key). ZPK was communicated between parties in encrypted format and we need to decrypt it first using ZMK (Zone Master key)

 

public static string GetEncryptedPINwithZPK(string CardNumber, string PIN)
{

         HexKey key = new HexKey("ZMK");
         string ZPK = ThalesSim.Core.Cryptography.TripleDES.TripleDESDecrypt(key, "EncryptedZPK");
            
         string PINBlock1 = ("0" + PIN.Length + PIN).PadRight(16, 'F');
         string CNumber = CardNumber.Substring(0, CardNumber.Length - 1); // to skip right most check digit
         string PINBlock2 = "0000" + CNumber.Substring(CNumber.Length - 12);

         HexKey ZPKHex = new HexKey(ZPK);
         string EncryptedPIN =  ThalesSim.Core.Cryptography.TripleDES.TripleDESEncrypt
(ZPKHex, XORStrings(PINBlock1, PINBlock2)); return EncryptedPIN; }
Posted in BizTalk, C#. 2 Comments »

Software Development – Design Concepts

 

I was going though scott hanselman’s post on Interview Questions and found some concepts that are new/interesting for me. posting here for my reference

SOLID (in context of Object Oriented Design)

S: Single responsibility

every object should have single responsibility. Easier to change code with minimum side effects

O: Open/closed

open for extension, but closed for modification. provides backward compatibility when extending the functionality

L: Liskov substitution

objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program

I:Interface segregation

many client specific interfaces are better than one general purpose interface. No client should be forced to depend on methods it does not use. Easy to change code, faster deployment when interface for only one client is changed

D: Dependency inversion

High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend upon details. Details should depend upon abstractions. advantage is loose coupling

Concurrency Control

Optimistic approach assumes that multiple transactions can complete without affecting each other and transactions  proceed without locking. Just before committing, each transaction verifies that no other transaction has modified its data. If the check reveals conflicting modifications, the committing transaction rolls back. Used in environments with low data contention.
In Pessimistic concurrency control, a transaction puts a lock before reading/writing and thus prevents other transactions to update the same data. suitable for high data contention scenarios

Posted in C#. Tags: . Leave a Comment »

Cannot Destroy Cluster on Windows 2008 R2

 

System error 1722 has occurred (0x000006ba).
The RPC server is unavailable.

1. Remove the following registry keys

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\ClusDisk

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\ClusSvc

2. Restart machine

3.Remove Failover Cluster Feature

Posted in C#. 10 Comments »

Invoke MiSys Equation API From .NET

Introduction

This article explains how to invoke MiSys Equation API (or any AS/400 program in general) through IBM i Access
for Windows component. The code is about calling an RPG compiled program (or
any OS/400 command) on IBM AS/400 iSeries server from .NET application

Background

MiSys Equation is the core banking system at one of my client, hosted on an iSeries server. we
need to expose Equation API/commands as .NET Services for any application to consume them regardless of the platform.
BizTalk and WCF is the platform for our middleware SOA implementation. IBM iSeries Access to Windows is a library from IBM to connect to iSeries application over TCP protocol.
This walk through describes how to expose MiSys Equation functionality as .NET library. we need to build a WCF or BizTalk service on top of this library method to expose it as web service.

Code Walk through

1. Install IBM iSeries Access to Windows. Also check for service packs
at this URL

http://www-03.ibm.com/systems/i/software/access/windows/casp.html

2. Create a new Console Application project in Visual Studio

3. Add Project Reference to cwbx.dll ActiveX from C:\Program Files
(x86)\IBM\Client Access\Shared

4. Add the attached API.cs file to your project

5. Now, we are going to connect to iSeries. we need to provide iSeries Server IP/Name, User Name and Password to connect.

//code snippet from attached API.cs

AS400System as400 = new AS400SystemClass()

Program program = new Program(); // iSeries Program (PGM)  

as400.Define("10.10.10.10"); //Server Name/IP
program.system  = as400;
program.system.UserID =User;
program.system.Password = Password;

as400.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd);
//Connect to execute Remote commands only

6. Once we are connected to iSeries, we need to initialize
liability(context) with Equation application. This context specifies to which Equation application instance we are going to connect, as there could be multiple application instances running on the server.
Parameters.Append() is used to defined the parameters and their length. All the parameters will be passed as a Byte array and the response will be a Byte array as well.

program.LibraryName = "KAPBASELIB";
program.ProgramName = "KAPUNLIBL"; 

StringConverter stringConverter = new StringConverterClass();
ProgramParameters parameters = new ProgramParametersClass();

parameters.Append("Env", cwbrcParameterTypeEnum.cwbrcInput, 3);
parameters.Append("A1", cwbrcParameterTypeEnum.cwbrcInput,4); 

parameters["Env"].Value = stringConverter.ToBytes("DEV");//Equation Instance
parameters["A1"].Value = stringConverter.ToBytes("*DFT");//default value 

program.Call(parameters);

7. Next step is to define and assign values to In and Out parameters and call Equation
API. you need to consult MiSys Equation Journal File Documentation to check for parameters length and whether they are Input or Output parameters

program.ProgramName = "H46HMR";//Inquiry API Wrapper
ProgramParameters parameters = new ProgramParametersClass();

SetInParameter(ref parameters, "EPGM",10, "H68EER");//Bal Inq Function identifier
SetInOutParameter(ref parameters, "DSAIF",3000, "00001xxxxx"); //Account No. 

program.Call(parameters);

8. Final step is to parse the response received from Equation. As you can see in the above code, DSAIF is input/output parameter and will have the response from Equation in the form of Byte array. we need to parse the byte array through StringConverter helper method

_response.Bytes = parameters[2].Value;

StringConverter stringConverter = new StringConverterClass();
stringConverter.Length = 0; // Use all bytes in source byte array to build string
string str = stringConverter.FromBytes(_response.Fields["HZCUN"].Value);

Points of Interest

couple of points worth noting

1. Input and Output parameters are Byte array. i.e. you need to take
care of order of parameters when using parameters.append()

2. use StringConverter, PackedConverter helper methods to convert
from Byte array to string

see the attached zip file for a sample implementation for Account
Balance Inquiry API.

Thanks to Joe Rattz for this article, which was starting point for me.