
OpenGraph-Sammler für BloodHound, der Angriffspfade von DevOps- zu MLOps-Infrastrukturen abbildet und CI/CD-Pipeline-, Dienstprinzipal- und ML-Plattform-Ressourcen für die Lateral-Movement-Analyse sammelt.
Ein Proof-of-Concept OpenGraph-Collector für BloodHound, der Angriffspfade von DevOps- zu MLOps-Infrastruktur abbildet.
Basierend auf Pipelines of Privilege: Attack Paths from DevOps to MLOps Infrastructure von Brett Hawkins (@h4wkst3r).
Dop2Mop sammelt Daten von DevOps- und MLOps-Plattformen, um Angriffspfade zu identifizieren, die laterale Bewegungen von CI/CD-Pipelines zur Trainingsinfrastruktur für maschinelles Lernen ermöglichen. Die Ausgabe erfolgt als BloodHound-kompatibles OpenGraph-JSON zur Visualisierung und Analyse.
| DevOps-Plattformen | MLOps-Plattformen | Identitätsanbieter |
|---|---|---|
| GitHub (Actions, Repos, Secrets) | Azure Machine Learning | Azure AD-Dienstprinzipale |
| Azure DevOps (Pipelines, Serviceverbindungen) | Amazon SageMaker | AWS IAM-Rollen OIDC/Föderierte Identität |
Dop2Mop modelliert die fünf in der Forschung identifizierten kritischen Vertrauensgrenzen:
git clone https://github.com/h4wkst3r/dop2mop.git cd dop2mop pip install -r requirements.txt pip install -e .
## Was gesammelt wird
Jeder Collector sammelt plattformspezifische Ressourcen und kartiert die Vertrauensgrenzen zwischen ihnen:
| Collector | Gesammelte Ressourcen |
|-----------|----------------------|
| **GitHub** | Organisationen, Repositories, Workflows, Secrets, Branch-Protection-Regeln, OIDC-Konfigurationen, Container-Image-Referenzen, S3-Bucket-Referenzen |
| **Azure DevOps** | Organisationen, Projekte, Pipelines (YAML), Serviceverbindungen (mit Umfangsdetails), Variablengruppen, Agent-Pools, Repositories |
| **Azure ML** | Workspaces, Compute-Cluster/-Instanzen, Datastores, ML-Umgebungen, registrierte Modelle, Jobs/Experimente, Online- und Batch-Endpunkte |
| **SageMaker** | Training-Jobs, Modelle, Endpoints, Domains, Notebook-Instanzen, IAM-Ausführungsrollen (mit Richtlinienanalyse), ECR-Repositories/-Images, S3-Buckets (gefiltert auf ML-relevante) |
## Schnellstart
### Demo-Daten generieren
Der schnellste Weg, Dop2Mop in Aktion zu sehen, besteht darin, Demo-Daten zu generieren, die die Angriffsszenarien aus der Forschung zeigen:```bash
dop2mop demo -o demo.json
MATCH (u:User)
RETURN u
``````cypher
// Azure DevOps to Azure ML Lateral Movement
MATCH p=(repo)-[:TriggersPipeline]->(pipeline)-[:UsesServiceConnection]->(svcconn)-[:AuthenticatesAs]->(workspace)-[:CodeExecution]->(compute)
RETURN p
// Container Image Poisoning (Supply Chain Attack)
MATCH p=(workflow)-[:CanPoisonImage]->(image)<-[:PullsImage]-(job)
RETURN p
// OIDC/Federated Identity Abuse (confirmed edges)
MATCH p=(workflow)-[:OIDCTrust]->(oidc)-[:CanAssumeRole]->(role)-[:SubmitsJob]->(job)
RETURN p
// OIDC abuse including inferred paths
MATCH p=(workflow)-[:OIDCTrust]->(oidc)-[:InferredCanAssumeRole]->(role)
RETURN p
// Dataset Poisoning via Pickle Deserialization
MATCH p=(workflow)-[:CanPoisonDataset]->(dataset)<-[:LoadsDataset]-(job)
RETURN p
// Find repos with weak/no branch protection (TB1 exploitable)
MATCH (repo)-[:BypassesProtection]->(repo)
RETURN repo.name, repo.default_branch
// Find overprivileged SageMaker IAM roles
MATCH (role:IAMRole) WHERE role.is_admin = true OR role.has_s3_full_access = true
RETURN role.name, role.attached_policies
// Find SageMaker notebooks with root + internet access
MATCH (nb:SMNotebook) WHERE nb.root_access = 'Enabled' AND nb.direct_internet_access = 'Enabled'
RETURN nb.name, nb.status
// Find self-hosted ADO agent pools
MATCH (agent:ADOAgent) WHERE agent.is_hosted = false
RETURN agent.name, agent.pool_type
Anstatt bei jeder Ausführung Anmeldeinformationen zu übergeben, können Sie diese in einer Konfigurationsdatei speichern. Kopieren Sie das beigefügte Beispiel und füllen Sie Ihre Werte ein:
cp config.example.yml config.yml```bash
cp dop2mop.yaml.example dop2mop.yaml
Dop2Mop überprüft diese Orte in der folgenden Reihenfolge:
1. Pfad, der mit `--config` angegeben wurde
2. `dop2mop.yaml` / `dop2mop.yml` / `.dop2mop.yaml` im aktuellen Verzeichnis
3. `~/.dop2mop.yaml`
> **Hinweis:** `dop2mop.yaml` befindet sich in `.gitignore`, um ein versehentliches Committen von Anmeldedaten zu verhindern. Die Beispieldatei (`dop2mop.yaml.example`) kann bedenkenlos committet werden.
Siehe [dop2mop.yaml.example](https://github.com/h4wkst3r/dop2mop/blob/HEAD/dop2mop.yaml.example) für alle verfügbaren Optionen mit Kommentaren.
**Prioritätsreihenfolge:** CLI-Argumente > Konfigurationsdatei > Umgebungsvariablen.
### Anmeldedatenvalidierung
Testen Sie Anmeldedaten vor dem Durchführen einer vollständigen Sammlung:```bash
# Validate all configured collectors
dop2mop collect --validate -v
# Validate specific collectors
dop2mop collect --validate --collectors github,sagemaker -v
Dies führt einen leichten API-Aufruf pro Plattform durch, um die Gültigkeit der Tokens vor Beginn der Sammlung zu überprüfen.
Sie können kurze Namen anstelle der vollständigen Klassennamen mit --collectors verwenden:
dop2mop collect --collectors GitHubCollector,SageMakerCollector dop2mop collect --collectors github,sagemaker dop2mop collect --collectors gh,sm
## CLI-Referenz
### Befehlsübersicht```
dop2mop <command> [options]
Commands:
collect Collect data from DevOps/MLOps platforms
demo Generate demo data with attack scenarios
| Option | Beschreibung |
|---|---|
-v, --verbose | Ausführliche Ausgabe aktivieren (Protokollierung auf INFO-Ebene) |
--debug | Debug-Ausgabe aktivieren (Protokollierung auf DEBUG-Ebene) |
dop2mop collectSammle Daten von konfigurierten DevOps- und MLOps-Plattformen.```bash dop2mop collect [OPTIONS]
#### Allgemeine Optionen
| Option | Beschreibung |
|--------|-------------|
| `-o, --output FILE` | Ausgabedateipfad (Standard: `dop2mop_output.json`) |
| `--zip` | Ausgabe in ZIP-Datei komprimieren |
| `--config FILE` | Pfad zur YAML/JSON-Konfigurationsdatei |
| `--validate` | Anmeldeinformationen vor der Sammlung validieren |
| `--collectors LIST` | Kommagetrennte Liste von Collectors oder Aliasen (z.B. `github,sm`) |
| `--max-items N` | Maximale Anzahl zu sammelnder Elemente pro Typ |
| `--no-secrets` | Geheimnis-/Anmeldeinformationsaufzählung überspringen |
#### GitHub-Optionen
| Option | Beschreibung |
|--------|-------------|
| `--github-token TOKEN` | GitHub persönlicher Zugriffstoken |
| `--github-org ORG` | GitHub-Organisationsname |
| `--github-enterprise-url URL` | URL des GitHub Enterprise Servers |
#### Azure DevOps-Optionen
| Option | Beschreibung |
|--------|-------------|
| `--azure-devops-token TOKEN` | Azure DevOps persönlicher Zugriffstoken (PAT) |
| `--azure-devops-access-token TOKEN` | Azure DevOps-Zugriffstoken (Bearer-Authentifizierung, optional) |
| `--azure-devops-org ORG` | Azure DevOps-Organisationsname |
#### Azure ML-Optionen
| Option | Beschreibung |
|--------|-------------|
| `--azure-subscription-id ID` | Azure-Abonnement-ID |
| `--azure-tenant-id ID` | Azure AD-Mandanten-ID |
| `--azure-client-id ID` | Client-ID des Dienstprinzipals (optional) |
| `--azure-client-secret SECRET` | Client-Geheimnis des Dienstprinzipals (optional) |
| `--azure-access-token TOKEN` | Azure-Zugriffstoken für die Azure ML-Authentifizierung (optional) |
#### AWS SageMaker-Optionen
| Option | Beschreibung |
|--------|-------------|
| `--aws-access-key-id KEY` | AWS-Zugriffsschlüssel-ID |
| `--aws-secret-access-key SECRET` | AWS-Geheimzugriffsschlüssel |
| `--aws-region REGION` | AWS-Region (Standard: `us-east-1`) |
| `--aws-profile PROFILE` | AWS CLI-Profilname |
#### Verfügbare Collectors
| Collectorname | Plattform | Erforderliche Anmeldeinformationen |
|----------------|----------|---------------------|
| `GitHubCollector` | GitHub | `--github-token`, `--github-org` |
| `AzureDevOpsCollector` | Azure DevOps | `--azure-devops-token` oder `--azure-devops-access-token`, `--azure-devops-org` |
| `AzureMLCollector` | Azure ML | `--azure-subscription-id`, `--azure-tenant-id` |
| `SageMakerCollector` | AWS SageMaker | `--aws-profile` oder `--aws-access-key-id` |
---
### `dop2mop demo`
Demodaten generieren, die die vier Angriffsszenarien aus der Forschung zeigen.```bash
dop2mop demo [OPTIONS]
dop2mop iconsGenerieren Sie eine benutzerdefinierte Icon-Konfiguration für BloodHound-Knotentypen.
| Option | Beschreibung |
|---|---|
-o, --output FILE | Ausgabedateipfad (Standard: dop2mop_demo.json) |
| dop2mop icons [OPTIONS] |
| Option | Beschreibung |
|--------|-------------|
| `-o, --output FILE` | Pfad zur Ausgabedatei (Standard: `dop2mop_icons.json`) |
---
## CLI-Nutzungsbeispiele
### Grundlegende Sammlung```bash
# Collect from all configured platforms (uses environment variables)
dop2mop collect -o output.json
# Use a config file
dop2mop collect --config dop2mop.yaml -o output.json -v
# Validate credentials first, then collect
dop2mop collect --validate -o output.json -v
# Collect with verbose logging
dop2mop collect -o output.json -v
# Collect with debug logging
dop2mop collect -o output.json --debug
# Collect and compress to ZIP
dop2mop collect -o output.json --zip
# Limit collection size
dop2mop collect --max-items 100 -o output.json
# Skip secret enumeration
dop2mop collect --no-secrets -o output.json
dop2mop collect --collectors github -o github.json -v
dop2mop collect --collectors ado -o ado.json -v
dop2mop collect --collectors azureml -o azureml.json -v
dop2mop collect --collectors sm -o sagemaker.json -v
### Sammlung für mehrere Plattformen```bash
# GitHub + SageMaker
dop2mop collect --collectors github,sagemaker -o output.json -v
# GitHub + Azure DevOps
dop2mop collect --collectors github,ado -o output.json -v
# Azure DevOps + Azure ML (full Azure stack)
dop2mop collect --collectors ado,azureml -o azure.json -v
# All collectors explicitly
dop2mop collect --collectors github,ado,azureml,sagemaker -o full.json -v
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx" export GITHUB_ORG="your-org" dop2mop collect --collectors GitHubCollector -o github.json -v
dop2mop collect --collectors GitHubCollector
--github-token ghp_xxxxxxxxxxxx
--github-org your-org
-o github.json -v
dop2mop collect --collectors GitHubCollector
--github-token ghp_xxxxxxxxxxxx
--github-org your-org
--github-enterprise-url https://github.yourcompany.com/api/v3
-o github.json -v
dop2mop collect --collectors GitHubCollector
--github-token ghp_xxxxxxxxxxxx
--github-org your-org
--no-secrets
-o github.json -v
dop2mop collect --collectors GitHubCollector
--github-token ghp_xxxxxxxxxxxx
--github-org your-org
--max-items 50
-o github.json -v
### Azure DevOps Sammlungsbeispiele```bash
# Using environment variables
export AZURE_DEVOPS_TOKEN="your-pat"
export AZURE_DEVOPS_ORG="your-org"
dop2mop collect --collectors AzureDevOpsCollector -o ado.json -v
# Using command-line arguments (PAT)
dop2mop collect --collectors AzureDevOpsCollector \
--azure-devops-token your-pat \
--azure-devops-org your-org \
-o ado.json -v
# Using access token (Bearer auth)
dop2mop collect --collectors AzureDevOpsCollector \
--azure-devops-access-token eyJ0... \
--azure-devops-org your-org \
-o ado.json -v
Hinweis: Azure DevOps-Authentifizierungspriorität: Zugriffstoken (Bearer) > PAT (Basic). Zugriffstoken können mit
az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798abgerufen werden.
export AZURE_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" export AZURE_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" dop2mop collect --collectors AzureMLCollector -o azureml.json -v
dop2mop collect --collectors AzureMLCollector
--azure-subscription-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
--azure-tenant-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
-o azureml.json -v
dop2mop collect --collectors AzureMLCollector
--azure-subscription-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
--azure-tenant-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
--azure-client-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
--azure-client-secret your-secret
-o azureml.json -v
dop2mop collect --collectors AzureMLCollector
--azure-subscription-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
--azure-tenant-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
--azure-access-token eyJ0...
-o azureml.json -v
> **Hinweis:** Azure ML-Authentifizierungspriorität: Zugriffstoken > Dienstprinzipal > DefaultAzureCredential (az login).
> Zugriffstoken können über `az account get-access-token --resource https://management.azure.com/` bezogen werden.
### AWS SageMaker Sammlungsbeispiele```bash
# Using AWS profile (environment variable)
export AWS_PROFILE="your-profile"
dop2mop collect --collectors SageMakerCollector -o sagemaker.json -v
# Using AWS profile (command-line)
dop2mop collect --collectors SageMakerCollector \
--aws-profile your-profile \
-o sagemaker.json -v
# Using access keys
dop2mop collect --collectors SageMakerCollector \
--aws-access-key-id AKIAXXXXXXXXXXXXXXXX \
--aws-secret-access-key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
--aws-region us-east-1 \
-o sagemaker.json -v
# Different AWS region
dop2mop collect --collectors SageMakerCollector \
--aws-profile your-profile \
--aws-region us-west-2 \
-o sagemaker.json -v
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx" export GITHUB_ORG="your-org" export AZURE_DEVOPS_TOKEN="your-pat" export AZURE_DEVOPS_ORG="your-org" export AZURE_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" export AZURE_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" export AWS_PROFILE="your-profile"
dop2mop collect -o full_collection.json -v
dop2mop collect
--collectors GitHubCollector,AzureDevOpsCollector,AzureMLCollector,SageMakerCollector
-o full_collection.json -v
---
## Umgebungsvariablen
Alle Befehlszeilenoptionen können über Umgebungsvariablen gesetzt werden:
| Umgebungsvariable | CLI-Äquivalent | Beschreibung |
|---------------------|----------------|-------------|
| `GITHUB_TOKEN` | `--github-token` | GitHub persönlicher Zugriffstoken |
| `GITHUB_ORG` | `--github-org` | GitHub Organisationsname |
| `GITHUB_ENTERPRISE_URL` | `--github-enterprise-url` | GitHub Enterprise Server URL |
| `AZURE_DEVOPS_TOKEN` | `--azure-devops-token` | Azure DevOps PAT |
| `AZURE_DEVOPS_ACCESS_TOKEN` | `--azure-devops-access-token` | Azure DevOps Zugriffstoken (Bearer) |
| `AZURE_DEVOPS_ORG` | `--azure-devops-org` | Azure DevOps Organisation |
| `AZURE_SUBSCRIPTION_ID` | `--azure-subscription-id` | Azure Abonnement-ID |
| `AZURE_TENANT_ID` | `--azure-tenant-id` | Azure AD Mandanten-ID |
| `AZURE_CLIENT_ID` | `--azure-client-id` | Azure Dienstprinzipal-Client-ID |
| `AZURE_CLIENT_SECRET` | `--azure-client-secret` | Azure Dienstprinzipal-Geheimnis |
| `AZURE_ACCESS_TOKEN` | `--azure-access-token` | Azure Zugriffstoken für Azure ML |
| `AWS_ACCESS_KEY_ID` | `--aws-access-key-id` | AWS Zugriffsschlüssel-ID |
| `AWS_SECRET_ACCESS_KEY` | `--aws-secret-access-key` | AWS geheimer Zugriffsschlüssel |
| `AWS_REGION` | `--aws-region` | AWS Region (Standard: us-east-1) |
| `AWS_PROFILE` | `--aws-profile` | AWS CLI-Profilname |
**Priorität:** CLI-Argumente > Konfigurationsdatei > Umgebungsvariablen.
---
## Knotentypen
### DevOps-Knoten
| Art | Beschreibung |
|------|-------------|
| `GHOrganization` | GitHub Organisation |
| `GHRepository` | GitHub Repository |
| `GHWorkflow` | GitHub Actions Workflow |
| `GHSecret` | GitHub Actions Geheimnis |
| `ADOOrganization` | Azure DevOps Organisation |
| `ADOProject` | Azure DevOps Projekt |
| `ADOPipeline` | Azure DevOps Pipeline |
| `ADOServiceConnection` | Azure DevOps Dienstverbindung (NHI) mit Bereichsdetails |
| `ADOAgent` | Azure DevOps Agentenpool (gehostet oder selbst gehostet) |
| `ADOVariableGroup` | Azure DevOps Variablengruppe |
### MLOps-Knoten
| Art | Beschreibung |
|------|-------------|
| `AzMLWorkspace` | Azure ML Arbeitsbereich |
| `AzMLCompute` | Azure ML Compute-Cluster/-Instanz |
| `AzMLExperiment` | Azure ML Auftrag/Experiment |
| `AzMLDatastore` | Azure ML Datenspeicher |
| `AzMLEnvironment` | Azure ML Umgebung (Containerdefinition) |
| `AzMLModel` | Azure ML registriertes Modell |
| `SMDomain` | SageMaker Studio Domäne |
| `SMTrainingJob` | SageMaker Trainingsauftrag |
| `SMModel` | SageMaker Modell |
| `SMEndpoint` | SageMaker Endpunkt (auch für Azure ML Endpunkte verwendet) |
| `SMNotebook` | SageMaker Notebook-Instanz |
### Identitätsknoten
| Art | Beschreibung |
|------|-------------|
| `ServicePrincipal` | Azure AD Dienstprinzipal |
| `IAMRole` | AWS IAM-Rolle |
| `OIDCIdentity` | OIDC föderierte Identität |
| `ManagedIdentity` | Azure verwaltete Identität |
### Artefaktknoten
| Art | Beschreibung |
|------|-------------|
| `ContainerRegistry` | Container-Repository (ECR, ACR) |
| `ContainerImage` | Container-Image |
| `S3Bucket` | AWS S3 Bucket |
| `Dataset` | ML Datensatz |
## Kantentypen
### Angriffspfad-Kanten
| Art | Vertrauensgrenze | Beschreibung |
|------|----------------|-------------|
| `TriggersPipeline` | TB1 | Code-Commit löst CI/CD aus |
| `HasBranchProtection` | TB1 | Repository hat Branch-Schutzregeln |
| `BypassesProtection` | TB1 | Schwacher/fehlender Branch-Schutz (ausnutzbar) |
| `AuthenticatesAs` | TB2 | Pipeline verwendet Dienstprinzipal |
| `CanAssumeRole` | TB2 | OIDC-Identität kann IAM-Rolle annehmen |
| `OIDCTrust` | TB2 | Workflow verwendet OIDC-Föderation |
| `UsesServiceConnection` | TB2 | Pipeline verwendet ADO Dienstverbindung |
| `PullsImage` | TB3 | Trainingsauftrag zieht Container-Image |
| `CanPoisonImage` | TB3 | Pipeline kann Container-Image ändern |
| `SubmitsJob` | TB4 | Dienstprinzipal reicht ML-Auftrag ein |
| `CodeExecution` | TB4 | Auftrag führt Code auf Compute aus |
| `LoadsDataset` | TB5 | Trainingsauftrag lädt Datensatz |
| `CanPoisonDataset` | TB5 | Pipeline kann Datensatz ändern |
| `Deserializes` | TB5 | Unsicheres Deserialisieren |
### Abgeleitete Kanten
Diese Kanten werden durch heuristische Analyse erstellt, wenn keine expliziten API-Daten verfügbar sind (z.B. Rollen-ARNs, die in Geheimnissen gespeichert sind). Sie verwenden unterschiedliche Kantentypen, sodass Sie sie in BloodHound-Abfragen filtern können.
| Art | Beschreibung |
|------|-------------|
| `InferredCanAssumeRole` | OIDC-Identität kann möglicherweise Rolle annehmen (abgeleitet) |
| `InferredSubmitsJob` | Workflow kann möglicherweise Trainingsauftrag über OIDC einreichen (abgeleitet) |
| `InferredPullsImage` | Trainingsauftrag kann möglicherweise vergiftetes Container-Image ziehen (abgeleitet) |
| `InferredLoadsDataset` | Trainingsauftrag kann möglicherweise vergifteten Datensatz laden (abgeleitet) |
### Strukturelle Kanten
| Art | Beschreibung |
|------|-------------|
| `Contains` | Eltern-Kind-Beziehung |
| `MemberOf` | Gruppenmitgliedschaft |
| `HasAccessTo` | Berechtigung auf Ressource zuzugreifen |
| `HasExecutionRole` | Ressource verwendet eine IAM/Ausführungsrolle |
| `Owns` | Eigentümerschaftsbeziehung |
## Beispielabfragen
Siehe [queries/dop2mop_queries.cypher](https://github.com/h4wkst3r/dop2mop/blob/HEAD/queries/dop2mop_queries.cypher) für umfassende Abfragebeispiele.
---
## Benutzerdefinierte Symbole
Dop2Mop enthält eine vorkonfigurierte Symboldatei für benutzerdefinierte BloodHound-Knotentypen in [data/custom_icons.json](https://github.com/h4wkst3r/dop2mop/blob/HEAD/data/custom_icons.json).
### Hochladen von Symbolen in BloodHound
#### Option 1: API-Explorer (Einfachste)
1. Öffnen Sie BloodHound CE und gehen Sie zu **Einstellungen** → **API-Explorer**
2. Suchen Sie **POST /api/v2/custom-nodes**
3. Klicken Sie auf "Try it out"
4. Fügen Sie den Inhalt von `custom_icons.json` ein
5. Klicken Sie auf "Execute"
#### Option 2: HMAC-Authentifizierung (Empfohlen für Automatisierung)
Erstellen Sie zuerst einen API-Token in BloodHound:
1. Gehen Sie zu **Einstellungen** → **Administration** → **Benutzer verwalten**
2. Klicken Sie auf Ihren Benutzer → **Token erstellen**
3. Speichern Sie die **Token-ID** und den **Token-Schlüssel**
Verwenden Sie dann dieses Python-Skript zum Hochladen:```python
#!/usr/bin/env python3
"""Upload custom icons to BloodHound CE using HMAC authentication."""
import base64
import hashlib
import hmac
import json
from datetime import datetime, timezone
import requests
# Configuration
BLOODHOUND_URL = "http://localhost:8080"
TOKEN_ID = "your-token-id"
TOKEN_KEY = "your-token-key"
ICONS_FILE = "custom_icons.json"
def hmac_auth(method: str, uri: str, body: bytes = b"") -> dict:
"""Generate HMAC authentication headers."""
digester = hmac.new(
base64.b64decode(TOKEN_KEY),
msg=None,
digestmod=hashlib.sha256
)
now = datetime.now(timezone.utc)
timestamp = now.strftime("%Y-%m-%dT%H:%M:%SZ")
digester.update(f"{method}".encode())
digester.update(f"{uri}".encode())
digester.update(timestamp.encode())
if body:
digester.update(body)
signature = base64.b64encode(digester.digest()).decode()
return {
"Authorization": f"bhesignature {TOKEN_ID}",
"RequestDate": timestamp,
"Signature": signature,
"Content-Type": "application/json",
}
def upload_icons():
"""Upload custom icons to BloodHound."""
uri = "/api/v2/custom-nodes"
url = f"{BLOODHOUND_URL}{uri}"
with open(ICONS_FILE, "rb") as f:
body = f.read()
headers = hmac_auth("POST", uri, body)
response = requests.post(url, headers=headers, data=body)
print(f"Status: {response.status_code}")
print(f"Response: {response.text}")
return response.status_code == 200
if __name__ == "__main__":
upload_icons()
Holen Sie sich ein JWT aus dem DevTools-Netzwerk-Tab Ihres Browsers, während Sie in BloodHound angemeldet sind:```bash
curl -X POST http://localhost:8080/api/v2/custom-nodes
-H "Authorization: Bearer eyJ..."
-H "Content-Type: application/json"
-d @custom_icons.json
---
## Python API```python
from dop2mop import Dop2MopCollector, CollectorConfig
# Configure collection
config = CollectorConfig(
github_token="ghp_xxx",
github_org="myorg",
aws_profile="default",
)
# Validate credentials first
collector = Dop2MopCollector(config)
results = collector.validate_all()
print(results) # {'GitHubCollector': True, 'SageMakerCollector': True, ...}
# Run collection (supports aliases)
collector.run(collectors=["github", "sm"])
# Save output
collector.save("output.json")
# Get statistics
print(collector.get_stats())
# Get per-collector failure/skip details
print(collector.get_collection_summary())
from dop2mop import CollectorConfig, GitHubCollector, SageMakerCollector from dop2mop.graph import OpenGraphBuilder
builder = OpenGraphBuilder(source_kind="MLOpsBase")
config = CollectorConfig( github_token="ghp_xxx", github_org="myorg", aws_profile="default", )
github = GitHubCollector(config, builder) github.collect()
sagemaker = SageMakerCollector(config, builder) sagemaker.collect()
builder.save("combined.json")
### Benutzerdefinierte Graphen erstellen```python
from dop2mop.graph import OpenGraphBuilder
from dop2mop.models import NodeKind, EdgeType
builder = OpenGraphBuilder(source_kind="CustomSource")
# Add nodes
builder.create_node(
id="my-pipeline",
kinds=[NodeKind.AZURE_DEVOPS_PIPELINE.value],
name="My Pipeline",
displayname="Production Pipeline",
)
builder.create_node(
id="my-ml-workspace",
kinds=[NodeKind.AZURE_ML_WORKSPACE.value],
name="ML Workspace",
displayname="Training Workspace",
)
# Add edge
builder.create_edge(
start_id="my-pipeline",
end_id="my-ml-workspace",
kind=EdgeType.SUBMITS_JOB,
properties={"trust_boundary": "TB4"}
)
# Export
builder.save("custom_graph.json")
Beginnen Sie immer mit der Validierung von Anmeldeinformationen, um Authentifizierungsprobleme frühzeitig zu erkennen:```bash dop2mop collect --validate --collectors github,sm -v
Die Ausgabe zeigt OK/FEHLGESCHLAGEN pro Collector, bevor eine Sammlung beginnt.
### Sammlungszusammenfassung
Nach jedem Durchlauf gibt Dop2Mop eine Zusammenfassung aus, die zeigt, was gesammelt wurde und was fehlgeschlagen ist:```
============================================================
Dop2Mop Collection Summary
============================================================
Total Nodes: 142
DevOps: 45
MLOps: 38
Identity: 12
Artifact: 47
Total Edges: 201
Contains: 62
TriggersPipeline: 15
...
────────────────────────────────────────────────────────
Collection Issues:
GitHubCollector: 45 collected, 3 failed, 1 skipped
FAIL: branch_protection:org/repo - 404 Not Found
SKIP: branch_protection:org/private - Insufficient permissions
Output: output.json
============================================================
"GitHub-Collector nicht konfiguriert, wird übersprungen"
GITHUB_TOKEN und GITHUB_ORG gesetzt sind, oder übergeben Sie --github-token und --github-org"Azure-ML-Collector nicht konfiguriert, wird übersprungen"
AZURE_SUBSCRIPTION_ID und AZURE_TENANT_ID gesetzt sindaz login aus, wenn Sie DefaultAzureCredential verwenden--azure-access-token mit einem gültigen Token von az account get-access-token"SageMaker-Collector nicht konfiguriert, wird übersprungen"
AWS_PROFILE oder sowohl AWS_ACCESS_KEY_ID als auch AWS_SECRET_ACCESS_KEYBranch-Schutz gibt 403 zurück
Ratenbegrenzung (429-Fehler)
--max-items, um API-Aufrufe zu reduzierenKeine Ergebnisse in der BloodHound Cypher-Konsole
RETURN a, b) zurückgeben, nicht Eigenschaften (RETURN a.name, b.name)Filtern von abgeleiteten vs. erfassten Kanten
InferredCanAssumeRole statt CanAssumeRole)MATCH p=()-[:CanAssumeRole]->() RETURN pMATCH p=()-[:InferredCanAssumeRole]->() RETURN pMIT-Lizenz – Einzelheiten finden Sie in LICENSE.
| Alias | Collector |
|---|
github, gh | GitHubCollector |
ado, azuredevops, azure-devops | AzureDevOpsCollector |
azureml, azure-ml | AzureMLCollector |
sagemaker, sm | SageMakerCollector |