Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cogs - Combine OpenGraphS

cogs (short for "Combine OpenGraphS") is a command-line tool that merges multiple BloodHound OpenGraph JSON files into a single unified graph.

Built using the gopengraph library for BloodHound OpenGraph compatibility.

Features

  • Multiple input methods: Read from stdin (pipeline) or specify files via command-line arguments
  • Smart node merging: Union operation on node properties (last wins on conflicts)
  • Kinds merging: Automatically merges node kinds up to 2 types maximum
  • Edge deduplication: Merges edges with the same start/end/kind, combining properties
  • Metadata handling: Intelligently handles source_kind across multiple graphs
  • Validation: Validates all input graphs against BloodHound OpenGraph schema

Installation

go build -o cogs

Usage

Basic Usage

Merge graphs via pipeline:

cat graph1.json graph2.json | cogs > merged.json

Merge graphs via command-line arguments:

cogs -j graph1.json -j graph2.json > merged.json
cogs --json graph1.json --json graph2.json > merged.json

Mix both methods:

cat graph1.json | cogs -j graph2.json -j graph3.json > merged.json

With source_kind Override

Override the source_kind in the merged output:

cat graph1.json graph2.json | cogs -s CombinedSource > merged.json
cogs -j graph1.json -j graph2.json --source_kind CombinedSource > merged.json

Merging Behavior

Node Merging

When nodes with the same id appear in multiple graphs:

  1. Properties: Union of all properties, last value wins on conflicts
  2. Kinds: Union of all kinds, maximum 2 kinds allowed (error if exceeded)

Example:

// Graph 1
{"id": "user-1", "kinds": ["User"], "properties": {"name": "Alice", "age": 30}}

// Graph 2
{"id": "user-1", "kinds": ["Admin"], "properties": {"email": "alice@example.com", "age": 31}}

// Merged Result
{"id": "user-1", "kinds": ["User", "Admin"], "properties": {"name": "Alice", "email": "alice@example.com", "age": 31}}

Edge Merging

Edges with identical start/end/kind/match_by are considered duplicates:

  1. Properties: Union of all properties, last value wins on conflicts
  2. Edges with different start, end, or kind are kept as separate edges

Example:

// Graph 1
{"start": {"match_by": "id", "value": "user-1"}, "end": {"match_by": "id", "value": "user-2"},
 "kind": "Knows", "properties": {"since": "2020", "confidence": 0.8}}

// Graph 2
{"start": {"match_by": "id", "value": "user-1"}, "end": {"match_by": "id", "value": "user-2"},
 "kind": "Knows", "properties": {"verified": true, "confidence": 0.9}}

// Merged Result
{"start": {"match_by": "id", "value": "user-1"}, "end": {"match_by": "id", "value": "user-2"},
 "kind": "Knows", "properties": {"since": "2020", "verified": true, "confidence": 0.9}}

Metadata Handling

The source_kind field in metadata follows these rules:

  1. Same across all graphs: Preserved in output
  2. Different across graphs: Dropped from output (empty metadata)
  3. Override flag (-s): Always takes precedence
  4. All empty: Output has empty metadata

Examples:

# All graphs have source_kind "TestSource" → Output has "TestSource"
cat graph1.json graph2.json | cogs

# Graphs have different source_kinds → Output has no metadata
cat graph1.json graph2.json | cogs

# Override regardless of input
cat graph1.json graph2.json | cogs -s MySource

Error Handling

cogs will exit with an error if:

  1. Invalid JSON: Input is not valid JSON
  2. Invalid OpenGraph: Missing required fields (graph.nodes, graph.edges, node id, etc.)
  3. Too many kinds: Merging would result in more than 2 kinds for a node
  4. Empty node ID: A node has an empty id field
  5. Empty kinds array: A node has no kinds
  6. Invalid edge: Missing required fields (start, end, kind, match_by)

Validation

All input graphs are validated against the BloodHound OpenGraph schema:

  • Nodes must have: id, kinds (1-2 values), properties
  • Edges must have: start.value, start.match_by, end.value, end.match_by, kind
  • Optional: properties on edges, metadata.source_kind

Testing

Run the test suite:

go test -v

Test with sample data:

cat testdata/graph1.json testdata/graph2.json | ./cogs

Command-line Options

  • -j, --json: JSON file to process (can be specified multiple times)
  • -s, --source_kind: Source kind for the merged OpenGraph metadata (optional, overrides input)

Examples

Example 1: Merge two graphs with same source_kind

cat testdata/graph1.json testdata/graph2.json | ./cogs

Output includes "source_kind": "TestSource" since both inputs have the same value.

Example 2: Merge graphs with different source_kinds

cat testdata/graph1.json testdata/graph3-different-source.json | ./cogs

Output has empty metadata since source_kinds differ.

Example 3: Override source_kind

./cogs -j testdata/graph1.json -j testdata/graph2.json -s MergedData

Output has "source_kind": "MergedData" regardless of inputs.

Example 4: Merge node properties and kinds

cat testdata/graph1.json testdata/graph4-kinds-merge.json | ./cogs

Merges properties and kinds for user-001.

Integration with og

cogs is designed to work seamlessly with the og tool:

# Generate multiple OpenGraph files from CSVs
cat users1.csv | og -s Source1 > graph1.json
cat users2.csv | og -s Source2 > graph2.json

# Combine them with cogs
cogs -j graph1.json -j graph2.json -s CombinedUsers > merged.json

# Or in a pipeline
cat users1.csv | og | cogs -j additional.json > combined.json

About

Combine OpenGraph objects

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages