Skip to main content Link Search Menu Expand Document (external link)

Extending DocIntel with Modules

In DocIntel, a module is a set of files that enhances the platform’s functionalities. These modules are dynamically loaded during startup.

Each module requires a configuration file named “module.json” placed at the root of its corresponding folder. For instance, a module designed to import all Malpedia reports would have the following folder structure:

/modules
- malpedia
  - module.json
  - ...  

All the dependencies required for the module, except those provided by DocIntel.Core, should be included in the subfolder.

Configuration with module.json

The module.json file serves as a descriptor for the modules to be loaded in DocIntel. It contains several key-value pairs:

  • Name: Identifies the name of the module.
  • Assembly: Specifies the assembly to be loaded.
  • Exporters: A dictionary that associates exporter endpoints with their respective classes (currently undocumented).
  • Metadata: A dictionary that maps known DocIntel types to additional metadata. For example, additional geographical metadata for tags.
  • Profiles: A list of AutoMapper profiles to load.
  • Collectors: A dictionary that maps collector names to their associated classes. This allows adding additional collectors to DocIntel.

For instance, consider a module that provides additional geographical metadata to tags, which would have a configuration file similar to the example below:

{
  "name": "geo",
  "assembly": "Cyantlabs.DocIntel.Geo.dll",
  "metadata": {
    "DocIntel.Core.Models.Tag": {
      "name": "geo",
      "title": "Geography Mapping",
      "classname": "Cyantlabs.DocIntel.Geo.GeoTagMetadata"
    }
  },
  "profiles": [ "Cyantlabs.DocIntel.Geo.GeoProfile" ]
}

Similarly, a module providing additional collectors might have a configuration file like this:

{
  "name": "malpedia",
  "assembly": "Cyantlabs.DocIntel.Malpedia.dll",
  "collectors": {
    "threat-intel-reports": {
      "class": "Cyantlabs.DocIntel.Malpedia.ReportCollector",
      "settings": "Cyantlabs.DocIntel.Malpedia.ReportCollectorSettings"
    }
  },
  "metadata": {
  },
  "profiles": [ 
    "Cyantlabs.DocIntel.Malpedia.MalpediaProfile"
  ]
}

Metadata

A metadata class defines the fields to be presented to the user when editing the corresponding type. For instance, consider the following example:

public class GeoTagMetadata
{
    [Title("Country Code")]
    public string CountryCode { get; set; }
}

In this case, the GeoTagMetadata class contains a field named CountryCode, which will be displayed to the user as “Country Code” when editing the corresponding type.

You can view an example of such metadata in the documentation of the ThreatQ module.

Collectors

A collector is a class that implements the IDocumentCollector interface. The method Collect is invoked by the DocIntel.Service.Cron service according to the specified configuration. The collector returns objects that are then processed and updated based on its configuration.

public interface IDocumentCollector
{
    IAsyncEnumerable<DocumentImport> Collect(Collector lastCollection, object settings = null);
}

The type of the settings object is defined in the settings key of the corresponding object in the configuration file. For example, in the provided interface, the settings object type would be Cyantlabs.DocIntel.Malpedia.ReportCollectorSettings.

The returned objects are instances of DocumentImport, which describe the documents to be imported. You can find further details about the DocumentImport class in the DocIntel.Core.Collectors namespace.

To import files, you add FileImport objects, containing a StringContent object or a SteamContent object, to the DocumentImport object via the AddFile method.

mapped.AddFile(new FileImport()
{
    Title = "JSON Report",
    Filename = $"{reportEntry.ReportId}.json",
    MimeType = "application/json",
    Content = new StringContent(await _client.Report.Json.FindByIdAsync(reportEntry.ReportId)),
    Preview = false,
    Visible = false
});

mapped.AddFile(new FileImport()
{
    Title = "PDF Report",
    Filename = $"{reportEntry.ReportId}.pdf",
    MimeType = "application/pdf",
    Content = new StreamContent(await _client.Report.Download(reportEntry.ReportId)),
    Preview = true,
    Visible = true
});

Profiles

DocIntel automatically loads profiles, which are standard AutoMapper profiles. To learn how to write these profiles, you can refer to the official documentation of AutoMapper.

Here is a skeleton of a profiles class as an example:

using AutoMapper;
...

namespace Cyantlabs.DocIntel.Geo
{
    public class GeoProfile : Profile
    {
        public GeoProfile(ApplicationSettings settings)
        {
            ...
        }
    }
}

In this example, the GeoProfile class extends Profile from AutoMapper, and it can be used to configure mapping between different types. You can include specific mappings within the constructor of the profile class, utilizing the ApplicationSettings to further customize the mappings as needed.