IQ Server Webhooks

Overview

Webhooks are HTTP callbacks that POST data to defined URLs. They let you build integrations registered to certain events on IQ Server. When a registered event is triggered, an HTTP POST payload is sent to the webhook’s defined URL.

Use webhooks to receive notifications about events that happen in IQ Server. When an event occurs - for example, when an application evaluation is completed - IQ Server creates an event object. This object has relevant information about what just happened, such as the type of event and any data associated with the event. IQ Server then sends the event object to defined URLs using HTTP POST requests.

IQ Server lets you use webhooks for policy management, application evaluation, security vulnerability override management, and license override management events.

Each webhook is defined by the following:

  • The URL to POST the payload.
  • An optional secret key that ensures authenticity of the source.
  • Event types subscribed by the webhook.

Configuring Webhooks

Webhooks can only be created by a System Administrator. Webhooks do not have a permissions model and will send HTTP requests for every event in the system. Be aware that the system consuming the webhooks will have access to all the data provided by the event types.

Creating Webhooks

To create a webhook, perform the following steps:

  1. Click the System Preferences icon  in the IQ Server toolbar and then click Webhooks.
  2. Click the Create Webhook button. The Create Webhook dialog opens:
  3. Enter the webhook URL.
  4. Optional: Enter the webhook secret key.
  5. Optional: Enter a description for the webhook.
  6. Select one or more Event Types.
  7. Click Create.

Editing Webhooks

To edit a webhook, perform the following steps:

  1. Click the System Preferences icon  in the IQ Server toolbar and then click Webhooks.
  2. Click the webhook you want to edit.
  3. Edit the URL, secret key, or selected event types and then click Update.

Deleting Webhooks

To delete a webhook, perform the following steps:

  1. Click the System Preferences icon  in the IQ Server toolbar and then click Webhooks.
  2. Click the webhook you want to delete.
  3. Click Remove Webhook.
  4. Click Continue in the Remove Webhook dialog.

Working with HMAC Payloads

If you enable a secret key to generate an HMAC digest, a special header is sent with all of your webhook payloads. This header is X-Nexus-Webhook-Signature and ensures that you receive an authentic message.

Webhooks can be consumed easily in node.js. Use the following setup to get started, substituting foo for the secret key you configured with your webhook:

npm init
npm install express
npm install body-parser
echo {\"secretKey\":\"foo\"} > settings.json

When verifying the HMAC digest, the HmacDigest value should match the signature value.

Add the code below to a file named app.js, and run the web hook listener via the command: node app.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const settings = require('./settings.json');
const crypto = require('crypto');

app.use(bodyParser.json());

app.post('/', function(req, res) {
  const body = req.body;
  const signature = req.headers['x-nexus-webhook-signature'];
  var hmacDigest = crypto.createHmac("sha1", settings.secretKey).update(JSON.stringify(body)).digest("hex");

  console.log('Webhook received');
  console.log('Headers: ' + JSON.stringify(req.headers));
  console.log('Body: ' + JSON.stringify(req.body));
  console.log('HmacDigest: ' + hmacDigest);
  console.log('Signature: ' + signature);
  res.send();
});

app.listen(3000, function() {
  console.log('Server running on port 3000.');
});

Example Headers and Payloads

It is important to understand the payload being received. Each event contains special headers that help describe the event.

The following headers are of special importance:

HeaderDescription

X-Nexus-Webhook-ID

This is the event type. For example, iq:policyManagement.

X-Nexus-Webhook-Delivery

A unique UUID identifying the event.

X-Nexus-Webhook-Signature

The HMAC digest of the payload body, if an optional secret key has been configured.

X-Nexus-Webhook-Signature-Algorithm

The algorithm that calculates the HMAC digest of the body, currently only HmacSHA1.

Content-Type: application/json; charset=UTF-8
User-Agent: Sonatype_CLM_Server/1.24.0-SNAPSHOT (Java 1.7.0_25; Mac OS X 10.11.5)
X-Nexus-Webhook-Signature: 687f3719b87232cf1c11b3ef7ea10c49218b6df1
X-Nexus-Webhook-Id: iq:policyManagement
X-Nexus-Webhook-Delivery: 7f4a6dde-5c68-4999-bcc0-a62f3fb8ae48

A payload is returned with each event type. An example application evaluation payload is shown below:

{
    'applicationEvaluation': {
        'policyEvaluationId': 'debceb1d-9209-485d-8d07-bd5390de7ef5',
        'stage': 'build',
        'ownerId': '6a454175-f55d-4d33-ba44-90ac3af2e8b8',
        'evaluationDate': '2015-05-05T23:40:12Z',
        'affectedComponentCount': 10,
        'criticalComponentCount': 2,
        'severeComponentCount': 5,
        'moderateComponentCount': 3,
        'outcome': 'fail'
    }
}

Event Fields

The data structure of the event payload differs by event. Event types share the following common fields:

FieldDescription
Timestamp

An ISO 8601 representation of the time.

Initiator

userId or "anonymous", "system" for system events.

Policy Management Event

Policy Management events include updates to owners, policies, tags, labels, license threat groups, and owner membership mappings.

Policy Management events have the following fields:

  • action: i.e. CREATED, UPDATED, DELETED.
  • type: the type of entity which was updated i.e. APPLICATION, ORGANIZATION, APPLICATION_CATEGORY, LABEL, LICENSE_THREAT_GROUP, ACCESS, POLICY.
  • id: system ID used to identify the entity which was updated.
{
    'owner': {
        'id': '6a454175-f55d-4d33-ba44-90ac3af2e8b8',
        'publicId': 'webhooks_application',
        'name': 'Webhooks Application',
        'parentOwnerId': 'abaed4e0-d31e-4a67-9f71-1a8861641077',
        'type': 'APPLICATION',
        'tags': [{
            'id': '35304aee-c52f-4f66-9f7c-718e465a0e41',
            'name': 'Tag Foo',
            'description': 'A tag description.',
            'color': 'dark_red'
        }],
        'labels': [{
            'id': '35304aee-c52f-4f66-9f7c-718e465a0e41',
            'name': 'Label Foo',
            'description': 'A label description.',
            'color': 'dark_red'
        }],
        'licenseThreatGroups': [{
            'id': '35304aee-c52f-4f66-9f7c-718e465a0e41',
            'name': 'LTG Foo',
            'threatLevel': 5
        }],
        'policies': [{
            'id': '35304aee-c52f-4f66-9f7c-718e465a0e41',
            'name': 'Policy Foo',
            'threatLevel': 5
        }],
        'access': [{
            'id': '35304aee-c52f-4f66-9f7c-718e465a0e41',
            'name': 'Developers',
            'members': [{
                'type': 'USER',
                'name': 'jyoung'
            }]
        }]
    }
}

Application Evaluation Event

Application Evaluation events are those occurring during the lifecycle of a policy evaluation. Evaluation completed is the only evaluation event currently available.

Application Evaluation events have the following fields:

  • policyEvaluationId: ID of the policy evaluation.
{
    'applicationEvaluation': {
        'policyEvaluationId': 'debceb1d-9209-485d-8d07-bd5390de7ef5',
        'stage': 'build',
        'ownerId': '6a454175-f55d-4d33-ba44-90ac3af2e8b8',
        'evaluationDate': '2015-05-05T23:40:12Z',
        'affectedComponentCount': 10,
        'criticalComponentCount': 2,
        'severeComponentCount': 5,
        'moderateComponentCount': 3,
        'outcome': 'fail'
    }
}

Violation Alert Event

Application Evaluation events are those occurring during the lifecycle of a policy evaluation. The Violation Alert event is triggered when policy violations have been detected. If an evaluation did not detect any policy violations then no webhook events will be sent.

Violation Alert events contain the same fields as the Application Evaluation (see above) event and contains additional information about all policy violations found during the evaluation:

  • application: Contains ids and name of the affected application.
  • policyAlerts: A list of all policy alerts triggered by this evaluation.
{
  "initiator": "admin",
  "applicationEvaluation": {
    "policyEvaluationId": "e534d2c0bb64473a8206ead3cdee9d84",
    "stage": "build",
    "ownerId": "5c2cb33bc52e48b7ad04b4905bf74337",
    "evaluationDate": "2019-08-27T20:33:47.854+0000",
    "affectedComponentCount": 1,
    "criticalComponentCount": 1,
    "severeComponentCount": 0,
    "moderateComponentCount": 0,
    "outcome": "fail",
    "reportId": "38e07c8866a242a485e6d7d2c1fd5692"
  },
  "application": {
    "id": "1e010417a9fd4624b0eaccebccac21f6",
    "publicId": "appPublicId",
    "name": "app",
    "organizationId": "2edd9a73b5444ca7b563501445b7b2fc"
  },
  "policyAlerts": [
    {
      "policyId": "6f981ceb94684b3da36ee1a1d863956f",
      "policyName": "Security-Critical",
      "threatLevel": 10,
      "componentFacts": [
        {
          "hash": "40fb048097caeacdb11d",
          "displayName": "apache-collections : commons-collections : 3.1",
          "componentIdentifier": {
            "format": "maven",
            "coordinates": {
              "artifactId": "commons-collections",
              "classifier": "",
              "extension": "jar",
              "groupId": "apache-collections",
              "version": "3.1"
            }
          },
          "pathNames": [],
          "constraintFacts": [
            {
              "constraintName": "Critical risk CVSS score",
              "satisfiedConditions": [
                {
                  "summary": "Security Vulnerability Severity >= 9",
                  "reason": "Found security vulnerability sonatype-2015-0002 with severity 9.0."
                }
              ]
            }
          ]
        }
      ],
      "policyViolationId": "62c3f1fc67b149f1a584cd63acb23eed"
    }
  ]
}

Security Vulnerability Override Management Event

Security Vulnerability Override Management events are issued when a security vulnerability override is created, updated, or deleted.

Security Vulnerability Override Management events have the following fields:

  • id: ID of the security vulnerability override.
  • action: CREATED, UPDATED, DELETED.
{
    'securityVulnerabilityOverride': {
        'id': 'd08a4954c2f942e6bbd95517030ebcf7',
        'ownerId': '6a454175-f55d-4d33-ba44-90ac3af2e8b8',
        'hash': '46c81da3225f991faa2b',
        'source': 'cve',
        'referenceId': 'CVE-2016-0788',
        'status': 'ACKNOWLEDGED',
        'comment': 'Ack'
    }
}

License Override Management Event

License Override Management events are issued when a license override is created, updated, or deleted.

License Override Management events have the following fields:

  • id: ID of the license override.
  • action: CREATED, UPDATED, DELETED.
{
    'licenseOverride': {
        'id': 'cafdf38d458d461583ec6cd509dc8c31',
        'ownerId': '6a454175-f55d-4d33-ba44-90ac3af2e8b8',
        'status': 'OVERRIDEN',
        'comment': '',
        'licenseIds': [
            'Apache-2.0'
        ],
        'componentIdentifier': {
            'format': 'maven',
            'coordinates': {
                'artifactId': 'foo',
                'classifier': '',
                'extension': 'jar',
                'groupId': 'net.java.bar',
                'version': '1.9'
            }
        }
    }
}

Webhooks Example: IQ and Slack Integration

Using all of the information described in this topic, we wrote an article in the Sonatype Guides Site space showing you how to build a webhook and deploy it to a Serverless framework like AWS Lambda. The Serverless function will consume an IQ policy evaluation event and push a message about it to Slack.

Check out the example here: Using Webhooks: IQ & Slack Integration.