curl --request PUT \
--url https://your-tenant.bloodhoundenterprise.io/api/v2/extensions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"schema": {
"name": "OpenGraph_Extension",
"display_name": "OpenGraph Extension",
"version": "v1.0.0",
"namespace": "OGE"
},
"node_kinds": [
{
"name": "OGE_Node_Kind_1",
"display_name": "Node Kind 1",
"description": "A generic node kind",
"is_display_kind": true,
"icon": "computer",
"color": "#FF0000",
"info": {
"overview": {
"title": "Overview",
"position": 1,
"markdown": {
"content": "This is an overview panel for **{{ .Properties.name | upper }}** (node {{ .NodeID }})"
}
},
"details": {
"title": "Additional Details",
"position": 2,
"markdown": {
"content": "This panel provides additional information about the node"
}
}
}
},
{
"name": "OGE_Node_Kind_2",
"display_name": "Node Kind 2",
"description": "A secondary generic node kind",
"is_display_kind": false
},
{
"name": "OGE_Environment_Kind",
"display_name": "Environment",
"description": "A generic environment kind",
"icon": "sitemap",
"color": "#00FF00",
"is_display_kind": true
}
],
"relationship_kinds": [
{
"name": "OGE_ConnectedTo",
"description": "A generic relationship kind",
"is_traversable": true,
"info": {
"abuse": {
"title": "Abuse Info",
"position": 1,
"markdown": {
"content": "Information about how the {{ .Kind.Name }} relationship from {{ .Source.Properties.name }} to {{ .Target.Properties.name }} can be abused"
}
}
}
}
],
"environments": [
{
"environment_kind": "OGE_Environment_Kind",
"source_kind": "OGExtension",
"principal_kinds": [
"OGE_Node_Kind_1",
"OGE_Node_Kind_2"
]
}
],
"relationship_findings": [
{
"name": "OGE_Finding_1",
"display_name": "Finding 1",
"relationship_kind": "OGE_ConnectedTo",
"environment_kind": "OGE_Environment_Kind",
"remediation": {
"short_description": "a remediation",
"long_description": "a remediation to fix Finding 1",
"short_remediation": "Do X",
"long_remediation": "Do X to fix Finding 1"
}
}
],
"queries": [
{
"query_key": "all-node-kind-1",
"name": "All Node Kind 1",
"query": "MATCH (n:OGE_Node_Kind_1) RETURN n",
"description": "Lists all OGE_Node_Kind_1 nodes.",
"category": "Asset Management"
}
]
}
'{
"http_status": 400,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "The JSON payload could not be unmarshalled."
}
]
}{
"http_status": 401,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "login",
"message": "Unauthorized"
}
]
}{
"http_status": 403,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "You do not have permission to access this resource"
}
]
}{
"http_status": 404,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "The requested client could not be found."
}
]
}{
"http_status": 415,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "invalid content-type: [application/incorrect]; Content type must be application/json or application/zip"
}
]
}{
"http_status": 429,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "middleware",
"message": "Too many requests. Please try again later."
}
]
}{
"http_status": 500,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "The request could not be handled due to an unexpected database error."
}
]
}Upserts the OpenGraph Extension
Experimental - Upserts the OpenGraph extension.
The request body may be a JSON extension payload or a ZIP bundle. A ZIP root must contain schema.json without optional components and may contain pz_rules.json ({"rules":[...]}) and saved_queries.json ({"queries":[...]}). Duplicate or unexpected files are rejected; findings require pz_rules.json with at least one rule.
Each recognized ZIP component is limited to 10 MiB after decompression; an oversized component is rejected as a bad request.
curl --request PUT \
--url https://your-tenant.bloodhoundenterprise.io/api/v2/extensions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"schema": {
"name": "OpenGraph_Extension",
"display_name": "OpenGraph Extension",
"version": "v1.0.0",
"namespace": "OGE"
},
"node_kinds": [
{
"name": "OGE_Node_Kind_1",
"display_name": "Node Kind 1",
"description": "A generic node kind",
"is_display_kind": true,
"icon": "computer",
"color": "#FF0000",
"info": {
"overview": {
"title": "Overview",
"position": 1,
"markdown": {
"content": "This is an overview panel for **{{ .Properties.name | upper }}** (node {{ .NodeID }})"
}
},
"details": {
"title": "Additional Details",
"position": 2,
"markdown": {
"content": "This panel provides additional information about the node"
}
}
}
},
{
"name": "OGE_Node_Kind_2",
"display_name": "Node Kind 2",
"description": "A secondary generic node kind",
"is_display_kind": false
},
{
"name": "OGE_Environment_Kind",
"display_name": "Environment",
"description": "A generic environment kind",
"icon": "sitemap",
"color": "#00FF00",
"is_display_kind": true
}
],
"relationship_kinds": [
{
"name": "OGE_ConnectedTo",
"description": "A generic relationship kind",
"is_traversable": true,
"info": {
"abuse": {
"title": "Abuse Info",
"position": 1,
"markdown": {
"content": "Information about how the {{ .Kind.Name }} relationship from {{ .Source.Properties.name }} to {{ .Target.Properties.name }} can be abused"
}
}
}
}
],
"environments": [
{
"environment_kind": "OGE_Environment_Kind",
"source_kind": "OGExtension",
"principal_kinds": [
"OGE_Node_Kind_1",
"OGE_Node_Kind_2"
]
}
],
"relationship_findings": [
{
"name": "OGE_Finding_1",
"display_name": "Finding 1",
"relationship_kind": "OGE_ConnectedTo",
"environment_kind": "OGE_Environment_Kind",
"remediation": {
"short_description": "a remediation",
"long_description": "a remediation to fix Finding 1",
"short_remediation": "Do X",
"long_remediation": "Do X to fix Finding 1"
}
}
],
"queries": [
{
"query_key": "all-node-kind-1",
"name": "All Node Kind 1",
"query": "MATCH (n:OGE_Node_Kind_1) RETURN n",
"description": "Lists all OGE_Node_Kind_1 nodes.",
"category": "Asset Management"
}
]
}
'{
"http_status": 400,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "The JSON payload could not be unmarshalled."
}
]
}{
"http_status": 401,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "login",
"message": "Unauthorized"
}
]
}{
"http_status": 403,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "You do not have permission to access this resource"
}
]
}{
"http_status": 404,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "The requested client could not be found."
}
]
}{
"http_status": 415,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "invalid content-type: [application/incorrect]; Content type must be application/json or application/zip"
}
]
}{
"http_status": 429,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "middleware",
"message": "Too many requests. Please try again later."
}
]
}{
"http_status": 500,
"timestamp": "2024-02-19T19:27:43.866Z",
"request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"errors": [
{
"context": "clients",
"message": "The request could not be handled due to an unexpected database error."
}
]
}Authorizations
Authorization: Bearer $JWT_TOKEN
Body
An OpenGraph extension JSON payload or ZIP bundle.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Optional privilege-zone rules component.
Show child attributes
Show child attributes
Declares the extension's desired saved queries. Omitting this property or providing an empty array removes existing saved queries associated with the extension.
Show child attributes
Show child attributes
Response
OK