Configure the ServiceNow Webhook Integration

By integrating ServiceNow with Forescout Cloud, you can more seamlessly synchronize your data between both systems bi-directionally. This means that case statuses and comments can be synchronized between both systems, streamlining your case management workflows.

With a webhook integration, you can configure one business rule in ServiceNow that sends updates to your Forescout Cloud endpoint.

Prerequisites

Before you can configure the ServiceNow webhook, you must have:

  • Administrator-level access to your ServiceNow instance.
  • The Forescout Account ID and API Key from the Administration > Integrations tab. See Generate an API key for more information.
    Important: Keep your API key information safe. Do not share or paste it in public spaces.

Configuration steps

To configure the ServiceNow webhook for Forescout Cloud:

  1. Sign in to ServiceNow as an admin-capable user.
  2. Go to System Definition > Business Rules.
  3. Click New to create a new business rule.
  4. Provide a name for the new Forescout Cloud webhook, and then select Incident (incident) for the Table.
  5. Select the Active check box.
  6. In the When to Run tab, select or specify the following:
    • When: After.
    • Order: 100, or place this rule after your other ServiceNow business rules.
    • Update and Query: Select these check boxes.
    • Insert and Delete: Clear these check boxes.
  7. In the Filter Conditions section, add OR condition clauses so that the rule runs when any of the following fields change:
    • State
    • Assigned To
    • Priority
    • Severity
    • Short Description
    • Additional Comments
      Note: You can adjust these fields as needed for your organization, but Forescout recommends State and Additional Comments as starting points.
  8. In the Advanced tab, enable the Script option.
  9. Paste the script that builds a JSON body and sends it to your Forescout endpoint. Be sure to replace the following placeholders in the script:
    • {{accountID}}: Replace with your Forescout account ID.
    • {{API Token}}: Replace with your Forescout API Key. Use the format your environment expects (ex: Authorization: ApiKey <token>).
Copy
var gr = new GlideRecord('incident');
gr.addQuery('number', current.getValue('number'));
gr.query();

if (gr.next()) {
    var caseId = "";
    var caseIdRegex = /Case ID=(\d+)/;

    var commentsArray = [];

    // Get all comments for the incident, latest being the first here
    var jf = new GlideRecord('sys_journal_field');
    jf.addQuery('element_id', gr.getValue('sys_id'));
    jf.orderByDesc('sys_created_on');
    jf.query();

    while (jf.next()) {
        var commentObj = {
            sys_id: jf.getValue('sys_id'),
            sys_created_on: jf.getValue('sys_created_on').replace('T', ' ').substring(0, 19),
            name: jf.getValue('name'),
            element_id: jf.getValue('element_id'),
            sys_tags: jf.getValue('sys_tags'),
            value: jf.getValue('value'),
            sys_created_by: jf.getValue('sys_created_by'),
            element: jf.getValue('element')
        };
        commentsArray.push(commentObj);

        // Find caseId from the latest comment with pattern
        if (!caseId && commentObj.value) {
            var match = commentObj.value.match(caseIdRegex);
            if (match && match[1]) {
                caseId = match[1];
            }
        }
    }

    var payload = {
        case_id: caseId,
        sys_id: gr.getValue("sys_id"),
        number: gr.getValue("number"),
        state: gr.getDisplayValue("state"),
        severity: gr.getDisplayValue("severity"),
        priority: gr.getDisplayValue("priority"),
        sys_created_by: gr.getValue("sys_created_by"),
        sys_created_on: gr.getValue("sys_created_on"),
        sys_updated_by: gr.getValue("sys_updated_by"),
        sys_updated_on: gr.getValue("sys_updated_on"),
        close_code: gr.getDisplayValue("close_code"),
        close_notes: gr.getValue("close_notes"),
        resolved_by: gr.resolved_by.getDisplayValue(),
        resolved_at: gr.getValue("resolved_at"),
        assigned_to: gr.assigned_to.getDisplayValue(),
        comments: commentsArray, // Now array of objects
        opened_by: gr.opened_by.getDisplayValue(),
        opened_at: gr.getValue("opened_at")
    };

    var client = new sn_ws.RESTMessageV2();
    client.setHttpMethod('POST');
    client.setEndpoint('https://app.cloud.forescout.com/api/public/v1/accounts/{{accountID}}/update-snow-incident');
    client.setRequestHeader("Authorization", "{{API Token}}");
    client.setRequestHeader("Content-Type", "application/json");
    client.setRequestBody(JSON.stringify(payload));

    try {
        var response = client.execute();
        var responseBody = response.getBody();
        var httpStatus = response.getStatusCode();

        if (httpStatus == 200) {
            gs.info('Successfully sent incident: ' + gr.getValue('number'));
        } else {
            gs.error('Failed to send: ' + responseBody);
        }
    } catch (e) {
        gs.error('Error sending incident: ' + e.message);
    }
}

For more information about ServiceNow business rules, refer to the ServiceNow documentation.