opentide

MISP connector

`sharing::misp::1.0` publishes one Tide object as one MISP Event. Each MISP instance is one `[[misp]]` block in `sharing.toml`. The Event carries exactly one instance of the upstream `opentide` MISP object, and its `opentide-object` attribute holds the source document verbatim. Exposure is the block's `max_tlp` ceiling

Summary

sharing::misp::1.0 publishes one Tide object as one MISP Event. Each MISP instance is one [[misp]] block in sharing.toml. The Event carries exactly one instance of the upstream opentide MISP object, and its opentide-object attribute holds the source document verbatim. Exposure is the block's max_tlp ceiling and the MISP distribution that the object's metadata.tlp permits. The connector does not filter fields out of the document.

This first revision keeps the block small: where to connect, what to select, and how high TLP may go. Distribution width, sharing groups, file export, and Event title decoration are not configurable in 1.0.

The pinned template is schemas/misp/opentide.definition.json, copied from MISP/misp-objects objects/opentide/definition.json. Refresh direction is upstream MISP → this repository, the reverse of vocabulary sync. A refresh that changes the pinned relation set is a revision of this spec.

Requirements

  • Each MISP instance MUST be one [[misp]] entry in sharing.toml.
  • A [[misp]] block MUST set name, url, api_key, and max_tlp. Every other key has a default.
  • A key not listed in this spec MUST be rejected as a configuration error before any instance is contacted.
  • The publishing organisation MUST be the block's organisation_uuid when set, otherwise the object's metadata.organisation.uuid. An object with neither MUST fail and MUST NOT be written. The resolved value MUST be verified against the API key's organisation before any write.
  • The connector MUST emit exactly one opentide object per Event and zero Event-level attributes.
  • The opentide-object value MUST be the verbatim UTF-8 YAML bytes of the source document. Comments, key order, indentation, and blank lines MUST be preserved. The connector MUST NOT re-serialise, encode, truncate, split, or wrap that body.
  • No configuration value, API key, authorization header, or ${ENV_VAR} substitution result MAY be injected into the document, object, envelope, tag set, share report, share state, or CLI output.
  • The connector MUST NOT create, modify, enable, delete, or upload a galaxy or cluster.
  • pull is not supported.

Definition

Capability

CapabilityMISP 1.0
Integration keymisp ([[misp]])
schemasharing::misp::1.0
pushyes
previewyes
statusyes (local state; MAY view the remote)
retractyes (unpublish; optional delete)
pullno

[[misp]] block

[[misp]]
name = "misp-internal"
enabled = true
url = "https://misp.internal.example.org"
api_key = "${MISP_INTERNAL_API_KEY}"
max_tlp = "amber"
object_types = ["threat", "objective", "rule"]
rule_statuses = ["PRODUCTION"]

[[misp]]
name = "misp-isac"
enabled = true
url = "https://misp.isac.example.net"
api_key = "${MISP_ISAC_API_KEY}"
max_tlp = "green"
object_types = ["rule"]
publish = true
organisation_uuid = "00000000-0000-4000-8aaa-000000000002"
FieldTypeRequiredDefaultNotes
namestringyes—Block identifier (sharing.md)
enabledboolnofalse
urlstring (URL)yes—Instance origin. Trailing slash ignored.
api_keystringyes—MUST be a ${ENV_VAR} reference in committed config. An unset or empty variable excludes the block before any request. A literal key SHOULD raise a validation warning and MUST NOT be printed.
max_tlpstringyes—Highest metadata.tlp this block shares. No default.
object_typeslist[string]noall three
rule_statuseslist[string]no["PRODUCTION"]
organisation_uuidstring (UUID)nofrom the objectOverride for the publishing organisation. Canonical 36-character UUID.
publishboolnofalseCall publish after each create or update
verify_sslboolnotrue

Requests use an implementation default timeout, which SHOULD be 30 seconds.

Not configurable in 1.0

These keys are rejected like any other unknown key. They name behaviour this revision fixes rather than exposes; a later revision MAY add them.

KeyFixed 1.0 behaviour
distribution, sharing_group_id, sharing_group_uuidDistribution derived from metadata.tlp (below). No sharing groups.
mode, directoryAPI only. preview prints the share report and writes no file.
analysiscompleted
info_prefixEvent info is the object name
extra_tagsClosed tag set
timeout_seconds, client_cert, client_keyImplementation default timeout; no mutual TLS
require_validationAlways validates (sharing.md)
connector, schema, identifierThe array key is the connector; name is the identifier
event_mode, threat_level_source, threat_level_id, verify_event_org, tag_namespace, include_*One Event per object; derived threat level; organisation in the lookup key; no tag namespace; no payload filtering

Publishing organisation

The publishing organisation is half of the Event lookup key. opentide already records an owning organisation on each object as metadata.organisation.uuid (metadata.md), so the connector consumes that value first:

OrderSourceWhen used
1[[misp]].organisation_uuidSet on the block. Overrides every object for that block.
2Object metadata.organisation.uuidBlock value absent

An object where both are absent is failed / organisation_uuid_missing. Other objects continue. The connector MUST NOT fall back to the API key's organisation.

MISP records the API key's organisation as the Event creator, whatever the payload says. Before any create or update, the connector MUST read that organisation with GET /users/view/me and compare it case-insensitively to the resolved value:

ResultOutcome
MatchContinue
Mismatch, value from the blockFail the block with organisation_uuid_mismatch; write nothing to it
Mismatch, value from the objectFail that object with organisation_uuid_mismatch; other objects continue
Read failureFail the block with organisation_uuid_unverified

A mismatch is never written through, because an Event created under another organisation would not match the lookup key on the next run and would duplicate. An object whose metadata.organisation belongs to someone else can be republished by setting organisation_uuid on the block to the publisher's own organisation.

preview makes no request. It resolves the organisation from the same two sources. A resolved value is noted organisation_unverified. A missing value is failed / organisation_uuid_missing, the same as a push.

Distribution

1.0 derives distribution from the object's TLP only. Objects above the block's max_tlp are skipped_tlp and never reach this table. max_tlp = "red" shares TLP:RED; there is no second flag.

Object metadata.tlpMISP distribution
clear1 (this community)
green1 (this community)
amber0 (your organisation)
amber+strict0 (your organisation)
red0 (your organisation)

sharing_group_id is always 0. Wider distribution (connected or all communities) and sharing groups are out of scope for 1.0.

HTTP subset

Minimum server: a MISP release that ships opentide template version 5 (uuid 892fd46a-f69e-455c-8c4f-843a4b8f4295).

Every request MUST send the API key as Authorization: <key>. The key MUST NOT appear in query strings. On 401 or 403, the block MUST fail with authentication failed and MUST NOT dump response bodies.

OperationRequestUse
Server identityGET /servers/getVersionConnectivity probe
Authenticated organisationGET /users/view/meOrganisation check. Compare Organisation.uuid case-insensitively.
Find eventsPOST /events/restSearchBody includes "returnFormat": "json", "object_name": "opentide", "value": "<metadata.uuid>", and a page size. Page with page and limit until a page returns fewer than limit hits.
View eventGET /events/view/<uuid-or-id>Read a candidate, including Orgc and objects
Add eventPOST /events/addCreate, including the nested object and tags
Edit eventPOST /events/edit/<id>Update after lookup
PublishPOST /events/publish/<id>When publish resolves true
UnpublishPOST /events/unpublish/<id>Retract default
Delete eventDELETE /events/<id>Retract --delete
Galaxy clustersRead-only galaxy cluster searchResolve threat-actor and mitre-attack-pattern

restSearch is not assumed to constrain creator organisation and object attribute in one predicate. The connector MUST keep a hit only when both halves of the lookup key match, and MUST exclude every other hit from the match count. A foreign organisation's Event is an informational note, not a match and not an error.

PyMISP is the recommended opentide library. The spec is HTTP/JSON. Any client that speaks this subset conforms.

A galaxy lookup that fails for transport, timeout, or authorization fails the affected object with galaxy_lookup_failed. It MUST NOT degrade into a guessed value.

Tags

Emission order: TLP, PAP, threat-actor clusters, then mitre-attack-pattern clusters. Ascending code point order within each group. Each distinct tag string at most once.

SourceCardinalityValue
tlp vocabulary misp for metadata.tlpexactly 1copied character-for-character
pap vocabulary misp for metadata.pap0 or 1copied character-for-character
threat-actor galaxy cluster0..nmisp-galaxy:threat-actor="<cluster value as returned>"
mitre-attack-pattern galaxy cluster0..nmisp-galaxy:mitre-attack-pattern="<cluster value as returned>"

A missing or unmapped metadata.tlp fails the object with unmapped_tlp. An unmapped metadata.pap fails it with unmapped_pap. An absent metadata.pap emits no PAP tag.

Cluster values MUST be the value string the instance returns. The connector MUST NOT derive a cluster value from an opentide vocabulary field.

Identifier sourceGalaxyFirst key that yields exactly one match
threat.mitre_attack[], objective.mitre_attack[], rule.techniques[]mitre-attack-patternmeta.external_id contains the technique id, case-insensitive after trimming
threat.actors[].name scope att&ck::threat-actor(a) meta.external_id contains the id; else (b) meta.refs URL final path segment equals the id; else (c) meta.synonyms contains the id
threat.actors[].name scope misp::threat-actorcluster uuid equals the scoped identifier, canonical form, case-insensitive
ConditionBehaviour
Actor name has no scope, or a scope other than att&ck:: or misp::Omit the tag, note actor_unscoped. Bare strings MUST NOT be coerced.
No cluster matchesOmit the tag, note cluster_not_found, emit the Event
More than one cluster matchesOmit the tag, note cluster_ambiguous listing every matched cluster UUID
Lookup fails for transport, timeout, or authorizationFail the object with galaxy_lookup_failed; leave the remote Event unmodified

A sub-technique emits its own cluster tag only. The parent is emitted only when the object lists the parent identifier separately.

preview makes no lookup. It omits cluster tags with note cluster_not_resolved and still emits the Event.

Golden fixtures MUST assert galaxy tag shape (misp-galaxy:<galaxy>="<non-empty>") rather than one instance's cluster value. Cluster strings are not stable across galaxy versions.

Event envelope

The connector sets exactly these Event fields:

FieldSource
infoObject top-level name, truncated to 255 characters
dateUTC calendar date of metadata.created (YYYY-MM-DD), on create and update. Never the run date.
distributionThe TLP-derived value above
sharing_group_id0
threat_level_idThe table below
analysis2 (completed)
publishedfalse on every create and update payload. Publishing is a separate call.

uuid, timestamp, orgc_id, org_id, Orgc, Org, event_creator_email, EventReport, and CryptographicKey are server-owned and MUST NOT be set on create. The Event uuid is assigned by the instance and is sent only to address an existing Event on update.

An object whose top-level name is absent or empty after trimming, or whose metadata.created is absent or not a valid YYYY-MM-DD date, is failed with the field named. No remote Event is created or modified.

threat_level_id (1 High, 2 Medium, 3 Low, 4 Undefined) is derived, never configured. Threat uses top-level criticality. Rule uses top-level severity. Objective has no source and is 4.

opentide scaleSource valuesthreat_level_id
criticality::1.0Emergency, Severe, High1
criticality::1.0Medium2
criticality::1.0Low, Baseline - Minor, Baseline - Negligible3
severity::1.0National cyber emergency, Highly significant incident, Significant incident1
severity::1.0Substantial incident, Moderate incident2
severity::1.0Localised incident3
alert_severity::1.0Critical, High1
alert_severity::1.0Medium2
alert_severity::1.0Low, Informational3
—every objective; absent or unmatched source4

Match the full vocabulary name, case-sensitive first, then case-insensitive equality. Never substring. A rule severity is matched against both severity::1.0 and alert_severity::1.0 rows. Low and Medium resolve identically on every scale that contains them.

opentide object

Pinned template identity:

PropertyValue
Nameopentide
uuid892fd46a-f69e-455c-8c4f-843a4b8f4295
version5
meta-categorymisc
Required relationsname, opentide-object, opentide-type, uuid, version, schema
Optional repeatable relationsopentide-relation, misp-event-relation

opentide-type MUST be one of the template values_list entries: threat, objective, rule. Those strings are the opentide family names.

RelationCardinalitySourcedisable_correlation
nameexactly 1Object top-level name, verbatimfalse
uuidexactly 1metadata.uuid, verbatim. Never the Event UUIDfalse
versionexactly 1metadata.version as a decimal digit string, no leading zeroes. The template sane_default of 1 MUST NOT replace a real valuetrue
opentide-typeexactly 1Family name: threat, objective, or ruletrue
schemaexactly 1metadata.schema, verbatim (rule::1.0 and siblings)true
opentide-objectexactly 1Verbatim source documentfalse
opentide-relation0..nParent object UUIDs belowfalse
misp-event-relation0Not emitted. MISP Event UUIDs are server-assigned and are not opentide identity—

Every emitted attribute MUST set type to text, category to Other, to_ids to false, and distribution to 5 (inherit the Event). The object itself MUST set distribution to 5, so a stored object cannot outreach its Event.

disable_correlation MUST follow the table. Correlation of uuid and opentide-relation text MAY surface related events on an instance that correlates text. This spec does not require that UI behaviour. The authoritative link is the attribute value.

A missing template fails the object with template_missing. A missing required relation on the instance template fails it with template_relation_missing, naming each absent relation. A template version other than 5, while all six required relations exist and opentide-type accepts the family name, is an informational note. The connector still emits the pinned relation set.

Updates touch the seven envelope fields, the tag set, and the one opentide object. Remote objects or Event-level attributes the connector did not emit stay, with an informational note. The remote Event uuid and creator organisation are never rewritten.

Relations

opentide-relation points from child to parent:

FamilySourceEmitted
threat—zero relations
objectiveobjective.threats[], and on objective::1.1 the owning objective UUID of each signal bound with reuseone per distinct UUID
ruletop-level detection_model, verbatim: an objective UUID, or a signal UUID whose owning objective's Event carries the definitionzero or one

Values are 36-character lowercase canonical UUIDs of Tide objects (or, for a rule, a signal), never MISP Event or object UUIDs, at most one attribute per distinct UUID, ordered ascending. A non-canonical UUID fails the object. An absent, null, or empty source emits zero relations. A relation UUID whose object was not shared to that block is still emitted, with an informational note.

No extends_uuid is set and no MISP event extension is created.

Identity

lookup key = (Event.Orgc.uuid == resolved publishing organisation)
           ∧ (opentide object uuid attribute == Tide metadata.uuid)

Orgc.uuid is compared as a canonical UUID, case-insensitively. The uuid attribute is compared as an exact case-sensitive string. An Event satisfying only one half is not a match.

Lookup resultStored content hashOutcomeAction
No matchanycreatedCreate without an Event uuid; store the UUID the instance returns
Exactly oneabsent or differentupdatedUpdate; store the new hash
Exactly oneequalunchangedNo create, update, or publish request
More than oneanyfailed / ambiguous_remote_eventReport every matched Event UUID; write nothing
Object UUID matches, organisation differsanynot a matchLeave it untouched; informational note
Transport or auth failureanyfailed / remote_lookup_failedLeave state unchanged
Update rejectedanyfailed / remote_update_rejectedNever fall back to create

The content hash is the SHA-256 of the verbatim UTF-8 bytes of the emitted object document, written as lowercase hex. It is computed locally before any request.

If the instance rejects opentide-object for length, fail that object with attribute_too_large and write nothing. The connector MUST NOT split the document across attributes.

Payload

The emitted document is one YAML document whose root is a mapping. It passes uuid-format and schema checks against its own metadata.schema whenever the source object does.

Nothing in the document is removed for any block, TLP value, or flag. Withholding content is done by raising metadata.tlp, lowering the block's max_tlp, or leaving the object out of the block's selection.

preview and push produce a byte-identical opentide-object value and the same outcome class for the same object and block, apart from the notes that only a live instance can settle (organisation, clusters).

Retract

ModeMISP action
defaultunpublish if published; leave the event. Set the ledger line to state retracted and published false.
--deletedelete the event. Implementations SHOULD require --yes or an equivalent confirm flag. The ledger line MUST be removed.

Retract operates on records present in state or on the remote, not on objects that were never pushed.

Preflight reasons

These are preflight (exit 1) for this connector, before the exit rules in sharing.md: an unknown key in a [[misp]] block, a missing name, url, api_key, or max_tlp, an unset api_key variable, a malformed organisation_uuid, and organisation_uuid_mismatch on every selected block.

Validation check sharing-config

opentide validate SHOULD offer sharing-config (off by default, on for opentide share push). It checks sharing.toml and every [[misp]] block in the merged result:

ConditionChecker code
name, url, api_key, or max_tlp missingmissing_field
name repeated in one layer, or used by two integrationsduplicate_name
name outside the allowed charactersname_invalid
A key not defined by this spec, or a top-level key that is not an array of tablesunknown_key
max_tlp not a tlp namemax_tlp_unknown
organisation_uuid not a canonical UUIDorganisation_uuid_invalid
object_types entry not a familyobject_type_unknown
A sharing/ configuration directory existssharing_directory

Relationships

Defaults & overrides

A block needs name, url, api_key, and max_tlp. It ships disabled, selects all three families and PRODUCTION rules, takes its organisation from each object unless the block sets one, and does not publish.

Examples

History

VersionDateNotes
1.02026-10-19objective::1.1 relations include the owner of each signal bound with reuse (RFC 0011).
1.02026-10-06Technique-list sources are threat.mitre_attack and objective.mitre_attack. rule.techniques is unchanged.
1.02026-09-28Initial connector spec from accepted RFC 0005. Pins upstream opentide template version 5. Minimal [[misp]] block; organisation from metadata.organisation.uuid, overridable per block; distribution derived from TLP.

On this page