EDK Manifest File Format#

The EDK manifest file is a JSON file which contains metadata that describes an extension. For this reason, each extension must have one manifest file.

Compose the extension manifest#

Your extension must include a file named manifest.json at the repository root. It must contain the following fields:

Keyword

Description

name

Name of the extension.

extension_type

Type of extension.

Each extension_type has their own set of additional required fields.

license

License of the extension.

maintainer

Maintainer’s contact details.

producer

Producer assigned to data processed by this extension.

eiq_verified

If the extension has been verified by EclecticIQ.

repository

Extension repository URL.

application_path

Path to the extension once it is installed on the extension application host.

edk_protocol

Supported EDK protocol version.

version

Version of the extension.

programming_language

Programming language used in the extension.

programming_language_version

Version of the programming language used in the extension.

Example manifest.json:

{
  "name": "Intel 471",
  "extension_type": "enricher",
  "license": "MIT license",
  "maintainer": "Developer <[email protected]>",
  "producer": "Eclectic IQ B.V.",
  "eiq_verified": true,
  "repository": "https://extensions.eclecticiq.com",
  "application_path": "/foo/bar/bin",
  "edk_protocol": "1.0",
  "version": "0.1.0",
  "source_reliability": "A",
  "supported_extract_types": [
    "email",
    "host"
  ],
  "source_urls": [
    {
      "name": "email",
      "uri": "https://foo.com/email.php/email=${input}"
    },
    {
      "name": "host",
      "uri": "https://foo.com/host.php/host=${input}"
    }
  ],
  "programming_language": "python",
  "programming_language_version": "3.8",
  "content_types": [
    {
      "configuration": [
        {
          "default": "https://api.intel471.com/v1/",
          "required": false,
          "type": "string",
          "description": "The URL pointing to the API endpoint exposing the service that makes the data available for retrieval through the feed.",
          "format": "uri",
          "title": "API URL",
          "name": "api_url"
        }
      ]
    }
  ]
}

List of keywords#

name#

Use the name keyword to provide the name of your extension.

  • Type: String

  • Function: General

  • Required: yes

Example of name:

{
  // ...
  "name": "Example Extension",
  // ...
}

extension_type#

Use extension_type to assign a type to this extension.

  • Type: String

  • Function: General

  • Required: yes

The EDK-ERE supports three types of extensions:

  • Incoming feeds (incoming): Incoming feeds retrieve data from a data vendor, (if needed) processes it, and then sends it to the IC for ingestion.

  • Outgoing feeds (outgoing): Outgoing feeds retrieves data from the IC and makes it available through a published endpoint, pushes it to a remote service, or other means of dissemination.

  • Enrichers (enricher): Enrichers allow users to take a given observable and “enrich” it by retrieving related data from a data vendor.

Warning

An extension can only be assigned one extension_type. If you want to provide more than one extension_type, build separate extensions for each extension_type.

Accepted Values:

  • incoming

  • outgoing

  • enricher

Example of extension_type:

{
  // ...
  "extension_type":"incoming",
  // ...
}

Each extension_type requires you to specify different additional fields in the manifest:

extension_type

Additional field

Description

incoming/outgoing

content_types

List of content types supported by this feed.

outgoing

supported_update_strategies

List of packer update strategies and default update strategy

enricher

source_reliability

Reliability score

enricher

supported_extract_types

List supported observable types.

enricher

source_urls

(Optional) List of objects that function as URI templates.

For example, for extension_type:enricher:

{
  "name": "Example enricher",
  "extension_type": "enricher",
  // ...
  "source_reliability": "A",
  "supported_extract_types": ["email"],
  "source_urls": [
    {"name": "email", "uri": "https://example.com/endpoint/${input}"},
    //...
  ]
  // ...
}

license#

Choose a license to publish your extension.

  • Type: String

  • Function: General

  • Required: yes

Accepted Values:

  • MIT license

  • BSD license

  • ISC license

  • Apache Software License 2.0

  • GNU General Public License v3

  • GNU AGPLv3

  • GNU LGPLv3

  • Mozilla Public License 2.0

  • Boost Software License 1.0

  • The Unlicensed

  • Proprietary

Example of license:

{
  // ...
  "license":"MIT License",
  // ...
}

maintainer#

Information about the extension’s maintainer.

  • Type: String

  • Function: General

  • Required: yes

Example of maintainer:

{
  // ...
  "maintainer":"Developer <[email protected]>"
  // ...
}

producer#

Use the producer keyword to give the name of the producer of the data that the extension handles.

  • Type: String

  • Function: General

  • Required: yes

Example of producer:

{
  // ...
  "producer": "Eclectic IQ B.V.",
  // ...
}

eiq_verified#

Use the eiq_verified keyword to indicate if the extension has been verified by EclecticIQ.

Note

Only set this to true after you have received confirmation that EclecticIQ has verified your extension.

  • Type: Boolean

  • Function: General

  • Required: yes

Example of eiq_verified:

{
  // ...
  "eiq_verified": false,
  // ...
}

repository#

Use the repository keyword to specify the repository from which the extension can installed.

  • Type: URL

  • Function: General

  • Required: yes

Example of repository:

{
  // ...
  "repository":"https://extensions.eclecticiq.com",
  // ...
}

application_path#

Use the application_path keyword to specify the installation directory of the extension application on the extension application host.

  • Type: String

  • Function: General

  • Required: yes

Example of application_path:

{
  // ...
  "application_path": "/foo/bar/bin",
  // ...
}

edk_protocol#

Use the edk_protocol keyword to provide the EDK protocol version which your extension supports.

  • Type: String

  • Function: General

  • Required: yes

Accepted Values:

  • 1.0: EIQ JSON data model

  • 2.0: STIX 2.1 data model

Example of edk_protocol:

{
  // ...
  "edk_protocol": "1.0"
  // ...
}

version#

Use the version keyword to include the version of your extension.

  • Type: String

  • Function: General

  • Required: yes

Example of version:

{
  // ...
  "version": "0.1.0"
  // ...
}

programming_language#

Use the programming_language keyword to specify with which programming language used to develop the extension.

  • Type: String

  • Function: General

  • Required: yes

Accepted Values:

  • Python

Example of programming_language:

{
  // ...
  "programming_language":"Python"
  // ...
}

programming_language_version#

Use the programming_language_version keyword to specify the version of the programming language used to develop the extension.

  • Type: String

  • Function: General

  • Required: yes

Example of programming_language_version:

{
  // ...
  "programming_language_version":"3.8"
}

supported_update_strategies#

Use the supported_update_strategies to specify how data is updated on the eventual destination of the data (e.g. the EIQ Intelligence Center). Exact implementation may vary among extensions.

  • Type: Object

  • Function: Outgoing

  • Required: yes

Accepted values:

  • APPEND: Only push data that was created or modified since the last time the outgoing feed was run.

  • REPLACE: Purge previously pushed data, and then push all data for that feed.

  • DIFF: Push all data that does not already exist on its target destination.

{
  // ...
  "supported_update_strategies": {
    "enum": ["APPEND", "REPLACE", "DIFF"],
    "default": "REPLACE"
  },
  // ...
}

content_types#

Use the content_types keyword to define transformers and the type of data they can process.

  • Type: List of JSON objects

  • Function: Incoming/Outgoing

  • Required: no

Example of content_types:

{
  "content_types": [
    {
      "id": "urn:bitdefender.ip:json:1.0",
      "name": "Bitdefender IP JSON",
      "description": "Bitdefender IP JSON",
      "content_groups": [
        "bitdefender_ip_json"
      ],
      "file_extension": "json",
      "mime_type": "application/json"
    },
    {
      "id": "urn:bitdefender.domain:json:1.0",
      "name": "Bitdefender Domain JSON",
      "description": "Bitdefender Domain JSON",
      "content_groups": [
        "bitdefender_domain_json"
      ],
      "file_extension": "json",
      "mime_type": "application/json"
    },
    {
      "id": "urn:bitdefender.hash:json:1.0",
      "name": "Bitdefender Hash JSON",
      "description": "Bitdefender Hash JSON",
      "content_groups": [
        "bitdefender_hash_json"
      ],
      "file_extension": "json",
      "mime_type": "application/json"
    }
  ]
}

content_types:id#

Use the content_types:id keyword to specify a URN for that content_types object.

  • Type: URN

  • Function: Incoming/Outgoing

  • Required: yes

Example of content_types:id:

{
  // ...
  "content_types": [
    {
      // ...
      "id": "urn:bitdefender.ip:json:1.0",
      // ...
    }
  ]
  // ...
}

content_types:name#

Use the content_types:name keyword to give the name displayed to users.

  • Type: String

  • Function: Incoming/Outgoing

  • Required: yes

Example of content_types:name:

{
  // ...
  "content_types": [
    {
      // ...
      "name": "Bitdefender IP JSON",
      // ...
    }
  ]
  // ...
}

content_types:description#

Use the content_types:description keyword to explain the content type that you are setting up.

  • Type: String

  • Function: Incoming/Outgoing

  • Required: yes

Example of content_types:description:

{
  // ...
  "content_types": [
    {
      // ...
      "description": "Bitdefender IP JSON",
      // ...
    }
  ]
  // ...
}

content_types:content_groups#

Use the content_types:content_groups keyword to link content types to transports.

  • Type: List of strings

  • Function: Incoming/Outgoing

  • Required: yes

Example of content_types:content_groups:

{
  // ...
  "content_types": [
    {
      // ...
      "content_groups": [
        "bitdefender_ip_json"
      ],
      // ...
    }
  ]
  // ...
}

content_types:file_extension#

Use the content_types:file_extension keyword to specify the file extension supported by this extension, such as ‘xml’ or ‘pdf’.

  • Type: String

  • Function: Incoming/Outgoing

  • Required: yes

Example of content_types:file_extension:

{
  // ...
  "content_types": [
    {
      // ...
      "file_extension": "json",
      // ...
    }
  ]
  // ...
}

content_types:mime_type#

Use the content_types:mime_type keyword to set a MIME type for a given content type.

  • Type: String

  • Function: Incoming/Outgoing

  • Required: yes

Example of content_types:mime_type:

{
  // ...
  "content_types": [
    {
      // ...
      "mime_type": "application/json"
      // ...
    }
  ]
  // ...
}

content_types:configuration#

Contains a list of objects with information describing user input fields. These user input fields collect information necessary for the extension to run (e.g. API baseurl for the vendor service, user credentials, etc.)

The IC uses information from these objects to display user input fields in the UI.

  • Type: List of JSON object

  • Function: General

  • Required: yes

Example of content_types:configuration:

{
  // ...
  "content_types": [
    {
      // ...
      "configuration": [
        {
          "default": "https://api.intel471.com/v1/",
          "required": false,
          "type": "string",
          "description": "The URL pointing to the API endpoint exposing the service that makes the data available for retrieval through the feed.",
          "title": "API URL",
          "name": "api_url"
        }
      ]
    // ...
    }
  ]
  // ...
}

content_types:configuration:name#

Use the content_types:configuration:name keyword to give a machine-readable name for your UI field.

  • Type: String

  • Function: General

  • Required: yes

Example of content_types:configuration:name:

{
  // ...
  "content_types": [
    {
      // ...
      "configuration": [
        {
          // ...
          "name": "api_url"
        }
      ]
      // ...
    }
   ]
  // ...
}

content_types:configuration:title#

Use the content_types:configuration:title keyword to give the label of your setting on the UI.

  • Type: String

  • Function: General

  • Required: yes

Example of content_types:configuration:title:

{
  // ...
  "content_types": [
    {
      // ...
      "configuration": [
        {
          // ...
          "title": "API URL",
          // ...
        }
      ]
      //...
    }
  ]
  // ...
}

content_types:configuration:description#

Use the content_types:configuration:description keyword to describe this user input field.

  • Type: String

  • Function: General

  • Required: yes

Example of content_types:configuration:description:

{
  // ...
  "content_types": [
    {
      // ...
      "configuration": [
        {
          // ...
          "description": "The URL pointing to the API endpoint exposing the service that makes the data available for retrieval through the feed.",
          // ...
        }
      ]
      // ...
    }
  ]
  // ...
}

content_types:configuration:type#

Use the content_types:configuration:type keyword to specify the data type expected in the user input field.

  • Type: String

  • Function: General

  • Required: yes

Accepted values:

  • string

  • number

  • boolean

  • hostname

  • uri

  • List

  • required

  • mapping

Example of content_types:configuration:type:

{
  // ...
  "content_types": [
    // ...
    "configuration": [
      {
        // ...
        "type": "string",
        // ...
      }
    ]
    // ...
  ]
  // ...
}

content_types:configuration:required#

Use the content_types:configuration:required keyword to define either the setting is required .

  • Type: Boolean

  • Function: General

  • Required: yes

Example of content_types:configuration:required:

{
  // ...
  "content_types": [
    // ...
    "configuration": [
      {
        // ...
        "required": false,
        // ...
      }
    ]
    // ...
  ]
  // ...
}

content_types:configuration:default#

Use the content_types:configuration:default to set a default value for this user input field.

Example of content_types:configuration:default:

{
  // ...
  "content_types": [
    {
      // ...
      "configuration": [
        {
          // ...
          "default": "https://api.intel471.com/v1/",
          // ...
        }
      ]
      // ...
    }
  ]
  // ...
}

source_reliability#

Default reliability score for data produced by this extension. Scores are the first character of the Admiralty Scale.

  • Type: String

  • Function: Enricher

  • Required: no

Accepted values:

  • A

  • B

  • C

  • D

  • E

  • F

Example of source_reliability:

{
  // ...
  "source_reliability":"A",
  // ...
}

supported_extract_types#

Use the supported_extract_types keyword to specify a list of extract types this extension supports.

  • Type: List of strings

  • Function: Enricher

  • Required: no

Accepted values:

  • actor-id

  • address

  • asn

  • bank-account

  • card

  • card-owner

  • cce

  • city

  • company

  • country

  • country-code

  • cve

  • cwe

  • domain

  • email

  • email-subject

  • eui-64

  • file

  • forum-name

  • forum-room

  • forum-thread

  • fox-it-portal-uri

  • geo

  • geo-lat

  • geo-long

  • handle

  • hash-authentihash

  • hash-imphash

  • hash-md5

  • hash-rich-pe-header

  • hash-sha1

  • hash-sha256

  • hash-sha512

  • hash-ssdeep

  • hash-vhash

  • host

  • industry

  • inetnum

  • ipv4

  • ipv4-cidr

  • ipv6

  • ipv6-cidr

  • ja3s-full

  • ja3s-hash

  • ja3-full

  • ja3-hash

  • mac-48

  • malware

  • mutex

  • name

  • nationality

  • netname

  • organization

  • person

  • port

  • postcode

  • process

  • product

  • registrar

  • rule

  • snort

  • street

  • telephone

  • uri

  • uri-hash-sha256

  • winregistry

  • yara

Example of supported_extract_types:

{
  // ...
  "supported_extract_types": [
    "email"
  ]
  // ...
}

source_urls#

source_urls are used by the IC to link observables resulting from enrichments to its external reference.

  • Type: List of JSON objects

  • Function: Enricher

  • Required: no

For example, with the following source_urls:

{
  // ...
  "source_urls": [
    {
      "name": "email",
      "uri": "https://foo.com/email.php/email=${input}"
    },
    // ...
  ]
  // ...
}

Enriching an email:user@example.com email observable will allow the UI to display it with a link to https://foo.com/email.php/email=user@example.com.

source_urls:name#

source_urls:name is the name of the observable type which the IC applies the URI template specified in source_urls:uri.

You must only specify one source_urls object for a given observable type:

// ✅ Valid
{ // ...
  "source_urls": [
    {"name": "email", "uri": "..."},
    {"name": "file", "uri": "..."}
    ]
  // ...
}

// ❌ Invalid
{ // ...
  "source_urls": [
    {"name": "email", "uri": "..."},
    {"name": "email", "uri": "..."}
    ]
  // ...
}
  • Type: String

  • Function: Enricher

  • Required: no

Accepted values: (same assupported_extract_types)

Example of source_urls:name:

{
  // ...
  "source_urls": [
    {
      "name": "email",
      // ...
    },
    // ...
  ]
  // ...
}

source_urls:uri#

Use the source_urls:uri to provide a URI template to apply to the observable type specified in source_urls:name.

  • Type: URL

  • Function: Enricher

  • Required: no

Example of source_urls:uri:

{
  // ...
  "source_urls": [
    {
      // ...
      "uri": "https://foo.com/email.php/email=${input}"
    }
  ]
  // ...
}