Monday, September 7, 2020

Azure Web Services Transformation


Summary

In this post I'll demonstrate an interim transformation of a premise-based web service to cloud-based services.  I'll be utilizing the MS Azure services stack for this transformation.

Premise Service Example

I'll use the key-value pair store implementation discussed in my previous post as the premise service to be transformed.  As a recap, this was a simple Nodejs/Express REST service defining Create (POST), Retrieve (GET), Update (PUT), and Delete (DELETE) service calls for key-value pairs stored in memory on the server.  Additionally, this service group used mutual TLS/client certificates for authentication to all the REST services.  Diagram below of the service.



FaaS Proxy

The first step in transforming this API to a cloud-based service will be creating proxy functions for each of the REST calls via Azure Functions.  Azure has a strong integration with VS Code via the Azure Functions Extension.  Below is a VS Code screen-shot of the resulting local REST API set developed for Azure Functions.  Note the 'authLevel' has been set to 'function'.  That means an Azure function-level API key must be provided to execute this function.



Code snippet below of the Azure CREATE function (REST POST).
'use strict';
'use esversion 6';
const https = require('https');
const fs = require('fs');
const fetch = require('node-fetch');
const key = fs.readFileSync("clientKey.pem");
const cert = fs.readFileSync("clientCert.pem");
const options = {
    key: key,
    cert: cert,
    rejectUnauthorized: false
};
const tlsAgent = new https.Agent(options);
const url = 'https://premiseServer:8443/kvp/';

module.exports = async function (context) { 
    try {
        const response = await fetch(url, {
            method: 'POST',
            body: JSON.stringify(context.req.body),
            headers: {'Content-Type': 'application/json'},
            agent: tlsAgent
        });

        context.res = {
            headers: {'Content-Type': 'application/json'},
            status: response.status, 
            body: await response.json()
        };
    }
    catch (err) {
        context.res = {
            headers: {'Content-Type': 'application/json'},
            status: 400, 
            body: {'error': err}
        };
    }
}



Deployment to the cloud can be accomplished via the VS Code extension as well.  Screen-shot below of the resulting push of this code/config to Azure.


Finally, diagram below of the full FaaS proxy model implemented with Azure Functions.  Function calls require the Azure Function key per function at this point.

 

API Gateway

Next step in the transformation is to place these Azure Functions behind an API Gateway.  The Azure implementation of that is the Azure API Management (APIM) service.  APIM adds important functionality such as authentication management, monitoring, throttling, etc.  Screen-shot below of the resulting mapping of each of the Azure functions to an APIM endpoint.  By default, APIM function access will require a 'subscription key'.  Additionally, APIM will auto-provision 'host key' authentication for access to the Azure functions that have 'function' auth level defined. 



Resulting architecture below:

 

Final Thoughts

Further Azure service integrations can be provisioned at this point.  Examples:  APIM will integrate directly with OAuth 2.0 authentications schemes, the APIM REST surface can be placed behind Azure Cloud CDN or Front Door services to add further functionality and resilience to the services.

Copyright ©1993-2024 Joey E Whelan, All rights reserved.