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 of the extension. |
|
Type of extension. Each |
|
License of the extension. |
|
Maintainer’s contact details. |
|
Producer assigned to data processed by this extension. |
|
If the extension has been verified by EclecticIQ. |
|
Extension repository URL. |
|
Path to the extension once it is installed on the extension application host. |
|
Supported EDK protocol version. |
|
Version of the extension. |
|
Programming language used in the extension. |
|
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:
|
Additional field |
Description |
---|---|---|
|
List of content types supported by this feed. |
|
|
List of packer update strategies and default update strategy |
|
|
Reliability score |
|
|
List supported observable types. |
|
|
(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 model2.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.
Type: Must match
content_types:configuration:type
Function: General
Required: no
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}"
}
]
// ...
}