Thursday, December 16, 2021

LB Cash In Mobile (CIM) awarded the Silver for Best Business Model Innovation at FITIS digital excellence awards

LB Finance is the largest Non-Banking Finance organization in Sri Lanka.

State of the art digital wallet of LB Finance, which is named LB CIM was awarded the Silver award at the Federation of Information Technology Industry Sri Lanka (FITIS)


























LB Cash In Mobile (CIM) is available for both Android and IOS platforms and provides financial transactions at fingertips. 

















Core Finance system of LB Finance was revamped with the latest cutting edge technologies and tooling. It is designed with Microservice APIs and considering Open API/Banking API models. Furthermore it is designed and developed as a Cloud-First and Mobile-First solution. 

Availability of secure APIs enabled the business to introduce new unique features for the customer facing application which is LB CIM. Due to that, the CIM and LB Finance was able to report a rapid growth even under the COVID pandemic.


















I am privileged to lead the software development unit which is Center for Innovation and Technology (CIT) that revolutionized the direction of LB Finance and pioneered the use of technologies in the banking sector as a whole. The technical team at CIT consists of around 30 software development professionals, 15 quality assurance professionals and 10 professionals to analyze business requirements.

We are taking the initial steps to migrate the Core Finance system to a public cloud which would enhance the agility further

Wednesday, December 8, 2021

Azure Policy : How I managed to comply ISO 27001:2013 for my cloud workloads

We can have many resources in our cloud. How can we enforce compliance and governance out there?

Let's say that we are already compliant with ISO 27001:2013 for our on-premises workloads. How can we achieve it after the cloud migration?

Or how can we stay compliant if we have a hybrid setup?

If your cloud provider is Microsoft Azure, then you are lucky. You can use the features of Azure Policy to save you.

Azure Policy is a service provided by Microsoft Azure, where you can assign individual policies or initiative (collection of policies) to a targeted scope (e.g. Subscription) to ensure they are governed according to those policies.

Let's try out by creating an initiative. Luckily we have ISO27001:2013 as a built-in initiative






























Let's see the result.

In order to check the level of compliance, navigate to the initiative and click on View compliance link.

This was my initial score. Lot to improve, isn't it :)














As you can see below, we can see a summary of compliance split into following areas

  • Controls
  • Policies
  • Non-compliant resources
  • Events

Let's see a sample control.

Let's take the Password management system control













Now we know the current position. It's time to do some housekeeping to make our tenant compliant

Tuesday, December 7, 2021

Azure Durable Functions with retry options and retry operations

This is the third post of a serious of articles on Azure Functions/Durable functions. This is the continuation of my previous post on Durable Functions.

In this post we will discuss how we handle failures, specifically retry operations with Durable Functions.

Ability to handle failures is a key benefit that Durable Functions offer us. It is implemented using features of Durable Task Framework.

In order to illustrate retry operations we use the same example we used in previous article. Let's say saving contact details in CRM system is a heavy process and it is not under our control. Let's say it is a SaaS platform provided by a vendor. It can fail due to various reasons like

  • Network related failures
  • Planned/unplanned downtimes of the SaaS platform
  • etc..
Let's implement the retry pattern

Step 1: Instantiate RetryOptions object in our Orchestrator function. We have to specify retry interval and maximum retry attempts

We will filter out the exception and I will retry only when there is a network error. And we will retry three attempts

var retryOptions = new RetryOptions(System.TimeSpan.FromSeconds(5), 3)
{
    Handle = ex => ex.Message.Contains("Network Error")
};


Step 2: Instead of using CallActivityAsync function we will use CallActivityWithRetryAsync function. Following is the implementation of orchestration function after using retry options

[FunctionName("DurableCustomer")]
public static async Task RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Customer customer =  context.GetInput();


    int customerId = await context.CallActivityAsync("DurableCustomer_AddToSQL", customer);


    var retryOptions = new RetryOptions(System.TimeSpan.FromSeconds(5), 3)
    {
        Handle = ex => ex.Message.Contains("Network Error")
    };

    int returnId = await context.CallActivityWithRetryAsync("DurableCustomer_AddCRM",retryOptions,customerId);

    return returnId;
}

Step 3: Let's change the AddCRM function a little bit and generate a custom error

[FunctionName("DurableCustomer_AddCRM")]
public static int AddToCRM([ActivityTrigger] int customerId, ILogger log)
{
    //insert to CRM
    int returnId = customerId * 10; //return code from CRM insert
    throw new System.Exception("Network Error");
    //return returnId;
}

Step 4: Let's deploy and check in postman. In the same time we will navigate to Monitoring -> Log Stream section of the Function App in Azure portal.























Let's check log stream. Look, I got four error messages. Original error and three attempts just after that




















Durable Functions have other error handling mechanisms as well. We have discussed only the retry pattern in this article.

Hope this helps :)

Update 16-02-2022 : I've uploaded the code to this repository

Thursday, December 2, 2021

Azure Durable Functions to implement function chaining with custom data

In my previous post I explained how to post to Azure Function with .NET 6. Let's  complicate the scenario a little bit.

Let's say that we need to save a customer, but we will store customer id and name in our own SQL database and need to send the email address to a CRM system. 
Following are the steps
  • Insert customer name to Azure SQL instance
  • Generate auto increment id in Azure SQL
  • Insert customer contact in external CRM with auto increment customer id
  •  











Can we develop this logic in a single Function?

Yes it is possible. But it is not the best practice. Following are some of the issues and risks I can see
  • First of all it is violating the Single Responsibility concept. 
  • We should not start CRM insertion part until the SQL insertion is completed. So some sort of statefulness is required.
  • How can we ensure the durability and consistency. Let's say External CRM fails, what can we do for the entire transaction.
What would be the best solution then?

We can use Azure Durable Functions to achieve the functionality. 

What is Azure Durable Function?

Azure Durable Functions allow you to author stateful functions in a serverless compute environment. We need to break our logic into several functions.
  • Client Function (trigger)
  • Orchestrator Function
  • Activity Function
Let's implement our logic

Step 1: Create Function. We need to specify storage account during the creation process. This is to maintain the state. Scaffolding generates a sample base which is very helpful.


























Step 2: Let's add our customer class




















Step 3: Let's create our activity functions

[FunctionName("DurableCustomer_AddToSQL")]
[FunctionName("DurableCustomer_AddToSQL")]
public static int AddToSQL([ActivityTrigger] Customer customer, ILogger log)
{
    //insert to SQL logic
    int customerId = customer.id; //should be populated with the reusult
    return customerId;
}

[FunctionName("DurableCustomer_AddCRM")]
public static int AddToCRM([ActivityTrigger] int customerId, ILogger log)
{
    //insert to CRM
    int returnId = customerId * 10; //return code from CRM insert
    return returnId;
}

Step 4: Let's modify our orchestrator

[FunctionName("DurableCustomer")]
public static async Task RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Customer customer =  context.GetInput();

    int customerId = await context.CallActivityAsync("DurableCustomer_AddToSQL", customer);
    int returnId = await context.CallActivityAsync("DurableCustomer_AddCRM", customerId);

    return returnId;
}
 

Step 5: Let's do necessary amendments to our http trigger function to accept Customer object

public static async Task HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
    // Function input comes from the request content.

    var customer = await req.Content.ReadAsAsync();

    string instanceId = await starter.StartNewAsync("DurableCustomer", customer);

    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

    return starter.CreateCheckStatusResponse(req, instanceId);
}

Step 6: Let's deploy our function













Step 7: Let's try this with Postman


















Step 8: Get the StatusQueryGetUri to check the status






















Great !!. We will discuss how to handle retry operation in my next post