
Collettore OpenGraph per BloodHound che mappa i percorsi di attacco dall'infrastruttura DevOps a quella MLOps, raccogliendo risorse di pipeline CI/CD, service principal e piattaforma ML per l'analisi del movimento laterale.
Un raccoglitore OpenGraph proof-of-concept per BloodHound che mappa i percorsi di attacco dall'infrastruttura DevOps all'infrastruttura MLOps.
Basato su Pipelines of Privilege: Attack Paths from DevOps to MLOps Infrastructure di Brett Hawkins (@h4wkst3r).
Dop2Mop raccoglie dati dalle piattaforme DevOps e MLOps per identificare percorsi di attacco che consentono il movimento laterale dalle pipeline CI/CD all'infrastruttura di addestramento del machine learning. Produce JSON OpenGraph compatibile con BloodHound per visualizzazione e analisi.
| Piattaforme DevOps | Piattaforme MLOps | Provider di Identità |
|---|---|---|
| GitHub (Actions, Repos, Secrets) | Azure Machine Learning | Azure AD Service Principals |
| Azure DevOps (Pipelines, Service Connections) | Amazon SageMaker | AWS IAM Roles OIDC/Federated Identity |
Dop2Mop modella i cinque confini di fiducia critici identificati nella ricerca:
git clone https://github.com/h4wkst3r/dop2mop.git cd dop2mop pip install -r requirements.txt pip install -e .
## Cosa viene raccolto
Ogni collettore raccoglie risorse specifiche della piattaforma e mappa i confini di fiducia tra di esse:
| Collettore | Risorse raccolte |
|-----------|-------------------|
| **GitHub** | Organizzazioni, repository, workflow, segreti, regole di protezione dei rami, configurazioni OIDC, riferimenti a immagini container, riferimenti a bucket S3 |
| **Azure DevOps** | Organizzazioni, progetti, pipeline (YAML), connessioni di servizio (con dettagli sull'ambito), gruppi di variabili, pool di agent, repository |
| **Azure ML** | Workspace, cluster/istanze di calcolo, datastore, ambienti ML, modelli registrati, job/esperimenti, endpoint online e batch |
| **SageMaker** | Job di addestramento, modelli, endpoint, domini, istanze notebook, ruoli di esecuzione IAM (con analisi delle policy), repository/immagini ECR, bucket S3 (filtrati per rilevanza ML) |
## Avvio Rapido
### Genera Dati Demo
Il modo più rapido per vedere Dop2Mop in azione è generare dati demo che mostrino gli scenari di attacco della ricerca:```bash
dop2mop demo -o demo.json
MATCH (n) RETURN n LIMIT 25
``````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
Invece di passare le credenziali ogni volta, puoi salvarle in un file di configurazione. Copia l'esempio incluso e inserisci i tuoi valori:```bash cp dop2mop.yaml.example dop2mop.yaml
Dop2Mop controlla queste posizioni in ordine:
1. Percorso specificato da `--config`
2. `dop2mop.yaml` / `dop2mop.yml` / `.dop2mop.yaml` nella directory corrente
3. `~/.dop2mop.yaml`
> **Nota:** `dop2mop.yaml` è in `.gitignore` per evitare di committare accidentalmente credenziali. Il file di esempio (`dop2mop.yaml.example`) è sicuro da committare.
Vedi [dop2mop.yaml.example](https://github.com/h4wkst3r/dop2mop/blob/HEAD/dop2mop.yaml.example) per tutte le opzioni disponibili con commenti.
**Ordine di priorità:** argomenti CLI > file di configurazione > variabili d'ambiente.
### Validazione delle credenziali
Verifica le credenziali prima di eseguire una raccolta completa:```bash
# Validate all configured collectors
dop2mop collect --validate -v
# Validate specific collectors
dop2mop collect --validate --collectors github,sagemaker -v
Questo effettua una chiamata API leggera per piattaforma per verificare che i token siano validi prima di iniziare la raccolta.
Puoi usare nomi brevi invece dei nomi completi delle classi con --collectors:
dop2mop collect --collectors GitHubCollector,SageMakerCollector dop2mop collect --collectors github,sagemaker dop2mop collect --collectors gh,sm
---
## Riferimento CLI
### Panoramica dei Comandi```
dop2mop <command> [options]
Commands:
collect Collect data from DevOps/MLOps platforms
demo Generate demo data with attack scenarios
| Opzione | Descrizione |
|---|---|
-v, --verbose | Abilita output verbose (logging a livello INFO) |
--debug | Abilita output debug (logging a livello DEBUG) |
dop2mop collectRaccogli dati dalle piattaforme DevOps e MLOps configurate.```bash dop2mop collect [OPTIONS]
#### Opzioni Generali
| Opzione | Descrizione |
|--------|-------------|
| `-o, --output FILE` | Percorso del file di output (default: `dop2mop_output.json`) |
| `--zip` | Comprimi output in file ZIP |
| `--config FILE` | Percorso del file di configurazione YAML/JSON |
| `--validate` | Convalida le credenziali prima della raccolta |
| `--collectors LIST` | Elenco separato da virgole di collector o alias (es. `github,sm`) |
| `--max-items N` | Numero massimo di elementi da raccogliere per tipo |
| `--no-secrets` | Salta l'enumerazione di segreti/credenziali |
#### Opzioni GitHub
| Opzione | Descrizione |
|--------|-------------|
| `--github-token TOKEN` | Token di accesso personale GitHub |
| `--github-org ORG` | Nome dell'organizzazione GitHub |
| `--github-enterprise-url URL` | URL di GitHub Enterprise Server |
#### Opzioni Azure DevOps
| Opzione | Descrizione |
|--------|-------------|
| `--azure-devops-token TOKEN` | Token di accesso personale Azure DevOps (PAT) |
| `--azure-devops-access-token TOKEN` | Token di accesso Azure DevOps (autenticazione Bearer, opzionale) |
| `--azure-devops-org ORG` | Nome dell'organizzazione Azure DevOps |
#### Opzioni Azure ML
| Opzione | Descrizione |
|--------|-------------|
| `--azure-subscription-id ID` | ID della sottoscrizione Azure |
| `--azure-tenant-id ID` | ID del tenant Azure AD |
| `--azure-client-id ID` | ID client del service principal (opzionale) |
| `--azure-client-secret SECRET` | Segreto client del service principal (opzionale) |
| `--azure-access-token TOKEN` | Token di accesso Azure per l'autenticazione Azure ML (opzionale) |
#### Opzioni AWS SageMaker
| Opzione | Descrizione |
|--------|-------------|
| `--aws-access-key-id KEY` | ID della chiave di accesso AWS |
| `--aws-secret-access-key SECRET` | Chiave di accesso segreta AWS |
| `--aws-region REGION` | Regione AWS (default: `us-east-1`) |
| `--aws-profile PROFILE` | Nome del profilo CLI AWS |
#### Collector Disponibili
| Nome Collector | Piattaforma | Credenziali Richieste |
|----------------|-------------|-----------------------|
| `GitHubCollector` | GitHub | `--github-token`, `--github-org` |
| `AzureDevOpsCollector` | Azure DevOps | `--azure-devops-token` o `--azure-devops-access-token`, `--azure-devops-org` |
| `AzureMLCollector` | Azure ML | `--azure-subscription-id`, `--azure-tenant-id` |
| `SageMakerCollector` | AWS SageMaker | `--aws-profile` o `--aws-access-key-id` |
---
### `dop2mop demo`
Genera dati dimostrativi che mostrano i quattro scenari di attacco della ricerca.```bash
dop2mop demo [OPTIONS]
| Opzione | Descrizione |
|---|---|
-o, --output FILE | Percorso del file di output (default: dop2mop_demo.json) |
dop2mop iconsGenera una configurazione personalizzata delle icone per i tipi di nodo di BloodHound.```bash dop2mop icons [OPTIONS]
| Option | Description |
|--------|-------------|
| `-o, --output FILE` | Percorso del file di output (predefinito: `dop2mop_icons.json`) |
---
## Esempi di utilizzo da riga di comando
### Raccolta di base```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
### Raccolta Multi Piattaforma```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
### Esempi di Azure DevOps Collection```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
Nota: Priorità di autenticazione di Azure DevOps: token di accesso (Bearer) > PAT (Basic). I token di accesso possono essere ottenuti tramite
az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798.
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
> **Nota:** Priorità di autenticazione di Azure ML: access token > service principal > DefaultAzureCredential (az login).
> I token di accesso possono essere ottenuti tramite `az account get-access-token --resource https://management.azure.com/`.
### Esempi di Raccolta AWS SageMaker```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
---
## Variabili d'Ambiente
Tutte le opzioni da riga di comando possono essere impostate tramite variabili d'ambiente:
| Variabile d'Ambiente | Equivalente CLI | Descrizione |
|---------------------|----------------|-------------|
| `GITHUB_TOKEN` | `--github-token` | Token di accesso personale di GitHub |
| `GITHUB_ORG` | `--github-org` | Nome dell'organizzazione GitHub |
| `GITHUB_ENTERPRISE_URL` | `--github-enterprise-url` | URL del server GitHub Enterprise |
| `AZURE_DEVOPS_TOKEN` | `--azure-devops-token` | PAT di Azure DevOps |
| `AZURE_DEVOPS_ACCESS_TOKEN` | `--azure-devops-access-token` | Token di accesso Azure DevOps (Bearer) |
| `AZURE_DEVOPS_ORG` | `--azure-devops-org` | Organizzazione Azure DevOps |
| `AZURE_SUBSCRIPTION_ID` | `--azure-subscription-id` | ID sottoscrizione Azure |
| `AZURE_TENANT_ID` | `--azure-tenant-id` | ID tenant Azure AD |
| `AZURE_CLIENT_ID` | `--azure-client-id` | ID client dell'entità servizio Azure |
| `AZURE_CLIENT_SECRET` | `--azure-client-secret` | Segreto dell'entità servizio Azure |
| `AZURE_ACCESS_TOKEN` | `--azure-access-token` | Token di accesso Azure per Azure ML |
| `AWS_ACCESS_KEY_ID` | `--aws-access-key-id` | ID chiave di accesso AWS |
| `AWS_SECRET_ACCESS_KEY` | `--aws-secret-access-key` | Chiave di accesso segreta AWS |
| `AWS_REGION` | `--aws-region` | Regione AWS (predefinita: us-east-1) |
| `AWS_PROFILE` | `--aws-profile` | Nome del profilo CLI AWS |
**Priorità:** Argomenti CLI > file di configurazione > variabili d'ambiente.
---
## Tipi di Nodo
### Nodi DevOps
| Tipo | Descrizione |
|------|-------------|
| `GHOrganization` | Organizzazione GitHub |
| `GHRepository` | Repository GitHub |
| `GHWorkflow` | Workflow GitHub Actions |
| `GHSecret` | Segreto GitHub Actions |
| `ADOOrganization` | Organizzazione Azure DevOps |
| `ADOProject` | Progetto Azure DevOps |
| `ADOPipeline` | Pipeline Azure DevOps |
| `ADOServiceConnection` | Connessione servizio Azure DevOps (NHI) con dettagli ambito |
| `ADOAgent` | Pool di agenti Azure DevOps (hosted o self-hosted) |
| `ADOVariableGroup` | Gruppo di variabili Azure DevOps |
### Nodi MLOps
| Tipo | Descrizione |
|------|-------------|
| `AzMLWorkspace` | Workspace Azure ML |
| `AzMLCompute` | Cluster/istanza di calcolo Azure ML |
| `AzMLExperiment` | Job/esperimento Azure ML |
| `AzMLDatastore` | Datastore Azure ML |
| `AzMLEnvironment` | Ambiente Azure ML (definizione contenitore) |
| `AzMLModel` | Modello registrato Azure ML |
| `SMDomain` | Dominio SageMaker Studio |
| `SMTrainingJob` | Job di addestramento SageMaker |
| `SMModel` | Modello SageMaker |
| `SMEndpoint` | Endpoint SageMaker (usato anche per endpoint Azure ML) |
| `SMNotebook` | Istanza notebook SageMaker |
### Nodi Identità
| Tipo | Descrizione |
|------|-------------|
| `ServicePrincipal` | Entità servizio Azure AD |
| `IAMRole` | Ruolo IAM AWS |
| `OIDCIdentity` | Identità federata OIDC |
| `ManagedIdentity` | Identità gestita Azure |
### Nodi Artefatto
| Tipo | Descrizione |
|------|-------------|
| `ContainerRegistry` | Registry contenitori (ECR, ACR) |
| `ContainerImage` | Immagine contenitore |
| `S3Bucket` | Bucket S3 AWS |
| `Dataset` | Dataset ML |
## Tipi di Bordo
### Bordi Percorso di Attacco
| Tipo | Boundary di Fiducia | Descrizione |
|------|----------------|-------------|
| `TriggersPipeline` | TB1 | Commit di codice attiva CI/CD |
| `HasBranchProtection` | TB1 | Il repository ha regole di protezione ramo |
| `BypassesProtection` | TB1 | Protezione ramo debole/mancante (sfruttabile) |
| `AuthenticatesAs` | TB2 | La pipeline usa un'entità servizio |
| `CanAssumeRole` | TB2 | L'identità OIDC può assumere il ruolo IAM |
| `OIDCTrust` | TB2 | Il workflow usa federazione OIDC |
| `UsesServiceConnection` | TB2 | La pipeline usa la connessione servizio ADO |
| `PullsImage` | TB3 | Il job di addestramento tira l'immagine contenitore |
| `CanPoisonImage` | TB3 | La pipeline può modificare l'immagine contenitore |
| `SubmitsJob` | TB4 | L'entità servizio invia il job ML |
| `CodeExecution` | TB4 | Il job esegue codice sul calcolo |
| `LoadsDataset` | TB5 | Il job di addestramento carica il dataset |
| `CanPoisonDataset` | TB5 | La pipeline può modificare il dataset |
| `Deserializes` | TB5 | Deserializzazione non sicura |
### Bordi Inferiti
Questi bordi sono creati da analisi euristica quando i dati espliciti dell'API non sono disponibili (es. ARN di ruoli memorizzati nei segreti). Usano tipi di bordo distinti per consentire il filtraggio nelle query BloodHound.
| Tipo | Descrizione |
|------|-------------|
| `InferredCanAssumeRole` | L'identità OIDC potrebbe essere in grado di assumere il ruolo (inferito) |
| `InferredSubmitsJob` | Il workflow potrebbe inviare il job di addestramento tramite OIDC (inferito) |
| `InferredPullsImage` | Il job di addestramento potrebbe tirare l'immagine contenitore avvelenata (inferito) |
| `InferredLoadsDataset` | Il job di addestramento potrebbe caricare il dataset avvelenato (inferito) |
### Bordi Strutturali
| Tipo | Descrizione |
|------|-------------|
| `Contains` | Relazione genitore-figlio |
| `MemberOf` | Appartenenza a gruppo |
| `HasAccessTo` | Permesso di accedere alla risorsa |
| `HasExecutionRole` | La risorsa usa un ruolo IAM/esecuzione |
| `Owns` | Relazione di proprietà |
## Query di Esempio
Vedi [queries/dop2mop_queries.cypher](https://github.com/h4wkst3r/dop2mop/blob/HEAD/queries/dop2mop_queries.cypher) per esempi di query complete.
---
## Icone Personalizzate
Dop2Mop include un file di icone preconfigurato per i tipi di nodo personalizzati di BloodHound in [data/custom_icons.json](https://github.com/h4wkst3r/dop2mop/blob/HEAD/data/custom_icons.json).
### Caricamento Icone in BloodHound
#### Opzione 1: API Explorer (La Più Semplice)
1. Apri BloodHound CE e vai a **Settings** → **API Explorer**
2. Trova **POST /api/v2/custom-nodes**
3. Fai clic su "Try it out"
4. Incolla il contenuto di `custom_icons.json`
5. Fai clic su "Execute"
#### Opzione 2: Autenticazione HMAC (Consigliata per Automazione)
Prima, crea un token API in BloodHound:
1. Vai a **Impostazioni** → **Amministrazione** → **Gestisci Utenti**
2. Fai clic sul tuo utente → **Crea Token**
3. Salva il **Token ID** e la **Token Key**
Quindi usa questo script Python per caricare:```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()
Ottieni un JWT dalla scheda Rete degli DevTools del tuo browser mentre sei connesso a BloodHound:```bash
curl -X POST http://localhost:8080/api/v2/custom-nodes
-H "Authorization: Bearer eyJ..."
-H "Content-Type: application/json"
-d @custom_icons.json
## API Python```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")
### Costruire Grafici Personalizzati```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")
Inizia sempre con la convalida delle credenziali per individuare tempestivamente i problemi di autenticazione:```bash dop2mop collect --validate --collectors github,sm -v
L'output mostrerà OK/FAILED per ogni collector prima che inizi qualsiasi raccolta.
### Riepilogo Raccolta
Dopo ogni esecuzione, Dop2Mop stampa un riepilogo che mostra cosa è stato raccolto e cosa ha fallito:```
============================================================
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
============================================================
"Collettore GitHub non configurato, saltato"
GITHUB_TOKEN e GITHUB_ORG siano impostate, oppure passa --github-token e --github-org"Collettore Azure ML non configurato, saltato"
AZURE_SUBSCRIPTION_ID e AZURE_TENANT_ID siano impostateaz login se usi DefaultAzureCredential--azure-access-token con un token valido ottenuto da az account get-access-token"Collettore SageMaker non configurato, saltato"
AWS_PROFILE oppure sia AWS_ACCESS_KEY_ID che AWS_SECRET_ACCESS_KEYLa protezione dei rami restituisce 403
Limitazione della frequenza (errori 429)
--max-items per ridurre le chiamate APINessun risultato nella console Cypher di BloodHound
RETURN a, b) non proprietà (RETURN a.name, b.name)Filtraggio degli archi inferiti rispetto a quelli raccolti
InferredCanAssumeRole invece di CanAssumeRole)MATCH p=()-[:CanAssumeRole]->() RETURN pMATCH p=()-[:InferredCanAssumeRole]->() RETURN pLicenza MIT - Vedi LICENSE per i dettagli.
| Alias | Raccoglitore |
|---|
github, gh | GitHubCollector |
ado, azuredevops, azure-devops | AzureDevOpsCollector |
azureml, azure-ml | AzureMLCollector |
sagemaker, sm | SageMakerCollector |