Integrating with Entuity via webhook


Entuity is a network monitoring software designed to monitor, visualize, and manage the networks by proactively generating alerts about service impacts. As a tenant administrator, it's important that you can monitor the connected systems and quickly identify and resolve any issues. The BMC Helix Intelligent Integrations Entuity connector collects incidents data from Entuity by using the webhook mechanism.

You can view the collected data in various BMC Helix applications and derive the following benefits:

BMC Helix application

Type of data collected or viewed

Benefits

BMC Helix Operations Management

Events (Entuity incidents received as events) 

Use a centralized event view to monitor and manage events, perform event operations, and filter events. Identify actionable events from a large volume of event data by processing events.

For more information, see Monitoring events and reducing event noise.

As a tenant administrator, perform the following steps to configure a connection with Entuity via webhook, verify the connection, and view the collected data in various BMC Helix applications.

ConnectorSteps.png

Supported versions

The Entuity connector supports version 20.x of Entuity for data collection.

Task 1: To plan for the connection

Review the following prerequisites to help you plan and configure a connection with Entuity via webhook.

Entuity prerequisites

If Entuity and BMC Helix Intelligent Integrations on-premises gateway servers are in different domains or sub-domains, and on-premises gateway is using a custom certificate, import the custom certificate into the Entuity server:

  1. Back up the existing Entuity truststore:

    cp $Entuity_HOME/install/JRE/lib/security/cacerts $Entuity_HOME/install/JRE/lib/security/cacerts1

  2. Copy the certificate <IIGateway_INSTALL_DIR>/hii/conf/certs/<hostname>.crt from the on-premises gateway server to the Entuity server in a temporary directory.
  3. Import the certificate into Entuity:

    keytool -keystore $Entuity_HOME/install/JRE/lib/security/cacerts -importcert -file <pathtoCertificate> -alias "iionprem"

    Enter Yes when prompted to trust the certificate during import.

BMC Helix Intelligent Integrations prerequisites

  • Depending on the location of the third-party product (SaaS, on-premises), choose one or more BMC Helix Intelligent Integrations deployment modes and review the corresponding port requirements. For information about various deployment modes and port requirements, see Deployment-scenarios.
  • Based on the deployment mode, use the BMC Helix Intelligent Integrations SaaS deployment or the BMC Helix Intelligent Integrations on-premises gateway or both. For more information about the gateway, see Deploying-the-BMC-Helix-Intelligent-Integrations-on-premises-gateway.
  • Plan to configure a separate connection for each third-party instance. For example, if you have three Entuity instances that discover various subnets in your environment and a fourth Entuity aggregator instance that shows the aggregated data from the three instances, we recommend that you configure individual connectors for these three instances. You do not need to configure any connector separately for the aggregator instance.

In the preceding list, third-party product refers to Entuity.


Task 2: To configure the connection with Entuity via webhook

  1. Depending on the deployment mode, perform one of the following steps to access BMC Helix Intelligent Integrations:
    • BMC Helix Intelligent Integrations SaaS – Log on to BMC Helix Portal, and click Launch on BMC Helix Intelligent Integrations.
    • BMC Helix Intelligent Integrationson-premises gateway – Use the following URL to access BMC Helix Intelligent Integrations:
      https://<hostName>:<portNumber>/swpui
  2. On the CONNECTORS  tab, click add_icon.pngin the SOURCES panel.
  3. Click the Entuity Events tile.
  4. Specify a unique instance name.

    Best practice
    We recommend that you specify the instance name in the following format: 

    <sourceType>_<sourceControllerServerName>_<InstanceQualifier>

    The instance qualifier helps you to distinguish the multiple instances configured from the same source server. For example, you can name your instances as Entuity_Host_PROD and Entuity_Host_TEST.


  5. Click CREATE COLLECTORS to create the collector stream for the selected data type.
  6. Configure the distributors for the selected data type by clicking the data type in the Distributors section and specifying the parameters for the selected data type, as explained in the following table:
    Parameter name
    Description
    Max Batching Size
    Specify the maximum number of data items to send in a single POST request to the destination API.
    The batch size 
    depends on the destination’s ability to buffer the incoming data.Default: 250
    Max Batching Delay
    Specify the maximum time (in seconds) to wait before building and processing a batch.Default: 3 seconds 
    Base Retry Delay
    Specify the initial time (in seconds) for which to wait before retrying to build and process a batch.
    The waiting time increases in the following sequence: n1, n2, n3, and so on, where n indicates the number of seconds.Default: 2 secondsExample:Base Retry Delay is set to 2 seconds.Retry is performed after 2, 4, 8, 16, ... seconds.
    Max Intra-Retry Delay
    Specify the maximum limit for the base retry delay. Default: 60 secondsExample:Max Intra-Retry Delay is set to 60 seconds.
    Base Retry Delay is set to 2 seconds.Retries are performed 2, 4, 8, 16, 32,... seconds later.
    Max Retry Duration
    Specify the total time for retrying a delivery. For REST destinations, a delivery is a batch of data items in one POST request. Default: 5 minutesExample:Max Retry Duration is set to 8 hours.
    Base Retry Delay is set to 2 seconds.Requests are sent for 2+4+8+16+32+64+132... until 8 hours in total duration is reached. After that, no subsequent attempts are made to retry the delivery.The assumption here is that if there is an outage or other issue with the destination tool, recovery should take less than the value of the Max Retry Duration parameter to be completed.
    Attributes To Be Dropped When Updating Events
    Specify the event attributes that you do not want to be updated in BMC Helix Operations Managementwhen events are updated. For example, if you do not want an event's severity, source address, source category, and subcategory to be updated in BMC Helix Operations Management , you need to specify those attributes in a comma-separated format: severity,source_address,source_category,source_subcategory .Important:You can obtain the event attribute names in BMC Helix Operations Management, by exporting any event data in JSON, BAROC, XML, or CSV format . The exported file contains all attributes of the event data, and from there you can identify the attributes to be dropped. 
  1. Click CREATE DISTRIBUTORS to create the required distributor stream for the selected data type.
  2. Click VALIDATE AND CREATE and then click SAVE STREAM to save the stream.
    After you save the stream, the connector that you just created is listed on the SOURCES panel.
  1. On the SOURCES panel, click Configure Mediator ConfigureMediator_icon.pngfor the source connection that you created and then expand ENTUITY EVENTS.
  2. Click copy copy_URL.pngto copy the auto-generated Entuity webhook collector URL and save it in a temporary file.
    For example, https://hostA/hii/api/mediator/v3/push/9mn-6c97-4c2e-8pc5-12c0asdf?token=API-KEY.
  3. Depending on whether you are using only SaaS deployment of BMC Helix Intelligent Integrations or BMC Helix Intelligent Integrations on-premises gateway, perform the following steps:
    • If you are using only SaaS deployment of BMC Helix Intelligent Integrations or the on-premises gateway with authentication enabled, perform the following steps:
      1. Log on to BMC Helix Portal and generate an access key.
        For instructions, see Setting up access keys for programmatic access.

      2. Copy the generated access key and save it in a temporary file.
        The key is generated in the format: <accessKey>::<secretKey>::<tenantID>.
        For example, Y40OSC49QZA11Q8A1H9H6::MnVLk69TNyCEponsthHJ1Hj1uKcjTB::385261281
      3. Change the format of the access key to <tenantID>::<accessKey>::<secretKey>.
        For example, 385261281::Y40OSC49QZA11Q8A1H9H6::MnVLk69TNyCEponsthHJ1Hj1uKcjTB
      4. In a temporary file, modify the auto-generated collector URL by replacing API-KEY with the access key that you formatted in the previous step.
        For example, https://host.ab.com/hii/api/mediator/v3/push/9mn-6c97-4c2e-8pc5-12c0asdfd?token=385261281::Y40OSC49QZA11Q8A1H9H6::MnVLk69TNyCEponsthHJ1Hj1uKcjTB.
      5. Configure Entuity to forward incidents data to BMC Helix Intelligent Integrations.
    • If you are using the on-premises gateway with authentication disabled, perform the following steps:
      1. Save the URL in a temporary file.
      2. Remove the following string from the collector URL:?token=API-KEY
        The updated collector URL looks like the following example:
        https://hostA/hii/api/mediator/v3/push/9mn-6c97-4c2e-8pc5-12c0asdf
      3. Configure Entuity to forward incidents data to BMC Helix Intelligent Integrations.
  4. On the SOURCES panel, move the slider to the right to start the data stream for the connector you created in step 7.
    ImportantFor a data stream, the Run Latency (max/avg), Items (Avg per Run), and Last Run Status columns on the Streams page might show the status as No Runs during the data collection process. After completion of the process, these columns are updated with an appropriate status.


Task 3: To configure Entuity to forward incidents data to BMC Helix Intelligent Integrations

First create an action and then a trigger in Entuity.

  1. Log on to Entuity, and from the main menu, select Administration.
  2. On the Entuity Administration page, click Event Administration.
  3. Create the action to forward incidents data to BMC Helix Intelligent Integrations:
    1. Select the Actions tab and then click Add.
    2. In the Add Action dialog box, enter the following information:
      1. Enter a name for the action, for example, Send incidents to BMC Helix Intelligent Integrations .
      2. (Optional) Enter a description for the action.
    3.  In the Parameters section, click Add and enter the following information in the New Parameters dialog box:
      1. Enter the parameter name as URL.
      2. (Optional) Enter a description for the parameter.
      3. Depending on whether you are using only SaaS deployment of BMC Helix Intelligent Integrations or the on-premises gateway, copy the collector URL that you modified in step 11 and paste it as the default value of the parameter, enclosed in double quotes.
    4. In the Action Steps section, click Add and enter the following information in the Add Action dialog box:
      1. From the Type list, s elect the Groovy Script option.
      2. Copy the following script and paste it   in the Script field:

        Click here to see the Groovy script
        //Send events or incidents to BMC Helix

        // Types for ENA config management incidents and events  
        def changeIncidents = [341,342,343,345,346,348,349,350]
        def changeEvents = 341..350

        def isChangeClass = {
            def res = false;
            if(incident && changeIncidents.contains(type.toInteger()))
                res = true;
            if(event && changeEvents.contains(type.toInteger()))
                res = true;

            return res;
        }

        def getClass = {
            if(name.startsWith("CM") && isChangeClass())
                return "CHANGE_EV"
            if(incident)
                return "ENA_INC"
            else
                return "ENA_EV"    
        }

        def getKey = {
            if(incident)
                return id.toString()
            else
                return id + ":" + sequenceNum    
        }

        def getType = { sd ->
            if(! sd)
                return "Unknown"
            switch (sd.classicType) {
                case 1           : return "Port"
                case 8           : return "VLAN"
                case 512         : return "Domain"
                case 1024        : return "Application"
                case 2048        : return "IP Address"
                case 4096        : return "System"
                case 8192        : return "View"
                case 65536       : return "Service"
                case 4           : return (sd.swType != null ? sd.swType : "Device")
                case 2147483648  :
                case -2147483648 : return sd.swType
                default          : return "Unknown"
            }
        }

        def getHSeverity = {
            def sev = (incident && ! stateOpen) ? 2 : severity;
            switch (sev) {
                case 10 : return "CRITICAL"
                case 8 : return "MAJOR"
                case 6 : return "MINOR"
                case 4 : return "WARNING"
                case 2 : return "INFO"
                case 0 : return "UNKNOWN"
            }
        }

        def getESeverity = {
            def sev = (incident && ! stateOpen) ? 2 : severity;
            switch (sev) {
                case 10 : return "CRITICAL"
                case 8 : return "SEVERE"
                case 6 : return "MAJOR"
                case 4 : return "MINOR"
                case 2 : return "INFO"
                default : return "UNKNOWN"
            }
        }


        def getStatus = {
            if(! incident)
                return "OPEN"
            switch(state) {
                case 1 :
                case 8 : return "OPEN"
                case 2 :
                case 4 : return "CLOSED"
            }
        }

        /**
         * Returns a source for the event, that is
         * as close to the containing device as possible
         */
        def getContainerSource = { sd ->
            if(! sd)
                return null
            if (sd.classicType == OBJ_IPV4ADDRESS || sd.classicType == OBJ_IPV6ADDRESS)
                return sd.externalId
            else
                return sd.containerName
        }


        /**
         * Returns last updated or raised timestamp in seconds
         */
        def getTimestamp = {
            def timestamp = 0;
            if(incident)
                timestamp = lastUpdatedMs
            else
                timestamp = raisedMs

            Date d = new Date(timestamp)
            return (long)(d.getTime()/1000)
        }


        /**
         * Returns a webUI URL for object summary page of event or incident source.
         */
        def constructCrossLaunchUrl = { sd ->
            def url = "";

            def classicType = sd?.classicType
            def OBJ_TYPE_SYSTEM = com.entuity.events.event.ObjType.OBJ_TYPE_SYSTEM.toInt()
            def OBJ_TYPE_VIEW = com.entuity.events.event.ObjType.OBJ_TYPE_VIEW.toInt()

            if(classicType != OBJ_TYPE_VIEW) {

                def ssl = getConfigProperty("consolidation_server_web_ssl")
                if(ssl == null)
                    ssl = getConfigProperty("server.ssl_enabled")
                def proto = ssl == "true" ? "https" : "http"
                def swId = sd.swId

                if (swId != null) {
                    url = "${proto}://"

                    def hostAndPort = getConsolidatedSourceHostAndPort()
                    url += "${hostAndPort}"

                    if (classicType != OBJ_TYPE_SYSTEM) {
                        url += "/webUI/main.do?url=/webUI/objectSummary.do%3Fserver%3D${sourceDescriptor?.eyeServerId}%26id%3D${swId}"
                    } else {
                        url += "/webUI/main.do?url=/webUI/viewEvents.do%3Fserver%3D${sourceDescriptor?.eyeServerId}%26view%3DMy%20Network"
                    }
                }
            }
            return url.toString()
        }


        def sendRequest = { data ->
            logger.info("Forwarding data to BMC Helix");
            logger.info("Data to be sent: " + data);
           
            def urlString = param("URL")
           
            def url = new URL(urlString);
            def connection = url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.doOutput = true;

            def writer = new OutputStreamWriter(connection.outputStream);
            writer.write(data);
            writer.flush();
            writer.close();
            connection.connect();
            logger.info("Forward to BMC Helix, response code: " + connection.getResponseCode());
        }

        // Start of processing
        def sd = sourceDescriptor
        if(sd)
        {
            sd.enrich(facilities)
            logger.info("Enriched source descriptor = ${sd}")
        }


        //Mandatory slot for ordering processing in Helix
        def hSourceDescriptor =  sd?.eyeServerId.toString() + "_" + sd?.swId + "_" + id


        def hObjectId = (sd?.toShortName()) + ":" + (sd?.swId)
        def hCategory = "INCIDENT_MANAGEMENT"
        def hSubCategory = "NETWORK"
        def hClass = getClass()
        def hStatus = getStatus()
        def hSeverity = getHSeverity()
        def hType = getType(sd)
        def hLocation = "Entuity " + shortHostname


        // Short form of event/incident descriptions, such as "ENA Event/Incident name on Object"
        def hMsg = name
        def sourceContainer = getContainerSource(sd)
        if(sourceContainer)
            hMsg = hMsg + " on " + sourceContainer

        // Long form of event/incident, given by our reason field
        def hDetails = reason

        // Callback URI for the object
        hURI = constructCrossLaunchUrl(sd)

        //Custom slots
        def eDescription = name
        def eDetails = reason
        def eKey = getKey()
        def eTimestamp = getTimestamp().toString()
        def eSeverity = getESeverity()
        def eState = getStatus()
        def eObject = sourceName
        def eObjectType = getType(sd)
        def eObjectId = sd?.swId + ":" + sd?.toShortName()
        def eObjectSource = sourceDescriptor?.eyeServerId
        def eEventSource = getConsolidatedSourceHostAndPort()

        def deviceTypeMap = [
        0:"Unknown",
        148:"Ethernet Switch",
        168:"Router",
        1001:"Blade Center",
        1010:"Custom Device",
        1046:"Autonomous WAP",
        1049:"Firewall",
        1058:"VPN",
        1002:"Managed Host",
        1059:"Managed Host",
        1070:"PoE Midspan Injector",
        1077:"Load Balancer",
        1079:"SSL Proxy",
        1073:"Wireless Controller",
        1102:"Wireless Controller",
        1104:"Uninterruptible Power Supply",
        1124:"Matrix Switch",
        1144:"VM Platform",
        1201:"Base Station",
        1202:"SDN Controller",
        1212:"Cloud Controller",
        1213:"Cisco DNA Center",
        1221:"Storage",
        1222:"Server"
        ]

        def sourceId = sd?.swId
        Integer devType = 0
        def parentType = ""
        def parentName = ""
        def parentId = sourceId
        def parentZone = ""
        if (source) {
        // source is not null
        if(source.devPolledIpAddr != null) {
        // This is a device
        try {
        devType = source.devType.toInteger()
        } catch (Exception e) {
        }
        parentType = deviceTypeMap[devType]
        logger.info("devType=${devType}, parentType=${parentType}")
        parentName = sourceName
        parentZone = evalExpression("simple;eval(getObject(${sourceId}),0,get_attribute(\"devZoneID\",1))")
        } else {
        if(source.device?.devPolledIpAddr != null) {
        try {
        devType = source.device?.devType.toInteger()
        } catch (Exception e) {
        }
        parentType = deviceTypeMap[devType]
        parentName = source.device?.name
        parentId = source.device?.id
        parentZone = evalExpression("simple;eval(getObject(${parentId}),0,get_attribute(\"devZoneID\",1))")
        }
        }
        }

        def ifType = null
        if((sourceId != null) && sourceId != 0)
            ifType = evalExpression("simple;eval(getObject(${sourceId}),0,get_attribute(\"ifType\",1))")

        def data =
        [
            [
                category: hCategory,
                sub_category: hSubCategory,
                status: hStatus,
                severity: hSeverity,
                msg: hMsg,
                details: hDetails,
                cross_launch_uri: hURI,
                source_attributes: [
                    source_hostname: parentName,
                    zone: parentZone,
                ],
                source_identifier: hSourceDescriptor,
                object_class: hType,
                object_id: hSourceDescriptor,
                object: sourceName,
                ENA_description: eDescription,
                ENA_event_key: eKey,
                ENA_timestamp: eTimestamp,
                ENA_state: eState,
                ENA_object_type: eObjectType,
                ENA_object_id: hSourceDescriptor,
                ENA_object_source: eObjectSource,
                ENA_event_source: eEventSource,
                ENA_swId: sourceId,
                ENA_Typdevice: parentType,
                ENA_TypeIANA: ifType,
        ENA_ParentDeviceName: parentName,
        ENA_ParentDeviceSwId: parentId,
        ENA_InterfaceDescription: source?.portDescr
            ]
        ]

        def jsonBody = groovy.json.JsonOutput.toJson(data).toString()

        if(incident)
            logger.info("Forwarding incident to BMC Helix ${jsonBody}")
        else
            logger.info("Forwarding event to BMC Helix ${jsonBody}")
           
        sendRequest(jsonBody)
        logger.info("Send completed");
      3. Click OK.
        Entuity_Add_Action_23.png
  4. Click OK to close the Add Action dialog box.
  5. Configure a trigger for the action you generated in the previous step:
    1. On the Event Administration page, select the Incidents tab and click Edit Global Triggers.
    2. In the Edit Global Triggers dialog box, click Add and enter the following information in the Create Trigger dialog box:
      1. Specify a name for the trigger, for example, Trigger to send incidents to BMC Helix Intelligent Integrations .
        By default, the enabled check box is selected, which indicates that this trigger is enabled.
      2. (Optional) Enter a description for the trigger .
      3. Ensure that the Any Change option is selected in the On Transition To list.
        The Any Change value indicates that the action will be triggered for any change in the incidents data.
      4. Ensure that the None option is selected in the Condition list.
        The None value indicates that the action will be triggered for all possible conditions.
      5. Ensure that the None option is selected in the Delay list.
        The None value indicates that the action will be triggered without any delay.
      6. In the Action Steps section, click Add.
      7. In the Add Action dialog box, from the Type list, select the action you created for sending incidents data to BMC Helix Intelligent Integrations. 
        The Parameters field shows the URL parameter that you created in step 3c.
      8. Click OK to close the Add Action dialog box.
        The Create Trigger dialog box shows the added action.  
        Entuity_Create_Trigger_23.png

    3. Click OK to close the Create Trigger dialog box.
  6. Click Save and Deploy Entuity_EventAdmin_SaveDeploy.png.
  7. Go to step 12 to start the data stream.


Task 4: To verify the connection

From BMC Helix Intelligent Integrations , on the SOURCES panel, confirm that the data streams for the connection you created are running. Data streaming is indicated by different colored moving arrows.

Entuity_Events_Stream.png

A moving blue arrow (EventsStream_Icon.png ) indicates that the event stream is running. Event data will be pushed as soon as incidents are available.

To view events in BMC Helix applications

Important

If the event or metric data is ingested by using BMC Helix Intelligent Integrations, and the topology data is ingested through some other means, all the use cases in BMC Helix AIOps might not work as expected because the external IDs generated by BMC Helix Intelligent Integrations and BMC Helix Discovery differ. In addition, host name might differ in both the products. 

  1. In BMC Helix Operations Management, select Monitoring > Events.
  2. Filter the events by the EntuityIncident class.
    EntuityIncident.png

Incoming events from Entuity are processed in BMC Helix Operations Management through a set of deduplication rules to determine whether the incoming event is a duplicate event or a new event. For more information, see Event-deduplication-suppression-and-closure-for-reducing-event-noise.

For more information about events, see Monitoring and managing events.


Mapping of attributes between Entuity and BMC Helix Operations Management

The following table shows the mapping between Entuity and BMC Helix Operations Management:

Attribute

Entuity

BMC Helix Operations Management

URI

hURI

originURI

Incident source

Source

Host 

Incident name

Name

Message (<Name> on <Source>)

Incident details

Details

Detailed Message

Status

State

Status

Severity

Severity

Severity

 

Tip: For faster searching, add an asterisk to the end of your partial query. Example: cert*