The major changes in this version are:
- Attribute edges need to be "described by" rather than describes. This will change the direction of the edges in the construct to the standard in version 0.1. This way edges are not a parent of the node they describe. This is important for risk calculations. CPTs are based on parents and so edges pointing from attributes to nodes need to have a relationship of "influences" rather than "describes" to make sure CPTs are calculating on the correct edges.
- Attributes no longer require a "metadata" property. Instead, the dictionary containing the single {type:value} dictionary will be stored in the "label" of the attributes
- Event, Condition, and Actor nodes are considered the same node if the have exactly matching labels.
- Edges are considered the same if they have the same source & target.
Defensive Construct Exchange Standard 0.3:
Mandatory Statements:
- All discrete pieces of information within a construct shall be given an individual node.
- All nodes within the construct shall have the property "class" of value "attribute".
- The actual attribute property shall be stored as a JSON object within the node's "label" property. The object shall have a single {"type":"value"} pair. All other type:value pares shall be rejected.
- All nodes shall be linked to a node containing a construct ID generated by the construct originator. (It is recommended that those receiving constructs into their own graphs generate a local construct ID so as to avoid conflicts within their graph.)
- The construct ID shall be a child node of all Attributes within the construct.
- The nodes and edges shall be represented in JSON. They shall be transmitted in accordance with the JSON format outlined by the gephi graph streaming project (Gephi graph streaming). In practice, all constructs shall be 'an' (add node) or 'ae' (add edge), with the recipient deciding how to actually handle the information. All required properties are documented at https://github.com/gdbassett/moirai/blob/dev-ms1/protocol_definitions.txt
- The DCES event shall have a "dces_version" property.
- The WAMP standard should be used when the DCES event is transmitted to/from an RPC or pubsub.
Optional Statements to facilitate usage:
- Attribute nodes within the construct may have their own attributes. (I.E. A threat construct's location attribute may have a 'classification' attribute.)
- Individual constructs should be contained in a single JSON message represent a single DCES event. (I.E. {"an":{1:{...}, 2:{...}, 3:{...}}, "ae":{4:{...}, 5:{...}}, "dces_version":"0.3"} could represent a single construct". While it is possible to create a construct in the receiving graph with multiple messages, it is unnecessarily complex.
- The recipient of a DCES event may define it's own response to receipt depending on it's needs. If the sender needs to understand the linkage of the construct in the recipient's attack graph, it is recommended the recipient return the the node ID of the node storing the construct ID in the recipient's graph.
- "an"s are implicitly anchored to originIDs. (Because the node doesn't exist in the DB graph yet, there is no dbID to anchor to.) If any "an"s are present in the event, any "ae"s in that event are explicitly anchored to originIDs to avoid confusion
- Event, Condition, and Actor nodes are considered the same node if the have exactly matching labels.
- Edges are considered the same if they have the same source & target.
Example:
This example, used previosuly has been updated to be a DCES version 0.3 compliant construct transmitted in a single event. Graphically, it can be represented as:
This produces the following Object which can be dumped to json. (Please note, as the CPT for the construct ID is quite large, I have left it out.)
{"dces_version":"0.3",
"ae":{"1":{"source":"B","target":"A","directed":true, "relationship":"describes","start":"2013-03-14T16:57Z"},
"2":{"source":"C","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"3":{"source":"D","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"4":{"source":"C","target":"D","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"5":{"source":"B","target":"C","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"6":{"source":"E","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"7":{"source":"F","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"8":{"source":"G","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"9":{"source":"F","target":"G","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"10":{"source":"E","target":"F","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"11":{"source":"H","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"12":{"source":"I","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"13":{"source":"J","target":"A","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"14":{"source":"I","target":"J","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"},
"15":{"source":"H","target":"I","directed":true, "relationship":"described by","start":"2013-03-14T16:57Z"}},
"an":{"A":{"label":{"id":"<value>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"A"}},
"B":{"label":{"url":"<value>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"B","index":["C",true,false],"0":[0,1,0],"1":[1,1,0]}},
"C":{"label":{"domain":"<value>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"C","index":["D",true,false],"0":[0,1,0],"1":[1,1,0]}},
"D":{"label":{"whois":"<value>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"D","index":[true,false],"0":[1,0]}},
"E":{"label":{"dns query":"<value>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"E","index":["F",true,false],"0":[0,1,0],"1":[1,1,0]}},
"F":{"label":{"dns record":"<value>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"F","index":["G",true,false],"0":[0,1,0],"1":[1,1,0]}},
"G":{"label":{"record type":"<value>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"G","index":[true,false],"0":[1,0]}},
"H":{"label":{"dns query":"<value2>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"H","index":["I",true,false],"0":[0,1,0],"1":[1,1,0]}},
"I":{"label":{"dns record":"<value2>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"I","index":["J",true,false],"0":[0,1,0],"1":[1,1,0]}},
"J":{"label":{"record type":"<value2>"},"start":"2013-03-14T16:57Z","cpt":{"nodeid":"J","index":[true,false],"0":[1,0]}}}}
This version of the DCES standard will be used for Moirai Milestone 1. For those interested, the following python code can reproduce the CPT for node A. .
d = {}
d["nodeid"] = "A"
d["index"] = ["B", "C", "D", "E", "F", "G", "H", "I", "J", true, false]
parents = len(d["index"]) - 2
for i in range(0,2**parents):
k = [int(x) for x in list('{0:0b}'.format(i))]
for l in range(0, parents - len(k)):
k.insert(0,0)
k.append(1)
k.append(0)
d[i] = k