DataPower

 View Only

IBM DataPower Gateway Configurator

By RAVINDRA BAVISKAR posted Mon June 01, 2020 02:57 PM

  
To ensure that servers can be stood up with minimal manual intervention, it is essential that the server configuration is treated as code. This allows for quick, reliable and repeatable setup of servers. IBM DataPower® Gateway is no different and configuration in any non-trivial scenario should be completed programmatically.
There are several ways to configure the DataPower® Gateway device. They consist of graphical tools, automated, scripted and programmatic processes. DataPower configuration can be implemented through,
  • Web Access (WebGUI)
  • Device Command Line Interface (CLI)
  • REST Management Interface
  • XML Management Interface
XML Management Interface allows programmatic access and can be used for completely automated configuration.Regardless of the interface, only authenticated and authorized users can access the device.
Here, we will discuss how to enable XML Management Interface and how DP configurator uses it.

XML Management Interface

The DataPower® Gateway can be configured and managed completely using XML Management interface. XML Management interface uses HTTPS protocol for communication. XML Management SOAP request are schema validated to ensure the input request is valid. XML Management interface supports the following endpoints:
  • SOAP management URI
  • SOAP configuration management
  • SOAP configuration management (v2004)
  • WS-Management endpoint
  • WSDM endpoint
  • AMP endpoint
  • SLM endpoint
  • UDDI subscription (deprecated)
  • WSRR subscription
The interface is available in this URL format: https://address:port/service_uri For example, the URI for SOMA is available at: https:// xx.xx.xx.xx:yyyy/service/mgmt/current
This article focuses on the SOMA (SOAP configuration management) endpoint service.
 
To enable XML Management interface on the DataPower device complete the following steps as shown in Figure 1:
  1. Login as an administrator on the DataPower default domain.
  2. Choose Network -> Management -> XML Management interface. A configuration window will open as show below:
XML_Management_Interface.jpgFigure 1   XML Management Interface
  1. Set all the details such as Local Address, Port Number on which XML Management Interface will run. To use local host alias instead of static IP address, click Select Alias. A host alias resolves a locally configured alias to a static IP address. Aliasing can help to move configurations among DataPower Gateway instances
  2. Setup Access Control list to prevent unauthorised access to XML Management Interface.

          For more details on the ACL setup please refer to:         
          https://www.ibm.com/support/knowledgecenter/en/SS9H2Y_7.7.0/com.ibm.dp.doc/acl.html

  1. From Enabled services list, activate the check box for SOAP management endpoint.
  2. Apply changes and save configuration.

        For more details please refer to:                                         
        https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.7.0/com.ibm.dp.doc/xmi_interfaceservices_enabling.html

After the XML Management Interface is up and running, you can send the request to configure and manage the DataPower® Gateway using SOMA endpoint service.

SOAP configuration management (SOMA)

SOAP interface is a programmatic interface and provides the same capabilities as the GUI and CLI.

All the operations and actions that can be performed using SOMA are defined in the WSDL and schema files stored on the device (within the store: directory of File Management). The files are as below:
  • xml-mgmt.xsd
Defines the non-primitive management types in SOAP messages.
  • xml-mgmt-base.xsd
Defines the primitive management types in SOAP messages.
  • xml-mgmt-b2b.xsd
Defines the structure of SOAP requests to query B2B transactional metadata.
  • xml-mgmt-ops.xsd
Defines the operations which can be used for SOAP requests.
  • xml-mgmt.wsdl
Defines the services that are available through the SOAP interface.


The general format of the request is as shown below. If you wish to specify the domain where the action will run, you can set the domain attribute as shown in the example below.

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Body>
        <dp:request domain="{domain}"
            xmlns:dp="http://www.datapower.com/schemas/management">
                   ……
        </dp:request>
    </env:Body>
</env:Envelope>

For example, to construct a request for the create configuration operation, first find the operation defined in the file store:/// xml-mgmt-ops.xsd which is as below:

<!-- create configuration -->

   
<xsd:element name="set-config" type="tns:AnyConfigElement"/>

Now refer to the AnyConfigElement type in the file store:///xml-mgmt.xsd to see all supported configuration object types such as DomainSettings, NetworkSettings, CryptoCertificate etc. The general format of the response is as below:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
  <env:Body>
      <dp:response xmlns:dp="http://www.datapower.com/schemas/management">
      <dp:timestamp>timestamp</dp:timestamp>
      ....
    </dp:response>
  </env:Body>
</env:Envelope>

Refer to the store:///xml-mgmt-ops.xsd schema file for all the supported operations.

Generally, an organization uses the DataPower device with multiple domains as per the business requirement. Each domain needs to be configured for various application specific settings such as crypto certificates, crypto keys, password aliases, shared secret keys, network settings, domain settings etc.

There are various ways to manage configuration objects on the DataPower domain which are describe in below sections:

  • DataPower® Gateway extension: 
The object configuration can be maintained in the configuration xml (export xml) of the DataPower gateway extension along with any code files.
The export xml’s can be maintained for different environment thus allowing unique configuration for that environment. An extract from the export xml for one of the crypto certificates and key pairs is as below:
<CryptoCertificate name="api-msg-sign"   xmlns:env="http://www.w3.org/2003/05/soap-envelope"
      xmlns:dp="http://www.datapower.com/schemas/management">
       <mAdminState>enabled</mAdminState>
      <Filename>sharedcert:///api-msg-sign-public.cer</Filename>
      <PasswordAlias>off</PasswordAlias>
</CryptoCertificate>
<CryptoKey name="api-msg-sign"    xmlns:env="http://www.w3.org/2003/05/soap-envelope"
      xmlns:dp="http://www.datapower.com/schemas/management">
        <mAdminState>enabled</mAdminState>
        <Filename>sharedcert:///api-msg-sign-private.pem</Filename>
        <PasswordAlias>off</PasswordAlias>
 </CryptoKey>
This export xml is then packaged along with the gateway extension custom code and then applied to the DataPower domain.

There is a shortcoming with this approach. The extension custom code and configuration files are tightly coupled as part of the same deployment artifact. Also, export xml’s has all the configurations i.e. existing as well as new configuration to be created or modified. So, any configuration change requires a full extension build and deployment. This implies full testing, extensive planning and live traffic management is needed even to create or update a single configuration object.
  • SOMA based Scripts: 
DataPower® Gateway objects can be created or updated using SOMA based script. This could be simple shell script files consuming configurations files.
However, scripts typically lack rich features provided by programming languages and even simple tasks require long complex programs. Scripting also does not align with the organizational requirements for automation of builds, versioning of the configurations and creation of deployment snapshots.
  • DP Configurator (Automated Utility using JSON configuration & DevOps pipeline): 
This utility can be created using Node JS and CI/CD pipelines with fully automated build, deployment and release process to create and manage the Datapower configurations. The objects definitions of the DP domain can be maintained using JSON configuration files in GIT (Source Control Management tool) which can be made environment specific (e.g. dev, test, prod) thus allowing each to have different configurations in the various different environments.
Keeping configuration in source control management requires discipline, proper control and review on every commit or deployment. This could be mitigated using GIT features such as Pull Request for merging the new configuration and setting reviewer for each merge/commit.
In the next section we will show an example of a DP Configurator using NodeJS along with Jenkins and Urban code for CI/CD pipeline.

DP Configurator

The main objective of DP Configurator is to create and manage configuration objects on the DataPower® Gateway domain through automation and ensuring operational governance.
The chosen technologies are GIT, Node JS, Jenkins, Artifact repository (such as Nexus), and Urban Code Deploy.

Below are some of the configuration objects handled using the DP Configurator described in this article:
  1. Crypto Certificates
  2. Crypto Keys and Crypto Keys with Password Alias
  3. Crypto Shared Secret Key
  4. Password Map Alias
  5. LunaPartition
  6. LunaHAGroup

The concepts discussed in this article can be easily extended to include other configuration objects too.

Use Cases

There are various scenarios where DP Configurator, which are as follows:

  1. Setup of a new device
  2. Configuration management of devices
  3. Recreation of setup after firmware upgrade
  4. After gateway resynchronization

Design

Figure 2 illustrates the overview of DP Configurator along with the automated deployment mechanism.
DP_Configurator.jpg

Figure 2   DP Configurator  
DP Configurator consists of:
  •  dp-configurator repository 1   which has the implementation code for creating and managing configuration objects provided in dp-config.
  • dp-config repository 2 which has the configuration files.

Jenkins pipeline job 3 could be used to build the DP configurator artifact. It checks out dp-configurator and dp-config repository, builds the artifact, runs unit test and on success, pushes the artifact to the Artifact repository 4 (e.g. Nexus repository). The artifact will be pulled by the Jenkins job from the repository while creating the UCD deployment snapshot.
IBM Urban Code Deploy (UCD) job 5 can be used to run the DP configurator against the IBM DataPower Gateway 6. UCD application’s resource properties will be used to keep the DataPower gateway connection information such as DataPower host name, port, domain name and user credentials.

The artifact is run and tested in Dev environment first. On successful testing, it is further promoted to higher environment till Production following all the required processes and approval mechanism recommended by an organization.During the deployment process the UCD deployment job gets triggered with the deployment snapshot. The job extracts the DP Configurator artifact from the deployment snapshot. During the job execution process, DP Configurator constructs the SOMA request calls with payload for each configuration object specified in the DP Config and executes the call for the specified DataPower® Gateway domain.

DP Configurator

The DP Configurator has the implementation code which uses configurations provided in dp-config, constructs the SOMA request calls for each of the configuration object and executes on the specified DataPower® Gateway domain. The following Figure 3 shows the repository structure used for the DP configurator.

   Figure 3   DP Configurator repository structure

Jenkinsfile:  The Jenkinsfile contains the DevOps pipeline code.

createConfig.js/deleteConfig.js: This has the implementation to retrieve/read specified config json, formulate and execute the corresponding SOMA request calls to create, modify or delete the specified config objects.

somaRequest.js: This has the utility code to executes SOMA request calls for the specified DataPower device.

src/template_xml: This directory contains template xml’s for SOMA requests of configuration objects such as creating/updating/deleting Crypto certs, Crypto keys, password map alias, shared secret key, luna partition, luna ha group etc. The view of template_xml directory with sample template xml’s is shown in below Figure 3-1:

         Figure 3-1   template_xml directory

The following sections describes the examples of SOMA request templates for Crypto objects used in DP Configurator.
  • dp-getConfig.xml

This template is used to create SOMA request for retrieving existing configuration at the specified DataPower domain.

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:dp="http://www.datapower.com/schemas/management">
  <soapenv:Body>
    <dp:request domain="{{domain}}">
      <dp:get-config/>
    </dp:request>
  </soapenv:Body>
</soapenv:Envelope>

Figure 3-2   dp-getConfig.xml

  • dp-config-certs.xml

This template is used to create SOMA request for creating or updating specified crypto certificate object on the specified DataPower domain.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:dp="http://www.datapower.com/schemas/management">
  <soapenv:Header/>
  <soapenv:Body>
    <dp:request domain="{{domain}}">
      <dp:set-config>
        <CryptoCertificate name="{{name}}">
          <mAdminState>enabled</mAdminState>
          <Filename>{{file}}</Filename>
          <PasswordAlias>off</PasswordAlias>
          <IgnoreExpiration>off</IgnoreExpiration>
        </CryptoCertificate>
      </dp:set-config>
    </dp:request>
  </soapenv:Body>
</soapenv:Envelope>

Figure 3-3   dp-config-certs.xml

  • dp-config-keys.xml
This template is used to create SOMA request for creating or updating specified crypto key object on the specified DataPower domain.
<soapenv:Envelope
   xmlns:soapenv="http://www.w3.org/2001/12/soap-envelope"
   xmlns:dp="http://www.datapower.com/schemas/management">
   <soapenv:Body>
      <dp:request domain="{{domain}}">
         <dp:set-config>
            <CryptoKey name="{{name}}">
               <mAdminState>enabled</mAdminState>
               <Filename>{{file}}</Filename>
               <PasswordAlias>off</PasswordAlias>
            </CryptoKey>
         </dp:set-config>
      </dp:request>
   </soapenv:Body>
</soapenv:Envelope>

Figure 3-4   dp-config-keys.xml

  • dp-config-luna-partition.xml

This template is used to create SOMA request for creating or updating specified luna HSM partition object on the specified DataPower domain. Refer to the page for more details on Luna HSM: https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.7.0/com.ibm.dp.doc/lunahsm.html

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2001/12/soap-envelope"
    xmlns:dp="http://www.datapower.com/schemas/management">
    <soapenv:Body>
        <dp:request domain="{{domain}}">
            <dp:set-config>
                <LunaPartition name="{{name}}">
                    <mAdminState>enabled</mAdminState>
                    <UserSummary> {{summary}} </UserSummary>
                    <PartitionName> {{partitionName}} </PartitionName>
                    <PartitionSerial> {{serial}} </PartitionSerial>
                    <PasswordAlias class="PasswordAlias"> {{aliasName}} </PasswordAlias>
                    <LoginRole> {{role}} </LoginRole>
                </LunaPartition>
            </dp:set-config>
        </dp:request>
    </soapenv:Body>
</soapenv:Envelope>

Figure 3-5   dp-config-luna-partition.xml 

  • dp-config-luna-ha-group.xml

This template is used to create SOMA request for creating or updating specified luna HSM HA Group object on the specified DataPower domain. Refer to the page for more details on Luna HSM: https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.7.0/com.ibm.dp.doc/lunahsm.html

<soapenv:Envelope
    xmlns:soapenv="http://www.w3.org/2001/12/soap-envelope"
    xmlns:dp="http://www.datapower.com/schemas/management">
    <soapenv:Body>
        <dp:request domain="{{domain}}">
            <dp:set-config>
                <LunaHAGroup name="{{name}}">
                    <mAdminState>enabled</mAdminState>
                    <UserSummary>"{{summary}}"</UserSummary>
                    <GroupName>"{{groupName}}" </GroupName>
                    <Member class="LunaPartition"> "{{partition1}}" </Member>
                    <Member class="LunaPartition"> "{{ partition2}}"</Member>
                </LunaHAGroup>
            </dp:set-config>
        </dp:request>
    </soapenv:Body>
</soapenv:Envelope>

Figure 3-6   dp-config-luna-ha-group.xml

  • dp-config-certs-del.xml

This template is used to create SOMA request for deleting specified crypto certificate object on the specified DataPower domain.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <dp:request domain="{{domain}}" xmlns:dp="http://www.datapower.com/schemas/management">
            <dp:del-config>
                <CryptoCertificate name="{{name}}"/>
            </dp:del-config>
        </dp:request>
    </soapenv:Body>
</soapenv:Envelope>

Figure 3-7   dp-config-certs-del.xml

  • dp-config-keys-del.xml

This template is used to create SOMA request for deleting specified crypto key object on the specified DataPower domain.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <dp:request domain="{{domain}}" xmlns:dp="http://www.datapower.com/schemas/management">
            <dp:del-config>
                <CryptoKey name="{{name}}"/>
            </dp:del-config>
        </dp:request>
    </soapenv:Body>
</soapenv:Envelope>

Figure 3-8   dp-config-keys-del.xml

Similarly, various template xml’s can be created and used for creating, modifying or deleting configuration objects payload such as crypto objects, DomainSettings, AAAPolicy, NetworkSettings, Luna HSM Partition, Luna HSM HA Group etc.
All the configuration objects to be created, updated or deleted are specified in the json configuration files (please refer to DP Config section for more details on the json configuration files.)
These template xml’s along with the json configuration files will form the payload for each of the configuration object which is then used for the SOMA request calls.

The following node js files under src directory describes implementations for creating and executing the SOMA calls.

  • somaRequest.js
This has the function callSomaRequest which triggers SOMA calls for the specified DataPower device and the specified domain.
The SOAP interface URL used is: /service/mgmt/current
async function callSomaRequest(payload, options) {
  let payload = payload.replace('{{domain}}', domain);
  return new Promise((resolve, reject) => {
    let req = https.request(options, function (res) {
      if (!res.statusCode || res.statusCode !== 200) {
        console.error(res.headers);
        reject(new Error('SOMA Request failed, response code: ' + res.statusCode));
      }
    let output = {
        code: res.statuusCode,
        headers: res.headers,
        body: ''
      };
      res.setEncoding('utf8');
      res.on('data', (chunk) => {
        output.body += chunk;
      });
     res.on('end', () => {
        if (!output.body.match(/<dp:result>[\s\n]*?OK[\s\n]*?<\/dp:result>/g)) {
          reject(new Error('SOMA Request failed, response: ' + output.body));
        }
        resolve(output);
      });
    });
    req.on('error', (e) => {
       reject(new Error(`Problem with request: ${e.message}`));
    });
    req.end(payload);
  })};

Figure 3-9   somaRequest.js

  • createConfig.js

This is the main implementation file with the functions for creating configuration. It reads the resource properties from UCD jobs as shown below.

const somaEndpoint = '/service/mgmt/current';
 
const host = process.env.DP_HOSTNAME;
const port = process.env.DP_PORT;
const user = process.env.DP_USER;
const password = process.env.DP_PASSWORD;
const domain = process.env.DP_DOMAIN;

It has various utility functions such as to retrieve existing configuration from the specified DataPower domain, read the new configuration provided using dp-config. The new provided configuration could be verified and matched against the existing configuration while constructing SOMA calls.

async function getConfig() {
  console.log('Getting DP Configurations');
  let payload = fs.readFileSync('build/template_xml/getConfig.xml', 'utf8');
  payload.replace('{{domain}}', domain);
  return await callSomaRequest(payload, somaEndpoint);
}

To read the specified configuration file following function is used.

function processCreateConfigObject(configFile, somaRequestTemplate, existingObjects, jsonObjKey) {
  let configArray = [];
  try {
    let config = JSON.parse(fs.readFileSync(configFile, 'utf8'));
    configArray = config['' + jsonObjKey];
  } catch (err) {
    console.error(err)
  }
  return callCreateConfigObjects(somaRequestTemplate, configArray, existingObjects, jsonObjKey);
}

To create or update config objects the utility functions as shown below could be used, which helps to create or update the config object provided in json configurations.

async function callCreateConfigObjects(somaRequestTemplate, configJSONArray, existingObjects, objectType) {
  let existingConfigNames = Object.keys(existingObjects);
  return await Promise.all(configJSONArray.map(async (conf) => {
    console.log('processing configuration: ', JSON.stringify(conf));
 
    let overwrite = JSON.parse(conf.overwrite);
    let confName = conf.name.toLowerCase();
 
    if (((!overwrite && !existingConfigNames.includes(confName)) ||
      (overwrite && existingConfigNames.includes(confName)))) {
      console.log('Adding config object: ' + conf);
      return await createObject(somaRequestXML, conf, objectType);
    } else if (existingConfigNames.includes(confName) && !overwrite) {
      console.log('The config object Already exist:' + conf);
    } else {
      console.log('Wrong configuration for the object:' + conf.;
    }
  }));
}
 

Depending on the required object type various utility functions could be defined to create or update the configuration objects, for example, the below utility function is used for creating or updating crypto objects such as crypto certificates, crypto keys, crypto password alias map etc.

async function createCryptoObject(somaTemplate, config, isPasswordAlias) {
  let payload = getBasePayload(somaTemplate);
 
  payload = payload.replace('{{name}}', config.name.trim()).replace('{{file}}', config.filePath.trim());
  if (isPasswordAlias) {
    payload = payload.replace('{{aliasname}}', config.passwordAlias.trim());
  }
  return await callSomaRequest(payload, options);
} 

The following Utility method is used to save the domain after processing all the SOMA calls.

async function save() {
    let payload = fs.readFileSync('build/template_xml/savedomain.xml', 'utf8');
  payload.replace('{{domain}}', domain);
  return await callSomaRequest(payload, options);
}
  }));
}
  •  deleteConfig.js
As shown below, this defines utility functions to delete the config objects from the DataPower domain.
async function callRemoveObjectByName(somaRequestTemplate, configJSONArray, existingObjects) {
 
  return await Promise.all(configJSONArray.map(async (conf) => {
    console.log('processing conf for deletion:' + JSON.stringify(conf));
    if (existingObjects.includes(conf.name)) {
      console.log('Delete config object:' + conf.name);
      return await deleteObject(somaRequestTemplate, conf.name);
    } else {
      console.log('The configuration object does not exist:' + conf.name);
    }
  }));
}
 
async function deleteObject(somaRequestTemplate, name) {
  let payload = getBasePayload(somaTemplate);
  payload = payload.replace('{{name}}', name.trim());
  return await callSomaRequest(payload, options);
}

The main function of the DP configurator is to process all the specified config objects using all these utility methods and relevant template xml’s to create, update or delete the config objects on the DataPower gateway domain.

DP Config

This repository is used to maintain all the configuration object’s files. This could be segregated by environment as shown below.

            Figure 4   dp-config

Configurations are categorized into multiple files depending on the type of config object, for example, dp-config-certs.json has all the definitions for crypto certificate objects.

All files are in json format here.  

Sample configuration files are described below in detail.

  • dp-config-certs.json

This file has all the definitions for crypto objects corresponding to crypto certificates.

Example configuration:

{
    "certs": [
         {
            "name": "access-token-sign-object",
            "filePath": "sharedcert:///access_token_sign_object.cer",
            "overwrite": false
        },
        {
            "name": "msg_sign_object",
            "filePath": "sharedcert:///msg_sign_object_public.cer",
            "overwrite": false
        }
    ]
}

Figure 4-1   dp-config-certs.json

Configuration Fields:

Field

Required

Purpose

name

Yes

The name of the Crypto certificate Object

filePath

Yes

The file path of the certificate file on the device.

overwrite

Yes

By default, false. It is true if we wish to overwrite the existing object.

 

  • dp-config-keys.json

This file has all the definitions for crypto objects corresponding to crypto keys.

Example configuration:

{
    "keys": [
        {
            "name": "access-token-sign-object",
            "filePath": "sharedcert:///access-token-sign-object-private.pem",
            "overwrite": false
        },
        {
            "name": "msg-sign-object",
            "filePath": "sharedcert:///msg-sign-object-private.pem",
            "overwrite": false
        }
    ]
}

Figure 4-2   dp-config-keys.json

Configuration Fields

Field

Required

Purpose

name

Yes

The name of the Crypto key Object

filePath

Yes

The file path of the key file on the device.

overwrite

Yes

By default false, is true if overwriting the existing object.

 

Similarly, there are configurations files for each type of config objects such as crypto objects (shared secret key, password map alias etc.), domain settings, network settings, luna HSM partition, luna HSM HA group etc.

Conclusion

DP configurator can be used as a good alternative to the DataPower® Gateway extension and SOMA based scripts for creating, updating or deleting the various configuration objects on the DataPower® Gateway. The source version control tool such as GIT and CI/CD pipeline tools such as Jenkins, IBM Urban code deploy (UCD) can be used to provide enhanced automation and governance mechanism to the solution.
In this article we have presented how to build, develop and use DP Configurator, the automated solution for creating and managing various configuration objects on the DataPower® Gateway following DevOps principles.

 

References

https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.7.0/com.ibm.dp.doc/welcome.html 

http://www.redbooks.ibm.com/redpapers/pdfs/redp4327.pdf

https://www.redbooks.ibm.com/redbooks/pdfs/sg247901.pdf

https://www.redbooks.ibm.com/redpapers/pdfs/redp4446.pdf

https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.7.0/com.ibm.dp.doc/xmi_soapinterface.html

https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.7.0/com.ibm.dp.doc/networkaccess_xmi.html

https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.7.0/com.ibm.dp.doc/lunahsm.html

 

Authors & Acknowledgement

This article is the outcome of problems and challenges we recently encounter while working with the customer. 
The authors @RAVINDRA BAVISKAR and @Shishir Narain feels that this would be useful for others in the technical community.


We would like to express our gratitude to @Aiden Gallagher for reviewing this article.




 

​​​​
1 comment
80 views

Permalink

Comments

Wed June 17, 2020 03:07 PM

from where we can down load this one