Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Dop2Mop — Recolector OpenGraph para BloodHound que mapea rutas de ataque desde infraestructura DevOps a MLOps, recopilando recursos de pipeline CI/CD, service principal y plataforma ML para análisis de movimiento lateral. | Kitploit
Herramientas/GitHubGitHub/h4wkst3r/dop2mop
Seguridad de Infraestructura en la NubeReconocimientoSeguridad de ContenedoresAnálisis de VulnerabilidadesRecopilación de InformaciónPruebas de PenetraciónSeguridad en la NubeDevSecOpsGestión de Identidad y Acceso (IAM)Seguridad de Cadena de SuministroRed Teaming
414hace 5 mesesAún no revisado
GitHubh4wkst3r/dop2mop

Dop2Mop

Recolector OpenGraph para BloodHound que mapea rutas de ataque desde infraestructura DevOps a MLOps, recopilando recursos de pipeline CI/CD, service principal y plataforma ML para análisis de movimiento lateral.

Ver Repositorio

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Dop2Mop

Un recolector OpenGraph de prueba de concepto para BloodHound que mapea rutas de ataque desde infraestructura DevOps hasta MLOps.

Basado en Pipelines of Privilege: Attack Paths from DevOps to MLOps Infrastructure de Brett Hawkins (@h4wkst3r).

Tabla de Contenidos

  • Agradecimientos
  • Resumen
    • Plataformas Compatibles
    • Límites de Confianza Mapeados
  • Instalación
    • Dependencias Opcionales
  • Inicio Rápido
    • Generar Datos de Demostración
    • Ingestar en BloodHound
  • Configuración
    • Archivo de Configuración
    • Validación de Credenciales
  • Referencia CLI
    • Resumen de Comandos
    • Opciones Globales
    • dop2mop collect
    • dop2mop demo
  • Ejemplos de Uso de CLI
    • Recolección Básica
    • Recolección de una Sola Plataforma
    • Recolección de Múltiples Plataformas
    • Ejemplos de Recolección de GitHub
    • Ejemplos de Recolección de Azure DevOps
    • Ejemplos de Recolección de Azure ML
    • Ejemplos de Recolección de AWS SageMaker
    • Recolección Completa del Entorno
  • Variables de Entorno
  • Tipos de Nodo
    • Nodos DevOps
    • Nodos MLOps
    • Nodos de Identidad
    • Nodos de Artefacto
  • Tipos de Borde
    • Bordes de Ruta de Ataque
    • Bordes Estructurales
  • Consultas de Ejemplo
  • Iconos Personalizados
    • Subir Iconos a BloodHound
  • API de Python
    • Usar Recolectores Individuales
    • Construir Grafos Personalizados
  • Solución de Problemas
    • Problemas Comunes
  • Licencia
  • Agradecimientos

    • SpecterOps por BloodHound y OpenGraph

    Resumen

    Dop2Mop recolecta datos de plataformas DevOps y MLOps para identificar rutas de ataque que permiten movimiento lateral desde pipelines CI/CD hasta infraestructura de entrenamiento de machine learning. Genera JSON OpenGraph compatible con BloodHound para visualización y análisis.

    Plataformas Compatibles

    Plataformas DevOpsPlataformas MLOpsProveedores de Identidad
    GitHub (Actions, Repos, Secrets)Azure Machine LearningAzure AD Service Principals
    Azure DevOps (Pipelines, Service Connections)Amazon SageMakerAWS IAM Roles
    OIDC/Federated Identity

    Límites de Confianza Mapeados

    Dop2Mop modela los cinco límites de confianza críticos identificados en la investigación:

    1. TB1: Repositorio de Código a Pipeline CI/CD - Activación automática de pipelines a partir de commits de código
    2. TB2: Autenticación de Principal de Servicio - Credenciales NHI usadas por pipelines para acceder a plataformas ML
    3. TB3: Confianza en Artefacto de Contenedor - Confianza implícita en imágenes de contenedor de registros internos
    4. TB4: Ejecución de Definición de Trabajo - Plataformas ML ejecutando definiciones de trabajo sin validación
    5. TB5: Deserialización de Código - Deserialización insegura de datasets (pickle, joblib)

    Instalación```bash

    git clone https://github.com/h4wkst3r/dop2mop.git cd dop2mop pip install -r requirements.txt pip install -e .

    root@kitploit:~
    ## Lo que se recopila
    
    Cada recopilador reúne recursos específicos de la plataforma y mapea los límites de confianza entre ellos:
    
    | Recopilador | Recursos Recopilados |
    |-----------|-------------------|
    | **GitHub** | Organizaciones, repositorios, flujos de trabajo, secretos, reglas de protección de ramas, configuraciones OIDC, referencias de imágenes de contenedores, referencias de buckets S3 |
    | **Azure DevOps** | Organizaciones, proyectos, pipelines (YAML), conexiones de servicio (con detalles de ámbito), grupos de variables, pools de agentes, repositorios |
    | **Azure ML** | Espacios de trabajo, clústeres/instancias de cómputo, almacenes de datos, entornos de ML, modelos registrados, trabajos/experimentos, endpoints en línea y por lotes |
    | **SageMaker** | Trabajos de entrenamiento, modelos, endpoints, dominios, instancias de notebook, roles de ejecución de IAM (con análisis de políticas), repositorios/imágenes de ECR, buckets de S3 (filtrados para relevantes de ML) |
    
    ## Inicio Rápido
    
    ### Generar Datos de Demostración
    
    La forma más rápida de ver Dop2Mop en acción es generar datos de demostración que muestren los escenarios de ataque de la investigación:```bash
    dop2mop demo -o demo.json
    

    Ingesta en BloodHound

    1. Abra BloodHound CE (v8.0+)
    2. Navegue a Administración → Ingesta de archivos
    3. Cargue el archivo JSON generado
    4. Consulte con Cypher:
    root@kitploit:~
    MATCH (n) RETURN n LIMIT 100
    ``````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
    

    Configuración

    Archivo de configuración

    En lugar de pasar credenciales en cada ejecución, puedes guardarlas en un archivo de configuración. Copia el ejemplo incluido y completa tus valores:```bash cp dop2mop.yaml.example dop2mop.yaml

    Edit dop2mop.yaml with your credentials

    root@kitploit:~
    Dop2Mop comprueba estas ubicaciones en orden:
    
    1. Ruta especificada por `--config`
    2. `dop2mop.yaml` / `dop2mop.yml` / `.dop2mop.yaml` en el directorio actual
    3. `~/.dop2mop.yaml`
    
    > **Nota:** `dop2mop.yaml` está en `.gitignore` para evitar confirmar credenciales accidentalmente. El archivo de ejemplo (`dop2mop.yaml.example`) es seguro para confirmar.
    
    Consulta [dop2mop.yaml.example](https://github.com/h4wkst3r/dop2mop/blob/main/dop2mop.yaml.example) para conocer todas las opciones disponibles con comentarios.
    
    **Orden de prioridad:** Argumentos de CLI > archivo de configuración > variables de entorno.
    
    ### Validación de credenciales
    
    Prueba las credenciales antes de ejecutar una recolección completa:```bash
    # Validate all configured collectors
    dop2mop collect --validate -v
    
    # Validate specific collectors
    dop2mop collect --validate --collectors github,sagemaker -v
    

    Esto realiza una llamada ligera a la API por plataforma para verificar que los tokens sean válidos antes de iniciar la recopilación.

    Alias de Collector

    Puede usar nombres cortos en lugar de nombres de clase completos con --collectors:

    AliasCollector
    github, ghGitHubCollector
    ado, azuredevops, azure-devopsAzureDevOpsCollector
    azureml, azure-mlAzureMLCollector
    sagemaker, smSageMakerCollector

    These are equivalent:

    dop2mop collect --collectors GitHubCollector,SageMakerCollector dop2mop collect --collectors github,sagemaker dop2mop collect --collectors gh,sm

    root@kitploit:~
    ---
    
    ## Referencia de CLI
    
    ### Descripción general de comandos```
    dop2mop <command> [options]
    
    Commands:
      collect    Collect data from DevOps/MLOps platforms
      demo       Generate demo data with attack scenarios
    

    Opciones Globales

    OpciónDescripción
    -v, --verboseHabilitar salida detallada (registro a nivel INFO)
    --debugHabilitar salida de depuración (registro a nivel DEBUG)

    dop2mop collect

    Recolectar datos de plataformas DevOps y MLOps configuradas.```bash dop2mop collect [OPTIONS]

    root@kitploit:~
    #### Opciones generales
    
    | Opción | Descripción |
    |--------|-------------|
    | `-o, --output FILE` | Ruta del archivo de salida (predeterminado: `dop2mop_output.json`) |
    | `--zip` | Comprimir la salida en un archivo ZIP |
    | `--config FILE` | Ruta al archivo de configuración YAML/JSON |
    | `--validate` | Validar credenciales antes de la recolección |
    | `--collectors LIST` | Lista separada por comas de recolectores o alias (p. ej., `github,sm`) |
    | `--max-items N` | Número máximo de elementos a recolectar por tipo |
    | `--no-secrets` | Omitir enumeración de secretos/credenciales |
    
    #### Opciones de GitHub
    
    | Opción | Descripción |
    |--------|-------------|
    | `--github-token TOKEN` | Token de acceso personal de GitHub |
    | `--github-org ORG` | Nombre de la organización de GitHub |
    | `--github-enterprise-url URL` | URL del servidor de GitHub Enterprise |
    
    #### Opciones de Azure DevOps
    
    | Opción | Descripción |
    |--------|-------------|
    | `--azure-devops-token TOKEN` | Token de acceso personal (PAT) de Azure DevOps |
    | `--azure-devops-access-token TOKEN` | Token de acceso de Azure DevOps (autenticación Bearer, opcional) |
    | `--azure-devops-org ORG` | Nombre de la organización de Azure DevOps |
    
    #### Opciones de Azure ML
    
    | Opción | Descripción |
    |--------|-------------|
    | `--azure-subscription-id ID` | ID de suscripción de Azure |
    | `--azure-tenant-id ID` | ID de inquilino de Azure AD |
    | `--azure-client-id ID` | ID de cliente de la entidad de servicio (opcional) |
    | `--azure-client-secret SECRET` | Secreto de cliente de la entidad de servicio (opcional) |
    | `--azure-access-token TOKEN` | Token de acceso de Azure para autenticación de Azure ML (opcional) |
    
    #### Opciones de AWS SageMaker
    
    | Opción | Descripción |
    |--------|-------------|
    | `--aws-access-key-id KEY` | ID de clave de acceso de AWS |
    | `--aws-secret-access-key SECRET` | Clave de acceso secreta de AWS |
    | `--aws-region REGION` | Región de AWS (predeterminado: `us-east-1`) |
    | `--aws-profile PROFILE` | Nombre del perfil de AWS CLI |
    
    #### Recolectores disponibles
    
    | Nombre del recolector | Plataforma | Credenciales requeridas |
    |----------------|----------|---------------------|
    | `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`
    
    Generar datos de demostración que muestren los cuatro escenarios de ataque de la investigación.```bash
    dop2mop demo [OPTIONS]
    
    OptionDescription
    -o, --output FILERuta del archivo de salida (por defecto: dop2mop_demo.json)

    dop2mop icons

    Genera configuración de iconos personalizados para los tipos de nodos de BloodHound.```bash dop2mop icons [OPTIONS]

    root@kitploit:~
    | Opción | Descripción |
    |--------|-------------|
    | `-o, --output FILE` | Ruta del archivo de salida (por defecto: `dop2mop_icons.json`) |
    
    ---
    
    ## Ejemplos de uso de CLI
    
    ### Colección básica```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
    

    Colección de Plataforma Única```bash

    GitHub only (aliases: github, gh)

    dop2mop collect --collectors github -o github.json -v

    Azure DevOps only (aliases: ado, azuredevops)

    dop2mop collect --collectors ado -o ado.json -v

    Azure ML only (aliases: azureml, azure-ml)

    dop2mop collect --collectors azureml -o azureml.json -v

    SageMaker only (aliases: sagemaker, sm)

    dop2mop collect --collectors sm -o sagemaker.json -v

    root@kitploit:~
    ### Colección multiplataforma```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
    

    Ejemplos de Colección de GitHub```bash

    Using environment variables

    export GITHUB_TOKEN="ghp_xxxxxxxxxxxx" export GITHUB_ORG="your-org" dop2mop collect --collectors GitHubCollector -o github.json -v

    Using command-line arguments

    dop2mop collect --collectors GitHubCollector
    --github-token ghp_xxxxxxxxxxxx
    --github-org your-org
    -o github.json -v

    GitHub Enterprise Server

    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

    Skip secret enumeration

    dop2mop collect --collectors GitHubCollector
    --github-token ghp_xxxxxxxxxxxx
    --github-org your-org
    --no-secrets
    -o github.json -v

    Limit to 50 repositories

    dop2mop collect --collectors GitHubCollector
    --github-token ghp_xxxxxxxxxxxx
    --github-org your-org
    --max-items 50
    -o github.json -v

    root@kitploit:~
    ### Ejemplos de la colección de Azure DevOps```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: Prioridad de autenticación de Azure DevOps: token de acceso (Bearer) > PAT (Básico). Los tokens de acceso se pueden obtener mediante az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798.

    Ejemplos de la Colección de Azure ML```bash

    Using environment variables

    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

    Using DefaultAzureCredential (az login)

    dop2mop collect --collectors AzureMLCollector
    --azure-subscription-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    --azure-tenant-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    -o azureml.json -v

    Using Service Principal

    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

    Using Access Token

    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

    root@kitploit:~
    > **Nota:** Prioridad de autenticación de Azure ML: token de acceso > entidad de servicio > DefaultAzureCredential (az login).
    > Los tokens de acceso se pueden obtener mediante `az account get-access-token --resource https://management.azure.com/`.
    
    ### Ejemplos de Colección de 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
    

    Recopilación completa del entorno```bash

    Set all environment variables

    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"

    Collect from all platforms (auto-detects configured collectors)

    dop2mop collect -o full_collection.json -v

    Or with explicit collectors

    dop2mop collect
    --collectors GitHubCollector,AzureDevOpsCollector,AzureMLCollector,SageMakerCollector
    -o full_collection.json -v

    root@kitploit:~
    ---
    
    ## Variables de Entorno
    
    Todas las opciones de línea de comandos se pueden configurar mediante variables de entorno:
    
    | Variable de Entorno | Equivalente CLI | Descripción |
    |---------------------|----------------|-------------|
    | `GITHUB_TOKEN` | `--github-token` | Token de acceso personal de GitHub |
    | `GITHUB_ORG` | `--github-org` | Nombre de la organización de GitHub |
    | `GITHUB_ENTERPRISE_URL` | `--github-enterprise-url` | URL de GitHub Enterprise Server |
    | `AZURE_DEVOPS_TOKEN` | `--azure-devops-token` | PAT de Azure DevOps |
    | `AZURE_DEVOPS_ACCESS_TOKEN` | `--azure-devops-access-token` | Token de acceso de Azure DevOps (Bearer) |
    | `AZURE_DEVOPS_ORG` | `--azure-devops-org` | Organización de Azure DevOps |
    | `AZURE_SUBSCRIPTION_ID` | `--azure-subscription-id` | ID de suscripción de Azure |
    | `AZURE_TENANT_ID` | `--azure-tenant-id` | ID de inquilino de Azure AD |
    | `AZURE_CLIENT_ID` | `--azure-client-id` | ID de cliente de la entidad de servicio de Azure |
    | `AZURE_CLIENT_SECRET` | `--azure-client-secret` | Secreto de la entidad de servicio de Azure |
    | `AZURE_ACCESS_TOKEN` | `--azure-access-token` | Token de acceso de Azure para Azure ML |
    | `AWS_ACCESS_KEY_ID` | `--aws-access-key-id` | ID de clave de acceso de AWS |
    | `AWS_SECRET_ACCESS_KEY` | `--aws-secret-access-key` | Clave de acceso secreta de AWS |
    | `AWS_REGION` | `--aws-region` | Región de AWS (predeterminada: us-east-1) |
    | `AWS_PROFILE` | `--aws-profile` | Nombre del perfil de AWS CLI |
    
    **Prioridad:** argumentos CLI > archivo de configuración > variables de entorno.
    
    ---
    
    ## Tipos de Nodo
    
    ### Nodos de DevOps
    
    | Tipo | Descripción |
    |------|-------------|
    | `GHOrganization` | Organización de GitHub |
    | `GHRepository` | Repositorio de GitHub |
    | `GHWorkflow` | Flujo de trabajo de GitHub Actions |
    | `GHSecret` | Secreto de GitHub Actions |
    | `ADOOrganization` | Organización de Azure DevOps |
    | `ADOProject` | Proyecto de Azure DevOps |
    | `ADOPipeline` | Pipeline de Azure DevOps |
    | `ADOServiceConnection` | Conexión de servicio de Azure DevOps (NHI) con detalles de ámbito |
    | `ADOAgent` | Grupo de agentes de Azure DevOps (alojado o autogestionado) |
    | `ADOVariableGroup` | Grupo de variables de Azure DevOps |
    
    ### Nodos de MLOps
    
    | Tipo | Descripción |
    |------|-------------|
    | `AzMLWorkspace` | Área de trabajo de Azure ML |
    | `AzMLCompute` | Clúster/instancia de cómputo de Azure ML |
    | `AzMLExperiment` | Trabajo/experimento de Azure ML |
    | `AzMLDatastore` | Almacén de datos de Azure ML |
    | `AzMLEnvironment` | Entorno de Azure ML (definición de contenedor) |
    | `AzMLModel` | Modelo registrado de Azure ML |
    | `SMDomain` | Dominio de SageMaker Studio |
    | `SMTrainingJob` | Trabajo de entrenamiento de SageMaker |
    | `SMModel` | Modelo de SageMaker |
    | `SMEndpoint` | Punto de conexión de SageMaker (también usado para puntos de conexión de Azure ML) |
    | `SMNotebook` | Instancia de cuaderno de SageMaker |
    
    ### Nodos de Identidad
    
    | Tipo | Descripción |
    |------|-------------|
    | `ServicePrincipal` | Entidad de servicio de Azure AD |
    | `IAMRole` | Rol de IAM de AWS |
    | `OIDCIdentity` | Identidad federada OIDC |
    | `ManagedIdentity` | Identidad administrada de Azure |
    
    ### Nodos de Artefacto
    
    | Tipo | Descripción |
    |------|-------------|
    | `ContainerRegistry` | Registro de contenedores (ECR, ACR) |
    | `ContainerImage` | Imagen de contenedor |
    | `S3Bucket` | Bucket S3 de AWS |
    | `Dataset` | Conjunto de datos de ML |
    
    ## Tipos de Arista
    
    ### Aristas de Ruta de Ataque
    
    | Tipo | Límite de Confianza | Descripción |
    |------|---------------------|-------------|
    | `TriggersPipeline` | TB1 | El commit de código activa CI/CD |
    | `HasBranchProtection` | TB1 | El repositorio tiene reglas de protección de ramas |
    | `BypassesProtection` | TB1 | Protección de ramas débil/ausente (explotable) |
    | `AuthenticatesAs` | TB2 | El pipeline usa una entidad de servicio |
    | `CanAssumeRole` | TB2 | La identidad OIDC puede asumir un rol de IAM |
    | `OIDCTrust` | TB2 | El flujo de trabajo usa federación OIDC |
    | `UsesServiceConnection` | TB2 | El pipeline usa una conexión de servicio de ADO |
    | `PullsImage` | TB3 | El trabajo de entrenamiento extrae una imagen de contenedor |
    | `CanPoisonImage` | TB3 | El pipeline puede modificar la imagen de contenedor |
    | `SubmitsJob` | TB4 | La entidad de servicio envía un trabajo de ML |
    | `CodeExecution` | TB4 | El trabajo ejecuta código en el cómputo |
    | `LoadsDataset` | TB5 | El trabajo de entrenamiento carga un conjunto de datos |
    | `CanPoisonDataset` | TB5 | El pipeline puede modificar el conjunto de datos |
    | `Deserializes` | TB5 | Deserialización no segura |
    
    ### Aristas Inferidas
    
    Estas aristas se crean mediante análisis heurístico cuando no están disponibles datos explícitos de la API (por ejemplo, ARN de roles almacenados en secretos). Utilizan tipos de arista distintos para que puedas filtrarlos en las consultas de BloodHound.
    
    | Tipo | Descripción |
    |------|-------------|
    | `InferredCanAssumeRole` | La identidad OIDC podría poder asumir un rol (inferido) |
    | `InferredSubmitsJob` | El flujo de trabajo podría enviar un trabajo de entrenamiento mediante OIDC (inferido) |
    | `InferredPullsImage` | El trabajo de entrenamiento podría extraer una imagen de contenedor envenenada (inferido) |
    | `InferredLoadsDataset` | El trabajo de entrenamiento podría cargar un conjunto de datos envenenado (inferido) |
    
    ### Aristas Estructurales
    
    | Tipo | Descripción |
    |------|-------------|
    | `Contains` | Relación padre-hijo |
    | `MemberOf` | Pertenencia a grupo |
    | `HasAccessTo` | Permiso para acceder a un recurso |
    | `HasExecutionRole` | El recurso usa un rol de IAM/ejecución |
    | `Owns` | Relación de propiedad |
    
    ## Consultas de Ejemplo
    
    Consulta [queries/dop2mop_queries.cypher](https://github.com/h4wkst3r/dop2mop/blob/main/queries/dop2mop_queries.cypher) para ejemplos completos de consultas.
    
    ---
    
    ## Iconos Personalizados
    
    Dop2Mop incluye un archivo de iconos preconfigurado para tipos de nodo personalizados de BloodHound en [data/custom_icons.json](https://github.com/h4wkst3r/dop2mop/blob/main/data/custom_icons.json).
    
    ### Subir Iconos a BloodHound
    
    #### Opción 1: Explorador de API (Más Sencilla)
    
    1. Abre BloodHound CE y ve a **Configuración** → **Explorador de API**
    2. Busca **POST /api/v2/custom-nodes**
    3. Haz clic en "Probar"
    4. Pega el contenido de `custom_icons.json`
    5. Haz clic en "Ejecutar"
    
    #### Opción 2: Autenticación HMAC (Recomendada para Automatización)
    
    Primero, crea un token de API en BloodHound:
    1. Ve a **Configuración** → **Administración** → **Gestionar Usuarios**
    2. Haz clic en tu usuario → **Crear Token**
    3. Guarda el **ID de Token** y la **Clave de Token**
    
    Luego, usa este script de Python para subir:```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()
    

    Opción 3: Bearer Token (Prueba rápida)

    Obtén un JWT desde la pestaña Red de DevTools de tu navegador mientras estás conectado 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

    root@kitploit:~
    ---
    
    ## 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())
    

    Usando Colectores Individuales```python

    from dop2mop import CollectorConfig, GitHubCollector, SageMakerCollector from dop2mop.graph import OpenGraphBuilder

    Create shared builder

    builder = OpenGraphBuilder(source_kind="MLOpsBase")

    Configure

    config = CollectorConfig( github_token="ghp_xxx", github_org="myorg", aws_profile="default", )

    Run individual collectors

    github = GitHubCollector(config, builder) github.collect()

    sagemaker = SageMakerCollector(config, builder) sagemaker.collect()

    Save combined output

    builder.save("combined.json")

    root@kitploit:~
    ### Construyendo gráficos personalizados```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")
    

    Solución de problemas

    Validar primero

    Comience siempre con la validación de credenciales para detectar problemas de autenticación de forma temprana:```bash dop2mop collect --validate --collectors github,sm -v

    root@kitploit:~
    La salida mostrará OK/FAILED por recolector antes de que comience cualquier recolección.
    
    ### Resumen de recolección
    
    Después de cada ejecución, Dop2Mop imprime un resumen que muestra lo que se recolectó y lo que falló:```
    ============================================================
      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
    ============================================================
    

    Problemas Comunes

    "Colector de GitHub no configurado, omitiendo"

    • Asegúrate de que las variables de entorno GITHUB_TOKEN y GITHUB_ORG estén configuradas, o pasa --github-token y --github-org

    "Colector de Azure ML no configurado, omitiendo"

    • Asegúrate de que AZURE_SUBSCRIPTION_ID y AZURE_TENANT_ID estén configuradas
    • Ejecuta az login si usas DefaultAzureCredential
    • Alternativamente, pasa --azure-access-token con un token válido de az account get-access-token

    "Colector de SageMaker no configurado, omitiendo"

    • Configura AWS_PROFILE o ambas AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY
    • Asegúrate de que las credenciales tengan permisos de lectura en SageMaker

    La protección de rama devuelve 403

    • La API de GitHub requiere acceso de administrador para leer las reglas de protección de rama
    • Los tokens que no sean de administrador omitirán la recopilación de protección de rama (reportado en el resumen)

    Límite de velocidad (errores 429)

    • Dop2Mop reintenta automáticamente con retroceso exponencial en respuestas de límite de velocidad
    • Para organizaciones grandes, usa --max-items para reducir las llamadas a la API
    • Límites de velocidad de GitHub: 5,000 solicitudes/hora para usuarios autenticados

    Sin resultados en la consola Cypher de BloodHound

    • Asegúrate de que las consultas devuelvan nodos completos (RETURN a, b) no propiedades (RETURN a.name, b.name)
    • La consola Cypher de BloodHound es para visualización de grafos, no datos tabulares
    • Usa Neo4j Browser (localhost:7474) para consultas basadas en propiedades

    Filtrar aristas inferidas vs. recopiladas

    • Las aristas inferidas usan tipos distintos (por ejemplo, InferredCanAssumeRole en lugar de CanAssumeRole)
    • Consulta solo aristas confirmadas: MATCH p=()-[:CanAssumeRole]->() RETURN p
    • Consulta aristas inferidas: MATCH p=()-[:InferredCanAssumeRole]->() RETURN p

    Licencia

    Licencia MIT - Consulta LICENSE para más detalles.

    Descargar herramienta