This commit is contained in:
rookit
2026-05-20 16:12:30 +08:00
parent 0fb5220dcf
commit 5576bdc41b
9 changed files with 14 additions and 183 deletions
-169
View File
@@ -1,169 +0,0 @@
import json
from Lib.baseplaybook import BasePlaybook
from PLUGINS.SIRP.sirpapi import Artifact, Case
from PLUGINS.SIRP.sirpcoremodel import EnrichmentModel, ArtifactModel, ArtifactType, EnrichmentType, EnrichmentProvider
from PLUGINS.SIRP.sirpextramodel import PlaybookJobStatus, PlaybookModel
TI_ENRICHMENT_TYPE = EnrichmentType.THREAT_INTELLIGENCE
TI_PROVIDER = EnrichmentProvider.MOCK_TI_PROVIDER
def _mock_ip_result(value: str) -> dict:
return {
"malicious": True,
"score": 85,
"indicator_type": "ip",
"indicator": value,
"description": "This IP is associated with known malicious activities.",
"source": "MockTIProvider",
"last_seen": "2024-10-01T12:34:56Z",
}
def _mock_hash_result(value: str) -> dict:
return {
"malicious": True,
"score": 90,
"indicator_type": "file",
"indicator": value,
"description": "This file hash is associated with known malware samples.",
"source": "MockTIProvider",
"last_seen": "2024-10-01T12:34:56Z",
}
def _mock_url_result(value: str) -> dict:
return {
"malicious": True,
"score": 80,
"indicator_type": "url",
"indicator": value,
"description": "This URL is associated with suspicious or malicious activity.",
"source": "MockTIProvider",
"last_seen": "2024-10-01T12:34:56Z",
}
MOCK_QUERY_HANDLERS = {
ArtifactType.IP_ADDRESS: _mock_ip_result,
ArtifactType.HASH: _mock_hash_result,
ArtifactType.URL_STRING: _mock_url_result,
ArtifactType.UNIFORM_RESOURCE_LOCATOR: _mock_url_result,
}
class Playbook(BasePlaybook):
NAME = "TI Enrichment (Mock)"
DESC = "Simulate threat intelligence enrichment. This playbook is for testing and demonstration purposes only. It does not perform real threat intelligence queries."
def __init__(self):
super().__init__() # do not delete this code
@staticmethod
def _normalize_artifact_type(artifact_type):
if isinstance(artifact_type, ArtifactType):
return artifact_type
try:
return ArtifactType(artifact_type)
except ValueError:
return artifact_type
def _query_ti(self, artifact) -> dict:
artifact_type = self._normalize_artifact_type(artifact.type)
handler = MOCK_QUERY_HANDLERS.get(artifact_type)
if not handler:
return {
"error": "Unsupported type.",
"artifact_type": str(artifact.type),
"supported_types": [artifact_type.value for artifact_type in MOCK_QUERY_HANDLERS],
}
return handler(artifact.value or "")
@staticmethod
def _update_artifact_enrichment(artifact, ti_result: dict):
enrichments = artifact.enrichments or []
for enrichment in enrichments:
if enrichment.type == TI_ENRICHMENT_TYPE and enrichment.provider == TI_PROVIDER:
enrichment.data = json.dumps(ti_result)
break
else:
enrichment = EnrichmentModel(
name="Mock TI Enrichment",
type=TI_ENRICHMENT_TYPE,
provider=TI_PROVIDER,
value=artifact.value,
data=json.dumps(ti_result),
)
enrichments.append(enrichment)
model_tmp = ArtifactModel(row_id=artifact.row_id, enrichments=enrichments)
Artifact.update(model_tmp)
@staticmethod
def _collect_unique_artifacts(case):
artifacts = {}
artifact_refs = 0
for alert in case.alerts or []:
for artifact in alert.artifacts or []:
artifact_refs += 1
if artifact and artifact.row_id and artifact.row_id not in artifacts:
artifacts[artifact.row_id] = artifact
return artifact_refs, artifacts
def run(self):
try:
case_row_id = self.param_source_row_id
case = Case.get(case_row_id, lazy_load=False)
if not case:
message = f"Case not found. row_id: {case_row_id}"
self.logger.error(message)
self.update_playbook_status(PlaybookJobStatus.FAILED, message)
return
artifact_refs, artifacts = self._collect_unique_artifacts(case)
stats = {
"alerts": len(case.alerts or []),
"artifacts": artifact_refs,
"unique": len(artifacts),
"enriched": 0,
"unsupported": 0,
"errors": 0,
}
for artifact in artifacts.values():
try:
self.logger.info(f"Mock threat intelligence enrichment for artifact: {artifact}")
ti_result = self._query_ti(artifact)
if ti_result.get("error") == "Unsupported type.":
stats["unsupported"] += 1
self._update_artifact_enrichment(artifact, ti_result)
stats["enriched"] += 1
except Exception as e:
stats["errors"] += 1
self.logger.exception(
f"Error during mock TI enrichment for artifact row_id={artifact.row_id}, "
f"type={artifact.type}, value={artifact.value}: {e}"
)
message = (
"Mock threat intelligence enrichment completed. "
f"alerts={stats['alerts']}, artifacts={stats['artifacts']}, unique={stats['unique']}, "
f"enriched={stats['enriched']}, unsupported={stats['unsupported']}, errors={stats['errors']}"
)
self.update_playbook_status(PlaybookJobStatus.SUCCESS, message)
except Exception as e:
self.logger.exception(e)
self.update_playbook_status(PlaybookJobStatus.FAILED, f"Error during mock TI enrichment: {e}")
return
if __name__ == "__main__":
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ASP.settings")
django.setup()
model = PlaybookModel(source_row_id='44958bcb-31ab-4fdf-85e7-60e02f9677f2')
module = Playbook()
module._playbook_model = model
module.run()
@@ -4,15 +4,15 @@ from Lib.baseplaybook import BasePlaybook
from PLUGINS.SIRP.sirpapi import Artifact, Case
from PLUGINS.SIRP.sirpcoremodel import EnrichmentModel, ArtifactModel, EnrichmentType, EnrichmentProvider
from PLUGINS.SIRP.sirpextramodel import PlaybookJobStatus, PlaybookModel
from PLUGINS.TI.tools import TIToolKit
from PLUGINS.ThreatIntelligence.tools import TIToolKit
TI_ENRICHMENT_TYPE = EnrichmentType.THREAT_INTELLIGENCE
TI_PROVIDER = EnrichmentProvider.ALIENVAULT_OTX
class Playbook(BasePlaybook):
NAME = "TI Enrichment (AlienVaultOTX)"
DESC = "TI Enrichment By AlienVaultOTX"
NAME = "Threat Intelligence Enrichment"
DESC = "Threat Intelligence Enrichment"
def __init__(self):
super().__init__() # do not delete this code
@@ -32,7 +32,7 @@ class Playbook(BasePlaybook):
break
else:
enrichment = EnrichmentModel(
name="TI Enrichment",
name="Threat Intelligence",
type=TI_ENRICHMENT_TYPE,
provider=TI_PROVIDER,
value=artifact.value,
@@ -1,6 +1,6 @@
---
name: asp-ti-en
description: 'Query threat intelligence for IOCs (IP, hash, URL, domain). Use when users want to check an indicator against TI providers, assess risk level, or gather threat context.'
name: asp-threat-intelligence-en
description: 'Query threat intelligence for IOCs (IP, hash, URL, domain). Use when users want to check an indicator against ThreatIntelligence providers, assess risk level, or gather threat context.'
argument-hint: 'query ti <indicator> | query ti <indicator> from <provider>'
compatibility: connect to asp mcp server
metadata:
@@ -1,5 +1,5 @@
---
name: asp-ti-zh
name: asp-threat-intelligence-zh
description: '查询 IOCIP、哈希、URL、域名)的威胁情报。当用户要检查某个指标是否恶意、评估风险等级或收集威胁上下文时使用。'
argument-hint: 'query ti <indicator> | query ti <indicator> from <provider>'
compatibility: connect to asp mcp server
+5 -5
View File
@@ -9,8 +9,8 @@ from PLUGINS.Redis.redis_stream_api import RedisStreamAPI
from PLUGINS.SIEM.models import AdaptiveQueryInput, KeywordSearchInput, SchemaExplorerInput, KeywordSearchOutput, IndexInfo, SchemaIndexSummary, \
DiscoverIndexFieldsInput, DiscoverIndexFieldsOutput
from PLUGINS.SIEM.tools import SIEMToolKit
from PLUGINS.TI.models import TIQueryOutput
from PLUGINS.TI.tools import TIToolKit
from PLUGINS.ThreatIntelligence.models import TIQueryOutput
from PLUGINS.ThreatIntelligence.tools import TIToolKit
from PLUGINS.SIRP.nocolymodel import Group, Condition, Operator
from PLUGINS.SIRP.sirpapi import Alert, Artifact, Case, Enrichment, Knowledge, Playbook
from PLUGINS.SIRP.sirpbasemodel import AI_PROFILE_MCP
@@ -377,12 +377,12 @@ def get_current_time() -> Annotated[str, Field(description="Current local time s
return datetime.now(timezone.utc).isoformat(timespec='seconds').replace('+00:00', 'Z')
# TI
# ThreatIntelligence
def ti_query(
indicator: Annotated[str, Field(
description="Indicator to look up: IP address, file hash, URL, or domain (待查询的指标: IP地址、文件哈希、URL 或域名)")],
provider: Annotated[Optional[str], Field(
description="Specific TI provider name, e.g. 'AlienVault OTX'; None queries all providers (指定 TI 提供商名称,None 表示查询所有提供商)")] = None,
description="Specific ThreatIntelligence provider name, e.g. 'AlienVault OTX'; None queries all providers (指定 ThreatIntelligence 提供商名称,None 表示查询所有提供商)")] = None,
) -> Annotated[TIQueryOutput, Field(
description="Aggregated threat intelligence results from one or more providers (来自一个或多个提供商的聚合威胁情报结果)")]:
"""Query threat intelligence providers for an indicator and return aggregated results. (查询指标的威胁情报,返回聚合结果)"""
@@ -420,7 +420,7 @@ REGISTERED_MCP_TOOLS = [
siem_keyword_search,
siem_discover_index_fields,
# TI
# ThreatIntelligence
ti_query,
# redis stream
+1 -1
View File
@@ -430,7 +430,7 @@ class ProductCategory(StrEnum):
OT = "OT"
PROXY = "Proxy"
UEBA = "UEBA"
TI = "TI"
TI = "ThreatIntelligence"
IAM = "IAM"
EDR = "EDR"
NDR = "NDR"
@@ -73,7 +73,7 @@ class TIToolKit:
@staticmethod
def list_providers() -> List[str]:
"""Return names of all registered TI providers."""
"""Return names of all registered ThreatIntelligence providers."""
return list(PROVIDERS.keys())
@staticmethod