feat(opencti): new OpenCTI threat-intelligence integration
Add a marketplace integration for the OpenCTI platform (GraphQL API, compatible with OpenCTI 5.x/6.x), built on the Python pycti client and run from a remote engine. 26 commands: observables (list/create/delete/field update/add/remove), indicators (list/create/update/field add/remove, types), incidents (list/create/delete, types) with an OCSF ingestion mapper, relationships (list/create/delete), and reference data (organizations, labels, marking definitions, external references). - Ingestion: get_incidents to an OCSF finding mapper + an OpenCTI Incident type. - Auth: user API key (Bearer) via pycti; requires pip install pycti on the engine host. - Scripts are self-contained (INTEGRATION_SECRETS/INTEGRATION_INPUTS in, JSON out) following the established marketplace pattern. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,378 @@
|
||||
id: opencti
|
||||
name: OpenCTI
|
||||
version: 1.0.0
|
||||
description: "OpenCTI threat-intelligence platform (GraphQL API, compatible with OpenCTI 5.x/6.x). Query and manage observables, indicators, incidents, relationships, labels, markings, organizations and external references; ingest OpenCTI incidents with an OCSF mapper. Runs on a remote engine. Requires the Python 'pycti' library on the engine host (pip install pycti)."
|
||||
changelog: "1.0.0 — Initial release: observables (list/create/delete/field update/add/remove), indicators (list/create/update/field add/remove, types), incidents (list/create/delete, types) with OCSF ingestion mapper, relationships (list/create/delete), and reference data (organizations, labels, marking definitions, external references)."
|
||||
category: threat_intel
|
||||
|
||||
# Per-instance configuration. The integration talks to the OpenCTI GraphQL API at
|
||||
# <base_url>/graphql using the user API key. Run it on a remote engine that can
|
||||
# reach the OpenCTI platform. The bundled scripts require the Python 'pycti'
|
||||
# library on the engine host: pip install pycti
|
||||
config_schema:
|
||||
properties:
|
||||
base_url:
|
||||
type: string
|
||||
description: "OpenCTI base URL, e.g. https://opencti.company.com (scripts append /graphql)"
|
||||
api_key:
|
||||
type: string
|
||||
description: "OpenCTI API key (user profile → API access → API KEY)"
|
||||
x-soar-sensitive: true
|
||||
insecure:
|
||||
type: boolean
|
||||
description: "Trust any TLS certificate (not secure)"
|
||||
default: false
|
||||
required:
|
||||
- base_url
|
||||
- api_key
|
||||
|
||||
# Documented for reference; pycti builds the Authorization header itself from the
|
||||
# api_key (Bearer token) when the scripts construct the client.
|
||||
auth:
|
||||
- id: apikey
|
||||
type: api_key
|
||||
in: header
|
||||
name: Authorization
|
||||
value_template: "Bearer {{secret}}"
|
||||
secret_field: api_key
|
||||
|
||||
commands:
|
||||
# ── Observables ───────────────────────────────────────────────────────────
|
||||
- id: get_observables
|
||||
name: opencti-get-observables
|
||||
description: "List/search observables, optionally filtered by type, score and free text."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
limit: { type: number, description: "Max observables to return (default 50, max 500)" }
|
||||
score_start: { type: number, description: "Minimum score to filter by (0-100)" }
|
||||
score_end: { type: number, description: "Maximum score to filter by (0-100)" }
|
||||
score: { type: string, description: "A specific score (0-100) or 'Unknown'" }
|
||||
observable_types: { type: string, description: "Comma-separated types: ALL, Account, Domain, Email, File, Host, IP, IPv6, Registry Key, URL (default ALL)" }
|
||||
last_run_id: { type: string, description: "Pagination cursor from a previous call (OpenCTI.Observables.LastRunID)" }
|
||||
search: { type: string, description: "Observable value to filter by (partial allowed)" }
|
||||
all_results: { type: boolean, description: "Fetch all results, ignoring limit (default false)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: observable_create
|
||||
name: opencti-observable-create
|
||||
description: "Create a new observable (optionally creating a related indicator)."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
type: { type: string, description: "Observable type: Account, Domain, Email, File-MD5, File-SHA1, File-SHA256, Host, IP, IPv6, Registry Key, URL" }
|
||||
value: { type: string, description: "Observable value" }
|
||||
created_by: { type: string, description: "Organization ID (see organization_list)" }
|
||||
marking_id: { type: string, description: "Marking definition ID (see marking_definition_list)" }
|
||||
label_id: { type: string, description: "Label ID (see label_list / label_create)" }
|
||||
external_references_id: { type: string, description: "External reference ID (see external_reference_create)" }
|
||||
description: { type: string, description: "Observable description" }
|
||||
score: { type: number, description: "Observable score 0-100 (default 50)" }
|
||||
create_indicator: { type: boolean, description: "Also create a related indicator (default false)" }
|
||||
required: [type, value]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: observable_delete
|
||||
name: opencti-observable-delete
|
||||
description: "Delete an observable by ID."
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Observable ID" }
|
||||
required: [id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: observable_field_update
|
||||
name: opencti-observable-field-update
|
||||
description: "Update an observable field (score or description)."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Observable ID" }
|
||||
field: { type: string, description: "Field to update: score or description" }
|
||||
value: { type: string, description: "New value" }
|
||||
required: [id, field, value]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: observable_field_add
|
||||
name: opencti-observable-field-add
|
||||
description: "Add a marking definition or label to an observable."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Observable ID" }
|
||||
field: { type: string, description: "Field to add: marking or label" }
|
||||
value: { type: string, description: "Label ID or marking definition ID to add" }
|
||||
required: [id, field, value]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: observable_field_remove
|
||||
name: opencti-observable-field-remove
|
||||
description: "Remove a marking definition or label from an observable."
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Observable ID" }
|
||||
field: { type: string, description: "Field to remove: marking or label" }
|
||||
value: { type: string, description: "Label ID or marking definition ID to remove" }
|
||||
required: [id, field, value]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Indicators ────────────────────────────────────────────────────────────
|
||||
- id: get_indicators
|
||||
name: opencti-get-indicators
|
||||
description: "List/search indicators with optional filters and pagination."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
search: { type: string, description: "Indicator value to filter by (partial allowed)" }
|
||||
created_by: { type: string, description: "Creator organization ID" }
|
||||
creator: { type: string, description: "Creator user ID" }
|
||||
created_after: { type: string, description: "Created-after date (YYYY-MM-DDThh:mm:ss.sssZ)" }
|
||||
created_before: { type: string, description: "Created-before date (YYYY-MM-DDThh:mm:ss.sssZ)" }
|
||||
valid_until_after: { type: string, description: "Valid-until-after date" }
|
||||
valid_until_before: { type: string, description: "Valid-until-before date" }
|
||||
valid_from_after: { type: string, description: "Valid-from-after date" }
|
||||
valid_from_before: { type: string, description: "Valid-from-before date" }
|
||||
indicator_types: { type: string, description: "Comma-separated indicator types (see indicator_types_list)" }
|
||||
label_id: { type: string, description: "Label ID to filter by" }
|
||||
limit: { type: number, description: "Max indicators to return (default 50, max 500)" }
|
||||
last_run_id: { type: string, description: "Pagination cursor (OpenCTI.Indicators.LastRunID)" }
|
||||
all_results: { type: boolean, description: "Fetch all results, ignoring limit (default false)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: indicator_create
|
||||
name: opencti-indicator-create
|
||||
description: "Create a new indicator (STIX pattern built from value + observable type)."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
name: { type: string, description: "Indicator name" }
|
||||
indicator: { type: string, description: "Indicator value" }
|
||||
main_observable_type: { type: string, description: "Main observable type: Account, Domain, Email, File-MD5, File-SHA1, File-SHA256, IP, IPv6, Registry Key, URL" }
|
||||
indicator_types: { type: string, description: "Comma-separated indicator types (see indicator_types_list)" }
|
||||
description: { type: string, description: "Indicator description" }
|
||||
confidence: { type: number, description: "Confidence 0-100 (default 50)" }
|
||||
score: { type: number, description: "Score 0-100 (default 50)" }
|
||||
valid_from: { type: string, description: "Valid-from date (YYYY-MM-DDThh:mm:ss.sssZ)" }
|
||||
valid_until: { type: string, description: "Valid-until date (YYYY-MM-DDThh:mm:ss.sssZ)" }
|
||||
created_by: { type: string, description: "Creator organization ID" }
|
||||
label_id: { type: string, description: "Label ID" }
|
||||
marking_id: { type: string, description: "Marking definition ID" }
|
||||
external_references_id: { type: string, description: "External reference ID" }
|
||||
create_observables: { type: boolean, description: "Also create the related observable (default false)" }
|
||||
required: [name, indicator, main_observable_type]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: indicator_update
|
||||
name: opencti-indicator-update
|
||||
description: "Update an existing indicator's fields."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Indicator ID" }
|
||||
name: { type: string, description: "Indicator name" }
|
||||
indicator_types: { type: string, description: "Comma-separated indicator types" }
|
||||
description: { type: string, description: "Indicator description" }
|
||||
confidence: { type: number, description: "Confidence 0-100 (default 50)" }
|
||||
score: { type: number, description: "Score 0-100 (default 50)" }
|
||||
valid_from: { type: string, description: "Valid-from date" }
|
||||
valid_until: { type: string, description: "Valid-until date" }
|
||||
label_id: { type: string, description: "Comma-separated label IDs" }
|
||||
marking_id: { type: string, description: "Comma-separated marking IDs" }
|
||||
external_references_id: { type: string, description: "Comma-separated external reference IDs" }
|
||||
required: [id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: indicator_field_add
|
||||
name: opencti-indicator-field-add
|
||||
description: "Add a marking definition or label to an indicator."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Indicator ID" }
|
||||
field: { type: string, description: "Field to add: marking or label" }
|
||||
value: { type: string, description: "Label ID or marking definition ID to add" }
|
||||
required: [id, field, value]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: indicator_field_remove
|
||||
name: opencti-indicator-field-remove
|
||||
description: "Remove a marking definition or label from an indicator."
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Indicator ID" }
|
||||
field: { type: string, description: "Field to remove: marking or label" }
|
||||
value: { type: string, description: "Label ID or marking definition ID to remove" }
|
||||
required: [id, field, value]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: indicator_types_list
|
||||
name: opencti-indicator-types-list
|
||||
description: "List all indicator types (vocabulary)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties: {}
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Incidents (ingestion source) ──────────────────────────────────────────
|
||||
- id: get_incidents
|
||||
name: opencti-get-incidents
|
||||
description: "Fetch OpenCTI incidents for ingestion or search. Returns the entities list; use it as the alert-rule results path."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
search: { type: string, description: "Incident value to filter by (partial allowed)" }
|
||||
created_by: { type: string, description: "Creator organization ID" }
|
||||
creator: { type: string, description: "Creator user ID" }
|
||||
created_after: { type: string, description: "Created-after date / incremental watermark (YYYY-MM-DDThh:mm:ss.sssZ)" }
|
||||
created_before: { type: string, description: "Created-before date" }
|
||||
incident_types: { type: string, description: "Comma-separated incident types (see incident_types_list)" }
|
||||
label_id: { type: string, description: "Label ID to filter by" }
|
||||
limit: { type: number, description: "Max incidents to return (default 50, max 500)" }
|
||||
last_run_id: { type: string, description: "Pagination cursor (OpenCTI.Incidents.LastRunID)" }
|
||||
all_results: { type: boolean, description: "Fetch all results, ignoring limit (default false)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
ingest:
|
||||
results_path: entities
|
||||
dedup_key: id
|
||||
incremental_field: created_after
|
||||
- id: incident_create
|
||||
name: opencti-incident-create
|
||||
description: "Create a new incident."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
name: { type: string, description: "Incident name" }
|
||||
incident_type: { type: string, description: "Incident type name (see incident_types_list)" }
|
||||
confidence: { type: number, description: "Confidence 0-100 (default 50)" }
|
||||
severity: { type: string, description: "Severity: low, medium, high, critical" }
|
||||
description: { type: string, description: "Incident description" }
|
||||
source: { type: string, description: "Incident source" }
|
||||
objective: { type: string, description: "Incident objective" }
|
||||
created_by: { type: string, description: "Creator organization ID" }
|
||||
first_seen: { type: string, description: "First seen (YYYY-MM-DDThh:mm:ss.sssZ)" }
|
||||
last_seen: { type: string, description: "Last seen (YYYY-MM-DDThh:mm:ss.sssZ)" }
|
||||
label_id: { type: string, description: "Label ID" }
|
||||
marking_id: { type: string, description: "Marking definition ID" }
|
||||
external_references_id: { type: string, description: "External reference ID" }
|
||||
required: [name]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: incident_delete
|
||||
name: opencti-incident-delete
|
||||
description: "Delete an incident by ID."
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Incident ID" }
|
||||
required: [id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: incident_types_list
|
||||
name: opencti-incident-types-list
|
||||
description: "List all incident types (vocabulary)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties: {}
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Relationships ─────────────────────────────────────────────────────────
|
||||
- id: relationship_create
|
||||
name: opencti-relationship-create
|
||||
description: "Create a relationship between two entities."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
from_id: { type: string, description: "Source entity ID" }
|
||||
to_id: { type: string, description: "Target entity ID" }
|
||||
relationship_type: { type: string, description: "Relationship type (e.g. related-to, indicates, targets, uses, mitigates; default related-to)" }
|
||||
description: { type: string, description: "Relationship description" }
|
||||
confidence: { type: number, description: "Confidence 0-100" }
|
||||
required: [from_id, to_id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: relationship_delete
|
||||
name: opencti-relationship-delete
|
||||
description: "Delete a relationship by ID."
|
||||
inputs_schema:
|
||||
properties:
|
||||
id: { type: string, description: "Relationship ID" }
|
||||
required: [id]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: relationship_list
|
||||
name: opencti-relationship-list
|
||||
description: "List relationships from a given entity."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
from_id: { type: string, description: "Source entity ID" }
|
||||
limit: { type: number, description: "Max relationships to return (default 50, max 200)" }
|
||||
last_run_id: { type: string, description: "Pagination cursor (OpenCTI.Relationships.relationshipsLastRun)" }
|
||||
required: [from_id]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
# ── Reference data ────────────────────────────────────────────────────────
|
||||
- id: organization_list
|
||||
name: opencti-organization-list
|
||||
description: "List all organizations."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
limit: { type: number, description: "Max organizations to return (default 50, max 200)" }
|
||||
last_run_id: { type: string, description: "Pagination cursor (OpenCTI.Organizations.organizationsLastRun)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: organization_create
|
||||
name: opencti-organization-create
|
||||
description: "Create a new organization."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
name: { type: string, description: "Organization name" }
|
||||
description: { type: string, description: "Organization description" }
|
||||
reliability: { type: string, description: "Reliability: A, B, C, D, E, F" }
|
||||
required: [name]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: label_list
|
||||
name: opencti-label-list
|
||||
description: "List all labels."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
limit: { type: number, description: "Max labels to return (default 50)" }
|
||||
last_run_id: { type: string, description: "Pagination cursor (OpenCTI.Labels.labelsLastRun)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: label_create
|
||||
name: opencti-label-create
|
||||
description: "Create a new label."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
name: { type: string, description: "Label name" }
|
||||
required: [name]
|
||||
outputs_schema: { properties: {} }
|
||||
- id: marking_definition_list
|
||||
name: opencti-marking-definition-list
|
||||
description: "List all marking definitions."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties:
|
||||
limit: { type: number, description: "Max marking definitions to return (default 50)" }
|
||||
last_run_id: { type: string, description: "Pagination cursor (OpenCTI.MarkingDefinitions.markingsLastRun)" }
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
- id: external_reference_create
|
||||
name: opencti-external-reference-create
|
||||
description: "Create an external reference."
|
||||
risk: safe_write
|
||||
inputs_schema:
|
||||
properties:
|
||||
url: { type: string, description: "External reference URL" }
|
||||
source_name: { type: string, description: "External reference source name" }
|
||||
required: [url, source_name]
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
- id: test_connection
|
||||
name: opencti-test-connection
|
||||
description: "Verify connectivity and credentials (used by the Test button)."
|
||||
risk: read
|
||||
inputs_schema:
|
||||
properties: {}
|
||||
required: []
|
||||
outputs_schema: { properties: {} }
|
||||
|
||||
ingestion:
|
||||
command: get_incidents
|
||||
mapper: get_incidents
|
||||
default_incident_type: "OpenCTI Incident"
|
||||
Reference in New Issue
Block a user