IQ Server Webhooks

Overview

Webhooks are HTTP callbacks that POST data to a URL defined by you. With webhooks, you can build custom integrations which respond to different events types in IQ Server. When an event is triggered, an HTTP POST payload is sent to the webhook’s defined URL.  With the received payload, your script can respond in any way you require by interacting through the IQ Server's REST API.

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.

When working with webhooks, one limitation is that IQ Server does not validate that the webhook was received by the external integration. It will also not try again if and when a network failure has occurred.  For this reason, we do not recommend using webhooks for auditing purposes as you may miss important notifications.  Using the audit.log is more ideal for mission critical reporting and monitoring.

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.

Events Types

Policy Management

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

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:

  • NEW IN RELEASE 1.91 application : Contains ids and name of the affected application.
  • policyEvaluationId: ID of the policy evaluation.
{
    "timestamp":"2020-04-22T18:30:04.673+0000",
    "initiator":"admin",
    "id":"d5cc2e91d6454545841da5599d3c7156",
    "applicationEvaluation":{
        "application":{
            "id":"0f256982c80b4e13abef4917b93ac343",
            "publicId":"My-Application-ID",
            "name":"My-Application",
            "organizationId":"f25acda2a413ab2c62b44917b93ac232"
        },
        "policyEvaluationId":"d5cc2e91d6454545841da5599d3c7156",
        "stage":"release",
        "ownerId":"0f256982c80b4e13abef4917b93ac343",
        "evaluationDate":"2020-04-22T18:30:04.404+0000",
        "affectedComponentCount":10,
        "criticalComponentCount":2,
        "severeComponentCount":5,
        "moderateComponentCount":3,
        "outcome":"fail",
        "reportId":"36f37cf776dd408bacd063450ab04f71"
    }
}

Violation Alert

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": {
    "application": {
      "id": "1e010417a9fd4624b0eaccebccac21f6",
      "publicId": "appPublicId",
      "name": "app",
      "organizationId": "2edd9a73b5444ca7b563501445b7b2fc"
    },
    "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"
    }
  ]
}

License Override Management

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'
            }
        }
    }
}

Security Vulnerability Override Management

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'
    }
}

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'
    }
}

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.