Add a Vulnerability Management Schema and Relation to Resources

There are many situations when we must attach additional entities to resources. One common one is attaching vulnerabilities. Let's see how you can accomplish this in configure8.

Defining the Schema

Let's assume we have the following properties for the Vulnerability entity

  • severity - One of low, medium, or high

  • description - Some additional description that may help you to get more details on this vulnerable

So let's define a new schema called Vulnerabilities and set its relation with the system resources schema. Please navigate to the schemas page and press the Add Schema button.

You will see the details part.

You need to select type as Base, Subtype as Vulnerable::Issue. With the name and the identifier, you may put anything that will make sense to you.

Our next step is to define the data model for the schema. Let's use this:

[
  {
    "hidden": false,
    "columnName": "Severity",
    "name": "severity",
    "calc": {
      "type": "PATH",
      "path": "details.severity"
    }
  },
  {
    "hidden": false,
    "columnName": "Description",
    "name": "description",
    "calc": {
      "type": "PATH",
      "path": "details.description"
    }
  }
]

We may also want to add validation for it, but it is not required by default:

{
  "$id": "https://app.configure8.io/vulnerable.schema.json",
  "title": "Vulnerable",
  "description": "",
  "type": "object",
  "required": [
    "severity",
    "description"
  ],
  "properties": {
    "severity": {
      "type": "string",
      "enum": ["low", "medium", "high"]
    },
    "description": {
      "description": "Vulnerable description",
      "type": "string"
    }
  }
}

The last thing is to add the relation to the resources, so we are able to attach vulnerabilities to a resource:

After filling in all the necessary fields and saving the schema you will see an additional menu item:

Before we start to create new Vulnerability issues, we assume that you have connected one of your cloud providers and resources available in configure8 (if not see the section on catalog onboarding).

Loading Data

Now let's dive into an example that shows how to load some vulnerability data through the Public API. This serves as a good proxy for any data you'll want to add to your schemas. For instance, if you have some resource analysis tools and want to push the results into configure8, it will look quite similar.

First, you need to add an API Key so you will be able to use Public API. Navigate to the API Keys page and press the Add API Key button.

You will need to fill out the form with the following data:

  • API Key Name - This should contain the name that makes sense for what purpose this key is going to be used.

  • Expiration date - For how long you may use this key. I recommend you to leave it as 1 month.

  • Scope - What do you want to do with this key? For our example, it will require read and write access.

  • Role - Indicates what access will be required for this key. You may only need to have a User.

After pressing the add button the key will be generated and you need to copy it as after you won't be able to receive it again. We will use it to access Public API.

Here is an example of a script to load data that is written in JavaScript, but the same approach might be used for any language.

package.json:

{
  "name": "upload",
  "version": "1.0.0",
  "description": "",
  "main": "script.mjs",
  "scripts": {
    "start": "node script.mjs"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-fetch": "^3.3.2"
  }
}

script.mjs

import fetch from "node-fetch";

const apiKey = "PUT_YOUR_API_KEY_HERE";
const headers = {
  "Api-Key": apiKey,
  "Content-Type": "application/json",
};

const baseUrl = 'https://app.configure8.io';

// Here we are requesting all the resources that available on you account
const getResources = async () => {
  const result = [];
  let done = false;
  let pageNumber = 0;
  while (!done) {
    const response = await fetch(
      `${baseUrl}/public/v1/catalog/entities`,
      {
        method: "post",
        headers,
        body: JSON.stringify({
          pageSize: 100,
          pageNumber,
          propertyFilters: [
            {
              filterType: "COMPOUND",
              operand: "OR",
              propertyFilters: [
                {
                  name: "provider",
                  value: "AWS",
                },
                {
                  name: "provider",
                  value: "GCP",
                },
                {
                  name: "provider",
                  value: "Azure",
                },
              ],
            },
          ],
        }),
      }
    );
    const data = await response.json();
    if (data.items.length < 100) {
      done = true;
    }
    result.push(...data.items.map((item) => item.id));
    pageNumber++;
  }
  return result;
};

const getRandomSeverity = () => {
  const v = Math.random() * 30;
  if (v < 10) {
    return "low";
  } else if (v < 20) {
    return "medium";
  }
  return "high";
};

let issueNumber = 1;
const generateIssues = (resourceId) => {
  const count = Math.round(Math.random() * 4 - 0.5) + 1;
  const result = [];
  for (let i = 0; i < count; i++) {
    result.push({
      name: `Demo Issue ${issueNumber++}`,
      providerResourceType: "Vulnerable::Issue",
      details: {
        severity: getRandomSeverity(),
        description: `I am an issue ${issueNumber}`,
      },
      parents: [{
        id: resourceId,
        label: '',
        field: 'resource'
      }]
    });
  }
  return result;
};

const createIssue = async (item) => {
  const response = await fetch(
    `${baseUrl}/public/v1/catalog/entities/base`,
    {
      method: "post",
      headers,
      body: JSON.stringify(item),
    }
  );
  const r = await response.json();
  return r;
};

const start = async () => {
  const resources = await getResources();
  const total = resources.length;
  let totalIssues = 0;
  console.log('Found resources', resources.length);
  let done = 0;
  while(resources.length > 0) {
    const [resourceId] = resources.splice(0, 1);
    const results = await Promise.all(generateIssues(resourceId).map(createIssue));
    totalIssues += results.length;
    done++;
    console.log('Done ', done, '/', total, 'Total issues', totalIssues);
  }
};

start();

To execute it you just need to change

const apiKey = "PUT_YOUR_API_KEY_HERE";

with your generated API token and execute the script with the following command:

npm start

Use the Data

After the script is executed you will observe the issues in the Vulnerability page.

You can open one of the Issues records and observe that it has a relation with one of the resources:

At the same moment if you click on the resource name and navigate to its Vulnerability page you will see the list of all associated issues.

Last updated

Copyright © 2023 configure8, Inc. All rights reserved.