Asset V2 Integration Guide#

Tip

To better understand the service and the terms covered in this guide please refer to the service lexicon

Warning

This integration guide targets the V2 of the Asset API, which replaces the deprecated V1 API. This guide is meant as a reference during testing and integration with the new API.

Detailed API documentation#

The Swagger API documentation is always up-to-date and lets you try out any query with your user session or an API-key.

Tip

Please read the General integration guide to learn the general concepts and common data structures used throughout the Argus API.

Integration Guide#

Note

The Asset service’s data model is highly interconnected. Make sure to get a decent understanding of the interdependencies before reading the rest of this guide.

Data Model#

All endpoints for fetching, searching/listing, updating and deleting assets return the same data model.

High level representation of the Asset V2 Model

See Swagger API documentation for details on the returned data model.

Creating Assets#

To create an asset you need to specify the shortName, name, criticality triad, and asset definition. The asset definition describes what components we can eventually attach to the asset and must already exist. The optional forceIndex (default=false) option when creating, updating, and deleting resources in the Asset service determines whether any changes are immediately pushed to the search index i.e. making the changes immediately searchable.

curl -X POST -H "Argus-API-Key: my/api/key" -H "Content-Type: application/json" https://api.mnemonic.no/assets/v2/asset -d '{
    "customer": "mnemonic",
    "shortName": "a1",
    "name": "asset1",
    "criticality": {
        "confidentiality": "low",
        "integrity": "high",
        "availability": "unknown"
    },
    "assetDefinition": "assetDefinition1",
    "components": [
      {
        "componentDefinition": "ipAddressComponentDefinition",
        "value": "10.0.0.1"
      }
    ]
}'

Asset Components#

Components, represent a piece of information about an Asset are defined by an Asset Component Definition. To be able to set a Component on an Asset it must be identifiable by its unique shortname or ID and defined on the Asset’s Definition.

Fetching Assets#

We can fetch individual Assets by identifying them by their ID or unique (per customer) shortName field.

curl -H "Argus-API-Key: my/api/key" https://api.mnemonic.no/assets/v2/asset/{assetIdOrShortName}

If successful, the above invocation will return the Asset basic model:

{
  "data": {
    "id": "0005cd25-2be2-44fa-a260-b0f735c9797a",
    "customer": { "id":1, "shortName":"mnemonic", ...},
    "shortName":"a1",
    "name":"asset1",
    "description":"This is the description for this asset",
    "assetDefinition": {
        "id": "00000000-0000-0000-0000-000000000001",
            "domain": {
                "id": 1,
                "name": "MNEMONIC"
            },
        "shortName": "HostAsset",
        "name": "HostAsset"
    },
    "components": [...],
    ...
  }
}

Updating Assets#

Updating the basic fields of an asset is done with a PUT request to the Asset’s, identified by its ID or unique short name, endpoint. Asset components can also be added, and removed, via this request.

If no parameters are provided, no changes are performed. Similarly, for any parameter sent to this endpoint, a null value will cause no change to the current value.

curl -X PUT -H "Argus-API-Key: my/api/key" -H "Content-Type: application/json" https://api.mnemonic.no/assets/v2/asset/{assetIdOrShortName} -d '{
    "criticality": {
        "confidentiality": "high",
        "integrity": "low",
        "availability": "high"
    },
    "addComponents": [
        {
            "componentDefinition": "cd1",
            "value": "componentValue",
            "ttl": 0
        }
    ],
    "deleteComponents": [
        "0005cd25-2be2-44fa-a260-b0f735c9797a",
        "0005cd25-2be2-44fa-a260-b0f735c9797a"
    ]
}'

Searching for Assets#

Assets are searchable by their basic properties and their relationships with other resources in the Asset Service e.g. parent or ancestor group(s). All searches are restricted to assets belonging to customers for whom the current user has at least read permission.

curl -X POST -H "Argus-API-Key: my/api/key" -H "Content-Type: application/json" https://api.mnemonic.no/assets/v2/asset/search -d '{
    "sortBy": [
        "lastUpdatedTimestamp"
    ],
    "keywords": [
        "content"
    ],
    "keywordFieldStrategy": [
        "description"
    ]
    "parent": [
        "assetGroupShortName"
    ],
    ...
}'

Asset Statistics#

Warning

The Asset Statistics API is not completely stable i.e. new features are still under development. Please contact Mnemonic directly for clarification.

The Asset statistics endpoint allows a user to retrieve quantitative data about a set of assets that match certain search criteria.

The statistics request supports the same search criteria as the search endpoint; the statistics criteria then apply to the results of the search.

The statistics request itself is composed of 3 key components:

  • field aggregation - the field(s) by which we want to group the resulting assets and structure the response

  • range metrics - return counts for assets matching the defined timestamp filters

  • statistics metrics - return basic statistical data (min, max, median, avg, e.t.c) for asset numerical fields e.g. CVSS or vulnerability count

For example, we could ask for vulnerability statistics for assets created within the last month and also determine which of them have been updated during the same time period, aggregated by the types of assets and the groups to which they belong:

curl -X 'POST' \
  'https://api.mnemonic.no/assets/v2/asset/statistics' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Argus-API-Key: my/api/key' \
  -d '{
  "startTimestamp": "now-1month",
  "endTimestamp": "now",
  "timeFieldStrategy": [
    "createdTimestamp"
  ],
  "fieldAggregation": [
    {
      "field": "assetGroup",
      "limit": 25
    },
    {
      "field": "assetDefinition",
      "limit": 25
    }
  ],
  "rangeMetric": [
    {
      "name": "updatedThisWeek",
      "field": "lastUpdated",
      "startTimestamp": "now-1week",
      "endTimestamp": "now"
    }
  ],
  "statisticsMetric": [
    {
      "field": "vulnerabilities"
    }
  ],
  "includeDeleted": false
}'

The response’s structure is a unidirectional tree where the branches represent unique field aggregation values i.e. in this example groups and definitions.

Each branch consists of the count of assets within the branch and metadata containing

  • identifier - the unique ID of the object

  • shortName - the unique human/machine readable identifier

  • name - the human readable non-unique identifier

  • type - the type (assetGroup or assetDefinition in this example) of the metadata

Each branch then potentially contains buckets, which represent the next layer in the tree.

The leaves contain the actual metrics response e.g.:

{
  "metadata": {
    "identifier": "assetGroupUUID",
    "shortName": "assetGroupShortName",
    "name": "Asset Group Name",
    "type": "assetGroup"
  },
  "count": 291,
  "buckets": [
    {
      "metadata": {
        "identifier": "00000000-0000-0000-0000-000000000001",
        "shortName": "HostAsset",
        "name": "Host Asset",
        "type": "assetDefinition"
      },
      "count": 291,
      "buckets": [
      ],
      "rangeMetrics": [
        {
          "key": "updatedThisWeek",
          "count": 1,
          "startTimestamp": 1681198844900,
          "endTimestamp": 1681803644900
        }
      ],
      "statisticsMetrics": [
        {
          "key": "vulnerabilities",
          "count": 291,
          "min": 0,
          "max": 441,
          "avg": 48.67697594501718,
          "sum": 14165
        }
      ]
    }
  ],
  "rangeMetrics": [
  ],
  "statisticsMetrics": [
  ]
}

Creating Asset Groups#

To create an asset you need to specify the shortName, name, and criticality triad.

curl -X POST -H "Argus-API-Key: my/api/key" -H "Content-Type: application/json" https://api.mnemonic.no/assets/v2/group -d '{
    "customer": "mnemonic",
    "shortName": "ag1",
    "name": "assetGroup1",
    "criticality": {
        "confidentiality": "low",
        "integrity": "high",
        "availability": "unknown"
    }
}'

Attaching Assets to a Group#

To add Assets to a Group submit their IDs or short names to the group’s attach endpoint.

curl -X POST -H "Argus-API-Key: my/api/key" -H "Content-Type: application/json" https://api.mnemonic.no/assets/v2/group/groupShortNameOrID/assets -d '{
        "assets": [
            "asset1",
            "asset2"
        ]
    }
}'

Searching for Groups#

Similar to Assets, Groups are searchable by their basic properties and by their relationships to other objects in the Asset Service. groups e.g. parent, ancestor, or child group(s) and member assets. All searches are restricted to groups belonging to customers for whom the current user has at least read permission.

curl -X POST -H "Argus-API-Key: my/api/key" -H "Content-Type: application/json" https://api.mnemonic.no/assets/v2/group/search -d '{
    "sortBy": [
        "lastUpdatedTimestamp"
    ],
    "keywords": [
        "content"
    ],
    "keywordFieldStrategy": [
        "description"
    ]
    "parent": [
        "assetGroupIDOrShortName"
    ],
    "asset": [
        "assetIdOrShortName"
    ],
    "child": [
        "assetGroupIDOrShortName"
    ]
    ...
}'

Creating Vulnerabilities#

To create a Vulnerability you need to specify the asset (identified by its UUID or shortname) on which the vulnerability was observed, its vulnerability definition, and CVSS value. If a severity is not specified, it will be assigned based on the submitted CVSS value using the following mapping:

.. list-table:: CVSS Severity Mappings :header-rows: 1

* - CVSS
  - Severity
* - <= 0
  - < 4
  - < 7
  - < 9
  - <= 10
* - INFO
  - LOW
  - MEDIUM
  - HIGH
  - CRITICAL

The optional forceIndex option (default=false) will instruct the service to refresh the search index such that new vulnerabilities are immediately searchable. Like Assets, Vulnerabilities can be created bound to specific components.

The time to live (TTL) field determines how long the component information is considered valid. Ideally it should be longer than the scan interval so that component information is not invalidated before it can be updated. Please see the Swagger API for how the other fields are handled or determined if not provided.

Specify Customer#

NB: If the request does not explicitly specify the Customer who owns the Asset on which the Vulnerability was detected and the Asset was defined by its short name then the service will attempt to resolve the Asset based on the requesting user’s Customer. As Asset shortNames are unique per customer it’s possible that this request might fail.

curl -X POST -H "Argus-API-Key: my/api/key" -H "accept: application/json" 
"https://api.mnemonic.no/assets/v2/vulnerability" -d '{
    "customer": "mnemonic",
    "asset": "internalAsset",
    "vulnerability": "vulnerabilityDefinition",
    "components": [
        {
            "componentDefinition": "cpeComponentDefinition",
            "value": "cpe:2.3:o:microsoft:windows:2008:r2",
            "ttl": 0
        }
    ],
    "cvss": 3,
    "severity": "low",
    "rawOutput": "output from scanner",
    "ttl": 0
}'

Fetching Vulnerabilities#

To fetch a single Vulnerability you need to provide its UUID:

curl -H "Argus-API-Key: my/api/key" https://api.mnemonic.no/assets/v2/vulnerability/53477c72-f4c8-4929-bc05-3a8c7d4ba7a2

A successful request will return the Vulnerability’s data model:

{
    "id": "53477c72-f4c8-4929-bc05-3a8c7d4ba7a2",
    "customer": {
        "id": 1,
        "name": "mnemonic",
        "shortName": "mnemonic",
        "domain": {
            "id": 1,
            "name": "MNEMONIC"
        }
    },
    "asset": {
        "id": "4cb3797b-35f6-4ca7-8102-46e8a3946829",
        "customer": {
            ...
        },
        "shortName": "GraphQLAsset_2",
        "name": "Asset 2 - Asset V2 Test"
    },
    "vulnerabilityID": "COVID-19",
    "vulnerabilityDefinition": null,
    "components": [],
    "cvss": 8.8,
    "severity": "high",
    "resolution": "unresolved",
    "resolutionTimestamp": 0,
    "resolvedByUser": null,
    "resolutionComment": null,
    "rawOutput": null,
    "firstSeenTimestamp": 1596539880803,
    "lastSeenTimestamp": 1596539880803,
    "firstSeenByUser": {
        "id": 8982,
        "shortName": "testUser",
        "name": "Test User",
        "domain": null,
        "customer": {
            ...
        },
        "type": "user"
    },
    "lastSeenByUser": {...},
    "ttl": 0,
    "expireTimestamp": 0,
    "createdTimestamp": 1596539880803,
    "createdByUser": {...},
    "lastUpdatedTimestamp": 1596539880803,
    "lastUpdatedByUser": {...},
    "deletedTimestamp": 0,
    "deletedByUser": null,
    "flags": []
}

Resolving Vulnerabilities#

Although actually resolving a Vulnerability is not handled by Argus, updating a Vulnerability’s resolution status is an important step in the Vulnerability management process.

When resolving a Vulnerability permitted resolution statuses are:

  • accepted - the Vulnerability is known and will not be handled

  • temporarilyAccepted - the Vulnerability is known and will be handled at a later date

  • falsePositive - not a Vulnerability

  • serviceNotAvailable

  • noLongerVulnerable - the Vulnerability has been handled

To resolve a vulnerability simply submit a resolution request to the vulnerability’s resolution endpoint:

curl -X PUT -H "Argus-API-Key: my/api/key" "accept: application/json" -H "Content-Type: application/json" \
    "https://devapi.mnemonic.no/assets/v2/vulnerability/4cb3797b-35f6-4ca7-8102-46e8a3946829/resolve" -d \
    '{ 
        "resolution": "accepted",
        "comment": "cannot resolve now"
    }'

Searching for Vulnerabilities#

Vulnerability are searchable by their basic properties and their direct relationship with the asset on which they were detected. All searches are restricted to Vulnerabilities on Assets belonging to the customer(s) for whom the requesting user has permission to access. Unlike Asset and Asset Groups, Vulnerabilities currently have no keyword fields. Only exact matches will return results.

{
  "sortBy": [
    "vulnerabilityID"
  ],
  "startTimestamp": 0,
  "endTimestamp": 0,
  "timeFieldStrategy": [
    "all"
  ],
  "timeMatchStrategy": "any",
  "userFieldStrategy": [
    "lastUpdatedByUser"
  ],
  "user": [
    "testUser"
  ],
  "asset": [
    "myVeryImportantAsset"
  ],
  "customer": [
    "mnemonic"
  ],
  "severity": "info",
  "resolution": "unresolved",
  "minimumCvss": 1,
  "maximumCvss": 2,
  "includeRawOutput": false,
  "limit": 0,
  "offset": 0,
  "includeDeleted": false
}

To, for example, retrieve all open Vulnerabilities created on Assets belong to a particular Customer for the last week you could submit the following query:

{
  "sortBy": [
    "createdTimestamp"
  ],
  "customer": [
    "customerIdOrShortName"
  ],
  "resolution": "unresolved",
  "startTimestamp": "startOfWeek - 1 week",
  "endTimestamp": "startOfWeek"
}