
DevOps에서 MLOps 인프라로 이어지는 공격 경로를 매핑하는 BloodHound용 OpenGraph 수집기로, CI/CD 파이프라인, 서비스 주체 및 ML 플랫폼 리소스를 수집하여 측면 이동 분석을 수행합니다.
BloodHound를 위한 개념 증명 OpenGraph 수집기로, DevOps에서 MLOps 인프라로 이어지는 공격 경로를 매핑합니다.
Brett Hawkins(@h4wkst3r)의 Pipelines of Privilege: Attack Paths from DevOps to MLOps Infrastructure를 기반으로 합니다.
Dop2Mop은 DevOps 및 MLOps 플랫폼에서 데이터를 수집하여 CI/CD 파이프라인에서 기계 학습 훈련 인프라로의 측면 이동을 가능하게 하는 공격 경로를 식별합니다. 시각화 및 분석을 위해 BloodHound와 호환되는 OpenGraph JSON을 출력합니다.
| DevOps 플랫폼 | MLOps 플랫폼 | ID 공급자 |
|---|---|---|
| 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은 연구에서 식별된 다섯 가지 중요한 신뢰 경계를 모델링합니다:
git clone https://github.com/h4wkst3r/dop2mop.git cd dop2mop pip install -r requirements.txt pip install -e .
## 수집되는 정보
각 수집기는 플랫폼별 리소스를 수집하고 그들 사이의 신뢰 경계를 매핑합니다:
| 수집기 | 수집된 리소스 |
|-----------|-------------------|
| **GitHub** | 조직, 리포지토리, 워크플로우, 시크릿, 브랜치 보호 규칙, OIDC 구성, 컨테이너 이미지 참조, S3 버킷 참조 |
| **Azure DevOps** | 조직, 프로젝트, 파이프라인 (YAML), 서비스 연결 (범위 세부 정보 포함), 변수 그룹, 에이전트 풀, 리포지토리 |
| **Azure ML** | 작업 영역, 컴퓨트 클러스터/인스턴스, 데이터 저장소, ML 환경, 등록된 모델, 작업/실험, 온라인 및 배치 엔드포인트 |
| **SageMaker** | 훈련 작업, 모델, 엔드포인트, 도메인, 노트북 인스턴스, IAM 실행 역할 (정책 분석 포함), ECR 리포지토리/이미지, S3 버킷 (ML 관련으로 필터링됨) |
## 빠른 시작
### 데모 데이터 생성
Dop2Mop을 실제로 확인하는 가장 빠른 방법은 연구에서 나온 공격 시나리오를 보여주는 데모 데이터를 생성하는 것입니다:```bash
dop2mop demo -o demo.json
MATCH (n:Group {name: "DOMAIN [email protected]"})
CALL {
WITH n
OPTIONAL MATCH (n)-[:MemberOf]->(g:Group)
RETURN collect(g.name) AS groupMembership
}
CALL {
WITH n
OPTIONAL MATCH (n)-[:AdminTo]->(c:Computer)
RETURN collect(c.name) AS adminTo
}
CALL {
WITH n
OPTIONAL MATCH (n)-[:HasSession]->(c:Computer)
RETURN collect(c.name) AS hasSession
}
RETURN n.name AS groupName, groupMembership, adminTo, hasSession
``````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
매번 실행할 때마다 자격 증명을 전달하는 대신, 설정 파일에 저장할 수 있습니다. 포함된 예제를 복사하여 값을 입력하세요:```bash cp dop2mop.yaml.example dop2mop.yaml
Dop2Mop은 다음 위치를 순서대로 확인합니다:
1. `--config`로 지정된 경로
2. 현재 디렉토리의 `dop2mop.yaml` / `dop2mop.yml` / `.dop2mop.yaml`
3. `~/.dop2mop.yaml`
> **참고:** `dop2mop.yaml`은 실수로 자격 증명을 커밋하는 것을 방지하기 위해 `.gitignore`에 있습니다. 예제 파일(`dop2mop.yaml.example`)은 커밋해도 안전합니다.
모든 옵션과 설명은 [dop2mop.yaml.example](https://github.com/h4wkst3r/dop2mop/blob/HEAD/dop2mop.yaml.example)을 참조하세요.
**우선순위:** CLI 인수 > 구성 파일 > 환경 변수.
### 자격 증명 검증
전체 수집을 실행하기 전에 자격 증명을 테스트하세요:```bash
# Validate all configured collectors
dop2mop collect --validate -v
# Validate specific collectors
dop2mop collect --validate --collectors github,sagemaker -v
이는 각 플랫폼에 대해 경량 API 호출을 수행하여 수집을 시작하기 전에 토큰이 유효한지 확인합니다.
--collectors와 함께 전체 클래스 이름 대신 짧은 이름을 사용할 수 있습니다:
dop2mop collect --collectors GitHubCollector,SageMakerCollector dop2mop collect --collectors github,sagemaker dop2mop collect --collectors gh,sm
---
## CLI 참조
### 명령어 개요```
dop2mop <command> [options]
Commands:
collect Collect data from DevOps/MLOps platforms
demo Generate demo data with attack scenarios
| 옵션 | 설명 |
|---|---|
-v, --verbose | 자세한 출력 활성화 (INFO 수준 로깅) |
--debug | 디버그 출력 활성화 (DEBUG 수준 로깅) |
dop2mop collect구성된 DevOps 및 MLOps 플랫폼에서 데이터를 수집합니다.```bash dop2mop collect [OPTIONS]
#### 일반 옵션
| 옵션 | 설명 |
|--------|-------------|
| `-o, --output FILE` | 출력 파일 경로 (기본값: `dop2mop_output.json`) |
| `--zip` | 출력을 ZIP 파일로 압축 |
| `--config FILE` | YAML/JSON 설정 파일 경로 |
| `--validate` | 수집 전 자격 증명 검증 |
| `--collectors LIST` | 쉼표로 구분된 수집기 또는 별칭 목록 (예: `github,sm`) |
| `--max-items N` | 유형별 최대 수집 항목 수 |
| `--no-secrets` | 비밀/자격 증명 열거 건너뛰기 |
#### GitHub 옵션
| 옵션 | 설명 |
|--------|-------------|
| `--github-token TOKEN` | GitHub 개인 액세스 토큰 |
| `--github-org ORG` | GitHub 조직 이름 |
| `--github-enterprise-url URL` | GitHub Enterprise Server URL |
#### Azure DevOps 옵션
| 옵션 | 설명 |
|--------|-------------|
| `--azure-devops-token TOKEN` | Azure DevOps 개인 액세스 토큰 (PAT) |
| `--azure-devops-access-token TOKEN` | Azure DevOps 액세스 토큰 (Bearer 인증, 선택 사항) |
| `--azure-devops-org ORG` | Azure DevOps 조직 이름 |
#### Azure ML 옵션
| 옵션 | 설명 |
|--------|-------------|
| `--azure-subscription-id ID` | Azure 구독 ID |
| `--azure-tenant-id ID` | Azure AD 테넌트 ID |
| `--azure-client-id ID` | 서비스 주체 클라이언트 ID (선택 사항) |
| `--azure-client-secret SECRET` | 서비스 주체 클라이언트 비밀 (선택 사항) |
| `--azure-access-token TOKEN` | Azure ML 인증용 Azure 액세스 토큰 (선택 사항) |
#### AWS SageMaker 옵션
| 옵션 | 설명 |
|--------|-------------|
| `--aws-access-key-id KEY` | AWS 액세스 키 ID |
| `--aws-secret-access-key SECRET` | AWS 비밀 액세스 키 |
| `--aws-region REGION` | AWS 리전 (기본값: `us-east-1`) |
| `--aws-profile PROFILE` | AWS CLI 프로필 이름 |
#### 사용 가능한 수집기
| 수집기 이름 | 플랫폼 | 필요 자격 증명 |
|----------------|----------|---------------------|
| `GitHubCollector` | GitHub | `--github-token`, `--github-org` |
| `AzureDevOpsCollector` | Azure DevOps | `--azure-devops-token` 또는 `--azure-devops-access-token`, `--azure-devops-org` |
| `AzureMLCollector` | Azure ML | `--azure-subscription-id`, `--azure-tenant-id` |
| `SageMakerCollector` | AWS SageMaker | `--aws-profile` 또는 `--aws-access-key-id` |
---
### `dop2mop demo`
연구에서 제시된 네 가지 공격 시나리오를 보여주는 데모 데이터를 생성합니다.```bash
dop2mop demo [OPTIONS]
| 옵션 | 설명 |
|---|---|
-o, --output FILE | 출력 파일 경로 (기본값: dop2mop_demo.json) |
dop2mop iconsBloodHound 노드 유형에 대한 사용자 지정 아이콘 구성을 생성합니다.```bash dop2mop icons [OPTIONS]
| 옵션 | 설명 |
|--------|-------------|
| `-o, --output FILE` | 출력 파일 경로 (기본값: `dop2mop_icons.json`) |
---
## CLI 사용 예제
### 기본 수집```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
### 다중 플랫폼 컬렉션```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 컬렉션 예제```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
참고: Azure DevOps 인증 우선순위: 액세스 토큰(Bearer) > PAT(Basic). 액세스 토큰은
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
> **참고:** Azure ML 인증 우선순위: 액세스 토큰 > 서비스 주체 > DefaultAzureCredential (az login).
> 액세스 토큰은 `az account get-access-token --resource https://management.azure.com/`을 통해 얻을 수 있습니다.
### 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
---
## 환경 변수
모든 명령줄 옵션은 환경 변수로 설정할 수 있습니다:
| 환경 변수 | CLI 해당 옵션 | 설명 |
|---------------------|----------------|-------------|
| `GITHUB_TOKEN` | `--github-token` | GitHub 개인 액세스 토큰 |
| `GITHUB_ORG` | `--github-org` | GitHub 조직 이름 |
| `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 액세스 토큰 (Bearer) |
| `AZURE_DEVOPS_ORG` | `--azure-devops-org` | Azure DevOps 조직 |
| `AZURE_SUBSCRIPTION_ID` | `--azure-subscription-id` | Azure 구독 ID |
| `AZURE_TENANT_ID` | `--azure-tenant-id` | Azure AD 테넌트 ID |
| `AZURE_CLIENT_ID` | `--azure-client-id` | Azure 서비스 주체 클라이언트 ID |
| `AZURE_CLIENT_SECRET` | `--azure-client-secret` | Azure 서비스 주체 비밀 |
| `AZURE_ACCESS_TOKEN` | `--azure-access-token` | Azure ML용 Azure 액세스 토큰 |
| `AWS_ACCESS_KEY_ID` | `--aws-access-key-id` | AWS 액세스 키 ID |
| `AWS_SECRET_ACCESS_KEY` | `--aws-secret-access-key` | AWS 비밀 액세스 키 |
| `AWS_REGION` | `--aws-region` | AWS 리전 (기본값: us-east-1) |
| `AWS_PROFILE` | `--aws-profile` | AWS CLI 프로필 이름 |
**우선순위:** CLI 인수 > 설정 파일 > 환경 변수.
---
## 노드 유형
### DevOps 노드
| 종류 | 설명 |
|------|-------------|
| `GHOrganization` | GitHub 조직 |
| `GHRepository` | GitHub 저장소 |
| `GHWorkflow` | GitHub Actions 워크플로 |
| `GHSecret` | GitHub Actions 비밀 |
| `ADOOrganization` | Azure DevOps 조직 |
| `ADOProject` | Azure DevOps 프로젝트 |
| `ADOPipeline` | Azure DevOps 파이프라인 |
| `ADOServiceConnection` | Azure DevOps 서비스 연결(NHI) 및 범위 세부 정보 |
| `ADOAgent` | Azure DevOps 에이전트 풀(호스트형 또는 자체 호스트형) |
| `ADOVariableGroup` | Azure DevOps 변수 그룹 |
### MLOps 노드
| 종류 | 설명 |
|------|-------------|
| `AzMLWorkspace` | Azure ML 작업 영역 |
| `AzMLCompute` | Azure ML 컴퓨트 클러스터/인스턴스 |
| `AzMLExperiment` | Azure ML 작업/실험 |
| `AzMLDatastore` | Azure ML 데이터 저장소 |
| `AzMLEnvironment` | Azure ML 환경(컨테이너 정의) |
| `AzMLModel` | Azure ML 등록 모델 |
| `SMDomain` | SageMaker Studio 도메인 |
| `SMTrainingJob` | SageMaker 학습 작업 |
| `SMModel` | SageMaker 모델 |
| `SMEndpoint` | SageMaker 엔드포인트(Azure ML 엔드포인트에도 사용됨) |
| `SMNotebook` | SageMaker 노트북 인스턴스 |
### ID 노드
| 종류 | 설명 |
|------|-------------|
| `ServicePrincipal` | Azure AD 서비스 주체 |
| `IAMRole` | AWS IAM 역할 |
| `OIDCIdentity` | OIDC 페더레이션 ID |
| `ManagedIdentity` | Azure 관리 ID |
### 아티팩트 노드
| 종류 | 설명 |
|------|-------------|
| `ContainerRegistry` | 컨테이너 레지스트리(ECR, ACR) |
| `ContainerImage` | 컨테이너 이미지 |
| `S3Bucket` | AWS S3 버킷 |
| `Dataset` | ML 데이터셋 |
## 엣지 유형
### 공격 경로 엣지
| 종류 | 신뢰 경계 | 설명 |
|------|----------------|-------------|
| `TriggersPipeline` | TB1 | 코드 커밋이 CI/CD를 트리거함 |
| `HasBranchProtection` | TB1 | 저장소에 브랜치 보호 규칙이 있음 |
| `BypassesProtection` | TB1 | 약함/없는 브랜치 보호(악용 가능) |
| `AuthenticatesAs` | TB2 | 파이프라인이 서비스 주체를 사용함 |
| `CanAssumeRole` | TB2 | OIDC ID가 IAM 역할을 수임할 수 있음 |
| `OIDCTrust` | TB2 | 워크플로가 OIDC 페더레이션을 사용함 |
| `UsesServiceConnection` | TB2 | 파이프라인이 ADO 서비스 연결을 사용함 |
| `PullsImage` | TB3 | 학습 작업이 컨테이너 이미지를 가져옴 |
| `CanPoisonImage` | TB3 | 파이프라인이 컨테이너 이미지를 수정할 수 있음 |
| `SubmitsJob` | TB4 | 서비스 주체가 ML 작업을 제출함 |
| `CodeExecution` | TB4 | 작업이 컴퓨트에서 코드를 실행함 |
| `LoadsDataset` | TB5 | 학습 작업이 데이터셋을 로드함 |
| `CanPoisonDataset` | TB5 | 파이프라인이 데이터셋을 수정할 수 있음 |
| `Deserializes` | TB5 | 안전하지 않은 역직렬화 |
### 추론된 엣지
이 엣지는 명시적 API 데이터가 없을 때(예: 비밀에 저장된 역할 ARN) 휴리스틱 분석을 통해 생성됩니다. BloodHound 쿼리에서 필터링할 수 있도록 고유한 엣지 유형을 사용합니다.
| 종류 | 설명 |
|------|-------------|
| `InferredCanAssumeRole` | OIDC ID가 역할을 수임할 수 있을 수 있음(추론) |
| `InferredSubmitsJob` | 워크플로가 OIDC를 통해 학습 작업을 제출할 수 있음(추론) |
| `InferredPullsImage` | 학습 작업이 감염된 컨테이너 이미지를 가져올 수 있음(추론) |
| `InferredLoadsDataset` | 학습 작업이 감염된 데이터셋을 로드할 수 있음(추론) |
### 구조적 엣지
| 종류 | 설명 |
|------|-------------|
| `Contains` | 부모-자식 관계 |
| `MemberOf` | 그룹 멤버십 |
| `HasAccessTo` | 리소스에 액세스할 권한 |
| `HasExecutionRole` | 리소스가 IAM/실행 역할을 사용함 |
| `Owns` | 소유권 관계 |
## 예제 쿼리
포괄적인 쿼리 예제는 [queries/dop2mop_queries.cypher](https://github.com/h4wkst3r/dop2mop/blob/HEAD/queries/dop2mop_queries.cypher)를 참조하세요.
---
## 사용자 정의 아이콘
Dop2Mop에는 [data/custom_icons.json](https://github.com/h4wkst3r/dop2mop/blob/HEAD/data/custom_icons.json)에 BloodHound 사용자 정의 노드 유형을 위한 사전 구성된 아이콘 파일이 포함되어 있습니다.
### BloodHound에 아이콘 업로드하기
#### 옵션 1: API 탐색기 (가장 쉬움)
1. BloodHound CE를 열고 **설정** → **API 탐색기**로 이동합니다.
2. **POST /api/v2/custom-nodes**를 찾습니다.
3. "시도하기"를 클릭합니다.
4. `custom_icons.json`의 내용을 붙여넣습니다.
5. "실행"을 클릭합니다.
#### 옵션 2: HMAC 인증 (자동화에 권장)
먼저 BloodHound에서 API 토큰을 생성합니다:
1. **설정** → **관리** → **사용자 관리**로 이동합니다.
2. 사용자를 클릭 → **토큰 생성**을 클릭합니다.
3. **토큰 ID**와 **토큰 키**를 저장합니다.
그런 다음 이 Python 스크립트를 사용하여 업로드합니다:```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()
BloodHound에 로그인한 상태에서 브라우저의 DevTools Network 탭에서 JWT를 가져오세요:```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")
### 커스텀 그래프 구축```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")
항상 자격 증명 검증부터 시작하여 인증 문제를 조기에 발견하십시오:```bash dop2mop collect --validate --collectors github,sm -v
출력은 수집이 시작되기 전에 각 수집기별로 OK/FAILED를 표시합니다.
### 수집 요약
매 실행 후, Dop2Mop은 수집된 항목과 실패한 항목을 보여주는 요약을 출력합니다:```
============================================================
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 not configured, skipping"
GITHUB_TOKEN 및 GITHUB_ORG 환경 변수가 설정되었는지 확인하거나, --github-token 및 --github-org를 전달하세요."Azure ML collector not configured, skipping"
AZURE_SUBSCRIPTION_ID와 AZURE_TENANT_ID가 설정되었는지 확인하세요.az login을 실행하세요.az account get-access-token에서 얻은 유효한 토큰을 --azure-access-token으로 전달하세요."SageMaker collector not configured, skipping"
AWS_PROFILE 또는 AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY를 모두 설정하세요.Branch protection returns 403
Rate limiting (429 errors)
--max-items를 사용하여 API 호출을 줄이세요.No results in BloodHound Cypher console
RETURN a, b)를 반환하는지 확인하세요(RETURN a.name, b.name 아님).Filtering inferred vs. collected edges
CanAssumeRole 대신 InferredCanAssumeRole).MATCH p=()-[:CanAssumeRole]->() RETURN pMATCH p=()-[:InferredCanAssumeRole]->() RETURN pMIT License - 자세한 내용은 LICENSE를 참조하세요.
| 별칭 | 수집기 |
|---|
github, gh | GitHubCollector |
ado, azuredevops, azure-devops | AzureDevOpsCollector |
azureml, azure-ml | AzureMLCollector |
sagemaker, sm | SageMakerCollector |