Spaces:
Running
Running
File size: 6,345 Bytes
5b76d85 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
"""
MITRE ATT&CK Navigator JSON Schema
"""
from pydantic import BaseModel, Field, validator, StringConstraints
from typing import Optional, Dict, Any, List, Annotated
import re
from datetime import datetime
# カスタム型の定義
TechniqueID = Annotated[str, StringConstraints(pattern=r'^T\d{4}(\.\d{3})?$')]
TacticName = Annotated[str, StringConstraints(pattern=r'^[a-z-]+$')]
HexColor = Annotated[str, StringConstraints(pattern=r'^#[0-9A-Fa-f]{6}$')]
Domain = Annotated[str, StringConstraints(pattern=r'^(enterprise-attack|mobile-attack|ics-attack)$')]
class Technique(BaseModel):
"""Technique model for ATT&CK Navigator"""
techniqueID: TechniqueID = Field(description="The MITRE ATT&CK technique ID (e.g., T1234 or T1234.001)")
tactic: Optional[TacticName] = Field(description="The tactic this technique belongs to (lowercase with hyphens)")
score: Optional[int] = Field(description="Score between 0 and 100", ge=0, le=100)
color: Optional[HexColor] = Field(description="Hex color code (e.g., #FF0000)")
comment: Optional[str] = Field(description="Comment about the technique", max_length=1000)
enabled: Optional[bool] = Field(description="Whether the technique is enabled", default=True)
metadata: Optional[List[Dict[str, str]]] = Field(description="Additional metadata")
links: Optional[List[Dict[str, str]]] = Field(description="Related links")
showSubtechniques: Optional[bool] = Field(description="Whether to show subtechniques", default=True)
@validator('links')
def validate_links(cls, v):
if v is not None:
for link in v:
if not all(k in link for k in ['label', 'url']):
raise ValueError("Each link must have 'label' and 'url' fields")
return v
class VersionInfo(BaseModel):
"""バージョン情報のサブスキーマ"""
attack: str = Field(
...,
description="""ATT&CKのバージョン。ユーザーが指定したバージョンを使用すること。
例: ユーザーが「ATT&CKバージョンは16で」と指定した場合、"16"と設定する。
指定がない場合は、DEFAULT_LAYER_SETTINGSの値を使用する。"""
)
navigator: str = Field(
...,
description="""Navigatorのバージョン。ユーザーが指定したバージョンを使用すること。
指定がない場合は、DEFAULT_LAYER_SETTINGSの値を使用する。"""
)
layer: str = Field(
...,
description="""レイヤーのバージョン。ユーザーが指定したバージョンを使用すること。
指定がない場合は、DEFAULT_LAYER_SETTINGSの値を使用する。"""
)
class AttackLayer(BaseModel):
"""MITRE ATT&CK Navigator Layer"""
name: str = Field(..., description="レイヤーの名前")
description: str = Field(..., description="レイヤーの説明")
domain: Domain = Field(..., description="ATT&CKドメイン")
versions: VersionInfo = Field(..., description="バージョン情報")
filters: Dict[str, Any] = Field(
default_factory=lambda: {
"platforms": [
"Windows",
"Linux",
"macOS",
"Containers",
"IaaS",
"Network"
]
},
description="フィルター設定"
)
sorting: int = Field(default=0, description="ソート順")
layout: Dict[str, Any] = Field(
default_factory=lambda: {
"layout": "side",
"showName": True,
"showID": False,
"showAggregateScores": True,
"countUnscored": True,
"aggregateFunction": "average"
},
description="レイアウト設定"
)
hideDisabled: bool = Field(default=False, description="無効なテクニックを非表示")
techniques: List[Technique] = Field(..., description="テクニックのリスト")
gradient: Dict[str, Any] = Field(
default_factory=lambda: {
"colors": ["#ff6666", "#ffe766", "#8ec843"],
"minValue": 0,
"maxValue": 100
},
description="スコアのグラデーション設定"
)
legendItems: List[Dict[str, Any]] = Field(
default_factory=list,
description="凡例アイテム"
)
showTacticRowBackground: bool = Field(default=False, description="タクティック行の背景を表示")
tacticRowBackground: str = Field(default="#dddddd", description="タクティック行の背景色")
selectTechniquesAcrossTactics: bool = Field(default=True, description="タクティック間でテクニックを選択")
selectSubtechniquesWithParent: bool = Field(default=False, description="サブテクニックを親と共に選択")
selectVisibleTechniques: bool = Field(default=False, description="表示されているテクニックのみを選択")
metadata: List[Dict[str, str]] = Field(
default_factory=lambda: [
{"name": "作成者", "value": "AIアシスタント"},
{"name": "作成日", "value": datetime.now().strftime("%Y-%m-%d")}
],
description="メタデータ"
)
# デフォルトのレイヤー設定
DEFAULT_LAYER_SETTINGS = {
"versions": {
"attack": "16.1",
"navigator": "5.1.0",
"layer": "4.5"
},
"layout": {
"layout": "side",
"showName": True,
"showID": False,
"showAggregateScores": True,
"countUnscored": True,
"aggregateFunction": "average"
},
"gradient": {
"colors": ["#ff6666", "#ffe766", "#8ec843"],
"minValue": 0,
"maxValue": 100
}
}
# プロンプトテンプレート
ATTACK_PROMPT = """
あなたはMITRE ATT&CKフレームワークの専門家です。
以下のシナリオに基づいて、MITRE ATT&CK NavigatorのレイヤーJSONを生成してください。
回答形式:
{format_instructions}
注意:
- 有効なMITRE ATT&CKテクニックIDを使用すること
- 適切なタクティクスを含めること
- スコアは0-100の範囲で設定すること
- 有効な16進数カラーコードを使用すること
- 意味のあるコメントを含めること
- 適切なメタデータを設定すること
""" |