### Plugin Contribution Structure Example Source: https://github.com/yeti-platform/yeti/blob/main/contrib/README.md Illustrates the recommended directory structure for contributing plugins to Yeti. This includes placement for the main Python code, configuration files, dependency lists, and README documentation. ```text contrib ├── README.md └── feeds # Could also be "analytics", create it if you must. └── my_feed # Your main contribution directory. Your code goes in here. ├── my_feed.py # 1. The core of your contribution! ├── config.txt # 2. Any extra configuration sections that need to go in the config file. ├── requirements.txt # 3. Any additional python library your code uses. └── README.md # Please provide a descirption & explanation on how to install your plugin. ``` -------------------------------- ### Using the Yeti Python Client for Database Operations Source: https://context7.com/yeti-platform/yeti/llms.txt Illustrates direct database interaction using the Yeti Python client library. Examples include creating and tagging observables, creating entities, linking them via relationships, performing searches, adding context to observables, finding related entities (neighbors), and matching observables against regex indicators. ```python from core.schemas import observable, entity, indicator from core.schemas.observables import hostname, ipv4 from core.schemas.entity import Malware, ThreatActor # Create observable host = hostname.Hostname(value="evil.com").save() host.tag(["apt29", "c2"]) # Create entity malware = Malware( name="Emotet", description="Banking trojan", malware_types=["trojan"] ).save() # Link them relationship = host.link_to(malware, "indicates", "C2 domain") # Search results, total = observable.Observable.filter( query_args={"tags": ["apt29"]}, count=100 ) # Add context host.add_context({ "source": "sandbox", "verdict": "malicious" }) # Find neighbors vertices, paths, total = host.neighbors( link_types=["indicates"], target_types=["malware"], hops=2 ) # Match observables against regex indicators matches = [] for obs_str, indi in indicator.Regex.search(["192.168.1.1", "evil.com"]): matches.append((obs_str, indi)) print(matches) ``` -------------------------------- ### Tagging Observables, Entities, and Indicators with Yeti API Source: https://context7.com/yeti-platform/yeti/llms.txt Demonstrates how to tag observables, entities, and indicators using the Yeti API. It shows both adding tags and replacing all existing tags using the 'strict' parameter. The examples include making POST requests to specific API endpoints and processing the JSON response. ```python import requests api_url = "YOUR_API_URL" headers = {"Authorization": "Bearer YOUR_API_KEY"} # Tag observables r = requests.post( f"{api_url}/observables/tag", headers=headers, json={ "ids": ["observable1_id", "observable2_id", "observable3_id"], "tags": ["apt29", "campaign_ghost", "high_confidence"], "strict": False # False = add tags, True = replace all tags } ) result = r.json() print(f"Tagged {result['tagged']} observables") for obs_id, tags in result['tags'].items(): print(f" {obs_id}: {list(tags.keys())}") # Tag entities r = requests.post( f"{api_url}/entities/tag", headers=headers, json={ "ids": ["entity1_id", "entity2_id"], "tags": ["russia", "state_sponsored"], "strict": False } ) # Tag indicators (strict mode - replace all tags) r = requests.post( f"{api_url}/indicators/tag", headers=headers, json={ "ids": ["indicator_id"], "tags": ["production", "validated"], "strict": True # Replace all existing tags } ) # Search by tags r = requests.post( f"{api_url}/observables/search", headers=headers, json={ "query": { "tags": ["apt29", "emotet"] # Observables with both tags }, "count": 100 } ) print(r.json()) ``` -------------------------------- ### User and RBAC Management with Yeti API Source: https://context7.com/yeti-platform/yeti/llms.txt Provides examples for managing users, groups, and role-based access control (RBAC) via the Yeti API. It covers creating users and groups, setting Access Control Lists (ACLs) on objects, retrieving ACLs, and searching for users. Requires admin privileges for some operations. ```python import requests api_url = "YOUR_API_URL" headers = {"Authorization": "Bearer YOUR_API_KEY"} admin_headers = {"Authorization": "Bearer YOUR_ADMIN_API_KEY"} # Create user (admin only) r = requests.post( f"{api_url}/users/", headers=admin_headers, json={ "username": "analyst_john", "password": "secure_password_123", "admin": False, "enabled": True } ) user = r.json() # Create group r = requests.post( f"{api_url}/groups/", headers=admin_headers, json={ "name": "security_analysts", "description": "Security analysts team", "users": ["analyst_john", "analyst_mary"] } ) group = r.json() # Set ACL on object (grant permissions) r = requests.post( f"{api_url}/rbac/acl", headers=headers, json={ "object_id": f"malware/{malware['id']}", "permissions": { "user:analyst_john": ["read", "write"], "group:security_analysts": ["read"] } } ) # Get object ACLs r = requests.get( f"{api_url}/rbac/acl", headers=headers, params={"object_id": f"malware/{malware['id']}"} ) acls = r.json() # Search users r = requests.post( f"{api_url}/users/search", headers=admin_headers, json={ "query": {"enabled": True}, "count": 50 } ) print(r.json()) ``` -------------------------------- ### Create Observable API Source: https://context7.com/yeti-platform/yeti/llms.txt Allows adding new observables (IOCs) to the database. Supports both simple observable creation and extended properties for file types. ```APIDOC ## POST /api/v2/observables/ ### Description Adds a new observable (IOC) to the database. The type is automatically detected based on the value, or can be explicitly specified. ### Method POST ### Endpoint /api/v2/observables/ ### Parameters #### Request Body - **value** (string) - Required - The value of the observable (e.g., an IP address, domain name). - **type** (string) - Optional - The type of the observable (e.g., hostname, ipv4, sha256). If not provided, Yeti will attempt to detect it. - **tags** (array of strings) - Optional - A list of tags to associate with the observable. ### Request Example ```json { "value": "malicious.example.com", "type": "hostname", "tags": ["apt29", "malware:emotet"] } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the created observable. - **type** (string) - The type of the observable. - **value** (string) - The value of the observable. #### Response Example ```json { "id": "observable--8e2e2d2b-17d4-4cbf-938f-98ee407b0000", "type": "hostname", "value": "malicious.example.com" } ``` ## POST /api/v2/observables/extended ### Description Adds a new observable with extended properties, typically used for file-related observables that require more details like size, hashes, and MIME type. ### Method POST ### Endpoint /api/v2/observables/extended ### Parameters #### Request Body - **observable** (object) - Required - An object containing the observable details: - **type** (string) - Required - The type of the observable (e.g., "file"). - **value** (string) - Required - The value of the observable (e.g., filename). - **name** (string) - Optional - The name of the file. - **size** (integer) - Optional - The size of the file in bytes. - **sha256** (string) - Optional - The SHA256 hash of the file. - **md5** (string) - Optional - The MD5 hash of the file. - **mime_type** (string) - Optional - The MIME type of the file. - **tags** (array of strings) - Optional - A list of tags to associate with the observable. ### Request Example ```json { "observable": { "type": "file", "value": "malware.exe", "name": "malware.exe", "size": 102400, "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "md5": "d41d8cd98f00b204e9800998ecf8427e", "mime_type": "application/x-dosexec" }, "tags": ["emotet", "trojan"] } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the created observable. - **type** (string) - The type of the observable. - **value** (string) - The value of the observable. #### Response Example ```json { "id": "observable--9f1e1c1b-1a2b-4c3d-4e5f-6a7b8c9d0e1f", "type": "file", "value": "malware.exe" } ``` ``` -------------------------------- ### POST /entities/ Source: https://context7.com/yeti-platform/yeti/llms.txt Creates high-level CTI entities like threat actors, malware families, or campaigns. ```APIDOC ## POST /entities/ ### Description Creates high-level CTI entities such as threat actors, malware families, or campaigns. This endpoint supports creating various entity types with associated metadata and tags. ### Method POST ### Endpoint /entities/ ### Parameters #### Request Body - **entity** (object) - Required - The entity object to create. - **type** (string) - Required - The type of the entity (e.g., "threat-actor", "malware", "campaign"). - **name** (string) - Required - The name of the entity. - **aliases** (array of strings) - Optional - Aliases for the entity. - **description** (string) - Optional - A description of the entity. - **first_seen** (string) - Optional - The first seen timestamp (ISO 8601 format). - **last_seen** (string) - Optional - The last seen timestamp (ISO 8601 format). - **kill_chain_phases** (array of strings) - Optional - Applicable for threat actors, lists kill chain phases. - **malware_types** (array of strings) - Optional - Applicable for malware, lists malware types. - **family** (string) - Optional - Applicable for malware, specifies the malware family. - **objective** (string) - Optional - Applicable for campaigns, describes the campaign's objective. - **tags** (array of strings) - Optional - Tags associated with the entity. ### Request Example (Threat Actor) ```json { "entity": { "type": "threat-actor", "name": "APT29", "aliases": ["Cozy Bear", "The Dukes"], "description": "Russian state-sponsored threat group", "first_seen": "2008-01-01T00:00:00Z", "last_seen": "2024-11-01T00:00:00Z", "kill_chain_phases": ["reconnaissance", "weaponization"] }, "tags": ["russia", "state_sponsored"] } ``` ### Request Example (Malware) ```json { "entity": { "type": "malware", "name": "Emotet", "aliases": ["Heodo"], "description": "Banking trojan and malware loader", "malware_types": ["trojan", "loader"], "family": "emotet" }, "tags": ["banking_trojan", "botnet"] } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the created entity. - **entity** (object) - The created entity object. - **tags** (array of strings) - The tags associated with the entity. #### Response Example ```json { "id": "entity_id_123", "entity": { "type": "threat-actor", "name": "APT29", "description": "Russian state-sponsored threat group" }, "tags": ["russia", "state_sponsored"] } ``` ``` -------------------------------- ### Create Regex Indicator Source: https://context7.com/yeti-platform/yeti/llms.txt This snippet illustrates creating a regular expression indicator. It uses a POST request to the /indicators/ endpoint, providing the indicator's type ('regex'), name, the regex pattern itself, location, and diamond model. ```Python # Create regex indicator for matching response = requests.post( f"{api_url}/indicators/", headers=headers, json={ "indicator": { "type": "regex", "name": "Bitcoin_Wallet_Pattern", "pattern": "^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$", "location": "network", "diamond": "infrastructure" } } ) ``` -------------------------------- ### Bulk Import Observables API Source: https://context7.com/yeti-platform/yeti/llms.txt Provides endpoints for importing multiple observables from various sources like plain text, URLs, or files, with automatic type detection. ```APIDOC ## POST /api/v2/observables/import/text ### Description Imports observables from a block of plain text. Yeti will attempt to detect and parse various types of observables present in the text. ### Method POST ### Endpoint /api/v2/observables/import/text ### Parameters #### Request Body - **text** (string) - Required - The text content containing observables. - **tags** (array of strings) - Optional - Tags to apply to all imported observables. ### Request Example ```json { "text": "Found suspicious activity from 192.168.1.100 connecting to malicious.com\nFile hash: d41d8cd98f00b204e9800998ecf8427e\nAlso contacted http://evil.example.org/payload.exe", "tags": ["incident_2024_001", "network_scan"] } ``` ### Response #### Success Response (200) - **added** (array of objects) - List of observables successfully added. - **failed** (array of strings) - List of items that failed to parse or import. #### Response Example ```json { "added": [ {"type": "ipv4", "value": "192.168.1.100"}, {"type": "hostname", "value": "malicious.com"}, {"type": "file", "value": "d41d8cd98f00b204e9800998ecf8427e"}, {"type": "url", "value": "http://evil.example.org/payload.exe"} ], "failed": [] } ``` ## POST /api/v2/observables/import/url ### Description Imports observables by fetching content from a given URL. Assumes the URL points to a resource containing a list of observables (e.g., a threat feed). ### Method POST ### Endpoint /api/v2/observables/import/url ### Parameters #### Request Body - **url** (string) - Required - The URL to fetch observables from. - **tags** (array of strings) - Optional - Tags to apply to all imported observables. ### Request Example ```json { "url": "https://example.com/ioc-feed.txt", "tags": ["external_feed", "daily_import"] } ``` ### Response #### Success Response (200) - **added** (array of objects) - List of observables successfully added. - **failed** (array of strings) - List of items that failed to parse or import. #### Response Example ```json { "added": [ {"type": "ipv4", "value": "1.2.3.4"}, {"type": "sha256", "value": "abcdef123..."} ], "failed": [] } ``` ## POST /api/v2/observables/import/file ### Description Imports observables from a file uploaded by the user. The file content is processed to extract observables. ### Method POST ### Endpoint /api/v2/observables/import/file ### Parameters #### Request Body - **file** (file) - Required - The file containing observables. - **tags** (string, form-encoded) - Optional - Comma-separated string of tags to apply to all imported observables. ### Request Example ``` POST /api/v2/observables/import/file HTTP/1.1 Host: localhost:8080 Authorization: Bearer YOUR_JWT_TOKEN Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; file=iocs.txt ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; tags=manual_import ------WebKitFormBoundary7MA4YWxkTrZu0gW-- ``` ### Response #### Success Response (200) - **added** (array of objects) - List of observables successfully added. - **failed** (array of strings) - List of items that failed to parse or import. #### Response Example ```json { "added": [ {"type": "hostname", "value": "compromised.net"} ], "failed": [] } ``` ``` -------------------------------- ### Create Malware Entity Source: https://context7.com/yeti-platform/yeti/llms.txt This snippet shows how to create a CTI entity for a malware family. It uses a POST request to the /entities/ endpoint with a JSON payload including the malware's type, name, aliases, description, malware types, and family. ```Python # Create malware entity response = requests.post( f"{api_url}/entities/", headers=headers, json={ "entity": { "type": "malware", "name": "Emotet", "aliases": ["Heodo"], "description": "Banking trojan and malware loader", "malware_types": ["trojan", "loader"], "family": "emotet" }, "tags": ["banking_trojan", "botnet"] } ) malware = response.json() ``` -------------------------------- ### POST /indicators/yara/bundle Source: https://context7.com/yeti-platform/yeti/llms.txt Generates a consolidated YARA rule bundle from multiple indicators. ```APIDOC ## POST /indicators/yara/bundle ### Description Generates a consolidated YARA rule bundle by combining multiple YARA indicators. This is useful for creating a single set of rules for scanning purposes. You can filter indicators by IDs or tags. ### Method POST ### Endpoint /indicators/yara/bundle ### Parameters #### Request Body - **ids** (array of strings) - Optional - A list of indicator IDs to include in the bundle. - **tags** (array of strings) - Optional - A list of tags to filter indicators for inclusion in the bundle. - **exclude_tags** (array of strings) - Optional - A list of tags to exclude indicators from the bundle. - **overlays** (set) - Optional - Not typically used in direct API calls, relates to rule overlaying. ### Request Example (by IDs) ```json { "ids": ["yara_id_1", "yara_id_2", "yara_id_3"], "exclude_tags": ["test", "disabled"], "overlays": set() } ``` ### Request Example (by Tags) ```json { "tags": ["apt29", "emotet"], "exclude_tags": ["false_positive"] } ``` ### Response #### Success Response (200) - **bundle** (string) - The generated YARA rule bundle as a single string. #### Response Example ```json { "bundle": "rule rule1 { ... }\nrule rule2 { ... }" } ``` ``` -------------------------------- ### Batch Analysis API Source: https://context7.com/yeti-platform/yeti/llms.txt This API allows for the batch analysis of multiple observables. It can match observables against known indicators, fetch related entities and observables, and automatically create unknown observables. ```APIDOC ## POST /graph/match ### Description Analyzes a list of observables, matches them against indicators, and retrieves related entities and observables. ### Method POST ### Endpoint /graph/match ### Parameters #### Request Body - **observables** (array of strings) - Required - A list of observables to analyze. - **add_tags** (array of strings) - Optional - Tags to add to any newly created entities or relationships during the analysis. - **regex_match** (boolean) - Optional - Whether to perform regular expression matching against indicators. Defaults to false. - **fetch_neighbors** (boolean) - Optional - Whether to fetch neighbors (related entities/observables) for matched observables. Defaults to false. - **add_unknown** (boolean) - Optional - Whether to automatically create entries for unknown observables. Defaults to false. ### Request Example ```json { "observables": [ "192.168.1.100", "malicious.example.com", "d41d8cd98f00b204e9800998ecf8427e" ], "add_tags": ["batch_analysis", "incident_001"], "regex_match": false, "fetch_neighbors": true, "add_unknown": true } ``` ### Response #### Success Response (200) - **known** (array of objects) - A list of known observables found. - **unknown** (array of strings) - A list of observables that were not recognized. - **matches** (array of arrays) - A list of indicator matches, where each item is a pair of [observable_string, indicator_object]. - **entities** (array of arrays) - A list of related entities, where each item is a pair of [relationship_object, entity_object]. - **observables** (array of arrays) - A list of related observables, where each item is a pair of [relationship_object, observable_object]. #### Response Example ```json { "known": [ { "type": "ip", "value": "192.168.1.100" } ], "unknown": [ "malicious.example.com" ], "matches": [ [ "d41d8cd98f00b204e9800998ecf8427e", { "name": "MD5 of known malicious file" } ] ], "entities": [ [ { "type": "indicates" }, { "type": "malware", "name": "Emotet" } ] ], "observables": [ [ { "type": "resolves_to" }, { "type": "domain", "value": "malicious.example.com" } ] ] } ``` ``` -------------------------------- ### POST /indicators/ Source: https://context7.com/yeti-platform/yeti/llms.txt Creates detection indicators including YARA rules, Sigma rules, and forensic artifacts. ```APIDOC ## POST /indicators/ ### Description Creates detection indicators such as YARA rules, Sigma rules, or regular expression patterns. This endpoint allows for the categorization and storage of threat detection logic. ### Method POST ### Endpoint /indicators/ ### Parameters #### Request Body - **indicator** (object) - Required - The indicator object to create. - **type** (string) - Required - The type of indicator (e.g., "yara", "sigma", "regex"). - **name** (string) - Required - The name of the indicator. - **pattern** (string) - Required - The actual rule or pattern content (e.g., YARA rule string, Sigma rule string, regex pattern). - **location** (string) - Optional - The intended location for the indicator (e.g., "memory", "endpoint", "network"). - **diamond** (string) - Optional - The diamond model category (e.g., "capability", "infrastructure"). ### Request Example (YARA Rule) ```json { "indicator": { "type": "yara", "name": "Emotet_Loader", "pattern": "rule Emotet_Loader { meta: description = \"Detects Emotet malware loader\" strings: $s1 = \"C:\\ProgramData\\emotet\" condition: $s1 }", "location": "memory", "diamond": "capability" } } ``` ### Request Example (Sigma Rule) ```json { "indicator": { "type": "sigma", "name": "Suspicious_PowerShell", "pattern": "title: Suspicious PowerShell Execution status: experimental description: Detects suspicious PowerShell command execution logsource: product: windows service: powershell detection: selection: EventID: 4104 ScriptBlockText|contains: - \'Invoke-Expression\' - \'DownloadString\' condition: selection", "location": "endpoint", "diamond": "capability" } } ``` ### Request Example (Regex Indicator) ```json { "indicator": { "type": "regex", "name": "Bitcoin_Wallet_Pattern", "pattern": "^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$", "location": "network", "diamond": "infrastructure" } } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the created indicator. - **indicator** (object) - The created indicator object. #### Response Example ```json { "id": "indicator_id_456", "indicator": { "type": "yara", "name": "Emotet_Loader", "pattern": "rule Emotet_Loader { ... }", "location": "memory", "diamond": "capability" } } ``` ``` -------------------------------- ### Bulk Import Observables with Python Source: https://context7.com/yeti-platform/yeti/llms.txt Shows how to import multiple observables into Yeti from various sources like plain text, URLs, or files using the Python requests library. Supports adding tags to imported observables. Requires API authentication. ```python # Import from text containing multiple IOCs text_with_iocs = """ Found suspicious activity from 192.168.1.100 connecting to malicious.com File hash: d41d8cd98f00b204e9800998ecf8427e Also contacted http://evil.example.org/payload.exe """ response = requests.post( f"{api_url}/observables/import/text", headers=headers, json={ "text": text_with_iocs, "tags": ["incident_2024_001", "network_scan"] } ) result = response.json() print(f"Added {len(result['added'])} observables") for obs in result['added']: print(f" - {obs['type']}: {obs['value']}") print(f"Failed to parse: {result['failed']}") # Import from URL (threat feed) response = requests.post( f"{api_url}/observables/import/url", headers=headers, json={ "url": "https://example.com/ioc-feed.txt", "tags": ["external_feed", "daily_import"] } ) # Import from file with open("iocs.txt", "rb") as f: response = requests.post( f"{api_url}/observables/import/file", headers=headers, files={"file": f}, data={"tags": ["manual_import"]} ) ``` -------------------------------- ### Task Management API Source: https://context7.com/yeti-platform/yeti/llms.txt Endpoints for scheduling, searching, and managing asynchronous tasks. ```APIDOC ## Task Management Schedule and manage asynchronous tasks for feeds, analytics, and data exports. ### Method: POST ### Endpoint: /tasks/{task_name}/run ### Description: Run a specific task immediately. Task parameters can be provided in the request body. ### Method: POST ### Endpoint: /tasks/search ### Description: Search for tasks based on various criteria. Returns a list of matching tasks. ### Parameters #### Request Body - **query** (object) - Required - Search query object. - **sorting** (array) - Optional - Array of sorting parameters. - **count** (integer) - Optional - Number of results per page. - **page** (integer) - Optional - Page number for pagination. ### Method: POST ### Endpoint: /tasks/{task_name}/toggle ### Description: Toggle the enabled status of a specific task. ### Method: POST ### Endpoint: /tasks/export/new ### Description: Create a new export task with specified configuration. ### Parameters #### Request Body - **export** (object) - Required - Configuration for the export task. - **name** (string) - Required - Name of the export task. - **template_name** (string) - Required - Name of the export template. - **enabled** (boolean) - Required - Whether the task is enabled. - **frequency** (string) - Required - Frequency of the export (e.g., 'daily'). - **frequency_interval** (integer) - Required - Interval for the frequency. - **include_tags** (array) - Optional - Tags to include in the export. - **exclude_tags** (array) - Optional - Tags to exclude from the export. ### Method: GET ### Endpoint: /tasks/export/{task_id}/content ### Description: Download the content generated by a specific export task. ``` -------------------------------- ### Create Campaign Entity Source: https://context7.com/yeti-platform/yeti/llms.txt This code illustrates the creation of a CTI entity for a threat campaign. It involves a POST request to the /entities/ endpoint, providing details such as the campaign's type, name, description, first seen date, and objective. ```Python # Create campaign entity response = requests.post( f"{api_url}/entities/", headers=headers, json={ "entity": { "type": "campaign", "name": "Operation Ghost", "description": "Targeted phishing campaign against financial sector", "first_seen": "2024-06-01T00:00:00Z", "objective": "Financial theft" }, "tags": ["phishing", "finance"] } ) ``` -------------------------------- ### Authentication API Source: https://context7.com/yeti-platform/yeti/llms.txt Provides endpoints for authenticating users and generating API keys. ```APIDOC ## Authentication Authenticate using username/password, API keys, or OIDC for programmatic access. ### Method: POST ### Endpoint: /auth/token ### Description: Obtain an access token using username and password. ### Method: POST ### Endpoint: /auth/api-token ### Description: Obtain an access token using an API key. ### Method: POST ### Endpoint: /users/{username}/api-key ### Description: Create an API key for a specific user. ### Method: GET ### Endpoint: /auth/me ### Description: Retrieve information about the currently authenticated user. ``` -------------------------------- ### Search Observables by Regex Pattern Source: https://context7.com/yeti-platform/yeti/llms.txt This snippet demonstrates how to search for observables using a regular expression pattern. It sends a POST request to the /observables/search endpoint with a JSON payload specifying the regex query and the desired count. ```Python response = requests.post( f"{api_url}/observables/search", headers=headers, json={ "query": {"value__regex": ".*\.evil\.com$"}, "count": 100 } ) ``` -------------------------------- ### Create Observable with Python Source: https://context7.com/yeti-platform/yeti/llms.txt Demonstrates how to create a new observable in Yeti using the Python requests library. It covers both simple observables with basic properties and extended observables with detailed file attributes. Requires API authentication. ```python import requests # API authentication api_url = "http://localhost:8080/api/v2" headers = {"Authorization": "Bearer YOUR_JWT_TOKEN"} # Create a simple observable response = requests.post( f"{api_url}/observables/", headers=headers, json={ "value": "malicious.example.com", "type": "hostname", "tags": ["apt29", "malware:emotet"] } ) if response.status_code == 200: observable = response.json() print(f"Created observable: {observable['id']}") print(f"Type: {observable['type']}, Value: {observable['value']}") else: print(f"Error: {response.json()['detail']}") # Create observable with extended properties (file example) response = requests.post( f"{api_url}/observables/extended", headers=headers, json={ "observable": { "type": "file", "value": "malware.exe", "name": "malware.exe", "size": 102400, "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "md5": "d41d8cd98f00b204e9800998ecf8427e", "mime_type": "application/x-dosexec" }, "tags": ["emotet", "trojan"] } ) ``` -------------------------------- ### Observables API Source: https://context7.com/yeti-platform/yeti/llms.txt Endpoints for managing and searching observables, including tagging and searching by tags. ```APIDOC ## POST /observables/tag ### Description Adds tags to a list of observables. If 'strict' is true, it replaces all existing tags. If false, it adds to existing tags. ### Method POST ### Endpoint /observables/tag ### Parameters #### Request Body - **ids** (array[string]) - Required - List of observable IDs to tag. - **tags** (array[string]) - Required - List of tags to add or replace. - **strict** (boolean) - Optional - If true, replaces all existing tags; if false, adds to existing tags. Defaults to false. ### Request Example ```json { "ids": ["observable1_id", "observable2_id", "observable3_id"], "tags": ["apt29", "campaign_ghost", "high_confidence"], "strict": false } ``` ### Response #### Success Response (200) - **tagged** (integer) - Number of observables that were tagged. - **tags** (object) - A dictionary where keys are observable IDs and values are dictionaries of their updated tags. #### Response Example ```json { "tagged": 3, "tags": { "observable1_id": {"apt29": {}, "campaign_ghost": {}, "high_confidence": {}}, "observable2_id": {"apt29": {}, "campaign_ghost": {}, "high_confidence": {}}, "observable3_id": {"apt29": {}, "campaign_ghost": {}, "high_confidence": {}} } } ``` ``` ```APIDOC ## POST /observables/search ### Description Searches for observables based on provided query criteria, such as tags. ### Method POST ### Endpoint /observables/search ### Parameters #### Request Body - **query** (object) - Required - The search query criteria. - **tags** (array[string]) - Optional - List of tags to search for. Observables must have all specified tags. - **count** (integer) - Optional - The maximum number of results to return. Defaults to 100. ### Request Example ```json { "query": { "tags": ["apt29", "emotet"] }, "count": 100 } ``` ### Response #### Success Response (200) - **results** (array) - A list of matching observables. - **total** (integer) - The total number of matching observables found. #### Response Example ```json { "results": [ { "id": "obs_123", "value": "evil.com", "tags": ["apt29", "emotet"] } ], "total": 1 } ``` ``` -------------------------------- ### Batch Analyze Observables in Yeti (Python) Source: https://context7.com/yeti-platform/yeti/llms.txt Demonstrates batch analysis of a list of observables using the Yeti API. This includes matching observables against indicators, fetching related entities and observables, and automatically creating unknown observables. It processes results for known, unknown, indicator matches, and related entities/observables. ```python import requests api_url = "YOUR_API_URL" headers = {"Authorization": "Bearer YOUR_API_KEY"} observables_to_check = [ "192.168.1.100", "malicious.example.com", "evil.org", "d41d8cd98f00b204e9800998ecf8427e" ] response = requests.post( f"{api_url}/graph/match", headers=headers, json={ "observables": observables_to_check, "add_tags": ["batch_analysis", "incident_001"], "regex_match": False, "fetch_neighbors": True, "add_unknown": True # Automatically create unknown observables } ) analysis = response.json() # Process known observables print(f"Known observables: {len(analysis['known'])}") for obs in analysis['known']: print(f" {obs['type']}: {obs['value']}") # Process unknown observables print(f"Unknown observables: {len(analysis['unknown'])}") for unknown in analysis['unknown']: print(f" {unknown}") # Process indicator matches (regex patterns) print(f"Indicator matches: {len(analysis['matches'])}") for observable_str, indicator in analysis['matches']: print(f" {observable_str} matched {indicator['name']}") # Process related entities print(f"Related entities: {len(analysis['entities'])}") for relationship, entity in analysis['entities']: print(f" {entity['type']}: {entity['name']} ({relationship['type']})") # Process related observables print(f"Related observables: {len(analysis['observables'])}") for relationship, obs in analysis['observables']: print(f" {obs['type']}: {obs['value']} ({relationship['type']})") ``` -------------------------------- ### Create and Update Relationships in Yeti Graph (Python) Source: https://context7.com/yeti-platform/yeti/llms.txt Demonstrates how to create various types of relationships (IOC to malware, threat actor to malware, indicator to malware) and update existing relationships using the Yeti Platform API. It utilizes the `requests` library for HTTP POST and PATCH requests. ```python import requests api_url = "YOUR_API_URL" headers = {"Authorization": "Bearer YOUR_API_KEY"} # Placeholder variables (replace with actual data) observable = {"id": "observable_id"} malware = {"id": "malware_id"} threat_actor = {"id": "threat_actor_id"} yara_indicator = {"id": "yara_indicator_id"} # Link observable to entity (IOC to malware) response = requests.post( f"{api_url}/graph/add", headers=headers, json={ "source": f"hostname/{observable['id']}", "target": f"malware/{malware['id']}", "link_type": "indicates", "description": "C2 domain for Emotet campaign" } ) relationship = response.json() # Link entity to entity (threat actor to malware) response = requests.post( f"{api_url}/graph/add", headers=headers, json={ "source": f"threat-actor/{threat_actor['id']}", "target": f"malware/{malware['id']}", "link_type": "uses", "description": "APT29 deploys Emotet as initial access" } ) # Link indicator to malware response = requests.post( f"{api_url}/graph/add", headers=headers, json={ "source": f"yara/{yara_indicator['id']}", "target": f"malware/{malware['id']}", "link_type": "detects", "description": "YARA rule to detect Emotet variants" } ) # Update relationship response = requests.patch( f"{api_url}/graph/{relationship['id']}", headers=headers, json={ "link_type": "indicates", "description": "Updated: Primary C2 domain for Emotet" } ) ``` -------------------------------- ### Create Sigma Rule Indicator Source: https://context7.com/yeti-platform/yeti/llms.txt This code shows how to create a Sigma rule indicator. It defines a Sigma rule as a multi-line string and sends a POST request to the /indicators/ endpoint, specifying the indicator's type, name, pattern, location, and diamond model. ```Python # Create Sigma rule sigma_rule = """ title: Suspicious PowerShell Execution status: experimental description: Detects suspicious PowerShell command execution logsource: product: windows service: powershell detection: selection: EventID: 4104 ScriptBlockText|contains: - 'Invoke-Expression' - 'DownloadString' condition: selection """ response = requests.post( f"{api_url}/indicators/", headers=headers, json={ "indicator": { "type": "sigma", "name": "Suspicious_PowerShell", "pattern": sigma_rule, "location": "endpoint", "diamond": "capability" } } ) ```