diff --git a/LICENSE b/LICENSE index f12f6b4..be8e4da 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 Crowdsec +Copyright (c) 2026 Crowdsec Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index c71f804..2ea145a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # crowdsec_service_api -**crowdsec_service_api** is a Python SDK for the [CrowdSec Service API](https://docs.crowdsec.net/u/service_api/intro/). +**crowdsec_service_api** is a Python SDK for the [CrowdSec Service API](https://docs.crowdsec.net/u/console/service_api/getting_started). This library enables you to manage CrowdSec resources such as blocklists, integrations in your python applications. ## Installation @@ -11,10 +11,11 @@ pip install crowdsec_service_api ## Usage -You can follow this [documentation](https://docs.crowdsec.net/u/service_api/quickstart/blocklists) to see the basic usage of the SDK. +You can follow this [documentation](https://docs.crowdsec.net/u/console/service_api/sdks/python) to see the basic usage of the SDK. ## Documentation -You can access the full usage documentation [here](https://github.com/crowdsecurity/crowdsec-service-api-sdk-python/tree/main/doc). +You can access [the quickstart guide here](https://docs.crowdsec.net/u/console/service_api/quickstart/authentication). +Or you have the full usage documentation [here](https://github.com/crowdsecurity/crowdsec-service-api-sdk-python/tree/main/doc). ## Contributing diff --git a/crowdsec_service_api/__init__.py b/crowdsec_service_api/__init__.py index af6c9a0..7e7da95 100644 --- a/crowdsec_service_api/__init__.py +++ b/crowdsec_service_api/__init__.py @@ -4,23 +4,35 @@ from .services.allowlists import Allowlists from .services.blocklists import Blocklists from .services.integrations import Integrations +from .services.decisions import Decisions from .services.info import Info from .services.metrics import Metrics from .services.hub import Hub from .services.cves import Cves +from .services.vendors import Vendors +from .services.products import Products +from .services.tracker_tags import TrackerTags +from .services.fingerprints import Fingerprints +from .services.tracker_events import TrackerEvents from .http_client import ApiKeyAuth class Server(Enum): - production_server = 'https://admin.api.crowdsec.net/v1/' + production_server = 'https://admin.api.crowdsec.net/v1' __all__ = [ 'Allowlists', 'Blocklists', 'Integrations', + 'Decisions', 'Info', 'Metrics', 'Hub', 'Cves', + 'Vendors', + 'Products', + 'TrackerTags', + 'Fingerprints', + 'TrackerEvents', 'AllowlistCreateRequest', 'AllowlistCreateResponse', 'AllowlistGetItemsResponse', @@ -61,6 +73,7 @@ class Server(Enum): 'BlocklistUpdateRequest', 'BlocklistUsageStats', 'Body_uploadBlocklistContent', + 'CVESubscription', 'ComputedMetrics', 'ComputedSavedMetrics', 'CtiAs', @@ -69,7 +82,16 @@ class Server(Enum): 'CtiCountry', 'CtiIp', 'CtiScenario', + 'DecisionCreateRequest', + 'DecisionCreateResponse', + 'DecisionResponse', + 'DecisionTargetModel', + 'DecisionTargetType', + 'DecisionsGetResponsePage', + 'DecisionsSortBy', + 'DecisionsSortOrder', 'EntityType', + 'FingerprintSubscription', 'GetRemediationMetricsResponse', 'HTTPValidationError', 'InfoResponse', @@ -97,6 +119,7 @@ class Server(Enum): 'Stats', 'SubscriberEntityType', 'ValidationError', + 'VendorSubscription', 'AppsecConfigIndex', 'AppsecRuleIndex', 'CollectionIndex', @@ -106,21 +129,64 @@ class Server(Enum): 'PostoverflowIndex', 'ScenarioIndex', 'VersionDetail', + 'AdjustmentScore', 'AffectedComponent', + 'AllowlistSubscription', 'AttackDetail', 'Behavior', + 'CVEEventOutput', + 'CVEExploitationPhase', + 'CVEResponseBase', + 'CVEsubscription', + 'CWE', 'Classification', 'Classifications', + 'ExploitationPhase', + 'ExploitationPhaseChangeEventItem', + 'ExploitationPhaseChangeEventsResponsePage', + 'FacetBucket', + 'FingerprintEventOutput', + 'FingerprintRuleResponse', + 'FingerprintRuleSummary', + 'FingerprintTimelineItem', 'GetCVEIPsResponsePage', + 'GetCVEProtectRulesResponse', 'GetCVEResponse', + 'GetCVESubscribedIntegrationsResponsePage', + 'GetCVEsResponsePage', + 'GetCVEsSortBy', + 'GetCVEsSortOrder', + 'GetFingerprintIPsResponsePage', + 'GetFingerprintRulesResponsePage', + 'GetFingerprintSubscribedIntegrationsResponsePage', + 'GetVendorIPsResponsePage', + 'GetVendorSubscribedIntegrationsResponsePage', 'History', 'IPItem', + 'IntegrationResponse', + 'IntervalOptions', + 'IpsDetailsStats', 'Location', + 'LookupImpactCVEItem', + 'LookupImpactFingerprintItem', + 'LookupImpactResponsePage', + 'LookupListItemWithStats', + 'LookupListWithStatsResponsePage', 'MitreTechnique', + 'ProtectRule', + 'ProtectRuleTag', 'Reference', 'ScoreBreakdown', 'Scores', + 'SinceOptions', 'SubscribeCVEIntegrationRequest', + 'SubscribeFingerprintIntegrationRequest', + 'SubscribeVendorIntegrationRequest', + 'ThreatContext', + 'TimelineItem', + 'TopProductItem', + 'VendorSortBy', + 'VendorStatsResponse', 'ApiKeyAuth', 'Server', 'Page' diff --git a/crowdsec_service_api/__pycache__/__init__.cpython-311.pyc b/crowdsec_service_api/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..e0de170 Binary files /dev/null and b/crowdsec_service_api/__pycache__/__init__.cpython-311.pyc differ diff --git a/crowdsec_service_api/__pycache__/base_model.cpython-311.pyc b/crowdsec_service_api/__pycache__/base_model.cpython-311.pyc index a8dddcd..9f7b737 100644 Binary files a/crowdsec_service_api/__pycache__/base_model.cpython-311.pyc and b/crowdsec_service_api/__pycache__/base_model.cpython-311.pyc differ diff --git a/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc b/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc index b77e6a7..6e8e83a 100644 Binary files a/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc and b/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc differ diff --git a/crowdsec_service_api/__pycache__/models.cpython-311.pyc b/crowdsec_service_api/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000..c9eae82 Binary files /dev/null and b/crowdsec_service_api/__pycache__/models.cpython-311.pyc differ diff --git a/crowdsec_service_api/base_model.py b/crowdsec_service_api/base_model.py index 411612f..853282f 100644 --- a/crowdsec_service_api/base_model.py +++ b/crowdsec_service_api/base_model.py @@ -1,6 +1,6 @@ from urllib.parse import urlparse -from pydantic import BaseModel, ConfigDict -from typing import Generic, Sequence, Optional, TypeVar +from pydantic import BaseModel, ConfigDict, PrivateAttr, RootModel +from typing import Generic, Sequence, Optional, TypeVar, Any from httpx import Auth from .http_client import HttpClient @@ -9,13 +9,25 @@ class BaseModelSdk(BaseModel): model_config = ConfigDict( extra="ignore", ) + _client: Optional["Service"] = PrivateAttr(default=None) + + def __init__(self, /, _client: "Service" = None, **data): + super().__init__(**data) + self._client = _client + + def next(self, client: "Service" = None) -> Optional["BaseModelSdk"]: + return (client if client is not None else self._client).next_page(self) + + +class RootModelSdk(RootModel): + def __getattr__(self, item: str) -> Any: + return getattr(self.root, item) T = TypeVar("T") class Page(BaseModelSdk, Generic[T]): - _client: "Service" items: Sequence[T] total: Optional[int] page: Optional[int] @@ -23,28 +35,26 @@ class Page(BaseModelSdk, Generic[T]): pages: Optional[int] = None links: Optional[dict] = None - def __init__(self, _client: "Service", **data): - super().__init__(**data) - self._client = _client - - def next(self, client: "Service" = None) -> "Page[T]": - return (client if client is not None else self._client).next_page(self) - class Service: - def __init__(self, base_url: str, auth: Auth) -> None: - self.http_client = HttpClient(base_url=base_url, auth=auth) + def __init__(self, base_url: str, auth: Auth, user_agent: str = None) -> None: + self.http_client = HttpClient( + base_url=base_url, auth=auth, user_agent=user_agent + ) - def next_page(self, page: Page[T]) -> Page[T]: - if not page.links: + def next_page(self, page: BaseModelSdk) -> Optional[BaseModelSdk]: + if not hasattr(page, "links") or not page.links: raise ValueError( "No links found in the response, this is not a paginated response." ) - if page.links.get("next"): + if page.links.next: # links are relative to host not to full base url. We need to pass a full formatted url here parsed_url = urlparse(self.http_client.base_url) response = self.http_client.get( - f"{parsed_url.scheme}://{parsed_url.netloc}{page.links['next']}", path_params=None, params=None, headers=None + f"{parsed_url.scheme}://{parsed_url.netloc}{page.links.next}", + path_params=None, + params=None, + headers=None, ) return page.__class__(_client=self, **response.json()) return None diff --git a/crowdsec_service_api/http_client.py b/crowdsec_service_api/http_client.py index 7fd53a6..63b3f93 100644 --- a/crowdsec_service_api/http_client.py +++ b/crowdsec_service_api/http_client.py @@ -45,11 +45,20 @@ def auth_flow(self, request): class HttpClient: - def __init__(self, base_url: str, auth: httpx.Auth, aws_region="eu-west-1") -> None: + def __init__( + self, + base_url: str, + auth: httpx.Auth, + user_agent: str = None, + aws_region="eu-west-1", + ) -> None: self.aws_region = aws_region self.base_url = base_url self.auth = auth - self.client = httpx.Client() + headers = {"Accept-Encoding": "gzip"} + if user_agent: + headers["User-Agent"] = user_agent + self.client = httpx.Client(headers=headers) self.timeout = 30 def _replace_path_params(self, url: str, path_params: dict): diff --git a/crowdsec_service_api/models.py b/crowdsec_service_api/models.py index 540e50a..7d19408 100644 --- a/crowdsec_service_api/models.py +++ b/crowdsec_service_api/models.py @@ -1,15 +1,16 @@ # generated by datamodel-codegen: # filename: -# timestamp: 2025-12-02T14:56:05+00:00 +# timestamp: 2026-04-14T15:17:48+00:00 from __future__ import annotations -from enum import StrEnum -from typing import Annotated, Dict, List, Optional, Union +from datetime import datetime +from enum import IntEnum, StrEnum +from typing import Annotated, Dict, List, Literal, Optional, Union -from pydantic import AnyUrl, AwareDatetime, ConfigDict, Field, RootModel +from pydantic import AnyUrl, ConfigDict, Field, RootModel -from .base_model import BaseModelSdk +from .base_model import BaseModelSdk, RootModelSdk class AllowlistCreateRequest(BaseModelSdk): @@ -49,11 +50,11 @@ class AllowlistCreateResponse(BaseModelSdk): Field(description='Description of the allowlist', title='Description'), ] = None created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the allowlist was created', title='Created At'), ] updated_at: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist was updated', title='Updated At'), ] = None from_cti_query: Annotated[ @@ -84,7 +85,7 @@ class AllowlistItemUpdateRequest(BaseModelSdk): Field(description='Description of the allowlist entry', title='Description'), ] = None expiration: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist entry will expire', title='Expiration'), ] = None @@ -102,7 +103,7 @@ class AllowlistItemsCreateRequest(BaseModelSdk): Field(description='Description of the allowlist entry', title='Description'), ] expiration: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist entry will expire', title='Expiration'), ] = None @@ -131,7 +132,7 @@ class AllowlistSubscriptionResponse(BaseModelSdk): ] = None -class Name(RootModel[str]): +class Name(RootModelSdk[str]): root: Annotated[ str, Field( @@ -179,7 +180,7 @@ class BlocklistAddIPsRequest(BaseModelSdk): ) ips: Annotated[List[str], Field(description='List of IPs or networks', title='Ips')] expiration: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field( description='Expiration date', examples=['2030-01-01T00:00:00.000Z'], @@ -326,7 +327,7 @@ class BlocklistUsageStats(BaseModelSdk): total_subscribed_organizations: Annotated[ Optional[int], Field(title='Total Subscribed Organizations') ] = 0 - updated_at: Annotated[Optional[AwareDatetime], Field(title='Updated At')] = None + updated_at: Annotated[Optional[datetime], Field(title='Updated At')] = None class BodyUploadBlocklistContent(BaseModelSdk): @@ -335,6 +336,10 @@ class BodyUploadBlocklistContent(BaseModelSdk): ] +class CVESubscription(BaseModelSdk): + id: Annotated[str, Field(description='CVE ID', title='Id')] + + class CtiAs(BaseModelSdk): model_config = ConfigDict( extra='allow', @@ -393,6 +398,28 @@ class CtiScenario(BaseModelSdk): total_ips: Annotated[int, Field(title='Total Ips')] +class DecisionCreateResponse(BaseModelSdk): + uuid: Annotated[ + str, Field(description='UUID of the created decision', title='Uuid') + ] + + +class DecisionTargetType(StrEnum): + ORG = 'org' + TAG = 'tag' + ENTITY = 'entity' + + +class DecisionsSortBy(StrEnum): + CREATED_AT = 'created_at' + EXPIRE_AT = 'expire_at' + + +class DecisionsSortOrder(StrEnum): + ASC = 'asc' + DESC = 'desc' + + class EntityType(StrEnum): ORG = 'org' TAG = 'tag' @@ -403,6 +430,10 @@ class EntityType(StrEnum): LOG_PROCESSOR = 'log_processor' +class FingerprintSubscription(BaseModelSdk): + id: Annotated[str, Field(description='Fingerprint ID', title='Id')] + + class InfoResponse(BaseModelSdk): organization_id: Annotated[ str, Field(description='The organization ID', title='Organization Id') @@ -481,7 +512,7 @@ class RemediationMetricsData(BaseModelSdk): Union[int, float], Field(description='Value of the metric', title='Value') ] timestamp: Annotated[ - AwareDatetime, Field(description='Timestamp of the metric', title='Timestamp') + datetime, Field(description='Timestamp of the metric', title='Timestamp') ] @@ -519,6 +550,10 @@ class ValidationError(BaseModelSdk): type: Annotated[str, Field(title='Error Type')] +class VendorSubscription(BaseModelSdk): + id: Annotated[str, Field(description='Vendor ID', title='Id')] + + class VersionDetail(BaseModelSdk): deprecated: Annotated[ Optional[bool], @@ -537,6 +572,19 @@ class VersionDetail(BaseModelSdk): ] +class AdjustmentScore(BaseModelSdk): + total: Annotated[ + Optional[int], Field(description='Total score adjustment', title='Total') + ] = 0 + recency: Annotated[ + Optional[int], Field(description='Recency score adjustment', title='Recency') + ] = 0 + low_info: Annotated[ + Optional[int], + Field(description='Low information score adjustment', title='Low Info'), + ] = 0 + + class AffectedComponent(BaseModelSdk): vendor: Annotated[ Optional[str], @@ -548,6 +596,10 @@ class AffectedComponent(BaseModelSdk): ] = None +class AllowlistSubscription(BaseModelSdk): + id: Annotated[str, Field(title='Id')] + + class AttackDetail(BaseModelSdk): name: Annotated[str, Field(description='Attack detail name', title='Name')] label: Annotated[str, Field(description='Attack detail label', title='Label')] @@ -568,6 +620,45 @@ class Behavior(BaseModelSdk): ] +class CVEEventOutput(BaseModelSdk): + name: Annotated[str, Field(title='Name')] + date: Annotated[str, Field(title='Date')] + description: Annotated[str, Field(title='Description')] + label: Annotated[str, Field(title='Label')] + sorting_priority: Annotated[int, Field(title='Sorting Priority')] + + +class CVEExploitationPhase(StrEnum): + INSUFFICIENT_DATA = 'insufficient_data' + EARLY_EXPLOITATION = 'early_exploitation' + FRESH_AND_POPULAR = 'fresh_and_popular' + TARGETED_EXPLOITATION = 'targeted_exploitation' + MASS_EXPLOITATION = 'mass_exploitation' + BACKGROUND_NOISE = 'background_noise' + UNPOPULAR = 'unpopular' + WEARING_OUT = 'wearing_out' + UNCLASSIFIED = 'unclassified' + + +class CvssScore(RootModelSdk[float]): + root: Annotated[ + float, + Field(description='CVSS score of the CVE', ge=0.0, le=10.0, title='Cvss Score'), + ] + + +class CVEsubscription(BaseModelSdk): + id: Annotated[str, Field(title='Id')] + + +class CWE(BaseModelSdk): + name: Annotated[str, Field(description='Name of the CWE', title='Name')] + label: Annotated[str, Field(description='Label of the CWE', title='Label')] + description: Annotated[ + str, Field(description='Description of the CWE', title='Description') + ] + + class Classification(BaseModelSdk): name: Annotated[str, Field(description='Classification name', title='Name')] label: Annotated[str, Field(description='Classification label', title='Label')] @@ -587,53 +678,183 @@ class Classifications(BaseModelSdk): ] = None -class GetCVEResponse(BaseModelSdk): - id: Annotated[str, Field(description='ID of the CVE', title='Id')] - name: Annotated[str, Field(description='Name of the CVE', title='Name')] - affected_components: Annotated[ - List[AffectedComponent], - Field(description='List of affected components', title='Affected Components'), +class ExploitationPhase(BaseModelSdk): + name: Annotated[ + str, Field(description='Name of the exploitation phase', title='Name') ] - let_score: Annotated[ - int, Field(description='LET score of the CVE', ge=0, le=10, title='Let Score') + label: Annotated[ + str, Field(description='Label of the exploitation phase', title='Label') ] - first_seen: Annotated[ - AwareDatetime, Field(description='First seen date', title='First Seen') + description: Annotated[ + str, + Field(description='Description of the exploitation phase', title='Description'), ] - last_seen: Annotated[ - AwareDatetime, Field(description='Last seen date', title='Last Seen') + + +class ExploitationPhaseChangeEventItem(BaseModelSdk): + cve_id: Annotated[str, Field(description='CVE identifier', title='Cve Id')] + name: Annotated[str, Field(description='Event type name', title='Name')] + date: Annotated[str, Field(description='Date of the phase change', title='Date')] + label: Annotated[ + str, Field(description='Human-readable event label', title='Label') ] - nb_ips: Annotated[ - int, Field(description='Number of unique IPs affected', ge=0, title='Nb Ips') + description: Annotated[ + str, Field(description='Rendered event description', title='Description') ] - published_date: Annotated[ - AwareDatetime, - Field(description='Published date of the CVE', title='Published Date'), + previous_phase: Annotated[ + str, + Field(description='Previous exploitation phase label', title='Previous Phase'), ] - cvss_score: Annotated[ - float, - Field(description='CVSS score of the CVE', ge=0.0, le=10.0, title='Cvss Score'), + new_phase: Annotated[ + str, Field(description='New exploitation phase label', title='New Phase') ] - references: Annotated[ - List[str], - Field(description='List of references for the CVE', title='References'), + + +class ExploitationPhaseChangeEventsResponsePage(BaseModelSdk): + items: Annotated[List[ExploitationPhaseChangeEventItem], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + +class FacetBucket(BaseModelSdk): + value: Annotated[str, Field(description='Facet value', title='Value')] + count: Annotated[ + int, Field(description='Number of IPs matching this value', ge=0, title='Count') ] - description: Annotated[ - str, Field(description='Description of the CVE', title='Description') + + +class FingerprintEventOutput(BaseModelSdk): + name: Annotated[str, Field(title='Name')] + date: Annotated[str, Field(title='Date')] + description: Annotated[str, Field(title='Description')] + label: Annotated[str, Field(title='Label')] + + +class FingerprintTimelineItem(BaseModelSdk): + timestamp: Annotated[ + datetime, + Field(description='Timestamp of the timeline event', title='Timestamp'), + ] + count: Annotated[ + int, Field(description='Count of occurrences at the timestamp', title='Count') ] +class GetCVEsSortBy(StrEnum): + RULE_RELEASE_DATE = 'rule_release_date' + TRENDING = 'trending' + NB_IPS = 'nb_ips' + NAME = 'name' + FIRST_SEEN = 'first_seen' + + +class GetCVEsSortOrder(StrEnum): + ASC = 'asc' + DESC = 'desc' + + class History(BaseModelSdk): first_seen: Annotated[ - AwareDatetime, Field(description='First seen timestamp', title='First Seen') + datetime, Field(description='First seen timestamp', title='First Seen') ] last_seen: Annotated[ - AwareDatetime, Field(description='Last seen timestamp', title='Last Seen') + datetime, Field(description='Last seen timestamp', title='Last Seen') ] full_age: Annotated[int, Field(description='Full age in days', title='Full Age')] days_age: Annotated[int, Field(description='Days age', title='Days Age')] +class IntegrationResponse(BaseModelSdk): + tags: Annotated[Optional[List[str]], Field(title='Tags')] = [] + organization_id: Annotated[str, Field(title='Organization Id')] + created_at: Annotated[ + Optional[datetime], + Field(description='Time the integration was created', title='Created At'), + ] = None + entity_type: Annotated[EntityType, Field(description='Type of the integration')] + id: Annotated[ + Optional[str], Field(description='ID of the integration', title='Id') + ] = None + blocklists: Annotated[ + Optional[List[BlocklistSubscription]], Field(title='Blocklists') + ] = [] + allowlists: Annotated[ + Optional[List[AllowlistSubscription]], Field(title='Allowlists') + ] = [] + cves: Annotated[Optional[List[CVEsubscription]], Field(title='Cves')] = None + fingerprints: Annotated[ + Optional[List[FingerprintSubscription]], Field(title='Fingerprints') + ] = None + vendors: Annotated[Optional[List[VendorSubscription]], Field(title='Vendors')] = ( + None + ) + name: Annotated[str, Field(description='Name of the integration', title='Name')] + updated_at: Annotated[ + Optional[datetime], + Field(description='Last time the integration was updated', title='Updated At'), + ] = None + description: Annotated[ + Optional[str], + Field(description='Description of the integration', title='Description'), + ] = None + output_format: Annotated[ + OutputFormat, Field(description='Output format of the integration') + ] + last_pull: Annotated[ + Optional[datetime], + Field( + description='Last time the integration pulled blocklists', title='Last Pull' + ), + ] = None + pull_limit: Annotated[ + Optional[int], + Field(description='Maximum number of items to pull', title='Pull Limit'), + ] = None + enable_ip_aggregation: Annotated[ + Optional[bool], + Field( + description='Whether to enable IP aggregation into ranges', + title='Enable Ip Aggregation', + ), + ] = False + + +class IntervalOptions(StrEnum): + HOUR = 'hour' + DAY = 'day' + WEEK = 'week' + + +class IpsDetailsStats(BaseModelSdk): + total: Annotated[ + int, Field(description='Total number of matching IPs', ge=0, title='Total') + ] + reputation: Annotated[ + List[FacetBucket], + Field(description='IP count by reputation', title='Reputation'), + ] + country: Annotated[ + List[FacetBucket], + Field(description='IP count by country (top 5)', title='Country'), + ] + as_name: Annotated[ + List[FacetBucket], + Field(description='IP count by AS name (top 5)', title='As Name'), + ] + cves: Annotated[ + List[FacetBucket], Field(description='IP count by CVE (top 5)', title='Cves') + ] + classifications: Annotated[ + List[FacetBucket], + Field( + description='IP count by classification (top 5)', title='Classifications' + ), + ] + + class Location(BaseModelSdk): country: Annotated[ Optional[str], Field(description='Country code', title='Country') @@ -647,6 +868,53 @@ class Location(BaseModelSdk): ] = None +class LookupListItemWithStats(BaseModelSdk): + value: Annotated[str, Field(description='Lookup entry value', title='Value')] + nb_cves: Annotated[ + Optional[int], Field(description='Number of CVEs', ge=0, title='Nb Cves') + ] = 0 + nb_fingerprints: Annotated[ + Optional[int], + Field(description='Number of fingerprint rules', ge=0, title='Nb Fingerprints'), + ] = 0 + nb_ips: Annotated[ + Optional[int], + Field( + description='Total number of unique IPs targeting this entry', + ge=0, + title='Nb Ips', + ), + ] = 0 + nb_ips_cves: Annotated[ + Optional[int], + Field(description='Number of IPs across CVEs', ge=0, title='Nb Ips Cves'), + ] = 0 + nb_ips_fingerprints: Annotated[ + Optional[int], + Field( + description='Number of IPs across fingerprint rules', + ge=0, + title='Nb Ips Fingerprints', + ), + ] = 0 + latest_rule_release: Annotated[ + Optional[datetime], + Field( + description='Most recent rule release date for this entry', + title='Latest Rule Release', + ), + ] = None + + +class LookupListWithStatsResponsePage(BaseModelSdk): + items: Annotated[List[LookupListItemWithStats], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + class MitreTechnique(BaseModelSdk): name: Annotated[str, Field(description='MITRE technique ID', title='Name')] label: Annotated[str, Field(description='MITRE technique label', title='Label')] @@ -655,6 +923,11 @@ class MitreTechnique(BaseModelSdk): ] +class ProtectRuleTag(BaseModelSdk): + tag: Annotated[str, Field(description='Tag identifier', title='Tag')] + label: Annotated[str, Field(description='Human-readable tag label', title='Label')] + + class Reference(BaseModelSdk): name: Annotated[str, Field(description='Reference name', title='Name')] label: Annotated[str, Field(description='Reference label', title='Label')] @@ -680,6 +953,12 @@ class Scores(BaseModelSdk): last_month: Annotated[ScoreBreakdown, Field(description='Last month scores')] +class SinceOptions(IntEnum): + INTEGER_1 = 1 + INTEGER_7 = 7 + INTEGER_30 = 30 + + class SubscribeCVEIntegrationRequest(BaseModelSdk): model_config = ConfigDict( extra='forbid', @@ -689,6 +968,133 @@ class SubscribeCVEIntegrationRequest(BaseModelSdk): ] +class SubscribeFingerprintIntegrationRequest(BaseModelSdk): + model_config = ConfigDict( + extra='forbid', + ) + name: Annotated[ + str, Field(description='Name of the integration to subscribe', title='Name') + ] + + +class SubscribeVendorIntegrationRequest(BaseModelSdk): + model_config = ConfigDict( + extra='forbid', + ) + name: Annotated[ + str, Field(description='Name of the integration to subscribe', title='Name') + ] + + +class ThreatContext(BaseModelSdk): + attacker_countries: Annotated[ + Optional[Dict[str, int]], + Field( + description='Attacker country distribution (country code → count)', + title='Attacker Countries', + ), + ] = None + defender_countries: Annotated[ + Optional[Dict[str, int]], + Field( + description='Defender country distribution (country code → count)', + title='Defender Countries', + ), + ] = None + industry_types: Annotated[ + Optional[Dict[str, int]], + Field( + description='Industry type distribution (type → count)', + title='Industry Types', + ), + ] = None + industry_risk_profiles: Annotated[ + Optional[Dict[str, int]], + Field( + description='Industry risk profile distribution (profile → count)', + title='Industry Risk Profiles', + ), + ] = None + attacker_objectives: Annotated[ + Optional[Dict[str, int]], + Field( + description='Attacker objective distribution (objective → count)', + title='Attacker Objectives', + ), + ] = None + + +class TimelineItem(BaseModelSdk): + timestamp: Annotated[ + datetime, + Field(description='Timestamp of the timeline event', title='Timestamp'), + ] + count: Annotated[ + int, Field(description='Count of occurrences at the timestamp', title='Count') + ] + + +class TopProductItem(BaseModelSdk): + value: Annotated[str, Field(description='Product name', title='Value')] + nb_ips_cves: Annotated[ + Optional[int], + Field(description='Number of IPs across CVEs', ge=0, title='Nb Ips Cves'), + ] = 0 + nb_ips_fingerprints: Annotated[ + Optional[int], + Field( + description='Number of IPs across fingerprint rules', + ge=0, + title='Nb Ips Fingerprints', + ), + ] = 0 + + +class VendorSortBy(StrEnum): + VALUE = 'value' + NB_CVES = 'nb_cves' + NB_IPS = 'nb_ips' + LATEST_RULE_RELEASE = 'latest_rule_release' + + +class VendorStatsResponse(BaseModelSdk): + value: Annotated[str, Field(description='Vendor name', title='Value')] + nb_cves: Annotated[ + Optional[int], Field(description='Number of CVEs', ge=0, title='Nb Cves') + ] = 0 + nb_fingerprints: Annotated[ + Optional[int], + Field(description='Number of fingerprint rules', ge=0, title='Nb Fingerprints'), + ] = 0 + nb_ips: Annotated[ + Optional[int], + Field( + description='Total number of unique IPs targeting this vendor', + ge=0, + title='Nb Ips', + ), + ] = 0 + nb_ips_cves: Annotated[ + Optional[int], + Field(description='Number of IPs across CVEs', ge=0, title='Nb Ips Cves'), + ] = 0 + nb_ips_fingerprints: Annotated[ + Optional[int], + Field( + description='Number of IPs across fingerprint rules', + ge=0, + title='Nb Ips Fingerprints', + ), + ] = 0 + top_products: Annotated[ + Optional[List[TopProductItem]], + Field( + description='Top products for this vendor sorted by total IPs descending', + title='Top Products', + ), + ] = None + + class AllowlistsListAllowlistsQueryParameters(BaseModelSdk): page: Annotated[ Optional[int], Field(description='Page number', ge=1, title='Page') @@ -871,10 +1277,10 @@ class BlocklistsDeleteBlocklistPathParameters(BaseModelSdk): class BlocklistsUploadBlocklistContentQueryParameters(BaseModelSdk): expiration: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field( description='Blocklist expiration', - examples='2025-12-02T14:55:58.773978+00:00', + examples=['2026-04-13T08:55:24.249164+00:00'], title='Expiration', ), ] = None @@ -998,8 +1404,18 @@ class IntegrationsUpdateIntegrationPathParameters(BaseModelSdk): integration_id: Annotated[str, Field(title='Integration Id')] -class IntegrationsDeleteIntegrationPathParameters(BaseModelSdk): - integration_id: Annotated[str, Field(title='Integration Id')] +class IntegrationsDeleteIntegrationQueryParameters(BaseModelSdk): + force: Annotated[ + Optional[bool], + Field( + description='Force delete the integration even if it has active subscriptions (it will unsubscribe from all lists)', + title='Force', + ), + ] = False + + +class IntegrationsDeleteIntegrationPathParameters(BaseModelSdk): + integration_id: Annotated[str, Field(title='Integration Id')] class IntegrationsHeadIntegrationContentPathParameters(BaseModelSdk): @@ -1008,7 +1424,7 @@ class IntegrationsHeadIntegrationContentPathParameters(BaseModelSdk): ] -class PageSize(RootModel[int]): +class PageSize(RootModelSdk[int]): root: Annotated[ int, Field( @@ -1030,6 +1446,10 @@ class IntegrationsGetIntegrationContentQueryParameters(BaseModelSdk): title='Page Size', ), ] = None + pull_limit: Annotated[Optional[int], Field(title='Pull Limit')] = None + enable_ip_aggregation: Annotated[ + Optional[bool], Field(title='Enable Ip Aggregation') + ] = False class IntegrationsGetIntegrationContentPathParameters(BaseModelSdk): @@ -1054,16 +1474,59 @@ class IntegrationsGetIntegrationContentStreamPathParameters(BaseModelSdk): ] +class DecisionsGetDecisionsQueryParameters(BaseModelSdk): + instance_ids: Annotated[ + Optional[List[str]], + Field(description='Filter decisions by instance IDs', title='Instance Ids'), + ] = [] + tag_ids: Annotated[ + Optional[List[str]], + Field(description='Filter decisions by tag IDs', title='Tag Ids'), + ] = [] + remediation_types: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by remediation types', + title='Remediation Types', + ), + ] = [] + ips: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by IPs (only for IP decisions)', title='Ips' + ), + ] = [] + sort_by: Annotated[ + Optional[DecisionsSortBy], + Field( + description='Field to sort by (e.g., created_at, duration)', title='Sort By' + ), + ] = 'created_at' + sort_order: Annotated[ + Optional[DecisionsSortOrder], + Field( + description="Sort order: 'asc' for ascending, 'desc' for descending", + title='Sort Order', + ), + ] = 'desc' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + class MetricsGetMetricsRemediationQueryParameters(BaseModelSdk): start_date: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field( description='Start date of the metrics, default to last day', title='Start Date', ), ] = None end_date: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='End date of the metrics', title='End Date'), ] = None engine_ids: Annotated[ @@ -1114,28 +1577,454 @@ class HubHeadItemContentPathParameters(BaseModelSdk): tenant: Annotated[str, Field(title='Tenant')] +class CvesGetCvesQueryParameters(BaseModelSdk): + query: Annotated[ + Optional[str], Field(description='Search query for CVEs', title='Query') + ] = None + sort_by: Annotated[ + Optional[GetCVEsSortBy], Field(description='Field to sort by', title='Sort By') + ] = 'rule_release_date' + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: ascending or descending', title='Sort Order'), + ] = 'desc' + exploitation_phase: Annotated[ + Optional[CVEExploitationPhase], + Field(description='Filter by exploitation phase', title='Exploitation Phase'), + ] = None + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + class CvesGetCvePathParameters(BaseModelSdk): cve_id: Annotated[str, Field(title='Cve Id')] -class Since(RootModel[str]): +class CvesGetCveProtectRulesPathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + + +class CvesDownloadCveIpsPathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + + +class Since(RootModelSdk[str]): root: Annotated[ str, Field( - description='Filter IPs seen since this date, format duration (e.g., 7d, 24h)', + description='Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d', pattern='^\\d+[hd]$', title='Since', ), ] -class CvesGetCveIpsQueryParameters(BaseModelSdk): +class CvesGetCveIpsDetailsQueryParameters(BaseModelSdk): + since: Annotated[ + Optional[Since], + Field( + description='Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d', + title='Since', + ), + ] = '14d' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class CvesGetCveIpsDetailsPathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + + +class CvesGetCveIpsDetailsStatsQueryParameters(BaseModelSdk): + since: Annotated[ + Optional[Since], + Field( + description='Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d', + title='Since', + ), + ] = '14d' + + +class CvesGetCveIpsDetailsStatsPathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + + +class CvesSubscribeIntegrationToCvePathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + + +class CvesGetCveSubscribedIntegrationsQueryParameters(BaseModelSdk): + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class CvesGetCveSubscribedIntegrationsPathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + + +class CvesUnsubscribeIntegrationFromCvePathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + integration_name: Annotated[str, Field(title='Integration Name')] + + +class CvesGetCveTimelineQueryParameters(BaseModelSdk): + since_days: Annotated[ + Optional[SinceOptions], + Field( + description='Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days.' + ), + ] = 7 + + +class CvesGetCveTimelinePathParameters(BaseModelSdk): + cve_id: Annotated[str, Field(title='Cve Id')] + + +class VendorsGetVendorsQueryParameters(BaseModelSdk): + query: Annotated[ + Optional[str], Field(description='Search query for vendors', title='Query') + ] = None + sort_by: Annotated[ + Optional[VendorSortBy], + Field( + description='Sort by: value, nb_cves, nb_ips, latest_rule_release', + title='Sort By', + ), + ] = None + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: asc or desc', title='Sort Order'), + ] = 'desc' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class VendorsGetVendorStatsPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + + +class VendorsDownloadVendorIpsPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + + +class VendorsGetVendorIpsDetailsQueryParameters(BaseModelSdk): + since: Annotated[ + Optional[Since], + Field( + description='Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d', + title='Since', + ), + ] = '14d' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class VendorsGetVendorIpsDetailsPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + + +class VendorsGetVendorIpsDetailsStatsQueryParameters(BaseModelSdk): + since: Annotated[ + Optional[Since], + Field( + description='Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d', + title='Since', + ), + ] = '14d' + + +class VendorsGetVendorIpsDetailsStatsPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + + +class VendorsSubscribeIntegrationToVendorPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + + +class VendorsGetVendorSubscribedIntegrationsQueryParameters(BaseModelSdk): + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class VendorsGetVendorSubscribedIntegrationsPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + + +class VendorsUnsubscribeIntegrationFromVendorPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + integration_name: Annotated[str, Field(title='Integration Name')] + + +class VendorsGetVendorImpactQueryParameters(BaseModelSdk): + sort_by: Annotated[ + Optional[GetCVEsSortBy], Field(description='Field to sort by', title='Sort By') + ] = 'rule_release_date' + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: ascending or descending', title='Sort Order'), + ] = 'desc' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class VendorsGetVendorImpactPathParameters(BaseModelSdk): + vendor: Annotated[str, Field(title='Vendor')] + + +class ProductsGetProductsQueryParameters(BaseModelSdk): + query: Annotated[ + Optional[str], Field(description='Search query for products', title='Query') + ] = None + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class ProductsGetProductImpactQueryParameters(BaseModelSdk): + sort_by: Annotated[ + Optional[GetCVEsSortBy], Field(description='Field to sort by', title='Sort By') + ] = 'rule_release_date' + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: ascending or descending', title='Sort Order'), + ] = 'desc' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class ProductsGetProductImpactPathParameters(BaseModelSdk): + product: Annotated[str, Field(title='Product')] + + +class TrackerTagsGetTagsQueryParameters(BaseModelSdk): + query: Annotated[ + Optional[str], Field(description='Search query for tags', title='Query') + ] = None + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class TrackerTagsGetTagImpactQueryParameters(BaseModelSdk): + sort_by: Annotated[ + Optional[GetCVEsSortBy], Field(description='Field to sort by', title='Sort By') + ] = 'rule_release_date' + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: ascending or descending', title='Sort Order'), + ] = 'desc' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class TrackerTagsGetTagImpactPathParameters(BaseModelSdk): + tag: Annotated[str, Field(title='Tag')] + + +class TrackerTagsGetTrackerTagsQueryParameters(BaseModelSdk): + query: Annotated[ + Optional[str], Field(description='Search query for tags', title='Query') + ] = None + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class TrackerTagsGetTrackerTagImpactQueryParameters(BaseModelSdk): + sort_by: Annotated[ + Optional[GetCVEsSortBy], Field(description='Field to sort by', title='Sort By') + ] = 'rule_release_date' + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: ascending or descending', title='Sort Order'), + ] = 'desc' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class TrackerTagsGetTrackerTagImpactPathParameters(BaseModelSdk): + tag: Annotated[str, Field(title='Tag')] + + +class FingerprintsGetFingerprintRulesQueryParameters(BaseModelSdk): + query: Annotated[ + Optional[str], + Field(description='Search query for fingerprint rules', title='Query'), + ] = None + sort_by: Annotated[ + Optional[GetCVEsSortBy], Field(description='Field to sort by', title='Sort By') + ] = 'rule_release_date' + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: ascending or descending', title='Sort Order'), + ] = 'desc' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class FingerprintsDownloadFingerprintIpsPathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + + +class FingerprintsGetFingerprintIpsDetailsQueryParameters(BaseModelSdk): + since: Annotated[ + Optional[Since], + Field( + description='Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d', + title='Since', + ), + ] = '14d' + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class FingerprintsGetFingerprintIpsDetailsPathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + + +class FingerprintsGetFingerprintIpsDetailsStatsQueryParameters(BaseModelSdk): + since: Annotated[ + Optional[Since], + Field( + description='Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d', + title='Since', + ), + ] = '14d' + + +class FingerprintsGetFingerprintIpsDetailsStatsPathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + + +class FingerprintsSubscribeIntegrationToFingerprintPathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + + +class FingerprintsGetFingerprintSubscribedIntegrationsQueryParameters(BaseModelSdk): + page: Annotated[ + Optional[int], Field(description='Page number', ge=1, title='Page') + ] = 1 + size: Annotated[ + Optional[int], Field(description='Page size', ge=1, le=100, title='Size') + ] = 50 + + +class FingerprintsGetFingerprintSubscribedIntegrationsPathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + + +class FingerprintsUnsubscribeIntegrationFromFingerprintPathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + integration_name: Annotated[str, Field(title='Integration Name')] + + +class FingerprintsGetFingerprintTimelineQueryParameters(BaseModelSdk): + since_days: Annotated[ + Optional[SinceOptions], + Field( + description='Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days.' + ), + ] = 7 + interval: Annotated[ + Optional[IntervalOptions], + Field( + description="Interval for aggregating timeline data. Options: 'hour', 'day', 'week'. Default is adapted based on 'since' parameter.", + title='Interval', + ), + ] = None + + +class FingerprintsGetFingerprintTimelinePathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + + +class FingerprintsGetFingerprintRulePathParameters(BaseModelSdk): + fingerprint: Annotated[str, Field(title='Fingerprint')] + + +class TrackerEventsGetExploitationPhaseChangeEventsQueryParameters(BaseModelSdk): since: Annotated[ - Optional[Since], + Optional[str], Field( - description='Filter IPs seen since this date, format duration (e.g., 7d, 24h)', + description="Duration string (e.g. '30d', '24h') to filter events", title='Since', ), + ] = '30d' + sort_order: Annotated[ + Optional[GetCVEsSortOrder], + Field(description='Sort order: ascending or descending', title='Sort Order'), + ] = 'desc' + cve_id: Annotated[ + Optional[str], + Field(description='Filter by CVE identifier (exact match)', title='Cve Id'), + ] = None + previous_phase: Annotated[ + Optional[CVEExploitationPhase], + Field( + description='Filter by previous exploitation phase name', + title='Previous Phase', + ), + ] = None + new_phase: Annotated[ + Optional[CVEExploitationPhase], + Field(description='Filter by new exploitation phase name', title='New Phase'), ] = None page: Annotated[ Optional[int], Field(description='Page number', ge=1, title='Page') @@ -1145,19 +2034,6 @@ class CvesGetCveIpsQueryParameters(BaseModelSdk): ] = 50 -class CvesGetCveIpsPathParameters(BaseModelSdk): - cve_id: Annotated[str, Field(title='Cve Id')] - - -class CvesSubscribeIntegrationToCvePathParameters(BaseModelSdk): - cve_id: Annotated[str, Field(title='Cve Id')] - - -class CvesUnsubscribeIntegrationFromCvePathParameters(BaseModelSdk): - cve_id: Annotated[str, Field(title='Cve Id')] - integration_name: Annotated[str, Field(title='Integration Name')] - - class AllowlistSubscriberEntity(BaseModelSdk): id: Annotated[str, Field(description='Subscriber entity id', title='Id')] entity_type: SubscriberEntityType @@ -1208,11 +2084,11 @@ class AllowlistUpdateResponse(BaseModelSdk): Field(description='Description of the allowlist', title='Description'), ] = None created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the allowlist was created', title='Created At'), ] updated_at: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist was updated', title='Updated At'), ] = None from_cti_query: Annotated[ @@ -1292,7 +2168,7 @@ class BlocklistContentStats(BaseModelSdk): Optional[List[CtiCountry]], Field(title='Top Attacking Countries') ] = [] top_ips: Annotated[Optional[List[CtiIp]], Field(title='Top Ips')] = [] - updated_at: Annotated[Optional[AwareDatetime], Field(title='Updated At')] = None + updated_at: Annotated[Optional[datetime], Field(title='Updated At')] = None class BlocklistOrigin(BaseModelSdk): @@ -1398,7 +2274,7 @@ class BlocklistStats(BaseModelSdk): Optional[float], Field(title='Change Month Percentage') ] = 0.0 count: Annotated[Optional[int], Field(title='Count')] = 0 - updated_at: Annotated[Optional[AwareDatetime], Field(title='Updated At')] = None + updated_at: Annotated[Optional[datetime], Field(title='Updated At')] = None class BlocklistSubscriberEntity(BaseModelSdk): @@ -1437,6 +2313,15 @@ class BlocklistSubscriptionRequest(BaseModelSdk): ] = None +class DecisionTargetModel(BaseModelSdk): + type: Annotated[ + DecisionTargetType, Field(description='Type of the decision target') + ] + value: Annotated[ + str, Field(description='Value of the decision target', title='Value') + ] + + class HTTPValidationError(BaseModelSdk): detail: Annotated[Optional[List[ValidationError]], Field(title='Detail')] = None @@ -1462,6 +2347,17 @@ class IntegrationCreateRequest(BaseModelSdk): output_format: Annotated[ OutputFormat, Field(description='Output format of the integration') ] + pull_limit: Annotated[ + Optional[int], + Field(description='Maximum number of items to pull', title='Pull Limit'), + ] = None + enable_ip_aggregation: Annotated[ + Optional[bool], + Field( + description='Whether to enable IP aggregation into ranges', + title='Enable Ip Aggregation', + ), + ] = False class IntegrationCreateResponse(BaseModelSdk): @@ -1481,11 +2377,11 @@ class IntegrationCreateResponse(BaseModelSdk): Field(description='Description of the integration', title='Description'), ] = None created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the integration was created', title='Created At'), ] updated_at: Annotated[ - AwareDatetime, + datetime, Field(description='Last time the integration was updated', title='Updated At'), ] entity_type: Annotated[ @@ -1495,7 +2391,7 @@ class IntegrationCreateResponse(BaseModelSdk): OutputFormat, Field(description='Output format of the integration') ] last_pull: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field( description='Last time the integration pulled blocklists', title='Last Pull' ), @@ -1507,6 +2403,24 @@ class IntegrationCreateResponse(BaseModelSdk): title='Blocklists', ), ] + cves: Annotated[ + List[CVESubscription], + Field(description='CVEs that are subscribed by the integration', title='Cves'), + ] + fingerprints: Annotated[ + List[FingerprintSubscription], + Field( + description='Fingerprints that are subscribed by the integration', + title='Fingerprints', + ), + ] + vendors: Annotated[ + List[VendorSubscription], + Field( + description='Vendors that are subscribed by the integration', + title='Vendors', + ), + ] endpoint: Annotated[ AnyUrl, Field( @@ -1521,6 +2435,17 @@ class IntegrationCreateResponse(BaseModelSdk): Optional[List[str]], Field(description='Tags associated with the integration', title='Tags'), ] = [] + pull_limit: Annotated[ + Optional[int], + Field(description='Maximum number of items to pull', title='Pull Limit'), + ] = None + enable_ip_aggregation: Annotated[ + Optional[bool], + Field( + description='Whether to enable IP aggregation into ranges', + title='Enable Ip Aggregation', + ), + ] = False credentials: Annotated[ Union[ApiKeyCredentials, BasicAuthCredentials], Field( @@ -1547,11 +2472,11 @@ class IntegrationGetResponse(BaseModelSdk): Field(description='Description of the integration', title='Description'), ] = None created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the integration was created', title='Created At'), ] updated_at: Annotated[ - AwareDatetime, + datetime, Field(description='Last time the integration was updated', title='Updated At'), ] entity_type: Annotated[ @@ -1561,7 +2486,7 @@ class IntegrationGetResponse(BaseModelSdk): OutputFormat, Field(description='Output format of the integration') ] last_pull: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field( description='Last time the integration pulled blocklists', title='Last Pull' ), @@ -1573,6 +2498,24 @@ class IntegrationGetResponse(BaseModelSdk): title='Blocklists', ), ] + cves: Annotated[ + List[CVESubscription], + Field(description='CVEs that are subscribed by the integration', title='Cves'), + ] + fingerprints: Annotated[ + List[FingerprintSubscription], + Field( + description='Fingerprints that are subscribed by the integration', + title='Fingerprints', + ), + ] + vendors: Annotated[ + List[VendorSubscription], + Field( + description='Vendors that are subscribed by the integration', + title='Vendors', + ), + ] endpoint: Annotated[ AnyUrl, Field( @@ -1587,6 +2530,17 @@ class IntegrationGetResponse(BaseModelSdk): Optional[List[str]], Field(description='Tags associated with the integration', title='Tags'), ] = [] + pull_limit: Annotated[ + Optional[int], + Field(description='Maximum number of items to pull', title='Pull Limit'), + ] = None + enable_ip_aggregation: Annotated[ + Optional[bool], + Field( + description='Whether to enable IP aggregation into ranges', + title='Enable Ip Aggregation', + ), + ] = False class IntegrationGetResponsePage(BaseModelSdk): @@ -1619,6 +2573,17 @@ class IntegrationUpdateRequest(BaseModelSdk): title='Regenerate Credentials', ), ] = None + pull_limit: Annotated[ + Optional[int], + Field(description='Maximum number of items to pull', title='Pull Limit'), + ] = None + enable_ip_aggregation: Annotated[ + Optional[bool], + Field( + description='Whether to enable IP aggregation into ranges', + title='Enable Ip Aggregation', + ), + ] = False class IntegrationUpdateResponse(BaseModelSdk): @@ -1638,11 +2603,11 @@ class IntegrationUpdateResponse(BaseModelSdk): Field(description='Description of the integration', title='Description'), ] = None created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the integration was created', title='Created At'), ] updated_at: Annotated[ - AwareDatetime, + datetime, Field(description='Last time the integration was updated', title='Updated At'), ] entity_type: Annotated[ @@ -1652,7 +2617,7 @@ class IntegrationUpdateResponse(BaseModelSdk): OutputFormat, Field(description='Output format of the integration') ] last_pull: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field( description='Last time the integration pulled blocklists', title='Last Pull' ), @@ -1664,6 +2629,24 @@ class IntegrationUpdateResponse(BaseModelSdk): title='Blocklists', ), ] + cves: Annotated[ + List[CVESubscription], + Field(description='CVEs that are subscribed by the integration', title='Cves'), + ] + fingerprints: Annotated[ + List[FingerprintSubscription], + Field( + description='Fingerprints that are subscribed by the integration', + title='Fingerprints', + ), + ] + vendors: Annotated[ + List[VendorSubscription], + Field( + description='Vendors that are subscribed by the integration', + title='Vendors', + ), + ] endpoint: Annotated[ AnyUrl, Field( @@ -1678,6 +2661,17 @@ class IntegrationUpdateResponse(BaseModelSdk): Optional[List[str]], Field(description='Tags associated with the integration', title='Tags'), ] = [] + pull_limit: Annotated[ + Optional[int], + Field(description='Maximum number of items to pull', title='Pull Limit'), + ] = None + enable_ip_aggregation: Annotated[ + Optional[bool], + Field( + description='Whether to enable IP aggregation into ranges', + title='Enable Ip Aggregation', + ), + ] = False credentials: Annotated[ Optional[Union[ApiKeyCredentials, BasicAuthCredentials]], Field(description='Credentials for the integration', title='Credentials'), @@ -1697,10 +2691,10 @@ class OriginMetrics(BaseModelSdk): class PublicBlocklistResponse(BaseModelSdk): id: Annotated[str, Field(description='Blocklist id', title='Id')] created_at: Annotated[ - AwareDatetime, Field(description='Blocklist creation date', title='Created At') + datetime, Field(description='Blocklist creation date', title='Created At') ] updated_at: Annotated[ - AwareDatetime, Field(description='Blocklist update date', title='Updated At') + datetime, Field(description='Blocklist update date', title='Updated At') ] name: Annotated[ str, @@ -2382,22 +3376,391 @@ class ScenarioIndex(BaseModelSdk): versions: Annotated[ Optional[Dict[str, VersionDetail]], Field( - description="A dictionary where each key is a version number (e.g., '0.1', '0.2')", - examples=[ - { - '0.1': { - 'deprecated': False, - 'digest': '3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1', - }, - '0.2': { - 'deprecated': False, - 'digest': 'd1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91', - }, - } - ], - title='Versions', + description="A dictionary where each key is a version number (e.g., '0.1', '0.2')", + examples=[ + { + '0.1': { + 'deprecated': False, + 'digest': '3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1', + }, + '0.2': { + 'deprecated': False, + 'digest': 'd1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91', + }, + } + ], + title='Versions', + ), + ] = None + + +class CVEResponseBase(BaseModelSdk): + id: Annotated[str, Field(description='ID of the CVE', title='Id')] + name: Annotated[str, Field(description='Name of the CVE', title='Name')] + title: Annotated[str, Field(description='Title of the CVE', title='Title')] + affected_components: Annotated[ + List[AffectedComponent], + Field(description='List of affected components', title='Affected Components'), + ] + crowdsec_score: Annotated[ + int, + Field( + description='Live Exploit Tracker score of the CVE', + ge=0, + le=10, + title='Crowdsec Score', + ), + ] + opportunity_score: Annotated[ + Optional[int], + Field( + description="Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5)", + ge=0, + le=5, + title='Opportunity Score', + ), + ] = 0 + momentum_score: Annotated[ + Optional[int], + Field( + description="Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5)", + ge=0, + le=5, + title='Momentum Score', + ), + ] = 0 + first_seen: Annotated[ + Optional[datetime], Field(description='First seen date', title='First Seen') + ] = None + last_seen: Annotated[ + Optional[datetime], Field(description='Last seen date', title='Last Seen') + ] = None + nb_ips: Annotated[ + int, Field(description='Number of unique IPs affected', ge=0, title='Nb Ips') + ] + published_date: Annotated[ + datetime, Field(description='Published date of the CVE', title='Published Date') + ] + cvss_score: Annotated[ + Optional[CvssScore], + Field(description='CVSS score of the CVE', title='Cvss Score'), + ] = None + has_public_exploit: Annotated[ + bool, + Field( + description='Indicates if there is a public exploit for the CVE', + title='Has Public Exploit', + ), + ] + rule_release_date: Annotated[ + Optional[datetime], + Field( + description='Release date of the associated detection rule', + title='Rule Release Date', + ), + ] = None + exploitation_phase: Annotated[ + ExploitationPhase, Field(description='Current exploitation phase of the CVE') + ] + adjustment_score: Annotated[ + Optional[AdjustmentScore], + Field( + description='Score adjustments applied to the CVE score based on various factors' + ), + ] = None + threat_context: Annotated[ + Optional[ThreatContext], + Field( + description='Threat context (attacker/defender countries, industries, objectives)' + ), + ] = None + + +class FingerprintRuleResponse(BaseModelSdk): + id: Annotated[str, Field(description='Fingerprint rule identifier', title='Id')] + name: Annotated[str, Field(description='Fingerprint rule name', title='Name')] + title: Annotated[str, Field(description='Fingerprint rule title', title='Title')] + affected_components: Annotated[ + List[AffectedComponent], + Field(description='List of affected components', title='Affected Components'), + ] + crowdsec_score: Annotated[ + int, + Field( + description='Live Exploit Tracker score for the fingerprint rule', + ge=0, + le=10, + title='Crowdsec Score', + ), + ] + opportunity_score: Annotated[ + Optional[int], + Field(description='Opportunity score', ge=0, le=5, title='Opportunity Score'), + ] = 0 + momentum_score: Annotated[ + Optional[int], + Field(description='Momentum score', ge=0, le=5, title='Momentum Score'), + ] = 0 + first_seen: Annotated[ + Optional[datetime], Field(description='First seen date', title='First Seen') + ] = None + last_seen: Annotated[ + Optional[datetime], Field(description='Last seen date', title='Last Seen') + ] = None + nb_ips: Annotated[ + int, Field(description='Number of unique IPs observed', ge=0, title='Nb Ips') + ] + rule_release_date: Annotated[ + Optional[datetime], + Field( + description='Release date of the fingerprint rule', + title='Rule Release Date', + ), + ] = None + exploitation_phase: Annotated[ + ExploitationPhase, Field(description='Current exploitation phase') + ] + adjustment_score: Annotated[ + Optional[AdjustmentScore], Field(description='Score adjustment details') + ] = None + threat_context: Annotated[ + Optional[ThreatContext], + Field( + description='Threat context (attacker/defender countries, industries, objectives)' + ), + ] = None + tags: Annotated[ + Optional[List[str]], + Field(description='Tags associated with the fingerprint rule', title='Tags'), + ] = None + description: Annotated[ + Optional[str], + Field(description='Fingerprint rule description', title='Description'), + ] = None + references: Annotated[ + Optional[List[str]], + Field( + description='Reference links for the fingerprint rule', title='References' + ), + ] = None + crowdsec_analysis: Annotated[ + Optional[str], + Field( + description='CrowdSec analysis for this fingerprint rule', + title='Crowdsec Analysis', + ), + ] = None + events: Annotated[ + Optional[List[FingerprintEventOutput]], + Field( + description='List of events related to the fingerprint rule', title='Events' + ), + ] = None + + +class FingerprintRuleSummary(BaseModelSdk): + id: Annotated[str, Field(description='Fingerprint rule identifier', title='Id')] + name: Annotated[str, Field(description='Fingerprint rule name', title='Name')] + title: Annotated[str, Field(description='Fingerprint rule title', title='Title')] + affected_components: Annotated[ + List[AffectedComponent], + Field(description='List of affected components', title='Affected Components'), + ] + crowdsec_score: Annotated[ + int, + Field( + description='Live Exploit Tracker score for the fingerprint rule', + ge=0, + le=10, + title='Crowdsec Score', + ), + ] + opportunity_score: Annotated[ + Optional[int], + Field(description='Opportunity score', ge=0, le=5, title='Opportunity Score'), + ] = 0 + momentum_score: Annotated[ + Optional[int], + Field(description='Momentum score', ge=0, le=5, title='Momentum Score'), + ] = 0 + first_seen: Annotated[ + Optional[datetime], Field(description='First seen date', title='First Seen') + ] = None + last_seen: Annotated[ + Optional[datetime], Field(description='Last seen date', title='Last Seen') + ] = None + nb_ips: Annotated[ + int, Field(description='Number of unique IPs observed', ge=0, title='Nb Ips') + ] + rule_release_date: Annotated[ + Optional[datetime], + Field( + description='Release date of the fingerprint rule', + title='Rule Release Date', + ), + ] = None + exploitation_phase: Annotated[ + ExploitationPhase, Field(description='Current exploitation phase') + ] + adjustment_score: Annotated[ + Optional[AdjustmentScore], Field(description='Score adjustment details') + ] = None + threat_context: Annotated[ + Optional[ThreatContext], + Field( + description='Threat context (attacker/defender countries, industries, objectives)' + ), + ] = None + + +class GetCVEResponse(BaseModelSdk): + id: Annotated[str, Field(description='ID of the CVE', title='Id')] + name: Annotated[str, Field(description='Name of the CVE', title='Name')] + title: Annotated[str, Field(description='Title of the CVE', title='Title')] + affected_components: Annotated[ + List[AffectedComponent], + Field(description='List of affected components', title='Affected Components'), + ] + crowdsec_score: Annotated[ + int, + Field( + description='Live Exploit Tracker score of the CVE', + ge=0, + le=10, + title='Crowdsec Score', + ), + ] + opportunity_score: Annotated[ + Optional[int], + Field( + description="Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5)", + ge=0, + le=5, + title='Opportunity Score', + ), + ] = 0 + momentum_score: Annotated[ + Optional[int], + Field( + description="Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5)", + ge=0, + le=5, + title='Momentum Score', + ), + ] = 0 + first_seen: Annotated[ + Optional[datetime], Field(description='First seen date', title='First Seen') + ] = None + last_seen: Annotated[ + Optional[datetime], Field(description='Last seen date', title='Last Seen') + ] = None + nb_ips: Annotated[ + int, Field(description='Number of unique IPs affected', ge=0, title='Nb Ips') + ] + published_date: Annotated[ + datetime, Field(description='Published date of the CVE', title='Published Date') + ] + cvss_score: Annotated[ + Optional[CvssScore], + Field(description='CVSS score of the CVE', title='Cvss Score'), + ] = None + has_public_exploit: Annotated[ + bool, + Field( + description='Indicates if there is a public exploit for the CVE', + title='Has Public Exploit', + ), + ] + rule_release_date: Annotated[ + Optional[datetime], + Field( + description='Release date of the associated detection rule', + title='Rule Release Date', + ), + ] = None + exploitation_phase: Annotated[ + ExploitationPhase, Field(description='Current exploitation phase of the CVE') + ] + adjustment_score: Annotated[ + Optional[AdjustmentScore], + Field( + description='Score adjustments applied to the CVE score based on various factors' + ), + ] = None + threat_context: Annotated[ + Optional[ThreatContext], + Field( + description='Threat context (attacker/defender countries, industries, objectives)' ), ] = None + tags: Annotated[ + Optional[List[str]], + Field(description='Tags associated with the CVE', title='Tags'), + ] = None + references: Annotated[ + List[str], + Field(description='List of references for the CVE', title='References'), + ] + description: Annotated[ + str, Field(description='Description of the CVE', title='Description') + ] + crowdsec_analysis: Annotated[ + Optional[str], + Field(description='CrowdSec analysis of the CVE', title='Crowdsec Analysis'), + ] = None + cwes: Annotated[ + List[CWE], + Field(description='List of CWEs associated with the CVE', title='Cwes'), + ] + events: Annotated[ + Optional[List[CVEEventOutput]], + Field(description='List of events related to the CVE', title='Events'), + ] = None + + +class GetCVESubscribedIntegrationsResponsePage(BaseModelSdk): + items: Annotated[List[IntegrationResponse], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + +class GetCVEsResponsePage(BaseModelSdk): + items: Annotated[List[CVEResponseBase], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + +class GetFingerprintRulesResponsePage(BaseModelSdk): + items: Annotated[List[FingerprintRuleSummary], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + +class GetFingerprintSubscribedIntegrationsResponsePage(BaseModelSdk): + items: Annotated[List[IntegrationResponse], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + +class GetVendorSubscribedIntegrationsResponsePage(BaseModelSdk): + items: Annotated[List[IntegrationResponse], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links class IPItem(BaseModelSdk): @@ -2475,6 +3838,232 @@ class IPItem(BaseModelSdk): scores: Annotated[Optional[Scores], Field(description='Scoring information')] = None +class LookupImpactCVEItem(BaseModelSdk): + id: Annotated[str, Field(description='ID of the CVE', title='Id')] + name: Annotated[str, Field(description='Name of the CVE', title='Name')] + title: Annotated[str, Field(description='Title of the CVE', title='Title')] + affected_components: Annotated[ + List[AffectedComponent], + Field(description='List of affected components', title='Affected Components'), + ] + crowdsec_score: Annotated[ + int, + Field( + description='Live Exploit Tracker score of the CVE', + ge=0, + le=10, + title='Crowdsec Score', + ), + ] + opportunity_score: Annotated[ + Optional[int], + Field( + description="Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5)", + ge=0, + le=5, + title='Opportunity Score', + ), + ] = 0 + momentum_score: Annotated[ + Optional[int], + Field( + description="Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5)", + ge=0, + le=5, + title='Momentum Score', + ), + ] = 0 + first_seen: Annotated[ + Optional[datetime], Field(description='First seen date', title='First Seen') + ] = None + last_seen: Annotated[ + Optional[datetime], Field(description='Last seen date', title='Last Seen') + ] = None + nb_ips: Annotated[ + int, Field(description='Number of unique IPs affected', ge=0, title='Nb Ips') + ] + published_date: Annotated[ + datetime, Field(description='Published date of the CVE', title='Published Date') + ] + cvss_score: Annotated[ + Optional[CvssScore], + Field(description='CVSS score of the CVE', title='Cvss Score'), + ] = None + has_public_exploit: Annotated[ + bool, + Field( + description='Indicates if there is a public exploit for the CVE', + title='Has Public Exploit', + ), + ] + rule_release_date: Annotated[ + Optional[datetime], + Field( + description='Release date of the associated detection rule', + title='Rule Release Date', + ), + ] = None + exploitation_phase: Annotated[ + ExploitationPhase, Field(description='Current exploitation phase of the CVE') + ] + adjustment_score: Annotated[ + Optional[AdjustmentScore], + Field( + description='Score adjustments applied to the CVE score based on various factors' + ), + ] = None + threat_context: Annotated[ + Optional[ThreatContext], + Field( + description='Threat context (attacker/defender countries, industries, objectives)' + ), + ] = None + tags: Annotated[ + Optional[List[str]], + Field(description='Tags associated with the CVE', title='Tags'), + ] = None + references: Annotated[ + List[str], + Field(description='List of references for the CVE', title='References'), + ] + description: Annotated[ + str, Field(description='Description of the CVE', title='Description') + ] + crowdsec_analysis: Annotated[ + Optional[str], + Field(description='CrowdSec analysis of the CVE', title='Crowdsec Analysis'), + ] = None + cwes: Annotated[ + List[CWE], + Field(description='List of CWEs associated with the CVE', title='Cwes'), + ] + events: Annotated[ + Optional[List[CVEEventOutput]], + Field(description='List of events related to the CVE', title='Events'), + ] = None + type: Annotated[ + Literal['cve'], Field(description='Resource type', title='Type') + ] = 'cve' + + +class LookupImpactFingerprintItem(BaseModelSdk): + id: Annotated[str, Field(description='Fingerprint rule identifier', title='Id')] + name: Annotated[str, Field(description='Fingerprint rule name', title='Name')] + title: Annotated[str, Field(description='Fingerprint rule title', title='Title')] + affected_components: Annotated[ + List[AffectedComponent], + Field(description='List of affected components', title='Affected Components'), + ] + crowdsec_score: Annotated[ + int, + Field( + description='Live Exploit Tracker score for the fingerprint rule', + ge=0, + le=10, + title='Crowdsec Score', + ), + ] + opportunity_score: Annotated[ + Optional[int], + Field(description='Opportunity score', ge=0, le=5, title='Opportunity Score'), + ] = 0 + momentum_score: Annotated[ + Optional[int], + Field(description='Momentum score', ge=0, le=5, title='Momentum Score'), + ] = 0 + first_seen: Annotated[ + Optional[datetime], Field(description='First seen date', title='First Seen') + ] = None + last_seen: Annotated[ + Optional[datetime], Field(description='Last seen date', title='Last Seen') + ] = None + nb_ips: Annotated[ + int, Field(description='Number of unique IPs observed', ge=0, title='Nb Ips') + ] + rule_release_date: Annotated[ + Optional[datetime], + Field( + description='Release date of the fingerprint rule', + title='Rule Release Date', + ), + ] = None + exploitation_phase: Annotated[ + ExploitationPhase, Field(description='Current exploitation phase') + ] + adjustment_score: Annotated[ + Optional[AdjustmentScore], Field(description='Score adjustment details') + ] = None + threat_context: Annotated[ + Optional[ThreatContext], + Field( + description='Threat context (attacker/defender countries, industries, objectives)' + ), + ] = None + tags: Annotated[ + Optional[List[str]], + Field(description='Tags associated with the fingerprint rule', title='Tags'), + ] = None + description: Annotated[ + Optional[str], + Field(description='Fingerprint rule description', title='Description'), + ] = None + references: Annotated[ + Optional[List[str]], + Field( + description='Reference links for the fingerprint rule', title='References' + ), + ] = None + crowdsec_analysis: Annotated[ + Optional[str], + Field( + description='CrowdSec analysis for this fingerprint rule', + title='Crowdsec Analysis', + ), + ] = None + events: Annotated[ + Optional[List[FingerprintEventOutput]], + Field( + description='List of events related to the fingerprint rule', title='Events' + ), + ] = None + type: Annotated[ + Literal['fingerprint'], Field(description='Resource type', title='Type') + ] = 'fingerprint' + + +class Items(RootModelSdk[Union[LookupImpactCVEItem, LookupImpactFingerprintItem]]): + root: Annotated[ + Union[LookupImpactCVEItem, LookupImpactFingerprintItem], + Field(discriminator='type'), + ] + + +class LookupImpactResponsePage(BaseModelSdk): + items: Annotated[List[Items], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + +class ProtectRule(BaseModelSdk): + link: Annotated[str, Field(description='URL to the rule source', title='Link')] + published_date: Annotated[ + Optional[datetime], + Field(description='Date the rule was published', title='Published Date'), + ] = None + tags: Annotated[ + Optional[List[ProtectRuleTag]], + Field(description='Tags associated with the rule', title='Tags'), + ] = None + name: Annotated[str, Field(description='Rule name', title='Name')] + label: Annotated[str, Field(description='Human-readable rule label', title='Label')] + content: Annotated[ + Optional[str], Field(description='Rule content/definition', title='Content') + ] = None + + class AllowlistGetItemsResponse(BaseModelSdk): id: Annotated[ str, @@ -2505,11 +4094,11 @@ class AllowlistGetItemsResponse(BaseModelSdk): str, Field(description='Value of the allowlist entry', title='Value') ] created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the allowlist entry was created', title='Created At'), ] updated_at: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist entry was updated', title='Updated At'), ] = None created_by: Annotated[ @@ -2520,7 +4109,7 @@ class AllowlistGetItemsResponse(BaseModelSdk): Field(description='The source user who updated the allowlist entry'), ] = None expiration: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist entry will expire', title='Expiration'), ] = None @@ -2552,11 +4141,11 @@ class AllowlistGetResponse(BaseModelSdk): Field(description='Description of the allowlist', title='Description'), ] = None created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the allowlist was created', title='Created At'), ] updated_at: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist was updated', title='Updated At'), ] = None from_cti_query: Annotated[ @@ -2623,11 +4212,11 @@ class AllowlistItemUpdateResponse(BaseModelSdk): str, Field(description='Value of the allowlist entry', title='Value') ] created_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the allowlist entry was created', title='Created At'), ] updated_at: Annotated[ - AwareDatetime, + datetime, Field(description='Time the allowlist entry was updated', title='Updated At'), ] created_by: Annotated[ @@ -2637,7 +4226,7 @@ class AllowlistItemUpdateResponse(BaseModelSdk): SourceInfo, Field(description='The source user who updated the allowlist entry') ] expiration: Annotated[ - Optional[AwareDatetime], + Optional[datetime], Field(description='Time the allowlist entry will expire', title='Expiration'), ] = None @@ -2657,6 +4246,104 @@ class ComputedSavedMetrics(BaseModelSdk): ] = [] +class DecisionCreateRequest(BaseModelSdk): + model_config = ConfigDict( + extra='forbid', + ) + created_at: Annotated[Optional[datetime], Field(title='Created At')] = None + uuid: Annotated[ + Optional[str], Field(description='UUID of the decision', title='Uuid') + ] = None + id: Annotated[ + Optional[int], Field(description='ID of the decision', title='Id') + ] = None + duration: Annotated[ + str, Field(description='Duration of the decision', title='Duration') + ] + origin: Annotated[str, Field(description='Origin of the decision', title='Origin')] + scenario: Annotated[ + str, Field(description='Scenario of the decision', title='Scenario') + ] + scope: Annotated[str, Field(description='Scope of the decision', title='Scope')] + type: Annotated[str, Field(description='Type of the decision', title='Type')] + value: Annotated[str, Field(description='Value of the decision', title='Value')] + country: Annotated[ + Optional[str], + Field(description='Country associated with the decision', title='Country'), + ] = None + as_name: Annotated[ + Optional[str], + Field(description='AS name associated with the decision', title='As Name'), + ] = None + as_num: Annotated[ + Optional[int], + Field(description='AS number associated with the decision', title='As Num'), + ] = None + city: Annotated[ + Optional[str], + Field(description='City associated with the decision', title='City'), + ] = None + latitude: Annotated[ + Optional[float], + Field(description='Latitude associated with the decision', title='Latitude'), + ] = None + longitude: Annotated[ + Optional[float], + Field(description='Longitude associated with the decision', title='Longitude'), + ] = None + target: Annotated[DecisionTargetModel, Field(description='Target of the decision')] + + +class DecisionResponse(BaseModelSdk): + created_at: Annotated[Optional[datetime], Field(title='Created At')] = None + uuid: Annotated[str, Field(description='UUID of the decision', title='Uuid')] + id: Annotated[int, Field(description='ID of the decision', title='Id')] + duration: Annotated[ + str, Field(description='Duration of the decision', title='Duration') + ] + origin: Annotated[str, Field(description='Origin of the decision', title='Origin')] + scenario: Annotated[ + str, Field(description='Scenario of the decision', title='Scenario') + ] + scope: Annotated[str, Field(description='Scope of the decision', title='Scope')] + type: Annotated[str, Field(description='Type of the decision', title='Type')] + value: Annotated[str, Field(description='Value of the decision', title='Value')] + country: Annotated[ + Optional[str], + Field(description='Country associated with the decision', title='Country'), + ] = None + as_name: Annotated[ + Optional[str], + Field(description='AS name associated with the decision', title='As Name'), + ] = None + as_num: Annotated[ + Optional[int], + Field(description='AS number associated with the decision', title='As Num'), + ] = None + city: Annotated[ + Optional[str], + Field(description='City associated with the decision', title='City'), + ] = None + latitude: Annotated[ + Optional[float], + Field(description='Latitude associated with the decision', title='Latitude'), + ] = None + longitude: Annotated[ + Optional[float], + Field(description='Longitude associated with the decision', title='Longitude'), + ] = None + target: Annotated[DecisionTargetModel, Field(description='Target of the decision')] + + +class DecisionsGetResponsePage(BaseModelSdk): + items: Annotated[List[DecisionResponse], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + class RawMetrics(BaseModelSdk): dropped: Annotated[ Optional[List[RemediationMetrics]], @@ -2701,6 +4388,34 @@ class GetCVEIPsResponsePage(BaseModelSdk): links: Links +class GetCVEProtectRulesResponse(BaseModelSdk): + protect_rules: Annotated[ + Optional[List[ProtectRule]], + Field( + description='Protection/detection rules associated with the CVE', + title='Protect Rules', + ), + ] = None + + +class GetFingerprintIPsResponsePage(BaseModelSdk): + items: Annotated[List[IPItem], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + +class GetVendorIPsResponsePage(BaseModelSdk): + items: Annotated[List[IPItem], Field(title='Items')] + total: Annotated[int, Field(ge=0, title='Total')] + page: Annotated[int, Field(ge=1, title='Page')] + size: Annotated[int, Field(ge=1, title='Size')] + pages: Annotated[int, Field(ge=0, title='Pages')] + links: Links + + class ComputedMetrics(BaseModelSdk): saved: Annotated[ComputedSavedMetrics, Field(description='estimated saved metrics')] dropped: Annotated[ diff --git a/crowdsec_service_api/services/__pycache__/__init__.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/__init__.cpython-311.pyc index b5d7b60..a8fd931 100644 Binary files a/crowdsec_service_api/services/__pycache__/__init__.cpython-311.pyc and b/crowdsec_service_api/services/__pycache__/__init__.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/allowlists.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/allowlists.cpython-311.pyc new file mode 100644 index 0000000..e159375 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/allowlists.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/blocklists.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/blocklists.cpython-311.pyc new file mode 100644 index 0000000..94ee861 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/blocklists.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/cves.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/cves.cpython-311.pyc new file mode 100644 index 0000000..385adb4 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/cves.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/decisions.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/decisions.cpython-311.pyc new file mode 100644 index 0000000..1a88cbb Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/decisions.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/fingerprints.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/fingerprints.cpython-311.pyc new file mode 100644 index 0000000..4bc6988 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/fingerprints.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/hub.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/hub.cpython-311.pyc new file mode 100644 index 0000000..00766b0 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/hub.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/info.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/info.cpython-311.pyc new file mode 100644 index 0000000..c865bd7 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/info.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/integrations.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/integrations.cpython-311.pyc new file mode 100644 index 0000000..7dacd1b Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/integrations.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/metrics.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/metrics.cpython-311.pyc new file mode 100644 index 0000000..fb5e997 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/metrics.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/products.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/products.cpython-311.pyc new file mode 100644 index 0000000..a9bf128 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/products.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/tracker_events.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/tracker_events.cpython-311.pyc new file mode 100644 index 0000000..6660233 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/tracker_events.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/tracker_tags.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/tracker_tags.cpython-311.pyc new file mode 100644 index 0000000..1045d80 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/tracker_tags.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/__pycache__/vendors.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/vendors.cpython-311.pyc new file mode 100644 index 0000000..1fcbe69 Binary files /dev/null and b/crowdsec_service_api/services/__pycache__/vendors.cpython-311.pyc differ diff --git a/crowdsec_service_api/services/allowlists.py b/crowdsec_service_api/services/allowlists.py index 2269f08..b0df36d 100644 --- a/crowdsec_service_api/services/allowlists.py +++ b/crowdsec_service_api/services/allowlists.py @@ -10,6 +10,8 @@ from ..http_client import HttpClient class Allowlists(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") def list_allowlists( self, @@ -30,7 +32,7 @@ def list_allowlists( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return AllowlistGetResponsePage(**response.json()) + return AllowlistGetResponsePage(_client=self, **response.json()) def create_allowlist( self, @@ -147,7 +149,7 @@ def get_allowlist_items( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return AllowlistGetItemsResponsePage(**response.json()) + return AllowlistGetItemsResponsePage(_client=self, **response.json()) def create_allowlist_items( self, @@ -267,7 +269,7 @@ def get_allowlist_subscribers( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return AllowlistSubscriberEntityPage(**response.json()) + return AllowlistSubscriberEntityPage(_client=self, **response.json()) def subscribe_allowlist( self, diff --git a/crowdsec_service_api/services/blocklists.py b/crowdsec_service_api/services/blocklists.py index 909b3fe..7ddced9 100644 --- a/crowdsec_service_api/services/blocklists.py +++ b/crowdsec_service_api/services/blocklists.py @@ -10,6 +10,8 @@ from ..http_client import HttpClient class Blocklists(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") def get_blocklists( self, @@ -35,7 +37,7 @@ def get_blocklists( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return PublicBlocklistResponsePage(**response.json()) + return PublicBlocklistResponsePage(_client=self, **response.json()) def create_blocklist( self, @@ -83,7 +85,7 @@ def search_blocklist( url=endpoint_url, path_params=path_params, params=params, headers=headers, json=payload ) - return PublicBlocklistResponsePage(**response.json()) + return PublicBlocklistResponsePage(_client=self, **response.json()) def get_blocklist( self, @@ -283,7 +285,7 @@ def get_blocklist_subscribers( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return BlocklistSubscriberEntityPage(**response.json()) + return BlocklistSubscriberEntityPage(_client=self, **response.json()) def subscribe_blocklist( self, diff --git a/crowdsec_service_api/services/cves.py b/crowdsec_service_api/services/cves.py index ee65b0f..3695b97 100644 --- a/crowdsec_service_api/services/cves.py +++ b/crowdsec_service_api/services/cves.py @@ -10,6 +10,33 @@ from ..http_client import HttpClient class Cves(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") + + def get_cves( + self, + query: Optional[str] = None, + sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + exploitation_phase: Optional[CVEExploitationPhase] = None, + page: int = 1, + size: int = 50, + )-> GetCVEsResponsePage: + endpoint_url = "/cves" + loc = locals() + headers = {} + params = json.loads( + CvesGetCvesQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetCVEsResponsePage(_client=self, **response.json()) def get_cve( self, @@ -31,23 +58,88 @@ def get_cve( return GetCVEResponse(**response.json()) - def get_cve_ips( + def get_cve_protect_rules( self, cve_id: str, - since: Optional[str] = None, + )-> GetCVEProtectRulesResponse: + endpoint_url = "/cves/{cve_id}/protect-rules" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + CvesGetCveProtectRulesPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetCVEProtectRulesResponse(**response.json()) + + def download_cve_ips( + self, + cve_id: str, + )-> str: + endpoint_url = "/cves/{cve_id}/ips-download" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + CvesDownloadCveIpsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return response.text + + def get_cve_ips_details( + self, + cve_id: str, + since: Optional[str] = "14d", page: int = 1, size: int = 50, )-> GetCVEIPsResponsePage: - endpoint_url = "/cves/{cve_id}/ips" + endpoint_url = "/cves/{cve_id}/ips-details" + loc = locals() + headers = {} + params = json.loads( + CvesGetCveIpsDetailsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + CvesGetCveIpsDetailsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetCVEIPsResponsePage(_client=self, **response.json()) + + def get_cve_ips_details_stats( + self, + cve_id: str, + since: Optional[str] = "14d", + )-> IpsDetailsStats: + endpoint_url = "/cves/{cve_id}/ips-details-stats" loc = locals() headers = {} params = json.loads( - CvesGetCveIpsQueryParameters(**loc).model_dump_json( + CvesGetCveIpsDetailsStatsQueryParameters(**loc).model_dump_json( exclude_none=True ) ) path_params = json.loads( - CvesGetCveIpsPathParameters(**loc).model_dump_json( + CvesGetCveIpsDetailsStatsPathParameters(**loc).model_dump_json( exclude_none=True ) ) @@ -56,7 +148,33 @@ def get_cve_ips( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return GetCVEIPsResponsePage(**response.json()) + return IpsDetailsStats(**response.json()) + + def get_cve_subscribed_integrations( + self, + cve_id: str, + page: int = 1, + size: int = 50, + )-> GetCVESubscribedIntegrationsResponsePage: + endpoint_url = "/cves/{cve_id}/integrations" + loc = locals() + headers = {} + params = json.loads( + CvesGetCveSubscribedIntegrationsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + CvesGetCveSubscribedIntegrationsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetCVESubscribedIntegrationsResponsePage(_client=self, **response.json()) def subscribe_integration_to_cve( self, @@ -104,4 +222,29 @@ def unsubscribe_integration_from_cve( ) return None + + def get_cve_timeline( + self, + cve_id: str, + since_days: SinceOptions, + )-> list[TimelineItem]: + endpoint_url = "/cves/{cve_id}/timeline" + loc = locals() + headers = {} + params = json.loads( + CvesGetCveTimelineQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + CvesGetCveTimelinePathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return [TimelineItem(**item) for item in response.json()] \ No newline at end of file diff --git a/crowdsec_service_api/services/decisions.py b/crowdsec_service_api/services/decisions.py new file mode 100644 index 0000000..8306e45 --- /dev/null +++ b/crowdsec_service_api/services/decisions.py @@ -0,0 +1,63 @@ +import json +from types import NoneType +from typing import Optional, Union, Annotated + +from ..models import * +from ..base_model import Page, Service +from pydantic import BaseModel, Field +from pydantic.fields import FieldInfo +from httpx import Auth +from ..http_client import HttpClient + +class Decisions(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") + + def get_decisions( + self, + instance_ids: list[str] = [], + tag_ids: list[str] = [], + remediation_types: list[str] = [], + ips: list[str] = [], + sort_by: Optional[DecisionsSortBy] = DecisionsSortBy("created_at"), + sort_order: Optional[DecisionsSortOrder] = DecisionsSortOrder("desc"), + page: int = 1, + size: int = 50, + )-> DecisionsGetResponsePage: + endpoint_url = "/decisions" + loc = locals() + headers = {} + params = json.loads( + DecisionsGetDecisionsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return DecisionsGetResponsePage(_client=self, **response.json()) + + def create_decision( + self, + request: DecisionCreateRequest, + )-> DecisionCreateResponse: + endpoint_url = "/decisions" + loc = locals() + headers = {} + params = {} + path_params = {} + + payload = json.loads( + request.model_dump_json( + exclude_none=True + ) + ) if "request" in loc else None + response = self.http_client.post( + url=endpoint_url, path_params=path_params, params=params, headers=headers, json=payload + ) + + return DecisionCreateResponse(**response.json()) + \ No newline at end of file diff --git a/crowdsec_service_api/services/fingerprints.py b/crowdsec_service_api/services/fingerprints.py new file mode 100644 index 0000000..3e0743b --- /dev/null +++ b/crowdsec_service_api/services/fingerprints.py @@ -0,0 +1,230 @@ +import json +from types import NoneType +from typing import Optional, Union, Annotated + +from ..models import * +from ..base_model import Page, Service +from pydantic import BaseModel, Field +from pydantic.fields import FieldInfo +from httpx import Auth +from ..http_client import HttpClient + +class Fingerprints(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") + + def get_fingerprint_rules( + self, + query: Optional[str] = None, + sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + page: int = 1, + size: int = 50, + )-> GetFingerprintRulesResponsePage: + endpoint_url = "/fingerprints" + loc = locals() + headers = {} + params = json.loads( + FingerprintsGetFingerprintRulesQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetFingerprintRulesResponsePage(_client=self, **response.json()) + + def download_fingerprint_ips( + self, + fingerprint: str, + )-> str: + endpoint_url = "/fingerprints/{fingerprint}/ips-download" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + FingerprintsDownloadFingerprintIpsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return response.text + + def get_fingerprint_ips_details( + self, + fingerprint: str, + since: Optional[str] = "14d", + page: int = 1, + size: int = 50, + )-> GetFingerprintIPsResponsePage: + endpoint_url = "/fingerprints/{fingerprint}/ips-details" + loc = locals() + headers = {} + params = json.loads( + FingerprintsGetFingerprintIpsDetailsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + FingerprintsGetFingerprintIpsDetailsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetFingerprintIPsResponsePage(_client=self, **response.json()) + + def get_fingerprint_ips_details_stats( + self, + fingerprint: str, + since: Optional[str] = "14d", + )-> IpsDetailsStats: + endpoint_url = "/fingerprints/{fingerprint}/ips-details-stats" + loc = locals() + headers = {} + params = json.loads( + FingerprintsGetFingerprintIpsDetailsStatsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + FingerprintsGetFingerprintIpsDetailsStatsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return IpsDetailsStats(**response.json()) + + def get_fingerprint_subscribed_integrations( + self, + fingerprint: str, + page: int = 1, + size: int = 50, + )-> GetFingerprintSubscribedIntegrationsResponsePage: + endpoint_url = "/fingerprints/{fingerprint}/integrations" + loc = locals() + headers = {} + params = json.loads( + FingerprintsGetFingerprintSubscribedIntegrationsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + FingerprintsGetFingerprintSubscribedIntegrationsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetFingerprintSubscribedIntegrationsResponsePage(_client=self, **response.json()) + + def subscribe_integration_to_fingerprint( + self, + request: SubscribeFingerprintIntegrationRequest, + fingerprint: str, + ): + endpoint_url = "/fingerprints/{fingerprint}/integrations" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + FingerprintsSubscribeIntegrationToFingerprintPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + payload = json.loads( + request.model_dump_json( + exclude_none=True + ) + ) if "request" in loc else None + response = self.http_client.post( + url=endpoint_url, path_params=path_params, params=params, headers=headers, json=payload + ) + + return None + + def unsubscribe_integration_from_fingerprint( + self, + fingerprint: str, + integration_name: str, + ): + endpoint_url = "/fingerprints/{fingerprint}/integrations/{integration_name}" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + FingerprintsUnsubscribeIntegrationFromFingerprintPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.delete( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return None + + def get_fingerprint_timeline( + self, + fingerprint: str, + since_days: SinceOptions, + interval: Optional[IntervalOptions] = None, + )-> list[FingerprintTimelineItem]: + endpoint_url = "/fingerprints/{fingerprint}/timeline" + loc = locals() + headers = {} + params = json.loads( + FingerprintsGetFingerprintTimelineQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + FingerprintsGetFingerprintTimelinePathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return [FingerprintTimelineItem(**item) for item in response.json()] + + def get_fingerprint_rule( + self, + fingerprint: str, + )-> FingerprintRuleResponse: + endpoint_url = "/fingerprints/{fingerprint}" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + FingerprintsGetFingerprintRulePathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return FingerprintRuleResponse(**response.json()) + \ No newline at end of file diff --git a/crowdsec_service_api/services/hub.py b/crowdsec_service_api/services/hub.py index 1705da2..dbf062b 100644 --- a/crowdsec_service_api/services/hub.py +++ b/crowdsec_service_api/services/hub.py @@ -10,6 +10,8 @@ from ..http_client import HttpClient class Hub(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") def get_index( self, diff --git a/crowdsec_service_api/services/info.py b/crowdsec_service_api/services/info.py index bac69b8..c6b9cd7 100644 --- a/crowdsec_service_api/services/info.py +++ b/crowdsec_service_api/services/info.py @@ -10,6 +10,8 @@ from ..http_client import HttpClient class Info(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") def get_info( self, diff --git a/crowdsec_service_api/services/integrations.py b/crowdsec_service_api/services/integrations.py index 4583420..9efef4c 100644 --- a/crowdsec_service_api/services/integrations.py +++ b/crowdsec_service_api/services/integrations.py @@ -10,6 +10,8 @@ from ..http_client import HttpClient class Integrations(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") def get_integrations( self, @@ -31,7 +33,7 @@ def get_integrations( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return IntegrationGetResponsePage(**response.json()) + return IntegrationGetResponsePage(_client=self, **response.json()) def create_integration( self, @@ -77,11 +79,16 @@ def get_integration( def delete_integration( self, integration_id: str, + force: bool = False, ): endpoint_url = "/integrations/{integration_id}" loc = locals() headers = {} - params = {} + params = json.loads( + IntegrationsDeleteIntegrationQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) path_params = json.loads( IntegrationsDeleteIntegrationPathParameters(**loc).model_dump_json( exclude_none=True @@ -124,7 +131,9 @@ def get_integration_content( integration_id: str, page: int = 1, page_size: Optional[int] = None, - ): + pull_limit: Optional[int] = None, + enable_ip_aggregation: bool = False, + )-> str: endpoint_url = "/integrations/{integration_id}/content" loc = locals() headers = {} @@ -143,7 +152,7 @@ def get_integration_content( url=endpoint_url, path_params=path_params, params=params, headers=headers ) - return None + return response.text def get_integration_content_stream( self, diff --git a/crowdsec_service_api/services/metrics.py b/crowdsec_service_api/services/metrics.py index 8f5d97f..c0362b9 100644 --- a/crowdsec_service_api/services/metrics.py +++ b/crowdsec_service_api/services/metrics.py @@ -10,6 +10,8 @@ from ..http_client import HttpClient class Metrics(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") def get_metrics_remediation( self, diff --git a/crowdsec_service_api/services/products.py b/crowdsec_service_api/services/products.py new file mode 100644 index 0000000..c9d1724 --- /dev/null +++ b/crowdsec_service_api/services/products.py @@ -0,0 +1,65 @@ +import json +from types import NoneType +from typing import Optional, Union, Annotated + +from ..models import * +from ..base_model import Page, Service +from pydantic import BaseModel, Field +from pydantic.fields import FieldInfo +from httpx import Auth +from ..http_client import HttpClient + +class Products(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") + + def get_products( + self, + query: Optional[str] = None, + page: int = 1, + size: int = 50, + )-> LookupListWithStatsResponsePage: + endpoint_url = "/products" + loc = locals() + headers = {} + params = json.loads( + ProductsGetProductsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupListWithStatsResponsePage(_client=self, **response.json()) + + def get_product_impact( + self, + product: str, + sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + page: int = 1, + size: int = 50, + )-> LookupImpactResponsePage: + endpoint_url = "/products/{product}" + loc = locals() + headers = {} + params = json.loads( + ProductsGetProductImpactQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + ProductsGetProductImpactPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupImpactResponsePage(_client=self, **response.json()) + \ No newline at end of file diff --git a/crowdsec_service_api/services/tracker_events.py b/crowdsec_service_api/services/tracker_events.py new file mode 100644 index 0000000..02b131f --- /dev/null +++ b/crowdsec_service_api/services/tracker_events.py @@ -0,0 +1,41 @@ +import json +from types import NoneType +from typing import Optional, Union, Annotated + +from ..models import * +from ..base_model import Page, Service +from pydantic import BaseModel, Field +from pydantic.fields import FieldInfo +from httpx import Auth +from ..http_client import HttpClient + +class TrackerEvents(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") + + def get_exploitation_phase_change_events( + self, + since: str = "30d", + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + cve_id: Optional[str] = None, + previous_phase: Optional[CVEExploitationPhase] = None, + new_phase: Optional[CVEExploitationPhase] = None, + page: int = 1, + size: int = 50, + )-> ExploitationPhaseChangeEventsResponsePage: + endpoint_url = "/tracker-events/exploitation-phase-change" + loc = locals() + headers = {} + params = json.loads( + TrackerEventsGetExploitationPhaseChangeEventsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return ExploitationPhaseChangeEventsResponsePage(_client=self, **response.json()) + \ No newline at end of file diff --git a/crowdsec_service_api/services/tracker_tags.py b/crowdsec_service_api/services/tracker_tags.py new file mode 100644 index 0000000..09609c1 --- /dev/null +++ b/crowdsec_service_api/services/tracker_tags.py @@ -0,0 +1,115 @@ +import json +from types import NoneType +from typing import Optional, Union, Annotated + +from ..models import * +from ..base_model import Page, Service +from pydantic import BaseModel, Field +from pydantic.fields import FieldInfo +from httpx import Auth +from ..http_client import HttpClient + +class TrackerTags(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") + + def get_tags( + self, + query: Optional[str] = None, + page: int = 1, + size: int = 50, + )-> LookupListWithStatsResponsePage: + endpoint_url = "/tags" + loc = locals() + headers = {} + params = json.loads( + TrackerTagsGetTagsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupListWithStatsResponsePage(_client=self, **response.json()) + + def get_tag_impact( + self, + tag: str, + sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + page: int = 1, + size: int = 50, + )-> LookupImpactResponsePage: + endpoint_url = "/tags/{tag}" + loc = locals() + headers = {} + params = json.loads( + TrackerTagsGetTagImpactQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + TrackerTagsGetTagImpactPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupImpactResponsePage(_client=self, **response.json()) + + def get_tracker_tags( + self, + query: Optional[str] = None, + page: int = 1, + size: int = 50, + )-> LookupListWithStatsResponsePage: + endpoint_url = "/tracker-tags" + loc = locals() + headers = {} + params = json.loads( + TrackerTagsGetTrackerTagsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupListWithStatsResponsePage(_client=self, **response.json()) + + def get_tracker_tag_impact( + self, + tag: str, + sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + page: int = 1, + size: int = 50, + )-> LookupImpactResponsePage: + endpoint_url = "/tracker-tags/{tag}" + loc = locals() + headers = {} + params = json.loads( + TrackerTagsGetTrackerTagImpactQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + TrackerTagsGetTrackerTagImpactPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupImpactResponsePage(_client=self, **response.json()) + \ No newline at end of file diff --git a/crowdsec_service_api/services/vendors.py b/crowdsec_service_api/services/vendors.py new file mode 100644 index 0000000..2770575 --- /dev/null +++ b/crowdsec_service_api/services/vendors.py @@ -0,0 +1,232 @@ +import json +from types import NoneType +from typing import Optional, Union, Annotated + +from ..models import * +from ..base_model import Page, Service +from pydantic import BaseModel, Field +from pydantic.fields import FieldInfo +from httpx import Auth +from ..http_client import HttpClient + +class Vendors(Service): + def __init__(self, auth: Auth, base_url: str = "https://admin.api.crowdsec.net/v1") -> None: + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/v0.15.25") + + def get_vendors( + self, + query: Optional[str] = None, + sort_by: Optional[VendorSortBy] = None, + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + page: int = 1, + size: int = 50, + )-> LookupListWithStatsResponsePage: + endpoint_url = "/vendors" + loc = locals() + headers = {} + params = json.loads( + VendorsGetVendorsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = {} + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupListWithStatsResponsePage(_client=self, **response.json()) + + def get_vendor_stats( + self, + vendor: str, + )-> VendorStatsResponse: + endpoint_url = "/vendors/{vendor}/stats" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + VendorsGetVendorStatsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return VendorStatsResponse(**response.json()) + + def download_vendor_ips( + self, + vendor: str, + )-> str: + endpoint_url = "/vendors/{vendor}/ips-download" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + VendorsDownloadVendorIpsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return response.text + + def get_vendor_ips_details( + self, + vendor: str, + since: Optional[str] = "14d", + page: int = 1, + size: int = 50, + )-> GetVendorIPsResponsePage: + endpoint_url = "/vendors/{vendor}/ips-details" + loc = locals() + headers = {} + params = json.loads( + VendorsGetVendorIpsDetailsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + VendorsGetVendorIpsDetailsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetVendorIPsResponsePage(_client=self, **response.json()) + + def get_vendor_ips_details_stats( + self, + vendor: str, + since: Optional[str] = "14d", + )-> IpsDetailsStats: + endpoint_url = "/vendors/{vendor}/ips-details-stats" + loc = locals() + headers = {} + params = json.loads( + VendorsGetVendorIpsDetailsStatsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + VendorsGetVendorIpsDetailsStatsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return IpsDetailsStats(**response.json()) + + def get_vendor_subscribed_integrations( + self, + vendor: str, + page: int = 1, + size: int = 50, + )-> GetVendorSubscribedIntegrationsResponsePage: + endpoint_url = "/vendors/{vendor}/integrations" + loc = locals() + headers = {} + params = json.loads( + VendorsGetVendorSubscribedIntegrationsQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + VendorsGetVendorSubscribedIntegrationsPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return GetVendorSubscribedIntegrationsResponsePage(_client=self, **response.json()) + + def subscribe_integration_to_vendor( + self, + request: SubscribeVendorIntegrationRequest, + vendor: str, + ): + endpoint_url = "/vendors/{vendor}/integrations" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + VendorsSubscribeIntegrationToVendorPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + payload = json.loads( + request.model_dump_json( + exclude_none=True + ) + ) if "request" in loc else None + response = self.http_client.post( + url=endpoint_url, path_params=path_params, params=params, headers=headers, json=payload + ) + + return None + + def unsubscribe_integration_from_vendor( + self, + vendor: str, + integration_name: str, + ): + endpoint_url = "/vendors/{vendor}/integrations/{integration_name}" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + VendorsUnsubscribeIntegrationFromVendorPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.delete( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return None + + def get_vendor_impact( + self, + vendor: str, + sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), + sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + page: int = 1, + size: int = 50, + )-> LookupImpactResponsePage: + endpoint_url = "/vendors/{vendor}" + loc = locals() + headers = {} + params = json.loads( + VendorsGetVendorImpactQueryParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + path_params = json.loads( + VendorsGetVendorImpactPathParameters(**loc).model_dump_json( + exclude_none=True + ) + ) + + response = self.http_client.get( + url=endpoint_url, path_params=path_params, params=params, headers=headers + ) + + return LookupImpactResponsePage(_client=self, **response.json()) + \ No newline at end of file diff --git a/doc/Allowlists.md b/doc/Allowlists.md index 90cccd2..b215c8b 100644 --- a/doc/Allowlists.md +++ b/doc/Allowlists.md @@ -38,16 +38,19 @@ ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.list_allowlists( - page=1, - size=50, -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.list_allowlists( + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -71,20 +74,23 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, AllowlistCreateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) +client = Allowlists(auth=auth) request = AllowlistCreateRequest( name=None, description=None, ) -response = client.create_allowlist( - request=request, -) -print(response) +try: + response = client.create_allowlist( + request=request, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -109,15 +115,18 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.get_allowlist( - allowlist_id='allowlist_id', -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.get_allowlist( + allowlist_id='allowlist_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -141,16 +150,19 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.delete_allowlist( - allowlist_id='allowlist_id', - force=True, -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.delete_allowlist( + allowlist_id='allowlist_id', + force=True, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -176,21 +188,24 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, AllowlistUpdateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) +client = Allowlists(auth=auth) request = AllowlistUpdateRequest( name=None, description=None, ) -response = client.update_allowlist( - request=request, - allowlist_id='allowlist_id', -) -print(response) +try: + response = client.update_allowlist( + request=request, + allowlist_id='allowlist_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -217,17 +232,20 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.get_allowlist_items( - allowlist_id='allowlist_id', - page=1, - size=50, -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.get_allowlist_items( + allowlist_id='allowlist_id', + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -251,22 +269,25 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, AllowlistItemsCreateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) +client = Allowlists(auth=auth) request = AllowlistItemsCreateRequest( items=None, description=None, expiration=None, ) -response = client.create_allowlist_items( - request=request, - allowlist_id='allowlist_id', -) -print(response) +try: + response = client.create_allowlist_items( + request=request, + allowlist_id='allowlist_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -292,16 +313,19 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.get_allowlist_item( - allowlist_id='allowlist_id', - item_id='item_id', -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.get_allowlist_item( + allowlist_id='allowlist_id', + item_id='item_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -325,16 +349,19 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.delete_allowlist_item( - allowlist_id='allowlist_id', - item_id='item_id', -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.delete_allowlist_item( + allowlist_id='allowlist_id', + item_id='item_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -361,22 +388,25 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, AllowlistItemUpdateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) +client = Allowlists(auth=auth) request = AllowlistItemUpdateRequest( description=None, expiration=None, ) -response = client.update_allowlist_item( - request=request, - allowlist_id='allowlist_id', - item_id='item_id', -) -print(response) +try: + response = client.update_allowlist_item( + request=request, + allowlist_id='allowlist_id', + item_id='item_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -403,17 +433,20 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.get_allowlist_subscribers( - allowlist_id='allowlist_id', - page=1, - size=50, -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.get_allowlist_subscribers( + allowlist_id='allowlist_id', + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -439,21 +472,24 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, AllowlistSubscriptionRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) +client = Allowlists(auth=auth) request = AllowlistSubscriptionRequest( ids=None, entity_type=None, ) -response = client.subscribe_allowlist( - request=request, - allowlist_id='allowlist_id', -) -print(response) +try: + response = client.subscribe_allowlist( + request=request, + allowlist_id='allowlist_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -477,15 +513,18 @@ print(response) ```python from crowdsec_service_api import ( Allowlists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Allowlists(base_url=Server.production_server.value, auth=auth) -response = client.unsubscribe_allowlist( - allowlist_id='allowlist_id', - entity_id='entity_id', -) -print(response) +client = Allowlists(auth=auth) +try: + response = client.unsubscribe_allowlist( + allowlist_id='allowlist_id', + entity_id='entity_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` diff --git a/doc/Blocklists.md b/doc/Blocklists.md index cd370ab..78168f1 100644 --- a/doc/Blocklists.md +++ b/doc/Blocklists.md @@ -45,21 +45,24 @@ ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) -response = client.get_blocklists( - page=1, - page_size=100, - subscribed_only=True, - exclude_subscribed=True, - include_filter=['private', 'shared'], - category=None, - size=50, -) -print(response) +client = Blocklists(auth=auth) +try: + response = client.get_blocklists( + page=1, + page_size=100, + subscribed_only=True, + exclude_subscribed=True, + include_filter=['private', 'shared'], + category=None, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -84,12 +87,12 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistCreateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistCreateRequest( name=None, label=None, @@ -97,10 +100,13 @@ request = BlocklistCreateRequest( references=None, tags=None, ) -response = client.create_blocklist( - request=request, -) -print(response) +try: + response = client.create_blocklist( + request=request, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -126,12 +132,12 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistSearchRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistSearchRequest( page=None, page_size=None, @@ -146,12 +152,15 @@ request = BlocklistSearchRequest( is_private=None, is_subscribed=None, ) -response = client.search_blocklist( - request=request, - page=1, - size=50, -) -print(response) +try: + response = client.search_blocklist( + request=request, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -176,15 +185,18 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) -response = client.get_blocklist( - blocklist_id='sample-blocklist-id', -) -print(response) +client = Blocklists(auth=auth) +try: + response = client.get_blocklist( + blocklist_id='sample-blocklist-id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -208,16 +220,19 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) -response = client.delete_blocklist( - blocklist_id='sample-blocklist-id', - force=True, -) -print(response) +client = Blocklists(auth=auth) +try: + response = client.delete_blocklist( + blocklist_id='sample-blocklist-id', + force=True, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -245,12 +260,12 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistUpdateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistUpdateRequest( label=None, description=None, @@ -259,11 +274,14 @@ request = BlocklistUpdateRequest( from_cti_query=None, since=None, ) -response = client.update_blocklist( - request=request, - blocklist_id='sample-blocklist-id', -) -print(response) +try: + response = client.update_blocklist( + request=request, + blocklist_id='sample-blocklist-id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -290,21 +308,24 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistAddIPsRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistAddIPsRequest( ips=None, expiration=None, ) -response = client.add_ips_to_blocklist( - request=request, - blocklist_id='sample-blocklist-id', -) -print(response) +try: + response = client.add_ips_to_blocklist( + request=request, + blocklist_id='sample-blocklist-id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -331,21 +352,24 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistAddIPsRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistAddIPsRequest( ips=None, expiration=None, ) -response = client.overwrite_ips( - request=request, - blocklist_id='sample-blocklist-id', -) -print(response) +try: + response = client.overwrite_ips( + request=request, + blocklist_id='sample-blocklist-id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -371,20 +395,23 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistDeleteIPsRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistDeleteIPsRequest( ips=None, ) -response = client.delete_ips_from_blocklist( - request=request, - blocklist_id='sample-blocklist-id', -) -print(response) +try: + response = client.delete_ips_from_blocklist( + request=request, + blocklist_id='sample-blocklist-id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -413,17 +440,20 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) -response = client.download_blocklist_content( - blocklist_id='sample-blocklist-id', - if_modified_since=None, - if_none_match=None, -) -print(response) +client = Blocklists(auth=auth) +try: + response = client.download_blocklist_content( + blocklist_id='sample-blocklist-id', + if_modified_since=None, + if_none_match=None, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -450,17 +480,20 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) -response = client.get_blocklist_subscribers( - blocklist_id='sample-blocklist-id', - page=1, - size=50, -) -print(response) +client = Blocklists(auth=auth) +try: + response = client.get_blocklist_subscribers( + blocklist_id='sample-blocklist-id', + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -486,22 +519,25 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistSubscriptionRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistSubscriptionRequest( ids=None, entity_type=None, remediation=None, ) -response = client.subscribe_blocklist( - request=request, - blocklist_id='sample-blocklist-id', -) -print(response) +try: + response = client.subscribe_blocklist( + request=request, + blocklist_id='sample-blocklist-id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -525,16 +561,19 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) -response = client.unsubscribe_blocklist( - blocklist_id='sample-blocklist-id', - entity_id='entity_id', -) -print(response) +client = Blocklists(auth=auth) +try: + response = client.unsubscribe_blocklist( + blocklist_id='sample-blocklist-id', + entity_id='entity_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -559,20 +598,23 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, BlocklistShareRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) +client = Blocklists(auth=auth) request = BlocklistShareRequest( organizations=None, ) -response = client.share_blocklist( - request=request, - blocklist_id='sample-blocklist-id', -) -print(response) +try: + response = client.share_blocklist( + request=request, + blocklist_id='sample-blocklist-id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -597,15 +639,18 @@ print(response) ```python from crowdsec_service_api import ( Blocklists, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Blocklists(base_url=Server.production_server.value, auth=auth) -response = client.unshare_blocklist( - blocklist_id='sample-blocklist-id', - unshare_organization_id='unshare_organization_id', -) -print(response) +client = Blocklists(auth=auth) +try: + response = client.unshare_blocklist( + blocklist_id='sample-blocklist-id', + unshare_organization_id='unshare_organization_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` diff --git a/doc/Cves.md b/doc/Cves.md index c8f396a..4b9c0ac 100644 --- a/doc/Cves.md +++ b/doc/Cves.md @@ -3,10 +3,61 @@ # Cves Methods | Method | Description | | ------ | ----------- | +| [get_cves](#get_cves) | Get a paginated list of CVEs that CrowdSec is tracking | | [get_cve](#get_cve) | Get information about a specific CVE ID | -| [get_cve_ips](#get_cve_ips) | Get information about IPs exploiting a specific CVE ID | +| [get_cve_protect_rules](#get_cve_protect_rules) | Get protection/detection rules associated with a specific CVE ID | +| [download_cve_ips](#download_cve_ips) | Download the list of IPs exploiting a specific CVE ID in raw format | +| [get_cve_ips_details](#get_cve_ips_details) | Get detailed information about IPs exploiting a specific CVE ID | +| [get_cve_ips_details_stats](#get_cve_ips_details_stats) | Get aggregated statistics about IPs exploiting a specific CVE ID | +| [get_cve_subscribed_integrations](#get_cve_subscribed_integrations) | Get the list of integrations subscribed to a specific CVE ID | | [subscribe_integration_to_cve](#subscribe_integration_to_cve) | Subscribe an integration to receive threats related to a specific CVE ID | | [unsubscribe_integration_from_cve](#unsubscribe_integration_from_cve) | Unsubscribe an integration from receiving threats related to a specific CVE ID | +| [get_cve_timeline](#get_cve_timeline) | Get timeline data of occurrences for a specific CVE ID | + +## **get_cves** +### Get a paginated list of CVEs that CrowdSec is tracking +- Endpoint: `/cves` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| query | Optional[str] | Search query for CVEs | False | None | +| sort_by | Optional[GetCVEsSortBy] | Field to sort by | False | GetCVEsSortBy("rule_release_date") | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: ascending or descending | False | GetCVEsSortOrder("desc") | +| exploitation_phase | Optional[CVEExploitationPhase] | Filter by exploitation phase | False | None | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[GetCVEsResponsePage](./Models.md#getcvesresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Cves, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Cves(auth=auth) +try: + response = client.get_cves( + query=None, + sort_by=rule_release_date, + sort_order=desc, + exploitation_phase=None, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + ## **get_cve** ### Get information about a specific CVE ID @@ -29,28 +80,103 @@ ```python from crowdsec_service_api import ( Cves, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Cves(auth=auth) +try: + response = client.get_cve( + cve_id='cve_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_cve_protect_rules** +### Get protection/detection rules associated with a specific CVE ID +- Endpoint: `/cves/{cve_id}/protect-rules` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| cve_id | str | | True | | +### Returns: +[GetCVEProtectRulesResponse](./Models.md#getcveprotectrulesresponse) +### Errors: +| Code | Description | +| ---- | ----------- | +| 404 | CVE Not Found | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Cves, + ApiKeyAuth, +) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Cves(base_url=Server.production_server.value, auth=auth) -response = client.get_cve( - cve_id='cve_id', +client = Cves(auth=auth) +try: + response = client.get_cve_protect_rules( + cve_id='cve_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **download_cve_ips** +### Download the list of IPs exploiting a specific CVE ID in raw format +- Endpoint: `/cves/{cve_id}/ips-download` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| cve_id | str | | True | | +### Returns: +[str](./Models.md#str) +### Errors: +| Code | Description | +| ---- | ----------- | +| 404 | CVE Not Found | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Cves, + ApiKeyAuth, ) -print(response) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Cves(auth=auth) +try: + response = client.download_cve_ips( + cve_id='cve_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` -## **get_cve_ips** -### Get information about IPs exploiting a specific CVE ID -- Endpoint: `/cves/{cve_id}/ips` +## **get_cve_ips_details** +### Get detailed information about IPs exploiting a specific CVE ID +- Endpoint: `/cves/{cve_id}/ips-details` - Method: `GET` ### Parameters: | Parameter | Type | Description | Required | Default | | --------- | ---- | ----------- | -------- | ------- | | cve_id | str | | True | | -| since | Optional[str] | Filter IPs seen since this date, format duration (e.g., 7d, 24h) | False | None | +| since | Optional[str] | Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d | False | "14d" | | page | int | Page number | False | 1 | | size | int | Page size | False | 50 | ### Returns: @@ -65,18 +191,99 @@ print(response) ```python from crowdsec_service_api import ( Cves, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Cves(base_url=Server.production_server.value, auth=auth) -response = client.get_cve_ips( - cve_id='cve_id', - since=None, - page=1, - size=50, +client = Cves(auth=auth) +try: + response = client.get_cve_ips_details( + cve_id='cve_id', + since=14d, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_cve_ips_details_stats** +### Get aggregated statistics about IPs exploiting a specific CVE ID +- Endpoint: `/cves/{cve_id}/ips-details-stats` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| cve_id | str | | True | | +| since | Optional[str] | Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d | False | "14d" | +### Returns: +[IpsDetailsStats](./Models.md#ipsdetailsstats) +### Errors: +| Code | Description | +| ---- | ----------- | +| 404 | CVE Not Found | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Cves, + ApiKeyAuth, ) -print(response) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Cves(auth=auth) +try: + response = client.get_cve_ips_details_stats( + cve_id='cve_id', + since=14d, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_cve_subscribed_integrations** +### Get the list of integrations subscribed to a specific CVE ID +- Endpoint: `/cves/{cve_id}/integrations` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| cve_id | str | | True | | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[GetCVESubscribedIntegrationsResponsePage](./Models.md#getcvesubscribedintegrationsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 404 | CVE Not Found | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Cves, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Cves(auth=auth) +try: + response = client.get_cve_subscribed_integrations( + cve_id='cve_id', + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -101,20 +308,23 @@ print(response) ```python from crowdsec_service_api import ( Cves, - Server, ApiKeyAuth, SubscribeCVEIntegrationRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Cves(base_url=Server.production_server.value, auth=auth) +client = Cves(auth=auth) request = SubscribeCVEIntegrationRequest( name=None, ) -response = client.subscribe_integration_to_cve( - request=request, - cve_id='cve_id', -) -print(response) +try: + response = client.subscribe_integration_to_cve( + request=request, + cve_id='cve_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -139,15 +349,56 @@ print(response) ```python from crowdsec_service_api import ( Cves, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Cves(base_url=Server.production_server.value, auth=auth) -response = client.unsubscribe_integration_from_cve( - cve_id='cve_id', - integration_name='integration_name', +client = Cves(auth=auth) +try: + response = client.unsubscribe_integration_from_cve( + cve_id='cve_id', + integration_name='integration_name', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_cve_timeline** +### Get timeline data of occurrences for a specific CVE ID +- Endpoint: `/cves/{cve_id}/timeline` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| cve_id | str | | True | | +| since_days | SinceOptions | Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days. | False | | +### Returns: +[list[TimelineItem]](./Models.md#list[timelineitem]) +### Errors: +| Code | Description | +| ---- | ----------- | +| 404 | CVE Not Found | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Cves, + ApiKeyAuth, ) -print(response) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Cves(auth=auth) +try: + response = client.get_cve_timeline( + cve_id='cve_id', + since_days=None, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` diff --git a/doc/Decisions.md b/doc/Decisions.md new file mode 100644 index 0000000..e4248a1 --- /dev/null +++ b/doc/Decisions.md @@ -0,0 +1,113 @@ + + +# Decisions Methods +| Method | Description | +| ------ | ----------- | +| [get_decisions](#get_decisions) | Get decisions | +| [create_decision](#create_decision) | Create a new decision. | + +## **get_decisions** +### Get decisions +- Endpoint: `/decisions` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| instance_ids | list[str] | Filter decisions by instance IDs | False | [] | +| tag_ids | list[str] | Filter decisions by tag IDs | False | [] | +| remediation_types | list[str] | Filter decisions by remediation types | False | [] | +| ips | list[str] | Filter decisions by IPs (only for IP decisions) | False | [] | +| sort_by | Optional[DecisionsSortBy] | Field to sort by (e.g., created_at, duration) | False | DecisionsSortBy("created_at") | +| sort_order | Optional[DecisionsSortOrder] | Sort order: 'asc' for ascending, 'desc' for descending | False | DecisionsSortOrder("desc") | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[DecisionsGetResponsePage](./Models.md#decisionsgetresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 404 | Not found | +| 500 | Internal server error | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Decisions, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Decisions(auth=auth) +try: + response = client.get_decisions( + instance_ids=['sample-item'], + tag_ids=['sample-item'], + remediation_types=['sample-item'], + ips=['sample-item'], + sort_by=created_at, + sort_order=desc, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **create_decision** +### Create a new decision. +- Endpoint: `/decisions` +- Method: `POST` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| request | [DecisionCreateRequest](./Models.md#decisioncreaterequest) | Request body | Yes | - | +### Returns: +[DecisionCreateResponse](./Models.md#decisioncreateresponse) +### Errors: +| Code | Description | +| ---- | ----------- | +| 409 | Conflict: Decision value is in allowlists; cannot create decision. | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Decisions, + ApiKeyAuth, + DecisionCreateRequest, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Decisions(auth=auth) +request = DecisionCreateRequest( + created_at=None, + uuid=None, + id=None, + duration=None, + origin=None, + scenario=None, + scope=None, + type=None, + value=None, + country=None, + as_name=None, + as_num=None, + city=None, + latitude=None, + longitude=None, + target=None, +) +try: + response = client.create_decision( + request=request, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + diff --git a/doc/Fingerprints.md b/doc/Fingerprints.md new file mode 100644 index 0000000..8336e47 --- /dev/null +++ b/doc/Fingerprints.md @@ -0,0 +1,357 @@ + + +# Fingerprints Methods +| Method | Description | +| ------ | ----------- | +| [get_fingerprint_rules](#get_fingerprint_rules) | Get a paginated list of fingerprint rules | +| [download_fingerprint_ips](#download_fingerprint_ips) | Download the list of IPs exploiting a specific fingerprint rule in raw format | +| [get_fingerprint_ips_details](#get_fingerprint_ips_details) | Get detailed information about IPs exploiting a specific fingerprint rule | +| [get_fingerprint_ips_details_stats](#get_fingerprint_ips_details_stats) | Get aggregated statistics about IPs exploiting a specific fingerprint rule | +| [get_fingerprint_subscribed_integrations](#get_fingerprint_subscribed_integrations) | Get the list of integrations subscribed to a specific fingerprint rule | +| [subscribe_integration_to_fingerprint](#subscribe_integration_to_fingerprint) | Subscribe an integration to receive threats related to a specific fingerprint rule | +| [unsubscribe_integration_from_fingerprint](#unsubscribe_integration_from_fingerprint) | Unsubscribe an integration from receiving threats related to a specific fingerprint rule | +| [get_fingerprint_timeline](#get_fingerprint_timeline) | Get timeline data of occurrences for a specific fingerprint rule | +| [get_fingerprint_rule](#get_fingerprint_rule) | Get information about a specific fingerprint rule | + +## **get_fingerprint_rules** +### Get a paginated list of fingerprint rules +- Endpoint: `/fingerprints` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| query | Optional[str] | Search query for fingerprint rules | False | None | +| sort_by | Optional[GetCVEsSortBy] | Field to sort by | False | GetCVEsSortBy("rule_release_date") | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: ascending or descending | False | GetCVEsSortOrder("desc") | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[GetFingerprintRulesResponsePage](./Models.md#getfingerprintrulesresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.get_fingerprint_rules( + query=None, + sort_by=rule_release_date, + sort_order=desc, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **download_fingerprint_ips** +### Download the list of IPs exploiting a specific fingerprint rule in raw format +- Endpoint: `/fingerprints/{fingerprint}/ips-download` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| fingerprint | str | | True | | +### Returns: +[str](./Models.md#str) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.download_fingerprint_ips( + fingerprint='fingerprint', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_fingerprint_ips_details** +### Get detailed information about IPs exploiting a specific fingerprint rule +- Endpoint: `/fingerprints/{fingerprint}/ips-details` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| fingerprint | str | | True | | +| since | Optional[str] | Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d | False | "14d" | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[GetFingerprintIPsResponsePage](./Models.md#getfingerprintipsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.get_fingerprint_ips_details( + fingerprint='fingerprint', + since=14d, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_fingerprint_ips_details_stats** +### Get aggregated statistics about IPs exploiting a specific fingerprint rule +- Endpoint: `/fingerprints/{fingerprint}/ips-details-stats` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| fingerprint | str | | True | | +| since | Optional[str] | Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d | False | "14d" | +### Returns: +[IpsDetailsStats](./Models.md#ipsdetailsstats) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.get_fingerprint_ips_details_stats( + fingerprint='fingerprint', + since=14d, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_fingerprint_subscribed_integrations** +### Get the list of integrations subscribed to a specific fingerprint rule +- Endpoint: `/fingerprints/{fingerprint}/integrations` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| fingerprint | str | | True | | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[GetFingerprintSubscribedIntegrationsResponsePage](./Models.md#getfingerprintsubscribedintegrationsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.get_fingerprint_subscribed_integrations( + fingerprint='fingerprint', + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **subscribe_integration_to_fingerprint** +### Subscribe an integration to receive threats related to a specific fingerprint rule +- Endpoint: `/fingerprints/{fingerprint}/integrations` +- Method: `POST` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| request | [SubscribeFingerprintIntegrationRequest](./Models.md#subscribefingerprintintegrationrequest) | Request body | Yes | - | +| fingerprint | str | | True | | +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, + SubscribeFingerprintIntegrationRequest, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +request = SubscribeFingerprintIntegrationRequest( + name=None, +) +try: + response = client.subscribe_integration_to_fingerprint( + request=request, + fingerprint='fingerprint', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **unsubscribe_integration_from_fingerprint** +### Unsubscribe an integration from receiving threats related to a specific fingerprint rule +- Endpoint: `/fingerprints/{fingerprint}/integrations/{integration_name}` +- Method: `DELETE` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| fingerprint | str | | True | | +| integration_name | str | | True | | +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.unsubscribe_integration_from_fingerprint( + fingerprint='fingerprint', + integration_name='integration_name', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_fingerprint_timeline** +### Get timeline data of occurrences for a specific fingerprint rule +- Endpoint: `/fingerprints/{fingerprint}/timeline` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| fingerprint | str | | True | | +| since_days | SinceOptions | Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days. | False | | +| interval | Optional[IntervalOptions] | Interval for aggregating timeline data. Options: 'hour', 'day', 'week'. Default is adapted based on 'since' parameter. | False | None | +### Returns: +[list[FingerprintTimelineItem]](./Models.md#list[fingerprinttimelineitem]) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.get_fingerprint_timeline( + fingerprint='fingerprint', + since_days=None, + interval=None, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_fingerprint_rule** +### Get information about a specific fingerprint rule +- Endpoint: `/fingerprints/{fingerprint}` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| fingerprint | str | | True | | +### Returns: +[FingerprintRuleResponse](./Models.md#fingerprintruleresponse) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Fingerprints, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Fingerprints(auth=auth) +try: + response = client.get_fingerprint_rule( + fingerprint='fingerprint', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + diff --git a/doc/Hub.md b/doc/Hub.md index 677fb51..8ee7fc9 100644 --- a/doc/Hub.md +++ b/doc/Hub.md @@ -36,17 +36,20 @@ content is returned. | ```python from crowdsec_service_api import ( Hub, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Hub(base_url=Server.production_server.value, auth=auth) -response = client.get_index( - branch='branch', - tenant='tenant', - with_content=True, -) -print(response) +client = Hub(auth=auth) +try: + response = client.get_index( + branch='branch', + tenant='tenant', + with_content=True, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -74,17 +77,20 @@ cache expiration policies. No body content is returned. ```python from crowdsec_service_api import ( Hub, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Hub(base_url=Server.production_server.value, auth=auth) -response = client.head_index( - branch='branch', - tenant='tenant', - with_content=True, -) -print(response) +client = Hub(auth=auth) +try: + response = client.head_index( + branch='branch', + tenant='tenant', + with_content=True, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -109,17 +115,20 @@ print(response) ```python from crowdsec_service_api import ( Hub, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Hub(base_url=Server.production_server.value, auth=auth) -response = client.get_item_content( - item_path='item_path', - branch='branch', - tenant='tenant', -) -print(response) +client = Hub(auth=auth) +try: + response = client.get_item_content( + item_path='item_path', + branch='branch', + tenant='tenant', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -145,16 +154,19 @@ content is returned. ```python from crowdsec_service_api import ( Hub, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Hub(base_url=Server.production_server.value, auth=auth) -response = client.head_item_content( - item_path='item_path', - branch='branch', - tenant='tenant', -) -print(response) +client = Hub(auth=auth) +try: + response = client.head_item_content( + item_path='item_path', + branch='branch', + tenant='tenant', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` diff --git a/doc/Info.md b/doc/Info.md index 32f783f..234ba08 100644 --- a/doc/Info.md +++ b/doc/Info.md @@ -20,13 +20,16 @@ ```python from crowdsec_service_api import ( Info, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Info(base_url=Server.production_server.value, auth=auth) -response = client.get_info( -) -print(response) +client = Info(auth=auth) +try: + response = client.get_info( + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` diff --git a/doc/Integrations.md b/doc/Integrations.md index 0c8619d..2eb97aa 100644 --- a/doc/Integrations.md +++ b/doc/Integrations.md @@ -34,17 +34,20 @@ ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) -response = client.get_integrations( - tag=None, - page=1, - size=50, -) -print(response) +client = Integrations(auth=auth) +try: + response = client.get_integrations( + tag=None, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -68,22 +71,27 @@ print(response) ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, IntegrationCreateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) +client = Integrations(auth=auth) request = IntegrationCreateRequest( name=None, description=None, entity_type=None, output_format=None, + pull_limit=None, + enable_ip_aggregation=None, ) -response = client.create_integration( - request=request, -) -print(response) +try: + response = client.create_integration( + request=request, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -107,15 +115,18 @@ print(response) ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) -response = client.get_integration( - integration_id='integration_id', -) -print(response) +client = Integrations(auth=auth) +try: + response = client.get_integration( + integration_id='integration_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -128,6 +139,7 @@ print(response) | Parameter | Type | Description | Required | Default | | --------- | ---- | ----------- | -------- | ------- | | integration_id | str | | True | | +| force | bool | Force delete the integration even if it has active subscriptions (it will unsubscribe from all lists) | False | False | ### Errors: | Code | Description | | ---- | ----------- | @@ -137,15 +149,19 @@ print(response) ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) -response = client.delete_integration( - integration_id='integration_id', -) -print(response) +client = Integrations(auth=auth) +try: + response = client.delete_integration( + integration_id='integration_id', + force=True, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -170,23 +186,28 @@ print(response) ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, IntegrationUpdateRequest, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) +client = Integrations(auth=auth) request = IntegrationUpdateRequest( name=None, description=None, output_format=None, regenerate_credentials=None, + pull_limit=None, + enable_ip_aggregation=None, ) -response = client.update_integration( - request=request, - integration_id='integration_id', -) -print(response) +try: + response = client.update_integration( + request=request, + integration_id='integration_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -201,27 +222,37 @@ print(response) | integration_id | str | | True | | | page | int | Page number to return | False | 1 | | page_size | Optional[int] | Maximum number of items to return, 0 means no limit (default), should be greater than 10000 | False | None | +| pull_limit | Optional[int] | | False | None | +| enable_ip_aggregation | bool | | False | False | +### Returns: +[str](./Models.md#str) ### Errors: | Code | Description | | ---- | ----------- | | 404 | Integration not found | +| 204 | Integration has no subscribed blocklists or no content available | | 422 | Validation Error | ### Usage ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) -response = client.get_integration_content( - integration_id='integration_id', - page=1, - page_size=None, -) -print(response) +client = Integrations(auth=auth) +try: + response = client.get_integration_content( + integration_id='integration_id', + page=1, + page_size=None, + pull_limit=None, + enable_ip_aggregation=True, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -244,15 +275,18 @@ print(response) ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) -response = client.head_integration_content( - integration_id='integration_id', -) -print(response) +client = Integrations(auth=auth) +try: + response = client.head_integration_content( + integration_id='integration_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` @@ -276,15 +310,18 @@ print(response) ```python from crowdsec_service_api import ( Integrations, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Integrations(base_url=Server.production_server.value, auth=auth) -response = client.get_integration_content_stream( - integration_id='integration_id', - startup=True, -) -print(response) +client = Integrations(auth=auth) +try: + response = client.get_integration_content_stream( + integration_id='integration_id', + startup=True, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` diff --git a/doc/Metrics.md b/doc/Metrics.md index 14a4942..4d88515 100644 --- a/doc/Metrics.md +++ b/doc/Metrics.md @@ -29,18 +29,21 @@ ```python from crowdsec_service_api import ( Metrics, - Server, ApiKeyAuth, ) +from httpx import HTTPStatusError auth = ApiKeyAuth(api_key='your_api_key') -client = Metrics(base_url=Server.production_server.value, auth=auth) -response = client.get_metrics_remediation( - start_date='start_date', - end_date='end_date', - engine_ids=['sample-item'], - integration_ids=['sample-item'], - tags=['sample-item'], -) -print(response) +client = Metrics(auth=auth) +try: + response = client.get_metrics_remediation( + start_date='start_date', + end_date='end_date', + engine_ids=['sample-item'], + integration_ids=['sample-item'], + tags=['sample-item'], + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` diff --git a/doc/Models.md b/doc/Models.md index 89efd30..7e05f77 100644 --- a/doc/Models.md +++ b/doc/Models.md @@ -34,7 +34,7 @@ id, allowlist_id, description, scope, value, created_at, created_by | id | str | ID of the allowlist entry || | allowlist_id | str | ID of the allowlist || | description | str | Description of the allowlist entry || -| scope | str | None || +| scope | AllowlistScope | None || | value | Union[str, str] | Value of the allowlist entry || | created_at | str | Time the allowlist entry was created || | updated_at | Optional[str] | Time the allowlist entry was updated || @@ -101,7 +101,7 @@ id, allowlist_id, description, scope, value, created_at, updated_at, created_by, | id | str | ID of the allowlist entry || | allowlist_id | str | ID of the allowlist || | description | str | Description of the allowlist entry || -| scope | str | None || +| scope | AllowlistScope | None || | value | Union[str, str] | Value of the allowlist entry || | created_at | str | Time the allowlist entry was created || | updated_at | str | Time the allowlist entry was updated || @@ -130,7 +130,7 @@ id, entity_type | Property | Type | Description | Example | |----------|------|-------------|---------| | id | str | Subscriber entity id || -| entity_type | str | None || +| entity_type | SubscriberEntityType | None || # **AllowlistSubscriberEntityPage** ## Required: @@ -151,7 +151,7 @@ entity_type, count ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| -| entity_type | str | None || +| entity_type | SubscriberEntityType | None || | count | int | Subscriber entity count || # **AllowlistSubscriptionRequest** @@ -161,7 +161,7 @@ entity_type | Property | Type | Description | Example | |----------|------|-------------|---------| | ids | list[str] | List of subscriber entity id || -| entity_type | str | None || +| entity_type | EntityType | None || # **AllowlistSubscriptionResponse** ## Required: @@ -294,7 +294,7 @@ label, id, pricing_tier |----------|------|-------------|---------| | label | str | Label of the blocklist || | id | str | ID of the blocklist || -| pricing_tier | str | None || +| pricing_tier | PricingTiers | None || # **BlocklistSearchRequest** ## Properties @@ -347,7 +347,7 @@ id, entity_type, remediation | Property | Type | Description | Example | |----------|------|-------------|---------| | id | str | Subscriber entity id || -| entity_type | str | None || +| entity_type | SubscriberEntityType | None || | remediation | str | Remediation || # **BlocklistSubscriberEntityPage** @@ -369,7 +369,7 @@ entity_type, count ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| -| entity_type | str | None || +| entity_type | SubscriberEntityType | None || | count | int | Subscriber entity count || # **BlocklistSubscription** @@ -390,7 +390,7 @@ entity_type | Property | Type | Description | Example | |----------|------|-------------|---------| | ids | list[str] | List of subscriber entity id || -| entity_type | str | None || +| entity_type | SubscriberEntityType | None || | remediation | Optional[str] | Remediation || # **BlocklistSubscriptionResponse** @@ -432,6 +432,14 @@ file |----------|------|-------------|---------| | file | str | Blocklist file in txt format || +# **CVESubscription** +## Required: +id +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | CVE ID || + # **ComputedMetrics** ## Required: saved @@ -514,10 +522,106 @@ name, label, description, references, total_ips | references | list[str] | None || | total_ips | int | None || +# **DecisionCreateRequest** +## Required: +duration, origin, scenario, scope, type, value, target +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| created_at | str | None || +| uuid | Optional[str] | UUID of the decision || +| id | Optional[int] | ID of the decision || +| duration | str | Duration of the decision || +| origin | str | Origin of the decision || +| scenario | str | Scenario of the decision || +| scope | str | Scope of the decision || +| type | str | Type of the decision || +| value | str | Value of the decision || +| country | Optional[str] | Country associated with the decision || +| as_name | Optional[str] | AS name associated with the decision || +| as_num | Optional[int] | AS number associated with the decision || +| city | Optional[str] | City associated with the decision || +| latitude | Optional[float] | Latitude associated with the decision || +| longitude | Optional[float] | Longitude associated with the decision || +| target | DecisionTargetModel | None || + +# **DecisionCreateResponse** +## Required: +uuid +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| uuid | str | UUID of the created decision || + +# **DecisionResponse** +## Required: +uuid, id, duration, origin, scenario, scope, type, value, target +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| created_at | str | None || +| uuid | str | UUID of the decision || +| id | int | ID of the decision || +| duration | str | Duration of the decision || +| origin | str | Origin of the decision || +| scenario | str | Scenario of the decision || +| scope | str | Scope of the decision || +| type | str | Type of the decision || +| value | str | Value of the decision || +| country | Optional[str] | Country associated with the decision || +| as_name | Optional[str] | AS name associated with the decision || +| as_num | Optional[int] | AS number associated with the decision || +| city | Optional[str] | City associated with the decision || +| latitude | Optional[float] | Latitude associated with the decision || +| longitude | Optional[float] | Longitude associated with the decision || +| target | DecisionTargetModel | None || + +# **DecisionTargetModel** +## Required: +type, value +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| type | DecisionTargetType | None || +| value | str | Value of the decision target || + +# **DecisionTargetType** +## Enum: +ORG, TAG, ENTITY + +# **DecisionsGetResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[DecisionResponse] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **DecisionsSortBy** +## Enum: +CREATED_AT, EXPIRE_AT + +# **DecisionsSortOrder** +## Enum: +ASC, DESC + # **EntityType** ## Enum: ORG, TAG, ENGINE, FIREWALL_INTEGRATION, REMEDIATION_COMPONENT_INTEGRATION, REMEDIATION_COMPONENT, LOG_PROCESSOR +# **FingerprintSubscription** +## Required: +id +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | Fingerprint ID || + # **GetRemediationMetricsResponse** ## Required: raw, computed @@ -551,12 +655,14 @@ name, entity_type, output_format |----------|------|-------------|---------| | name | str | Name of the integration || | description | str | Description of the integration || -| entity_type | str | None || -| output_format | str | None || +| entity_type | IntegrationType | None || +| output_format | OutputFormat | None || +| pull_limit | Optional[int] | Maximum number of items to pull || +| enable_ip_aggregation | bool | Whether to enable IP aggregation into ranges || # **IntegrationCreateResponse** ## Required: -id, name, organization_id, created_at, updated_at, entity_type, output_format, blocklists, endpoint, credentials +id, name, organization_id, created_at, updated_at, entity_type, output_format, blocklists, cves, fingerprints, vendors, endpoint, credentials ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| @@ -566,18 +672,23 @@ id, name, organization_id, created_at, updated_at, entity_type, output_format, b | description | str | Description of the integration || | created_at | str | Time the integration was created || | updated_at | str | Last time the integration was updated || -| entity_type | str | None || -| output_format | str | None || +| entity_type | IntegrationType | None || +| output_format | OutputFormat | None || | last_pull | Optional[str] | Last time the integration pulled blocklists || | blocklists | list[BlocklistSubscription] | Blocklists that are subscribed by the integration || +| cves | list[CVESubscription] | CVEs that are subscribed by the integration || +| fingerprints | list[FingerprintSubscription] | Fingerprints that are subscribed by the integration || +| vendors | list[VendorSubscription] | Vendors that are subscribed by the integration || | endpoint | str | Url that should be used by the firewall or the remediation component to fetch the integration's content || | stats | Stats | None || | tags | list[str] | Tags associated with the integration || +| pull_limit | Optional[int] | Maximum number of items to pull || +| enable_ip_aggregation | bool | Whether to enable IP aggregation into ranges || | credentials | Union[ApiKeyCredentials, BasicAuthCredentials] | Credentials that were generated for the integration || # **IntegrationGetResponse** ## Required: -id, name, organization_id, created_at, updated_at, entity_type, output_format, blocklists, endpoint +id, name, organization_id, created_at, updated_at, entity_type, output_format, blocklists, cves, fingerprints, vendors, endpoint ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| @@ -587,13 +698,18 @@ id, name, organization_id, created_at, updated_at, entity_type, output_format, b | description | str | Description of the integration || | created_at | str | Time the integration was created || | updated_at | str | Last time the integration was updated || -| entity_type | str | None || -| output_format | str | None || +| entity_type | IntegrationType | None || +| output_format | OutputFormat | None || | last_pull | Optional[str] | Last time the integration pulled blocklists || | blocklists | list[BlocklistSubscription] | Blocklists that are subscribed by the integration || +| cves | list[CVESubscription] | CVEs that are subscribed by the integration || +| fingerprints | list[FingerprintSubscription] | Fingerprints that are subscribed by the integration || +| vendors | list[VendorSubscription] | Vendors that are subscribed by the integration || | endpoint | str | Url that should be used by the firewall or the remediation component to fetch the integration's content || | stats | Stats | None || | tags | list[str] | Tags associated with the integration || +| pull_limit | Optional[int] | Maximum number of items to pull || +| enable_ip_aggregation | bool | Whether to enable IP aggregation into ranges || # **IntegrationGetResponsePage** ## Required: @@ -618,12 +734,14 @@ FIREWALL_INTEGRATION, REMEDIATION_COMPONENT_INTEGRATION |----------|------|-------------|---------| | name | str | New name || | description | str | New description || -| output_format | str | None || +| output_format | OutputFormat | None || | regenerate_credentials | bool | Regenerate credentials for the integration || +| pull_limit | Optional[int] | Maximum number of items to pull || +| enable_ip_aggregation | bool | Whether to enable IP aggregation into ranges || # **IntegrationUpdateResponse** ## Required: -id, name, organization_id, created_at, updated_at, entity_type, output_format, blocklists, endpoint +id, name, organization_id, created_at, updated_at, entity_type, output_format, blocklists, cves, fingerprints, vendors, endpoint ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| @@ -633,13 +751,18 @@ id, name, organization_id, created_at, updated_at, entity_type, output_format, b | description | str | Description of the integration || | created_at | str | Time the integration was created || | updated_at | str | Last time the integration was updated || -| entity_type | str | None || -| output_format | str | None || +| entity_type | IntegrationType | None || +| output_format | OutputFormat | None || | last_pull | Optional[str] | Last time the integration pulled blocklists || | blocklists | list[BlocklistSubscription] | Blocklists that are subscribed by the integration || +| cves | list[CVESubscription] | CVEs that are subscribed by the integration || +| fingerprints | list[FingerprintSubscription] | Fingerprints that are subscribed by the integration || +| vendors | list[VendorSubscription] | Vendors that are subscribed by the integration || | endpoint | str | Url that should be used by the firewall or the remediation component to fetch the integration's content || | stats | Stats | None || | tags | list[str] | Tags associated with the integration || +| pull_limit | Optional[int] | Maximum number of items to pull || +| enable_ip_aggregation | bool | Whether to enable IP aggregation into ranges || | credentials | Optional[ApiKeyCredentials, BasicAuthCredentials] | Credentials for the integration || # **Links** @@ -692,8 +815,8 @@ id, created_at, updated_at, name, description, is_private, pricing_tier, source, | references | list[str] | Blocklist references || | is_private | bool | Private blocklist if True or public if False || | tags | list[str] | Classification tags || -| pricing_tier | str | None || -| source | str | None || +| pricing_tier | PricingTiers | None || +| source | BlocklistSources | None || | stats | BlocklistStats | None || | from_cti_query | Optional[str] | CTI query from which the blocklist was created || | since | Optional[str] | Since duration for the CTI query (eg. 5m, 2h, 7d). Max is 30 days || @@ -729,7 +852,7 @@ total, unit, progression, data | Property | Type | Description | Example | |----------|------|-------------|---------| | total | Union[int, float] | Total value of the metric || -| unit | str | None || +| unit | MetricUnits | None || | progression | Optional[int] | Progression of the metric value from the previous period || | data | list[OriginMetrics] | Data points per origin || @@ -749,7 +872,7 @@ organization_id, permission | Property | Type | Description | Example | |----------|------|-------------|---------| | organization_id | str | None || -| permission | str | None || +| permission | Permission | None || # **SourceInfo** ## Required: @@ -757,7 +880,7 @@ source_type, identifier ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| -| source_type | str | None || +| source_type | SourceType | None || | identifier | str | The source identifier that created the allowlist entry || # **SourceType** @@ -786,6 +909,14 @@ loc, msg, type | msg | str | None || | type | str | None || +# **VendorSubscription** +## Required: +id +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | Vendor ID || + # **AppsecConfigIndex** ## Properties | Property | Type | Description | Example | @@ -904,12 +1035,28 @@ digest | deprecated | Optional[bool] | Indicates whether this version is deprecated. || | digest | str | The SHA256 digest of the versioned file. || +# **AdjustmentScore** +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| total | int | Total score adjustment || +| recency | int | Recency score adjustment || +| low_info | int | Low information score adjustment || + # **AffectedComponent** ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| -| vendor | str | Vendor of the affected component || -| product | str | Product name of the affected component || +| vendor | Optional[str] | Vendor of the affected component || +| product | Optional[str] | Product name of the affected component || + +# **AllowlistSubscription** +## Required: +id +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | None || # **AttackDetail** ## Required: @@ -932,6 +1079,64 @@ name, label, description | label | str | Behavior label || | description | str | Behavior description || +# **CVEEventOutput** +## Required: +name, date, description, label, sorting_priority +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| name | str | None || +| date | str | None || +| description | str | None || +| label | str | None || +| sorting_priority | int | None || + +# **CVEExploitationPhase** +## Enum: +INSUFFICIENT_DATA, EARLY_EXPLOITATION, FRESH_AND_POPULAR, TARGETED_EXPLOITATION, MASS_EXPLOITATION, BACKGROUND_NOISE, UNPOPULAR, WEARING_OUT, UNCLASSIFIED + +# **CVEResponseBase** +## Required: +id, name, title, affected_components, crowdsec_score, nb_ips, published_date, has_public_exploit, exploitation_phase +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | ID of the CVE || +| name | str | Name of the CVE || +| title | str | Title of the CVE || +| affected_components | list[AffectedComponent] | List of affected components || +| crowdsec_score | int | Live Exploit Tracker score of the CVE || +| opportunity_score | int | Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5) || +| momentum_score | int | Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5) || +| first_seen | Optional[str] | First seen date || +| last_seen | Optional[str] | Last seen date || +| nb_ips | int | Number of unique IPs affected || +| published_date | str | Published date of the CVE || +| cvss_score | Optional[float] | CVSS score of the CVE || +| has_public_exploit | bool | Indicates if there is a public exploit for the CVE || +| rule_release_date | Optional[str] | Release date of the associated detection rule || +| exploitation_phase | ExploitationPhase | None || +| adjustment_score | Optional[AdjustmentScore] | Score adjustments applied to the CVE score based on various factors || +| threat_context | Optional[ThreatContext] | Threat context (attacker/defender countries, industries, objectives) || + +# **CVEsubscription** +## Required: +id +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | None || + +# **CWE** +## Required: +name, label, description +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| name | str | Name of the CWE || +| label | str | Label of the CWE || +| description | str | Description of the CWE || + # **Classification** ## Required: name, label, description @@ -949,6 +1154,119 @@ name, label, description | false_positives | list[Classification] | False positive classifications || | classifications | list[Classification] | Main classifications || +# **ExploitationPhase** +## Required: +name, label, description +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| name | str | Name of the exploitation phase || +| label | str | Label of the exploitation phase || +| description | str | Description of the exploitation phase || + +# **ExploitationPhaseChangeEventItem** +## Required: +cve_id, name, date, label, description, previous_phase, new_phase +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| cve_id | str | CVE identifier || +| name | str | Event type name || +| date | str | Date of the phase change || +| label | str | Human-readable event label || +| description | str | Rendered event description || +| previous_phase | str | Previous exploitation phase label || +| new_phase | str | New exploitation phase label || + +# **ExploitationPhaseChangeEventsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[ExploitationPhaseChangeEventItem] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **FacetBucket** +## Required: +value, count +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| value | str | Facet value || +| count | int | Number of IPs matching this value || + +# **FingerprintEventOutput** +## Required: +name, date, description, label +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| name | str | None || +| date | str | None || +| description | str | None || +| label | str | None || + +# **FingerprintRuleResponse** +## Required: +id, name, title, affected_components, crowdsec_score, nb_ips, exploitation_phase +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | Fingerprint rule identifier || +| name | str | Fingerprint rule name || +| title | str | Fingerprint rule title || +| affected_components | list[AffectedComponent] | List of affected components || +| crowdsec_score | int | Live Exploit Tracker score for the fingerprint rule || +| opportunity_score | int | Opportunity score || +| momentum_score | int | Momentum score || +| first_seen | Optional[str] | First seen date || +| last_seen | Optional[str] | Last seen date || +| nb_ips | int | Number of unique IPs observed || +| rule_release_date | Optional[str] | Release date of the fingerprint rule || +| exploitation_phase | ExploitationPhase | None || +| adjustment_score | Optional[AdjustmentScore] | Score adjustment details || +| threat_context | Optional[ThreatContext] | Threat context (attacker/defender countries, industries, objectives) || +| tags | list[str] | Tags associated with the fingerprint rule || +| description | Optional[str] | Fingerprint rule description || +| references | list[str] | Reference links for the fingerprint rule || +| crowdsec_analysis | Optional[str] | CrowdSec analysis for this fingerprint rule || +| events | list[FingerprintEventOutput] | List of events related to the fingerprint rule || + +# **FingerprintRuleSummary** +## Required: +id, name, title, affected_components, crowdsec_score, nb_ips, exploitation_phase +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | Fingerprint rule identifier || +| name | str | Fingerprint rule name || +| title | str | Fingerprint rule title || +| affected_components | list[AffectedComponent] | List of affected components || +| crowdsec_score | int | Live Exploit Tracker score for the fingerprint rule || +| opportunity_score | int | Opportunity score || +| momentum_score | int | Momentum score || +| first_seen | Optional[str] | First seen date || +| last_seen | Optional[str] | Last seen date || +| nb_ips | int | Number of unique IPs observed || +| rule_release_date | Optional[str] | Release date of the fingerprint rule || +| exploitation_phase | ExploitationPhase | None || +| adjustment_score | Optional[AdjustmentScore] | Score adjustment details || +| threat_context | Optional[ThreatContext] | Threat context (attacker/defender countries, industries, objectives) || + +# **FingerprintTimelineItem** +## Required: +timestamp, count +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| timestamp | str | Timestamp of the timeline event || +| count | int | Count of occurrences at the timestamp || + # **GetCVEIPsResponsePage** ## Required: items, total, page, size, pages, links @@ -962,23 +1280,140 @@ items, total, page, size, pages, links | pages | int | None || | links | Links | None || +# **GetCVEProtectRulesResponse** +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| protect_rules | list[ProtectRule] | Protection/detection rules associated with the CVE || + # **GetCVEResponse** ## Required: -id, name, affected_components, let_score, first_seen, last_seen, nb_ips, published_date, cvss_score, references, description +id, name, title, affected_components, crowdsec_score, nb_ips, published_date, has_public_exploit, exploitation_phase, references, description, crowdsec_analysis, cwes ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| | id | str | ID of the CVE || | name | str | Name of the CVE || +| title | str | Title of the CVE || | affected_components | list[AffectedComponent] | List of affected components || -| let_score | int | LET score of the CVE || -| first_seen | str | First seen date || -| last_seen | str | Last seen date || +| crowdsec_score | int | Live Exploit Tracker score of the CVE || +| opportunity_score | int | Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5) || +| momentum_score | int | Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5) || +| first_seen | Optional[str] | First seen date || +| last_seen | Optional[str] | Last seen date || | nb_ips | int | Number of unique IPs affected || | published_date | str | Published date of the CVE || -| cvss_score | float | CVSS score of the CVE || +| cvss_score | Optional[float] | CVSS score of the CVE || +| has_public_exploit | bool | Indicates if there is a public exploit for the CVE || +| rule_release_date | Optional[str] | Release date of the associated detection rule || +| exploitation_phase | ExploitationPhase | None || +| adjustment_score | Optional[AdjustmentScore] | Score adjustments applied to the CVE score based on various factors || +| threat_context | Optional[ThreatContext] | Threat context (attacker/defender countries, industries, objectives) || +| tags | list[str] | Tags associated with the CVE || | references | list[str] | List of references for the CVE || | description | str | Description of the CVE || +| crowdsec_analysis | Optional[str] | CrowdSec analysis of the CVE || +| cwes | list[CWE] | List of CWEs associated with the CVE || +| events | list[CVEEventOutput] | List of events related to the CVE || + +# **GetCVESubscribedIntegrationsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[IntegrationResponse] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **GetCVEsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[CVEResponseBase] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **GetCVEsSortBy** +## Enum: +RULE_RELEASE_DATE, TRENDING, NB_IPS, NAME, FIRST_SEEN + +# **GetCVEsSortOrder** +## Enum: +ASC, DESC + +# **GetFingerprintIPsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[IPItem] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **GetFingerprintRulesResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[FingerprintRuleSummary] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **GetFingerprintSubscribedIntegrationsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[IntegrationResponse] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **GetVendorIPsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[IPItem] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **GetVendorSubscribedIntegrationsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[IntegrationResponse] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || # **History** ## Required: @@ -998,7 +1433,7 @@ ip | Property | Type | Description | Example | |----------|------|-------------|---------| | ip | str | IP address || -| reputation | str | Reputation of the IP || +| reputation | Optional[str] | Reputation of the IP || | ip_range | Optional[str] | IP range || | ip_range_score | Optional[int] | IP range score || | ip_range_24 | Optional[str] | IP range /24 || @@ -1006,20 +1441,61 @@ ip | ip_range_24_score | Optional[int] | IP range /24 score || | as_name | Optional[str] | AS name || | as_num | Optional[int] | AS number || -| background_noise_score | int | Background noise score || +| background_noise_score | Optional[int] | Background noise score || | background_noise | Optional[str] | Background noise level || | confidence | Optional[str] | Confidence level || | location | Optional[Location] | IP location information || | reverse_dns | Optional[str] | Reverse DNS || | behaviors | list[Behavior] | List of behaviors || | references | list[Reference] | List of references || -| history | History | None || -| classifications | Classifications | None || +| history | Optional[History] | Historical data || +| classifications | Optional[Classifications] | Classification data || | mitre_techniques | list[MitreTechnique] | MITRE techniques || | cves | list[str] | List of CVEs || | attack_details | list[AttackDetail] | Attack details || | target_countries | Target Countries | Target countries || -| scores | Scores | None || +| scores | Optional[Scores] | Scoring information || + +# **IntegrationResponse** +## Required: +organization_id, entity_type, name, output_format +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| tags | list[str] | None || +| organization_id | str | None || +| created_at | str | Time the integration was created || +| entity_type | EntityType | None || +| id | str | ID of the integration || +| blocklists | list[BlocklistSubscription] | None || +| allowlists | list[AllowlistSubscription] | None || +| cves | Optional[list[CVEsubscription]] | None || +| fingerprints | Optional[list[FingerprintSubscription]] | None || +| vendors | Optional[list[VendorSubscription]] | None || +| name | str | Name of the integration || +| updated_at | str | Last time the integration was updated || +| description | Optional[str] | Description of the integration || +| output_format | OutputFormat | None || +| last_pull | Optional[str] | Last time the integration pulled blocklists || +| pull_limit | Optional[int] | Maximum number of items to pull || +| enable_ip_aggregation | bool | Whether to enable IP aggregation into ranges || + +# **IntervalOptions** +## Enum: +HOUR, DAY, WEEK + +# **IpsDetailsStats** +## Required: +total, reputation, country, as_name, cves, classifications +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| total | int | Total number of matching IPs || +| reputation | list[FacetBucket] | IP count by reputation || +| country | list[FacetBucket] | IP count by country (top 5) || +| as_name | list[FacetBucket] | IP count by AS name (top 5) || +| cves | list[FacetBucket] | IP count by CVE (top 5) || +| classifications | list[FacetBucket] | IP count by classification (top 5) || # **Location** ## Properties @@ -1030,6 +1506,104 @@ ip | latitude | Optional[float] | Latitude coordinate || | longitude | Optional[float] | Longitude coordinate || +# **LookupImpactCVEItem** +## Required: +id, name, title, affected_components, crowdsec_score, nb_ips, published_date, has_public_exploit, exploitation_phase, references, description, crowdsec_analysis, cwes +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | ID of the CVE || +| name | str | Name of the CVE || +| title | str | Title of the CVE || +| affected_components | list[AffectedComponent] | List of affected components || +| crowdsec_score | int | Live Exploit Tracker score of the CVE || +| opportunity_score | int | Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5) || +| momentum_score | int | Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5) || +| first_seen | Optional[str] | First seen date || +| last_seen | Optional[str] | Last seen date || +| nb_ips | int | Number of unique IPs affected || +| published_date | str | Published date of the CVE || +| cvss_score | Optional[float] | CVSS score of the CVE || +| has_public_exploit | bool | Indicates if there is a public exploit for the CVE || +| rule_release_date | Optional[str] | Release date of the associated detection rule || +| exploitation_phase | ExploitationPhase | None || +| adjustment_score | Optional[AdjustmentScore] | Score adjustments applied to the CVE score based on various factors || +| threat_context | Optional[ThreatContext] | Threat context (attacker/defender countries, industries, objectives) || +| tags | list[str] | Tags associated with the CVE || +| references | list[str] | List of references for the CVE || +| description | str | Description of the CVE || +| crowdsec_analysis | Optional[str] | CrowdSec analysis of the CVE || +| cwes | list[CWE] | List of CWEs associated with the CVE || +| events | list[CVEEventOutput] | List of events related to the CVE || +| type | str | Resource type || + +# **LookupImpactFingerprintItem** +## Required: +id, name, title, affected_components, crowdsec_score, nb_ips, exploitation_phase +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | Fingerprint rule identifier || +| name | str | Fingerprint rule name || +| title | str | Fingerprint rule title || +| affected_components | list[AffectedComponent] | List of affected components || +| crowdsec_score | int | Live Exploit Tracker score for the fingerprint rule || +| opportunity_score | int | Opportunity score || +| momentum_score | int | Momentum score || +| first_seen | Optional[str] | First seen date || +| last_seen | Optional[str] | Last seen date || +| nb_ips | int | Number of unique IPs observed || +| rule_release_date | Optional[str] | Release date of the fingerprint rule || +| exploitation_phase | ExploitationPhase | None || +| adjustment_score | Optional[AdjustmentScore] | Score adjustment details || +| threat_context | Optional[ThreatContext] | Threat context (attacker/defender countries, industries, objectives) || +| tags | list[str] | Tags associated with the fingerprint rule || +| description | Optional[str] | Fingerprint rule description || +| references | list[str] | Reference links for the fingerprint rule || +| crowdsec_analysis | Optional[str] | CrowdSec analysis for this fingerprint rule || +| events | list[FingerprintEventOutput] | List of events related to the fingerprint rule || +| type | str | Resource type || + +# **LookupImpactResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[Annotated[Union[LookupImpactCVEItem, LookupImpactFingerprintItem], Field(discriminator='type')]] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + +# **LookupListItemWithStats** +## Required: +value +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| value | str | Lookup entry value || +| nb_cves | int | Number of CVEs || +| nb_fingerprints | int | Number of fingerprint rules || +| nb_ips | int | Total number of unique IPs targeting this entry || +| nb_ips_cves | int | Number of IPs across CVEs || +| nb_ips_fingerprints | int | Number of IPs across fingerprint rules || +| latest_rule_release | Optional[str] | Most recent rule release date for this entry || + +# **LookupListWithStatsResponsePage** +## Required: +items, total, page, size, pages, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[LookupListItemWithStats] | None || +| total | int | None || +| page | int | None || +| size | int | None || +| pages | int | None || +| links | Links | None || + # **MitreTechnique** ## Required: name, label, description @@ -1040,6 +1614,28 @@ name, label, description | label | str | MITRE technique label || | description | str | MITRE technique description || +# **ProtectRule** +## Required: +link, name, label +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| link | str | URL to the rule source || +| published_date | Optional[str] | Date the rule was published || +| tags | list[ProtectRuleTag] | Tags associated with the rule || +| name | str | Rule name || +| label | str | Human-readable rule label || +| content | Optional[str] | Rule content/definition || + +# **ProtectRuleTag** +## Required: +tag, label +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| tag | str | Tag identifier || +| label | str | Human-readable tag label || + # **Reference** ## Required: name, label, description @@ -1073,10 +1669,75 @@ overall, last_day, last_week, last_month | last_week | ScoreBreakdown | None || | last_month | ScoreBreakdown | None || +# **SinceOptions** + # **SubscribeCVEIntegrationRequest** ## Required: name ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| -| name | str | Name of the integration to subscribe || \ No newline at end of file +| name | str | Name of the integration to subscribe || + +# **SubscribeFingerprintIntegrationRequest** +## Required: +name +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| name | str | Name of the integration to subscribe || + +# **SubscribeVendorIntegrationRequest** +## Required: +name +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| name | str | Name of the integration to subscribe || + +# **ThreatContext** +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| attacker_countries | Attacker Countries | Attacker country distribution (country code → count) || +| defender_countries | Defender Countries | Defender country distribution (country code → count) || +| industry_types | Industry Types | Industry type distribution (type → count) || +| industry_risk_profiles | Industry Risk Profiles | Industry risk profile distribution (profile → count) || +| attacker_objectives | Attacker Objectives | Attacker objective distribution (objective → count) || + +# **TimelineItem** +## Required: +timestamp, count +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| timestamp | str | Timestamp of the timeline event || +| count | int | Count of occurrences at the timestamp || + +# **TopProductItem** +## Required: +value +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| value | str | Product name || +| nb_ips_cves | int | Number of IPs across CVEs || +| nb_ips_fingerprints | int | Number of IPs across fingerprint rules || + +# **VendorSortBy** +## Enum: +VALUE, NB_CVES, NB_IPS, LATEST_RULE_RELEASE + +# **VendorStatsResponse** +## Required: +value +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| value | str | Vendor name || +| nb_cves | int | Number of CVEs || +| nb_fingerprints | int | Number of fingerprint rules || +| nb_ips | int | Total number of unique IPs targeting this vendor || +| nb_ips_cves | int | Number of IPs across CVEs || +| nb_ips_fingerprints | int | Number of IPs across fingerprint rules || +| top_products | list[TopProductItem] | Top products for this vendor sorted by total IPs descending || \ No newline at end of file diff --git a/doc/Products.md b/doc/Products.md new file mode 100644 index 0000000..5e5e678 --- /dev/null +++ b/doc/Products.md @@ -0,0 +1,89 @@ + + +# Products Methods +| Method | Description | +| ------ | ----------- | +| [get_products](#get_products) | Get a paginated list of products | +| [get_product_impact](#get_product_impact) | Get CVE and fingerprint rules affecting a product | + +## **get_products** +### Get a paginated list of products +- Endpoint: `/products` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| query | Optional[str] | Search query for products | False | None | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupListWithStatsResponsePage](./Models.md#lookuplistwithstatsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Products, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Products(auth=auth) +try: + response = client.get_products( + query=None, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_product_impact** +### Get CVE and fingerprint rules affecting a product +- Endpoint: `/products/{product}` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| product | str | | True | | +| sort_by | Optional[GetCVEsSortBy] | Field to sort by | False | GetCVEsSortBy("rule_release_date") | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: ascending or descending | False | GetCVEsSortOrder("desc") | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupImpactResponsePage](./Models.md#lookupimpactresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Products, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Products(auth=auth) +try: + response = client.get_product_impact( + product='product', + sort_by=rule_release_date, + sort_order=desc, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + diff --git a/doc/README.md b/doc/README.md index 97e0a89..5c3aa07 100644 --- a/doc/README.md +++ b/doc/README.md @@ -17,6 +17,8 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [Integrations](./Integrations.md) +[Decisions](./Decisions.md) + [Info](./Info.md) [Metrics](./Metrics.md) @@ -25,6 +27,16 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [Cves](./Cves.md) +[Vendors](./Vendors.md) + +[Products](./Products.md) + +[TrackerTags](./TrackerTags.md) + +[Fingerprints](./Fingerprints.md) + +[TrackerEvents](./TrackerEvents.md) + ## API Endpoint models [AllowlistCreateRequest](./Models.md#allowlistcreaterequest) @@ -107,6 +119,8 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [Body_uploadBlocklistContent](./Models.md#body_uploadblocklistcontent) +[CVESubscription](./Models.md#cvesubscription) + [ComputedMetrics](./Models.md#computedmetrics) [ComputedSavedMetrics](./Models.md#computedsavedmetrics) @@ -123,8 +137,26 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [CtiScenario](./Models.md#ctiscenario) +[DecisionCreateRequest](./Models.md#decisioncreaterequest) + +[DecisionCreateResponse](./Models.md#decisioncreateresponse) + +[DecisionResponse](./Models.md#decisionresponse) + +[DecisionTargetModel](./Models.md#decisiontargetmodel) + +[DecisionTargetType](./Models.md#decisiontargettype) + +[DecisionsGetResponsePage](./Models.md#decisionsgetresponsepage) + +[DecisionsSortBy](./Models.md#decisionssortby) + +[DecisionsSortOrder](./Models.md#decisionssortorder) + [EntityType](./Models.md#entitytype) +[FingerprintSubscription](./Models.md#fingerprintsubscription) + [GetRemediationMetricsResponse](./Models.md#getremediationmetricsresponse) [HTTPValidationError](./Models.md#httpvalidationerror) @@ -179,6 +211,8 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [ValidationError](./Models.md#validationerror) +[VendorSubscription](./Models.md#vendorsubscription) + [AppsecConfigIndex](./Models.md#appsecconfigindex) [AppsecRuleIndex](./Models.md#appsecruleindex) @@ -197,32 +231,118 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [VersionDetail](./Models.md#versiondetail) +[AdjustmentScore](./Models.md#adjustmentscore) + [AffectedComponent](./Models.md#affectedcomponent) +[AllowlistSubscription](./Models.md#allowlistsubscription) + [AttackDetail](./Models.md#attackdetail) [Behavior](./Models.md#behavior) +[CVEEventOutput](./Models.md#cveeventoutput) + +[CVEExploitationPhase](./Models.md#cveexploitationphase) + +[CVEResponseBase](./Models.md#cveresponsebase) + +[CVEsubscription](./Models.md#cvesubscription) + +[CWE](./Models.md#cwe) + [Classification](./Models.md#classification) [Classifications](./Models.md#classifications) +[ExploitationPhase](./Models.md#exploitationphase) + +[ExploitationPhaseChangeEventItem](./Models.md#exploitationphasechangeeventitem) + +[ExploitationPhaseChangeEventsResponsePage](./Models.md#exploitationphasechangeeventsresponsepage) + +[FacetBucket](./Models.md#facetbucket) + +[FingerprintEventOutput](./Models.md#fingerprinteventoutput) + +[FingerprintRuleResponse](./Models.md#fingerprintruleresponse) + +[FingerprintRuleSummary](./Models.md#fingerprintrulesummary) + +[FingerprintTimelineItem](./Models.md#fingerprinttimelineitem) + [GetCVEIPsResponsePage](./Models.md#getcveipsresponsepage) +[GetCVEProtectRulesResponse](./Models.md#getcveprotectrulesresponse) + [GetCVEResponse](./Models.md#getcveresponse) +[GetCVESubscribedIntegrationsResponsePage](./Models.md#getcvesubscribedintegrationsresponsepage) + +[GetCVEsResponsePage](./Models.md#getcvesresponsepage) + +[GetCVEsSortBy](./Models.md#getcvessortby) + +[GetCVEsSortOrder](./Models.md#getcvessortorder) + +[GetFingerprintIPsResponsePage](./Models.md#getfingerprintipsresponsepage) + +[GetFingerprintRulesResponsePage](./Models.md#getfingerprintrulesresponsepage) + +[GetFingerprintSubscribedIntegrationsResponsePage](./Models.md#getfingerprintsubscribedintegrationsresponsepage) + +[GetVendorIPsResponsePage](./Models.md#getvendoripsresponsepage) + +[GetVendorSubscribedIntegrationsResponsePage](./Models.md#getvendorsubscribedintegrationsresponsepage) + [History](./Models.md#history) [IPItem](./Models.md#ipitem) +[IntegrationResponse](./Models.md#integrationresponse) + +[IntervalOptions](./Models.md#intervaloptions) + +[IpsDetailsStats](./Models.md#ipsdetailsstats) + [Location](./Models.md#location) +[LookupImpactCVEItem](./Models.md#lookupimpactcveitem) + +[LookupImpactFingerprintItem](./Models.md#lookupimpactfingerprintitem) + +[LookupImpactResponsePage](./Models.md#lookupimpactresponsepage) + +[LookupListItemWithStats](./Models.md#lookuplistitemwithstats) + +[LookupListWithStatsResponsePage](./Models.md#lookuplistwithstatsresponsepage) + [MitreTechnique](./Models.md#mitretechnique) +[ProtectRule](./Models.md#protectrule) + +[ProtectRuleTag](./Models.md#protectruletag) + [Reference](./Models.md#reference) [ScoreBreakdown](./Models.md#scorebreakdown) [Scores](./Models.md#scores) -[SubscribeCVEIntegrationRequest](./Models.md#subscribecveintegrationrequest) \ No newline at end of file +[SinceOptions](./Models.md#sinceoptions) + +[SubscribeCVEIntegrationRequest](./Models.md#subscribecveintegrationrequest) + +[SubscribeFingerprintIntegrationRequest](./Models.md#subscribefingerprintintegrationrequest) + +[SubscribeVendorIntegrationRequest](./Models.md#subscribevendorintegrationrequest) + +[ThreatContext](./Models.md#threatcontext) + +[TimelineItem](./Models.md#timelineitem) + +[TopProductItem](./Models.md#topproductitem) + +[VendorSortBy](./Models.md#vendorsortby) + +[VendorStatsResponse](./Models.md#vendorstatsresponse) \ No newline at end of file diff --git a/doc/TrackerEvents.md b/doc/TrackerEvents.md new file mode 100644 index 0000000..791e0f9 --- /dev/null +++ b/doc/TrackerEvents.md @@ -0,0 +1,53 @@ + + +# TrackerEvents Methods +| Method | Description | +| ------ | ----------- | +| [get_exploitation_phase_change_events](#get_exploitation_phase_change_events) | Get a paginated list of exploitation phase change events across tracked CVEs | + +## **get_exploitation_phase_change_events** +### Get a paginated list of exploitation phase change events across tracked CVEs +- Endpoint: `/tracker-events/exploitation-phase-change` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| since | str | Duration string (e.g. '30d', '24h') to filter events | False | "30d" | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: ascending or descending | False | GetCVEsSortOrder("desc") | +| cve_id | Optional[str] | Filter by CVE identifier (exact match) | False | None | +| previous_phase | Optional[CVEExploitationPhase] | Filter by previous exploitation phase name | False | None | +| new_phase | Optional[CVEExploitationPhase] | Filter by new exploitation phase name | False | None | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[ExploitationPhaseChangeEventsResponsePage](./Models.md#exploitationphasechangeeventsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + TrackerEvents, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = TrackerEvents(auth=auth) +try: + response = client.get_exploitation_phase_change_events( + since=30d, + sort_order=desc, + cve_id=None, + previous_phase=None, + new_phase=None, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + diff --git a/doc/TrackerTags.md b/doc/TrackerTags.md new file mode 100644 index 0000000..72cb44d --- /dev/null +++ b/doc/TrackerTags.md @@ -0,0 +1,173 @@ + + +# TrackerTags Methods +| Method | Description | +| ------ | ----------- | +| [get_tags](#get_tags) | Get a paginated list of tags | +| [get_tag_impact](#get_tag_impact) | Get CVE and fingerprint rules affecting a tag | +| [get_tracker_tags](#get_tracker_tags) | Get a paginated list of tracker tags | +| [get_tracker_tag_impact](#get_tracker_tag_impact) | Get CVE and fingerprint rules affecting a tracker tag | + +## **get_tags** +### Get a paginated list of tags +- Endpoint: `/tags` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| query | Optional[str] | Search query for tags | False | None | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupListWithStatsResponsePage](./Models.md#lookuplistwithstatsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + TrackerTags, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = TrackerTags(auth=auth) +try: + response = client.get_tags( + query=None, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_tag_impact** +### Get CVE and fingerprint rules affecting a tag +- Endpoint: `/tags/{tag}` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| tag | str | | True | | +| sort_by | Optional[GetCVEsSortBy] | Field to sort by | False | GetCVEsSortBy("rule_release_date") | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: ascending or descending | False | GetCVEsSortOrder("desc") | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupImpactResponsePage](./Models.md#lookupimpactresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + TrackerTags, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = TrackerTags(auth=auth) +try: + response = client.get_tag_impact( + tag='tag', + sort_by=rule_release_date, + sort_order=desc, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_tracker_tags** +### Get a paginated list of tracker tags +- Endpoint: `/tracker-tags` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| query | Optional[str] | Search query for tags | False | None | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupListWithStatsResponsePage](./Models.md#lookuplistwithstatsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + TrackerTags, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = TrackerTags(auth=auth) +try: + response = client.get_tracker_tags( + query=None, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_tracker_tag_impact** +### Get CVE and fingerprint rules affecting a tracker tag +- Endpoint: `/tracker-tags/{tag}` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| tag | str | | True | | +| sort_by | Optional[GetCVEsSortBy] | Field to sort by | False | GetCVEsSortBy("rule_release_date") | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: ascending or descending | False | GetCVEsSortOrder("desc") | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupImpactResponsePage](./Models.md#lookupimpactresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + TrackerTags, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = TrackerTags(auth=auth) +try: + response = client.get_tracker_tag_impact( + tag='tag', + sort_by=rule_release_date, + sort_order=desc, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + diff --git a/doc/Vendors.md b/doc/Vendors.md new file mode 100644 index 0000000..9368be1 --- /dev/null +++ b/doc/Vendors.md @@ -0,0 +1,361 @@ + + +# Vendors Methods +| Method | Description | +| ------ | ----------- | +| [get_vendors](#get_vendors) | Get a paginated list of vendors | +| [get_vendor_stats](#get_vendor_stats) | Get statistics for a vendor including CVE/fingerprint counts, IP counts, and top affected products | +| [download_vendor_ips](#download_vendor_ips) | Download the list of IPs exploiting a specific vendor in raw format | +| [get_vendor_ips_details](#get_vendor_ips_details) | Get detailed information about IPs exploiting a specific vendor | +| [get_vendor_ips_details_stats](#get_vendor_ips_details_stats) | Get aggregated statistics about IPs exploiting a specific vendor | +| [get_vendor_subscribed_integrations](#get_vendor_subscribed_integrations) | Get the list of integrations subscribed to a specific vendor | +| [subscribe_integration_to_vendor](#subscribe_integration_to_vendor) | Subscribe an integration to receive threats related to a specific vendor | +| [unsubscribe_integration_from_vendor](#unsubscribe_integration_from_vendor) | Unsubscribe an integration from receiving threats related to a specific vendor | +| [get_vendor_impact](#get_vendor_impact) | Get CVE and fingerprint rules affecting a vendor | + +## **get_vendors** +### Get a paginated list of vendors +- Endpoint: `/vendors` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| query | Optional[str] | Search query for vendors | False | None | +| sort_by | Optional[VendorSortBy] | Sort by: value, nb_cves, nb_ips, latest_rule_release | False | None | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: asc or desc | False | GetCVEsSortOrder("desc") | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupListWithStatsResponsePage](./Models.md#lookuplistwithstatsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.get_vendors( + query=None, + sort_by=None, + sort_order=desc, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_vendor_stats** +### Get statistics for a vendor including CVE/fingerprint counts, IP counts, and top affected products +- Endpoint: `/vendors/{vendor}/stats` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| vendor | str | | True | | +### Returns: +[VendorStatsResponse](./Models.md#vendorstatsresponse) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.get_vendor_stats( + vendor='vendor', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **download_vendor_ips** +### Download the list of IPs exploiting a specific vendor in raw format +- Endpoint: `/vendors/{vendor}/ips-download` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| vendor | str | | True | | +### Returns: +[str](./Models.md#str) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.download_vendor_ips( + vendor='vendor', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_vendor_ips_details** +### Get detailed information about IPs exploiting a specific vendor +- Endpoint: `/vendors/{vendor}/ips-details` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| vendor | str | | True | | +| since | Optional[str] | Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d | False | "14d" | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[GetVendorIPsResponsePage](./Models.md#getvendoripsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.get_vendor_ips_details( + vendor='vendor', + since=14d, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_vendor_ips_details_stats** +### Get aggregated statistics about IPs exploiting a specific vendor +- Endpoint: `/vendors/{vendor}/ips-details-stats` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| vendor | str | | True | | +| since | Optional[str] | Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d | False | "14d" | +### Returns: +[IpsDetailsStats](./Models.md#ipsdetailsstats) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.get_vendor_ips_details_stats( + vendor='vendor', + since=14d, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_vendor_subscribed_integrations** +### Get the list of integrations subscribed to a specific vendor +- Endpoint: `/vendors/{vendor}/integrations` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| vendor | str | | True | | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[GetVendorSubscribedIntegrationsResponsePage](./Models.md#getvendorsubscribedintegrationsresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.get_vendor_subscribed_integrations( + vendor='vendor', + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **subscribe_integration_to_vendor** +### Subscribe an integration to receive threats related to a specific vendor +- Endpoint: `/vendors/{vendor}/integrations` +- Method: `POST` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| request | [SubscribeVendorIntegrationRequest](./Models.md#subscribevendorintegrationrequest) | Request body | Yes | - | +| vendor | str | | True | | +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, + SubscribeVendorIntegrationRequest, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +request = SubscribeVendorIntegrationRequest( + name=None, +) +try: + response = client.subscribe_integration_to_vendor( + request=request, + vendor='vendor', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **unsubscribe_integration_from_vendor** +### Unsubscribe an integration from receiving threats related to a specific vendor +- Endpoint: `/vendors/{vendor}/integrations/{integration_name}` +- Method: `DELETE` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| vendor | str | | True | | +| integration_name | str | | True | | +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.unsubscribe_integration_from_vendor( + vendor='vendor', + integration_name='integration_name', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **get_vendor_impact** +### Get CVE and fingerprint rules affecting a vendor +- Endpoint: `/vendors/{vendor}` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| vendor | str | | True | | +| sort_by | Optional[GetCVEsSortBy] | Field to sort by | False | GetCVEsSortBy("rule_release_date") | +| sort_order | Optional[GetCVEsSortOrder] | Sort order: ascending or descending | False | GetCVEsSortOrder("desc") | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +### Returns: +[LookupImpactResponsePage](./Models.md#lookupimpactresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Validation Error | +### Usage + +```python +from crowdsec_service_api import ( + Vendors, + ApiKeyAuth, +) +from httpx import HTTPStatusError +auth = ApiKeyAuth(api_key='your_api_key') +client = Vendors(auth=auth) +try: + response = client.get_vendor_impact( + vendor='vendor', + sort_by=rule_release_date, + sort_order=desc, + page=1, + size=50, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + diff --git a/public-openapi.json b/public-openapi.json new file mode 100644 index 0000000..9d5ce94 --- /dev/null +++ b/public-openapi.json @@ -0,0 +1,13547 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Service API", + "description": "This is the API to manage Crowdsec services", + "version": "v0.15.25", + "contact": { + "name": "CrowdSec", + "url": "https://crowdsec.net", + "email": "info@crowdsec.net" + } + }, + "servers": [ + { + "url": "https://admin.api.crowdsec.net/v1", + "description": "Production server" + } + ], + "paths": { + "/allowlists": { + "post": { + "tags": [ + "Allowlists" + ], + "summary": "Create Allowlist", + "description": "Create a new allowlist for an organization", + "operationId": "createAllowlist", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistCreateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistCreateResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Allowlists" + ], + "summary": "List Allowlists", + "description": "List all allowlists for an organization", + "operationId": "listAllowlists", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistGetResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/allowlists/{allowlist_id}": { + "get": { + "tags": [ + "Allowlists" + ], + "summary": "Get Allowlist", + "description": "Get an allowlist by ID", + "operationId": "getAllowlist", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistGetResponse" + } + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "patch": { + "tags": [ + "Allowlists" + ], + "summary": "Update Allowlist", + "description": "Update an allowlist by ID", + "operationId": "updateAllowlist", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistUpdateResponse" + } + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Allowlists" + ], + "summary": "Delete Allowlist", + "description": "Delete an allowlist by ID", + "operationId": "deleteAllowlist", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + }, + { + "name": "force", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Force delete the allowlist, even if it has subscribers", + "default": false, + "title": "Force" + }, + "description": "Force delete the allowlist, even if it has subscribers" + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/allowlists/{allowlist_id}/items": { + "post": { + "tags": [ + "Allowlists" + ], + "summary": "Create Allowlist Items", + "description": "Create items for an allowlist", + "operationId": "createAllowlistItems", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistItemsCreateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Allowlists" + ], + "summary": "Get Allowlist Items", + "description": "Get items in an allowlist", + "operationId": "getAllowlistItems", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistGetItemsResponsePage" + } + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/allowlists/{allowlist_id}/items/{item_id}": { + "get": { + "tags": [ + "Allowlists" + ], + "summary": "Get Allowlist Item", + "description": "Get an allowlist item by ID", + "operationId": "getAllowlistItem", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + }, + { + "name": "item_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Item Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistGetItemsResponse" + } + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "patch": { + "tags": [ + "Allowlists" + ], + "summary": "Update Allowlist Item", + "description": "Update an allowlist item by ID", + "operationId": "updateAllowlistItem", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + }, + { + "name": "item_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Item Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistItemUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistItemUpdateResponse" + } + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Allowlists" + ], + "summary": "Delete Allowlist Item", + "description": "Delete an allowlist item by ID", + "operationId": "deleteAllowlistItem", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + }, + { + "name": "item_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Item Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/allowlists/{allowlist_id}/subscribers": { + "get": { + "tags": [ + "Allowlists" + ], + "summary": "Get Allowlist Subscribers", + "description": "Get subscribers of an allowlist", + "operationId": "getAllowlistSubscribers", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistSubscriberEntityPage" + } + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "post": { + "tags": [ + "Allowlists" + ], + "summary": "Subscribe Allowlist", + "description": "Subscribe to an allowlist", + "operationId": "subscribeAllowlist", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistSubscriptionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllowlistSubscriptionResponse" + } + } + } + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/allowlists/{allowlist_id}/subscribers/{entity_id}": { + "delete": { + "tags": [ + "Allowlists" + ], + "summary": "Unsubscribe Allowlist", + "description": "Unsubscribe from an allowlist", + "operationId": "unsubscribeAllowlist", + "parameters": [ + { + "name": "allowlist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Allowlist Id" + } + }, + { + "name": "entity_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Entity Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "404": { + "description": "Allowlist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Create Blocklist", + "description": "Create a new blocklist owned by your organization. The name must be unique within your organization. The list will only be visible to your organization and organizations you shared the blocklist with. This operation is submitted to quotas", + "operationId": "createBlocklist", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistCreateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicBlocklistResponse" + } + } + } + }, + "409": { + "description": "Blocklist already exists" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Blocklists" + ], + "summary": "Get Blocklists", + "description": "Get multiple blocklists. Only blocklists owned by your organization, shared with your organization or public blocklists are returned. Filters and pagination are available as query parameters.", + "operationId": "getBlocklists", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "description": "Page size", + "default": 100, + "title": "Page Size" + }, + "description": "Page size" + }, + { + "name": "subscribed_only", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "only subscribed blocklists", + "default": false, + "title": "Subscribed Only" + }, + "description": "only subscribed blocklists" + }, + { + "name": "exclude_subscribed", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "exclude subscribed blocklists", + "default": false, + "title": "Exclude Subscribed" + }, + "description": "exclude subscribed blocklists" + }, + { + "name": "include_filter", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BlocklistIncludeFilters" + }, + "description": "Include blocklists with the specified filters", + "default": [ + "private", + "shared" + ], + "title": "Include Filter" + }, + "description": "Include blocklists with the specified filters" + }, + { + "name": "category", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Filter by category", + "title": "Category" + }, + "description": "Filter by category" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicBlocklistResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/search": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Search Blocklists", + "description": "Search blocklists", + "operationId": "searchBlocklist", + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistSearchRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicBlocklistResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}": { + "get": { + "tags": [ + "Blocklists" + ], + "summary": "Get Blocklist", + "description": "Get the details of a blocklist by ID. The content of the blocklist is not returned.", + "operationId": "getBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicBlocklistResponse" + } + } + } + }, + "404": { + "description": "Blocklist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "patch": { + "tags": [ + "Blocklists" + ], + "summary": "Update Blocklist", + "description": "Update a blocklist's details by ID. It is not possible to update the blocklist content using this operation.", + "operationId": "updateBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicBlocklistResponse" + } + } + } + }, + "403": { + "description": "Blocklist is read-only" + }, + "404": { + "description": "Blocklist not found" + }, + "500": { + "description": "Internal server error" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Blocklists" + ], + "summary": "Delete Blocklist", + "description": "Delete a blocklist by ID. If the blocklist is shared with other organizations or it has subscriptions, the operation will fail. If you want to force delete the blocklist, you can use the force query parameter, so the blocklists will be unshared / unsubscribed.", + "operationId": "deleteBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + }, + { + "name": "force", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Force delete the blocklist if it is shared or subscribed", + "default": false, + "title": "Force" + }, + "description": "Force delete the blocklist if it is shared or subscribed" + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "404": { + "description": "Blocklist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/upload": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Upload Blocklist Content", + "description": "Upload a blocklist. The file must be in txt format with one IP per line. This operation will overwrite the existing blocklist content.", + "operationId": "uploadBlocklistContent", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + }, + { + "name": "expiration", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Blocklist expiration", + "examples": [ + "2026-04-13T08:55:24.249164+00:00" + ], + "title": "Expiration" + }, + "description": "Blocklist expiration" + }, + { + "name": "ignore_invalid_ips", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "Ignore invalid IPs", + "default": false, + "title": "Ignore Invalid Ips" + }, + "description": "Ignore invalid IPs" + } + ], + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_uploadBlocklistContent" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "400": { + "description": "Invalid IP in blocklist file content" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/ips": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Add Ips To Blocklist", + "description": "Add IPs to a blocklist. If an IP is already in the blocklist, its expiration will be updated with the new expiration.", + "operationId": "addIpsToBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistAddIPsRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "403": { + "description": "Blocklist is read-only" + }, + "404": { + "description": "Blocklist not found" + }, + "412": { + "description": "Payload too large for one operation, limit is 20000 IPs per request" + }, + "500": { + "description": "Internal server error" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/ips/bulk_overwrite": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Bulk Overwrite Blocklist Ips", + "description": "Overwrite blocklist content", + "operationId": "overwriteIps", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistAddIPsRequest" + } + } + } + }, + "responses": { + "202": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "403": { + "description": "Blocklist is read-only" + }, + "404": { + "description": "Blocklist not found" + }, + "412": { + "description": "Payload too large for one operation, limit is 20000 IPs per request" + }, + "500": { + "description": "Internal server error" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/ips/delete": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Delete Ips From Blocklist", + "description": "Delete IPs from a blocklist", + "operationId": "deleteIpsFromBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistDeleteIPsRequest" + } + } + } + }, + "responses": { + "204": { + "description": "Successful Response" + }, + "403": { + "description": "Blocklist is read-only" + }, + "404": { + "description": "Blocklist not found" + }, + "500": { + "description": "Internal server error" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/download": { + "get": { + "tags": [ + "Blocklists" + ], + "summary": "Download Blocklist Content", + "description": "Download blocklist content as a list of ips as plain text separated by new lines. The response will include the ETag header for cache control. If_Modified_Since and If_None_Match cache control headers are supported for conditional requests.", + "operationId": "downloadBlocklistContent", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + }, + { + "name": "if-modified-since", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "If_Modified_Since cache control header", + "title": "If-Modified-Since" + }, + "description": "If_Modified_Since cache control header" + }, + { + "name": "if-none-match", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "If_None_Match cache control header", + "title": "If-None-Match" + }, + "description": "If_None_Match cache control header" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Blocklist not found" + }, + "204": { + "description": "Blocklist is empty" + }, + "500": { + "description": "Internal server error" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/subscribers": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Subscribe Blocklist", + "description": "Subscribe to a blocklist with a remediation type. If the entity type is the full organization or a Tag, all the engines belonging to the organization or the Tag will be subscribed and new engines that will join the organization or the Tag will also be automatically subscribed. If the subscription has been done on an organization or Tag you cannot unsubscribe individual engines. In case of errors for some subscribers, the operation will still succeed for the entities that were successfully subscribed and you'll have the list of errors in the operation's result. This operation is submitted to quotas.", + "operationId": "subscribeBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistSubscriptionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistSubscriptionResponse" + } + } + } + }, + "404": { + "description": "Blocklist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Blocklists" + ], + "summary": "Get Blocklist Subscribers", + "description": "Get blocklist subscribers within your organization.", + "operationId": "getBlocklistSubscribers", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistSubscriberEntityPage" + } + } + } + }, + "404": { + "description": "Blocklist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/subscribers/{entity_id}": { + "delete": { + "tags": [ + "Blocklists" + ], + "summary": "Unsubscribe Blocklist", + "description": "Unsubscribe from a blocklist. You cannot unsubscribe individual engines if the subscription has been done on an organization or Tag.", + "operationId": "unsubscribeBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + }, + { + "name": "entity_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Entity Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Blocklist not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/shares": { + "post": { + "tags": [ + "Blocklists" + ], + "summary": "Share Blocklist", + "description": "Share a blocklist with other organizations given their IDs. The blocklist must be owned by your organization. You can give read-only access or read-write access to the blocklist. Sharing a blocklist will not automatically subscribe the shared organizations to the blocklist.", + "operationId": "shareBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistShareRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Blocklist not found" + }, + "409": { + "description": "Blocklist is not private" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/blocklists/{blocklist_id}/shares/{unshare_organization_id}": { + "delete": { + "tags": [ + "Blocklists" + ], + "summary": "Unshare Blocklist", + "description": "Unshare a blocklist with other organizations. If the blocklist is subscribed by the organization, the operation will fail.Use force query parameter to unshare a blocklist even if subscriptions exists.", + "operationId": "unshareBlocklist", + "parameters": [ + { + "name": "blocklist_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Blocklist Id" + } + }, + { + "name": "unshare_organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Unshare Organization Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "404": { + "description": "Blocklist not found" + }, + "409": { + "description": "Blocklist is not private" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/integrations": { + "post": { + "tags": [ + "Integrations" + ], + "summary": "Create Integration", + "description": "Create an integration to a firewall or remediation component, owned by your organization. The name should be unique within the organization. This operation is submitted to quotas.", + "operationId": "createIntegration", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationCreateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationCreateResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Integrations" + ], + "summary": "Get Integrations", + "description": "Get integrations owned by your organization", + "operationId": "getIntegrations", + "parameters": [ + { + "name": "tag", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "List of tags associated with the integrations (any of)", + "title": "Tag" + }, + "description": "List of tags associated with the integrations (any of)" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationGetResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/integrations/{integration_id}": { + "get": { + "tags": [ + "Integrations" + ], + "summary": "Get Integration", + "description": "Get an integration by ID", + "operationId": "getIntegration", + "parameters": [ + { + "name": "integration_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Integration Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationGetResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "patch": { + "tags": [ + "Integrations" + ], + "summary": "Update Integration", + "description": "Update the integration details", + "operationId": "updateIntegration", + "parameters": [ + { + "name": "integration_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Integration Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IntegrationUpdateResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Integrations" + ], + "summary": "Delete Integration", + "description": "Delete the integration by ID", + "operationId": "deleteIntegration", + "parameters": [ + { + "name": "integration_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Integration Id" + } + }, + { + "name": "force", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Force delete the integration even if it has active subscriptions (it will unsubscribe from all lists)", + "default": false, + "title": "Force" + }, + "description": "Force delete the integration even if it has active subscriptions (it will unsubscribe from all lists)" + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/integrations/{integration_id}/content": { + "head": { + "tags": [ + "Integrations" + ], + "summary": "Head Integration Content", + "description": "Check if the integration has content", + "operationId": "headIntegrationContent", + "parameters": [ + { + "name": "integration_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Integration Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Integration not found" + }, + "204": { + "description": "Integration has no subscribed blocklists or no content available" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Integrations" + ], + "summary": "Get Integration Content", + "description": "Get the ips associated to the integration in plain text format. The content can be paginated to accomodate limits in firewalls.", + "operationId": "getIntegrationContent", + "parameters": [ + { + "name": "integration_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Integration Id" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number to return", + "default": 1, + "title": "Page" + }, + "description": "Page number to return" + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer", + "minimum": 10000 + }, + { + "type": "null" + } + ], + "description": "Maximum number of items to return, 0 means no limit (default), should be greater than 10000", + "title": "Page Size" + }, + "description": "Maximum number of items to return, 0 means no limit (default), should be greater than 10000" + }, + { + "name": "pull_limit", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pull Limit" + } + }, + { + "name": "enable_ip_aggregation", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false, + "title": "Enable Ip Aggregation" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Integration not found" + }, + "204": { + "description": "Integration has no subscribed blocklists or no content available" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/integrations/{integration_id}/v1/decisions/stream": { + "get": { + "tags": [ + "Integrations" + ], + "summary": "Get Integration Content Stream", + "description": "Get the ips associated to the integration in a format compatible with a remediation component. As for the remediation components, you can fetch the full content with startup=true or only the changes since the last pull", + "operationId": "getIntegrationContentStream", + "parameters": [ + { + "name": "integration_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "ObjectId", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ], + "title": "Integration Id" + } + }, + { + "name": "startup", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Set to true if it's the first run to fetch all the content, otherwise only changes since the last pull.", + "default": false, + "title": "Startup" + }, + "description": "Set to true if it's the first run to fetch all the content, otherwise only changes since the last pull." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Integration not found" + }, + "204": { + "description": "Integration has no subscribed blocklists or no content available" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/decisions": { + "get": { + "tags": [ + "Decisions" + ], + "summary": "Get Decisions", + "description": "Get decisions", + "operationId": "getDecisions", + "parameters": [ + { + "name": "instance_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by instance IDs", + "default": [], + "title": "Instance Ids" + }, + "description": "Filter decisions by instance IDs" + }, + { + "name": "tag_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by tag IDs", + "default": [], + "title": "Tag Ids" + }, + "description": "Filter decisions by tag IDs" + }, + { + "name": "remediation_types", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by remediation types", + "default": [], + "title": "Remediation Types" + }, + "description": "Filter decisions by remediation types" + }, + { + "name": "ips", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by IPs (only for IP decisions)", + "default": [], + "title": "Ips" + }, + "description": "Filter decisions by IPs (only for IP decisions)" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/DecisionsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by (e.g., created_at, duration)", + "default": "created_at", + "title": "Sort By" + }, + "description": "Field to sort by (e.g., created_at, duration)" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/DecisionsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: 'asc' for ascending, 'desc' for descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: 'asc' for ascending, 'desc' for descending" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DecisionsGetResponsePage" + } + } + } + }, + "404": { + "description": "Not found" + }, + "500": { + "description": "Internal server error" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "post": { + "tags": [ + "Decisions" + ], + "summary": "Create Decision", + "description": "Create a new decision.", + "operationId": "createDecision", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DecisionCreateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DecisionCreateResponse" + } + } + } + }, + "409": { + "description": "Conflict: Decision value is in allowlists; cannot create decision." + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/info": { + "get": { + "tags": [ + "Info" + ], + "summary": "Get Me Info", + "description": "Get the current user and organization informations", + "operationId": "getInfo", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InfoResponse" + } + } + } + } + } + } + }, + "/metrics/remediation": { + "get": { + "tags": [ + "Metrics" + ], + "summary": "Get Metrics Remediation", + "description": "Get remediation metrics", + "operationId": "getMetricsRemediation", + "parameters": [ + { + "name": "start_date", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time", + "description": "Start date of the metrics, default to last day", + "title": "Start Date" + }, + "description": "Start date of the metrics, default to last day" + }, + { + "name": "end_date", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time", + "description": "End date of the metrics", + "title": "End Date" + }, + "description": "End date of the metrics" + }, + { + "name": "engine_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of engine ids", + "default": [], + "title": "Engine Ids" + }, + "description": "List of engine ids" + }, + { + "name": "integration_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of integration ids", + "default": [], + "title": "Integration Ids" + }, + "description": "List of integration ids" + }, + { + "name": "tags", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of tags", + "default": [], + "title": "Tags" + }, + "description": "List of tags" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetRemediationMetricsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/hub/index/{tenant}/{branch}/.index.json": { + "get": { + "description": "Get a (minimized) index file for 'cscli hub update'. May or may not include unused fields\n(content, long descriptions, labels...) or redundant ones (author, name).", + "operationId": "getIndex", + "parameters": [ + { + "in": "path", + "name": "branch", + "required": true, + "schema": { + "title": "Branch", + "type": "string" + } + }, + { + "in": "path", + "name": "tenant", + "required": true, + "schema": { + "title": "Tenant", + "type": "string" + } + }, + { + "description": "Include content in the index", + "in": "query", + "name": "with_content", + "required": false, + "schema": { + "default": false, + "description": "Include content in the index", + "title": "With Content", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Index" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get a minimized index file (crowdsec only)", + "tags": [ + "Hub" + ] + }, + "head": { + "description": "This endpoint returns cache-related headers for the index file without the full content.\nIt is useful for validating cache, checking resource freshness, and managing client-side\ncache expiration policies. No body content is returned.", + "operationId": "headIndex", + "parameters": [ + { + "in": "path", + "name": "branch", + "required": true, + "schema": { + "title": "Branch", + "type": "string" + } + }, + { + "in": "path", + "name": "tenant", + "required": true, + "schema": { + "title": "Tenant", + "type": "string" + } + }, + { + "description": "Include content in the index", + "in": "query", + "name": "with_content", + "required": false, + "schema": { + "default": false, + "description": "Include content in the index", + "title": "With Content", + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Index" + } + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Check cache control headers for the index file", + "tags": [ + "Hub" + ] + } + }, + "/hub/index/{tenant}/{branch}/{item_path}": { + "get": { + "description": "Get an item's content from its path. This is usually a YAML file.", + "operationId": "getItemContent", + "parameters": [ + { + "in": "path", + "name": "item_path", + "required": true, + "schema": { + "title": "Item Path", + "type": "string" + } + }, + { + "in": "path", + "name": "branch", + "required": true, + "schema": { + "title": "Branch", + "type": "string" + } + }, + { + "in": "path", + "name": "tenant", + "required": true, + "schema": { + "title": "Tenant", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "404": { + "description": "No content field" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Get an item's content (crowdsec only)", + "tags": [ + "Hub" + ] + }, + "head": { + "description": "This endpoint returns cache-related headers for an item's content. It is useful for validating\ncache, checking resource freshness, and managing client-side cache expiration policies. No body\ncontent is returned.", + "operationId": "headItemContent", + "parameters": [ + { + "in": "path", + "name": "item_path", + "required": true, + "schema": { + "title": "Item Path", + "type": "string" + } + }, + { + "in": "path", + "name": "branch", + "required": true, + "schema": { + "title": "Branch", + "type": "string" + } + }, + { + "in": "path", + "name": "tenant", + "required": true, + "schema": { + "title": "Tenant", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {} + } + }, + "description": "Successful Response" + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error" + } + }, + "summary": "Check cache control headers for an item's content", + "tags": [ + "Hub" + ] + } + }, + "/cves": { + "get": { + "tags": [ + "Cves" + ], + "summary": "Get list of CVEs CrowdSec is tracking", + "description": "Get a paginated list of CVEs that CrowdSec is tracking", + "operationId": "getCves", + "parameters": [ + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search query for CVEs", + "title": "Query" + }, + "description": "Search query for CVEs" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by", + "default": "rule_release_date", + "title": "Sort By" + }, + "description": "Field to sort by" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: ascending or descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: ascending or descending" + }, + { + "name": "exploitation_phase", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/CVEExploitationPhase" + }, + { + "type": "null" + } + ], + "description": "Filter by exploitation phase", + "title": "Exploitation Phase" + }, + "description": "Filter by exploitation phase" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCVEsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}": { + "get": { + "tags": [ + "Cves" + ], + "summary": "Get CVE ID informations", + "description": "Get information about a specific CVE ID", + "operationId": "getCve", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCVEResponse" + } + } + } + }, + "404": { + "description": "CVE Not Found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}/protect-rules": { + "get": { + "tags": [ + "Cves" + ], + "summary": "Get protection rules for a CVE ID", + "description": "Get protection/detection rules associated with a specific CVE ID", + "operationId": "getCveProtectRules", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCVEProtectRulesResponse" + } + } + } + }, + "404": { + "description": "CVE Not Found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}/ips-download": { + "get": { + "tags": [ + "Cves" + ], + "summary": "Download IPs exploiting a CVE ID (raw)", + "description": "Download the list of IPs exploiting a specific CVE ID in raw format", + "operationId": "downloadCveIps", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "CVE Not Found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}/ips-details": { + "get": { + "tags": [ + "Cves" + ], + "summary": "Get IPs details exploiting a CVE ID", + "description": "Get detailed information about IPs exploiting a specific CVE ID", + "operationId": "getCveIpsDetails", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "pattern": "^\\d+[hd]$" + }, + { + "type": "null" + } + ], + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d", + "default": "14d", + "title": "Since" + }, + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCVEIPsResponsePage" + } + } + } + }, + "404": { + "description": "CVE Not Found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}/ips-details-stats": { + "get": { + "tags": [ + "Cves" + ], + "summary": "Get stats about IPs exploiting a CVE ID", + "description": "Get aggregated statistics about IPs exploiting a specific CVE ID", + "operationId": "getCveIpsDetailsStats", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "pattern": "^\\d+[hd]$" + }, + { + "type": "null" + } + ], + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d", + "default": "14d", + "title": "Since" + }, + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IpsDetailsStats" + } + } + } + }, + "404": { + "description": "CVE Not Found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}/integrations": { + "post": { + "tags": [ + "Cves" + ], + "summary": "Subscribe an integration to a CVE ID", + "description": "Subscribe an integration to receive threats related to a specific CVE ID", + "operationId": "subscribeIntegrationToCve", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscribeCVEIntegrationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Integration Not Found" + }, + "400": { + "description": "CVE Already Subscribed" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Cves" + ], + "summary": "Get subscribed integrations for a CVE ID", + "description": "Get the list of integrations subscribed to a specific CVE ID", + "operationId": "getCveSubscribedIntegrations", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCVESubscribedIntegrationsResponsePage" + } + } + } + }, + "404": { + "description": "CVE Not Found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}/integrations/{integration_name}": { + "delete": { + "tags": [ + "Cves" + ], + "summary": "Unsubscribe an integration from a CVE ID", + "description": "Unsubscribe an integration from receiving threats related to a specific CVE ID", + "operationId": "unsubscribeIntegrationFromCve", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + }, + { + "name": "integration_name", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Integration Name" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Integration Not Found" + }, + "400": { + "description": "CVE Already Unsubscribed" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/cves/{cve_id}/timeline": { + "get": { + "tags": [ + "Cves" + ], + "summary": "Get timeline data for a CVE ID", + "description": "Get timeline data of occurrences for a specific CVE ID", + "operationId": "getCveTimeline", + "parameters": [ + { + "name": "cve_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Cve Id" + } + }, + { + "name": "since_days", + "in": "query", + "required": false, + "schema": { + "$ref": "#/components/schemas/SinceOptions", + "description": "Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days.", + "default": 7 + }, + "description": "Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TimelineItem" + }, + "title": "Response Getcvetimeline" + } + } + } + }, + "404": { + "description": "CVE Not Found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors": { + "get": { + "tags": [ + "Vendors" + ], + "summary": "Get list of vendors", + "description": "Get a paginated list of vendors", + "operationId": "getVendors", + "parameters": [ + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search query for vendors", + "title": "Query" + }, + "description": "Search query for vendors" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/VendorSortBy" + }, + { + "type": "null" + } + ], + "description": "Sort by: value, nb_cves, nb_ips, latest_rule_release", + "title": "Sort By" + }, + "description": "Sort by: value, nb_cves, nb_ips, latest_rule_release" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: asc or desc", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: asc or desc" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupListWithStatsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors/{vendor}/stats": { + "get": { + "tags": [ + "Vendors" + ], + "summary": "Get vendor statistics", + "description": "Get statistics for a vendor including CVE/fingerprint counts, IP counts, and top affected products", + "operationId": "getVendorStats", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VendorStatsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors/{vendor}/ips-download": { + "get": { + "tags": [ + "Vendors" + ], + "summary": "Download IPs exploiting a vendor (raw)", + "description": "Download the list of IPs exploiting a specific vendor in raw format", + "operationId": "downloadVendorIps", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors/{vendor}/ips-details": { + "get": { + "tags": [ + "Vendors" + ], + "summary": "Get IP details exploiting a vendor", + "description": "Get detailed information about IPs exploiting a specific vendor", + "operationId": "getVendorIpsDetails", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "pattern": "^\\d+[hd]$" + }, + { + "type": "null" + } + ], + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d", + "default": "14d", + "title": "Since" + }, + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetVendorIPsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors/{vendor}/ips-details-stats": { + "get": { + "tags": [ + "Vendors" + ], + "summary": "Get stats about IPs exploiting a vendor", + "description": "Get aggregated statistics about IPs exploiting a specific vendor", + "operationId": "getVendorIpsDetailsStats", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "pattern": "^\\d+[hd]$" + }, + { + "type": "null" + } + ], + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d", + "default": "14d", + "title": "Since" + }, + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IpsDetailsStats" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors/{vendor}/integrations": { + "post": { + "tags": [ + "Vendors" + ], + "summary": "Subscribe an integration to a vendor", + "description": "Subscribe an integration to receive threats related to a specific vendor", + "operationId": "subscribeIntegrationToVendor", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscribeVendorIntegrationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Vendors" + ], + "summary": "Get subscribed integrations for a vendor", + "description": "Get the list of integrations subscribed to a specific vendor", + "operationId": "getVendorSubscribedIntegrations", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetVendorSubscribedIntegrationsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors/{vendor}/integrations/{integration_name}": { + "delete": { + "tags": [ + "Vendors" + ], + "summary": "Unsubscribe an integration from a vendor", + "description": "Unsubscribe an integration from receiving threats related to a specific vendor", + "operationId": "unsubscribeIntegrationFromVendor", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + }, + { + "name": "integration_name", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Integration Name" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/vendors/{vendor}": { + "get": { + "tags": [ + "Vendors" + ], + "summary": "Get vendor impact", + "description": "Get CVE and fingerprint rules affecting a vendor", + "operationId": "getVendorImpact", + "parameters": [ + { + "name": "vendor", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Vendor" + } + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by", + "default": "rule_release_date", + "title": "Sort By" + }, + "description": "Field to sort by" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: ascending or descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: ascending or descending" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupImpactResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/products": { + "get": { + "tags": [ + "Products" + ], + "summary": "Get list of products", + "description": "Get a paginated list of products", + "operationId": "getProducts", + "parameters": [ + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search query for products", + "title": "Query" + }, + "description": "Search query for products" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupListWithStatsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/products/{product}": { + "get": { + "tags": [ + "Products" + ], + "summary": "Get product impact", + "description": "Get CVE and fingerprint rules affecting a product", + "operationId": "getProductImpact", + "parameters": [ + { + "name": "product", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Product" + } + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by", + "default": "rule_release_date", + "title": "Sort By" + }, + "description": "Field to sort by" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: ascending or descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: ascending or descending" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupImpactResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/tags": { + "get": { + "tags": [ + "Tracker Tags" + ], + "summary": "Get list of tags", + "description": "Get a paginated list of tags", + "operationId": "getTags", + "parameters": [ + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search query for tags", + "title": "Query" + }, + "description": "Search query for tags" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupListWithStatsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/tags/{tag}": { + "get": { + "tags": [ + "Tracker Tags" + ], + "summary": "Get tag impact", + "description": "Get CVE and fingerprint rules affecting a tag", + "operationId": "getTagImpact", + "parameters": [ + { + "name": "tag", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Tag" + } + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by", + "default": "rule_release_date", + "title": "Sort By" + }, + "description": "Field to sort by" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: ascending or descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: ascending or descending" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupImpactResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/tracker-tags": { + "get": { + "tags": [ + "Tracker Tags" + ], + "summary": "Get list of tracker tags", + "description": "Get a paginated list of tracker tags", + "operationId": "getTrackerTags", + "parameters": [ + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search query for tags", + "title": "Query" + }, + "description": "Search query for tags" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupListWithStatsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/tracker-tags/{tag}": { + "get": { + "tags": [ + "Tracker Tags" + ], + "summary": "Get tracker tag impact", + "description": "Get CVE and fingerprint rules affecting a tracker tag", + "operationId": "getTrackerTagImpact", + "parameters": [ + { + "name": "tag", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Tag" + } + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by", + "default": "rule_release_date", + "title": "Sort By" + }, + "description": "Field to sort by" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: ascending or descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: ascending or descending" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LookupImpactResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints": { + "get": { + "tags": [ + "Fingerprints" + ], + "summary": "Get list of fingerprint rules", + "description": "Get a paginated list of fingerprint rules", + "operationId": "getFingerprintRules", + "parameters": [ + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Search query for fingerprint rules", + "title": "Query" + }, + "description": "Search query for fingerprint rules" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by", + "default": "rule_release_date", + "title": "Sort By" + }, + "description": "Field to sort by" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: ascending or descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: ascending or descending" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetFingerprintRulesResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints/{fingerprint}/ips-download": { + "get": { + "tags": [ + "Fingerprints" + ], + "summary": "Download IPs exploiting a fingerprint rule (raw)", + "description": "Download the list of IPs exploiting a specific fingerprint rule in raw format", + "operationId": "downloadFingerprintIps", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints/{fingerprint}/ips-details": { + "get": { + "tags": [ + "Fingerprints" + ], + "summary": "Get IP details exploiting a fingerprint rule", + "description": "Get detailed information about IPs exploiting a specific fingerprint rule", + "operationId": "getFingerprintIpsDetails", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "pattern": "^\\d+[hd]$" + }, + { + "type": "null" + } + ], + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d", + "default": "14d", + "title": "Since" + }, + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetFingerprintIPsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints/{fingerprint}/ips-details-stats": { + "get": { + "tags": [ + "Fingerprints" + ], + "summary": "Get stats about IPs exploiting a fingerprint rule", + "description": "Get aggregated statistics about IPs exploiting a specific fingerprint rule", + "operationId": "getFingerprintIpsDetailsStats", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "pattern": "^\\d+[hd]$" + }, + { + "type": "null" + } + ], + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d", + "default": "14d", + "title": "Since" + }, + "description": "Filter IPs seen since this date, format duration (e.g., 7d, 24h), default to 14d" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IpsDetailsStats" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints/{fingerprint}/integrations": { + "post": { + "tags": [ + "Fingerprints" + ], + "summary": "Subscribe an integration to a fingerprint rule", + "description": "Subscribe an integration to receive threats related to a specific fingerprint rule", + "operationId": "subscribeIntegrationToFingerprint", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscribeFingerprintIntegrationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Fingerprints" + ], + "summary": "Get subscribed integrations for a fingerprint rule", + "description": "Get the list of integrations subscribed to a specific fingerprint rule", + "operationId": "getFingerprintSubscribedIntegrations", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetFingerprintSubscribedIntegrationsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints/{fingerprint}/integrations/{integration_name}": { + "delete": { + "tags": [ + "Fingerprints" + ], + "summary": "Unsubscribe an integration from a fingerprint rule", + "description": "Unsubscribe an integration from receiving threats related to a specific fingerprint rule", + "operationId": "unsubscribeIntegrationFromFingerprint", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + }, + { + "name": "integration_name", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Integration Name" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints/{fingerprint}/timeline": { + "get": { + "tags": [ + "Fingerprints" + ], + "summary": "Get timeline data for a fingerprint rule", + "description": "Get timeline data of occurrences for a specific fingerprint rule", + "operationId": "getFingerprintTimeline", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + }, + { + "name": "since_days", + "in": "query", + "required": false, + "schema": { + "$ref": "#/components/schemas/SinceOptions", + "description": "Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days.", + "default": 7 + }, + "description": "Time range for the timeline data (in days). Options: 1 (1 day), 7 (1 week), 30 (1 month). Default is 7 days." + }, + { + "name": "interval", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/IntervalOptions" + }, + { + "type": "null" + } + ], + "description": "Interval for aggregating timeline data. Options: 'hour', 'day', 'week'. Default is adapted based on 'since' parameter.", + "title": "Interval" + }, + "description": "Interval for aggregating timeline data. Options: 'hour', 'day', 'week'. Default is adapted based on 'since' parameter." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FingerprintTimelineItem" + }, + "title": "Response Getfingerprinttimeline" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/fingerprints/{fingerprint}": { + "get": { + "tags": [ + "Fingerprints" + ], + "summary": "Get fingerprint rule information", + "description": "Get information about a specific fingerprint rule", + "operationId": "getFingerprintRule", + "parameters": [ + { + "name": "fingerprint", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Fingerprint" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FingerprintRuleResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/tracker-events/exploitation-phase-change": { + "get": { + "tags": [ + "Tracker events" + ], + "summary": "Get exploitation phase change events", + "description": "Get a paginated list of exploitation phase change events across tracked CVEs", + "operationId": "getExploitationPhaseChangeEvents", + "parameters": [ + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "description": "Duration string (e.g. '30d', '24h') to filter events", + "default": "30d", + "title": "Since" + }, + "description": "Duration string (e.g. '30d', '24h') to filter events" + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/GetCVEsSortOrder" + }, + { + "type": "null" + } + ], + "description": "Sort order: ascending or descending", + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: ascending or descending" + }, + { + "name": "cve_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter by CVE identifier (exact match)", + "title": "Cve Id" + }, + "description": "Filter by CVE identifier (exact match)" + }, + { + "name": "previous_phase", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/CVEExploitationPhase" + }, + { + "type": "null" + } + ], + "description": "Filter by previous exploitation phase name", + "title": "Previous Phase" + }, + "description": "Filter by previous exploitation phase name" + }, + { + "name": "new_phase", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/CVEExploitationPhase" + }, + { + "type": "null" + } + ], + "description": "Filter by new exploitation phase name", + "title": "New Phase" + }, + "description": "Filter by new exploitation phase name" + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "description": "Page number", + "default": 1, + "title": "Page" + }, + "description": "Page number" + }, + { + "name": "size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "description": "Page size", + "default": 50, + "title": "Size" + }, + "description": "Page size" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExploitationPhaseChangeEventsResponsePage" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "AllowlistCreateRequest": { + "properties": { + "name": { + "type": "string", + "maxLength": 200, + "minLength": 1, + "title": "Name", + "description": "Name of the allowlist" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Description of the allowlist" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "name" + ], + "title": "AllowlistCreateRequest" + }, + "AllowlistCreateResponse": { + "properties": { + "id": { + "type": "string", + "format": "ObjectId", + "title": "Id", + "description": "ID of the allowlist", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "organization_id": { + "type": "string", + "title": "Organization Id", + "description": "ID of the owner organization" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the allowlist" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the allowlist" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the allowlist was created" + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At", + "description": "Time the allowlist was updated" + }, + "from_cti_query": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "From Cti Query", + "description": "CTI query from which the blocklist was created" + }, + "since": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Since", + "description": "Since duration for the CTI query (eg. 5m, 2h, 7d). Max is 30 days" + }, + "total_items": { + "type": "integer", + "title": "Total Items", + "description": "Number of items in the allowlist" + } + }, + "type": "object", + "required": [ + "id", + "organization_id", + "name", + "created_at", + "total_items" + ], + "title": "AllowlistCreateResponse" + }, + "AllowlistGetItemsResponse": { + "properties": { + "id": { + "type": "string", + "format": "ObjectId", + "title": "Id", + "description": "ID of the allowlist entry", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "allowlist_id": { + "type": "string", + "format": "ObjectId", + "title": "Allowlist Id", + "description": "ID of the allowlist", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "description": { + "type": "string", + "minLength": 1, + "title": "Description", + "description": "Description of the allowlist entry" + }, + "scope": { + "$ref": "#/components/schemas/AllowlistScope", + "description": "Scope of the allowlist entry" + }, + "value": { + "anyOf": [ + { + "type": "string", + "format": "ipvanyaddress" + }, + { + "type": "string", + "format": "ipvanynetwork" + } + ], + "title": "Value", + "description": "Value of the allowlist entry" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the allowlist entry was created" + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At", + "description": "Time the allowlist entry was updated" + }, + "created_by": { + "$ref": "#/components/schemas/SourceInfo", + "description": "The source user who created the allowlist entry" + }, + "updated_by": { + "anyOf": [ + { + "$ref": "#/components/schemas/SourceInfo" + }, + { + "type": "null" + } + ], + "description": "The source user who updated the allowlist entry" + }, + "expiration": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Expiration", + "description": "Time the allowlist entry will expire" + } + }, + "type": "object", + "required": [ + "id", + "allowlist_id", + "description", + "scope", + "value", + "created_at", + "created_by" + ], + "title": "AllowlistGetItemsResponse" + }, + "AllowlistGetItemsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/AllowlistGetItemsResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "AllowlistGetItemsResponsePage" + }, + "AllowlistGetResponse": { + "properties": { + "id": { + "type": "string", + "format": "ObjectId", + "title": "Id", + "description": "ID of the allowlist", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "organization_id": { + "type": "string", + "title": "Organization Id", + "description": "ID of the owner organization" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the allowlist" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the allowlist" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the allowlist was created" + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At", + "description": "Time the allowlist was updated" + }, + "from_cti_query": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "From Cti Query", + "description": "CTI query from which the blocklist was created" + }, + "since": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Since", + "description": "Since duration for the CTI query (eg. 5m, 2h, 7d). Max is 30 days" + }, + "total_items": { + "type": "integer", + "title": "Total Items", + "description": "Number of items in the allowlist" + }, + "subscribers": { + "items": { + "$ref": "#/components/schemas/AllowlistSubscribersCount" + }, + "type": "array", + "title": "Subscribers", + "description": "List of subscribers count by entity type", + "default": [] + } + }, + "type": "object", + "required": [ + "id", + "organization_id", + "name", + "created_at", + "total_items" + ], + "title": "AllowlistGetResponse" + }, + "AllowlistGetResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/AllowlistGetResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "AllowlistGetResponsePage" + }, + "AllowlistItemUpdateRequest": { + "properties": { + "description": { + "type": "string", + "title": "Description", + "description": "Description of the allowlist entry" + }, + "expiration": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Expiration", + "description": "Time the allowlist entry will expire" + } + }, + "additionalProperties": false, + "type": "object", + "title": "AllowlistItemUpdateRequest" + }, + "AllowlistItemUpdateResponse": { + "properties": { + "id": { + "type": "string", + "format": "ObjectId", + "title": "Id", + "description": "ID of the allowlist entry", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "allowlist_id": { + "type": "string", + "format": "ObjectId", + "title": "Allowlist Id", + "description": "ID of the allowlist", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "description": { + "type": "string", + "minLength": 1, + "title": "Description", + "description": "Description of the allowlist entry" + }, + "scope": { + "$ref": "#/components/schemas/AllowlistScope", + "description": "Scope of the allowlist entry" + }, + "value": { + "anyOf": [ + { + "type": "string", + "format": "ipvanyaddress" + }, + { + "type": "string", + "format": "ipvanynetwork" + } + ], + "title": "Value", + "description": "Value of the allowlist entry" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the allowlist entry was created" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At", + "description": "Time the allowlist entry was updated" + }, + "created_by": { + "$ref": "#/components/schemas/SourceInfo", + "description": "The source user who created the allowlist entry" + }, + "updated_by": { + "$ref": "#/components/schemas/SourceInfo", + "description": "The source user who updated the allowlist entry" + }, + "expiration": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Expiration", + "description": "Time the allowlist entry will expire" + } + }, + "type": "object", + "required": [ + "id", + "allowlist_id", + "description", + "scope", + "value", + "created_at", + "updated_at", + "created_by", + "updated_by" + ], + "title": "AllowlistItemUpdateResponse" + }, + "AllowlistItemsCreateRequest": { + "properties": { + "items": { + "items": { + "anyOf": [ + { + "type": "string", + "format": "ipvanyaddress" + }, + { + "type": "string", + "format": "ipvanynetwork" + } + ] + }, + "type": "array", + "title": "Items", + "description": "List of values to add to the allowlist" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the allowlist entry" + }, + "expiration": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Expiration", + "description": "Time the allowlist entry will expire" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "items", + "description" + ], + "title": "AllowlistItemsCreateRequest" + }, + "AllowlistScope": { + "type": "string", + "enum": [ + "ip", + "range" + ], + "title": "AllowlistScope" + }, + "AllowlistSubscriberEntity": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Subscriber entity id" + }, + "entity_type": { + "$ref": "#/components/schemas/SubscriberEntityType" + } + }, + "type": "object", + "required": [ + "id", + "entity_type" + ], + "title": "AllowlistSubscriberEntity" + }, + "AllowlistSubscriberEntityPage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/AllowlistSubscriberEntity" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "AllowlistSubscriberEntityPage" + }, + "AllowlistSubscribersCount": { + "properties": { + "entity_type": { + "$ref": "#/components/schemas/SubscriberEntityType", + "description": "Subscriber entity type" + }, + "count": { + "type": "integer", + "title": "Count", + "description": "Subscriber entity count" + } + }, + "type": "object", + "required": [ + "entity_type", + "count" + ], + "title": "AllowlistSubscribersCount" + }, + "AllowlistSubscriptionRequest": { + "properties": { + "ids": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Ids", + "description": "List of subscriber entity id" + }, + "entity_type": { + "$ref": "#/components/schemas/EntityType" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "entity_type" + ], + "title": "AllowlistSubscriptionRequest" + }, + "AllowlistSubscriptionResponse": { + "properties": { + "updated": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Updated", + "description": "List of updated allowlist ids", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "errors": { + "anyOf": [ + { + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Errors", + "description": "List of errors if any", + "examples": [ + { + "5f9d88b9e5c4f5b9a3d3e8b1": "error message" + } + ] + } + }, + "type": "object", + "required": [ + "updated", + "errors" + ], + "title": "AllowlistSubscriptionResponse" + }, + "AllowlistUpdateRequest": { + "properties": { + "name": { + "anyOf": [ + { + "type": "string", + "maxLength": 200, + "minLength": 1 + }, + { + "type": "null" + } + ], + "title": "Name", + "description": "Name of the allowlist" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Description of the allowlist" + } + }, + "additionalProperties": false, + "type": "object", + "title": "AllowlistUpdateRequest" + }, + "AllowlistUpdateResponse": { + "properties": { + "id": { + "type": "string", + "format": "ObjectId", + "title": "Id", + "description": "ID of the allowlist", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "organization_id": { + "type": "string", + "title": "Organization Id", + "description": "ID of the owner organization" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the allowlist" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the allowlist" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the allowlist was created" + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At", + "description": "Time the allowlist was updated" + }, + "from_cti_query": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "From Cti Query", + "description": "CTI query from which the blocklist was created" + }, + "since": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Since", + "description": "Since duration for the CTI query (eg. 5m, 2h, 7d). Max is 30 days" + }, + "total_items": { + "type": "integer", + "title": "Total Items", + "description": "Number of items in the allowlist" + }, + "subscribers": { + "items": { + "$ref": "#/components/schemas/AllowlistSubscribersCount" + }, + "type": "array", + "title": "Subscribers", + "description": "List of subscribers count by entity type", + "default": [] + } + }, + "type": "object", + "required": [ + "id", + "organization_id", + "name", + "created_at", + "total_items" + ], + "title": "AllowlistUpdateResponse" + }, + "ApiKeyCredentials": { + "properties": { + "api_key": { + "type": "string", + "title": "Api Key", + "description": "API key for the integration" + } + }, + "type": "object", + "required": [ + "api_key" + ], + "title": "ApiKeyCredentials" + }, + "AttacksMetrics": { + "properties": { + "total": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "title": "Total", + "description": "Total value of the metric" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Label of the metric which is the attack type" + }, + "progression": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Progression", + "description": "Progression of the metric value from the previous period" + }, + "data": { + "items": { + "$ref": "#/components/schemas/RemediationMetricsData" + }, + "type": "array", + "title": "Data", + "description": "Data points" + } + }, + "type": "object", + "required": [ + "total", + "label", + "progression", + "data" + ], + "title": "AttacksMetrics" + }, + "BasicAuthCredentials": { + "properties": { + "username": { + "type": "string", + "title": "Username", + "description": "Basic auth username for the integration" + }, + "password": { + "type": "string", + "title": "Password", + "description": "Basic auth password for the integration" + } + }, + "type": "object", + "required": [ + "username", + "password" + ], + "title": "BasicAuthCredentials" + }, + "BlocklistAddIPsRequest": { + "properties": { + "ips": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Ips", + "description": "List of IPs or networks" + }, + "expiration": { + "type": "string", + "format": "date-time", + "title": "Expiration", + "description": "Expiration date", + "examples": [ + "2030-01-01T00:00:00.000Z" + ] + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "ips" + ], + "title": "BlocklistAddIPsRequest" + }, + "BlocklistCategory": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + }, + "description": { + "type": "string", + "title": "Description" + }, + "priority": { + "type": "integer", + "title": "Priority" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description", + "priority" + ], + "title": "BlocklistCategory" + }, + "BlocklistContentStats": { + "properties": { + "total_seen": { + "type": "integer", + "title": "Total Seen", + "default": 0 + }, + "total_fire": { + "type": "integer", + "title": "Total Fire", + "default": 0 + }, + "total_seen_1m": { + "type": "integer", + "title": "Total Seen 1M", + "default": 0 + }, + "total_in_other_lists": { + "type": "integer", + "title": "Total In Other Lists", + "default": 0 + }, + "total_false_positive": { + "type": "integer", + "title": "Total False Positive", + "default": 0 + }, + "false_positive_removed_by_crowdsec": { + "type": "integer", + "title": "False Positive Removed By Crowdsec", + "default": 0 + }, + "most_present_behaviors": { + "items": { + "$ref": "#/components/schemas/CtiBehavior" + }, + "type": "array", + "title": "Most Present Behaviors", + "default": [] + }, + "most_present_categories": { + "items": { + "$ref": "#/components/schemas/CtiCategory" + }, + "type": "array", + "title": "Most Present Categories", + "default": [] + }, + "most_present_scenarios": { + "items": { + "$ref": "#/components/schemas/CtiScenario" + }, + "type": "array", + "title": "Most Present Scenarios", + "default": [] + }, + "top_as": { + "items": { + "$ref": "#/components/schemas/CtiAs" + }, + "type": "array", + "title": "Top As", + "default": [] + }, + "top_attacking_countries": { + "items": { + "$ref": "#/components/schemas/CtiCountry" + }, + "type": "array", + "title": "Top Attacking Countries", + "default": [] + }, + "top_ips": { + "items": { + "$ref": "#/components/schemas/CtiIp" + }, + "type": "array", + "title": "Top Ips", + "default": [] + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At" + } + }, + "additionalProperties": true, + "type": "object", + "title": "BlocklistContentStats" + }, + "BlocklistCreateRequest": { + "properties": { + "name": { + "type": "string", + "maxLength": 200, + "minLength": 1, + "title": "Name", + "description": "Blocklist name, must be unique within the organization" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Blocklist human readable name (Default: name)" + }, + "description": { + "type": "string", + "minLength": 1, + "title": "Description", + "description": "Blocklist description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "Useful references on the list's origins", + "default": [] + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Classification tags", + "default": [] + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "name", + "description" + ], + "title": "BlocklistCreateRequest" + }, + "BlocklistDeleteIPsRequest": { + "properties": { + "ips": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Ips", + "description": "List of IPs or networks" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "ips" + ], + "title": "BlocklistDeleteIPsRequest" + }, + "BlocklistIncludeFilters": { + "type": "string", + "enum": [ + "public", + "private", + "shared", + "all" + ], + "title": "BlocklistIncludeFilters" + }, + "BlocklistOrigin": { + "properties": { + "label": { + "type": "string", + "title": "Label", + "description": "Label of the blocklist" + }, + "id": { + "type": "string", + "title": "Id", + "description": "ID of the blocklist" + }, + "pricing_tier": { + "$ref": "#/components/schemas/PricingTiers", + "description": "Pricing tier of the blocklist" + } + }, + "type": "object", + "required": [ + "label", + "id", + "pricing_tier" + ], + "title": "BlocklistOrigin" + }, + "BlocklistSearchRequest": { + "properties": { + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page", + "description": "Page number", + "default": 1 + }, + "page_size": { + "type": "integer", + "maximum": 1000.0, + "title": "Page Size", + "description": "Page size", + "default": 100 + }, + "pricing_tiers": { + "items": { + "$ref": "#/components/schemas/PricingTiers" + }, + "type": "array", + "title": "Pricing Tiers", + "description": "Pricing tiers", + "default": [] + }, + "query": { + "type": "string", + "title": "Query", + "description": "Search query", + "default": "" + }, + "targeted_countries": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Targeted Countries", + "description": "Targeted countries", + "default": [] + }, + "classifications": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Classifications", + "description": "Classifications", + "default": [] + }, + "behaviors": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Behaviors", + "description": "Behaviors", + "default": [] + }, + "min_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Min Ips", + "description": "Minimum number of IPs", + "default": 0 + }, + "sources": { + "items": { + "$ref": "#/components/schemas/BlocklistSources" + }, + "type": "array", + "title": "Sources", + "description": "Sources", + "default": [] + }, + "categories": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Categories", + "description": "Categories", + "default": [] + }, + "is_private": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Private", + "description": "Private blocklist" + }, + "is_subscribed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Subscribed", + "description": "Subscribed blocklist (None: all)" + } + }, + "additionalProperties": false, + "type": "object", + "title": "BlocklistSearchRequest" + }, + "BlocklistShareRequest": { + "properties": { + "organizations": { + "items": { + "$ref": "#/components/schemas/Share" + }, + "type": "array", + "title": "Organizations", + "description": "List of organizations to share the blocklist" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "organizations" + ], + "title": "BlocklistShareRequest" + }, + "BlocklistSources": { + "type": "string", + "enum": [ + "crowdsec", + "third_party", + "custom" + ], + "title": "BlocklistSources" + }, + "BlocklistStats": { + "properties": { + "content_stats": { + "$ref": "#/components/schemas/BlocklistContentStats", + "default": { + "total_seen": 0, + "total_fire": 0, + "total_seen_1m": 0, + "total_in_other_lists": 0, + "total_false_positive": 0, + "false_positive_removed_by_crowdsec": 0, + "most_present_behaviors": [], + "most_present_categories": [], + "most_present_scenarios": [], + "top_as": [], + "top_attacking_countries": [], + "top_ips": [] + } + }, + "usage_stats": { + "anyOf": [ + { + "$ref": "#/components/schemas/BlocklistUsageStats" + }, + { + "type": "null" + } + ], + "default": { + "engines_subscribed_directly": 0, + "engines_subscribed_through_org": 0, + "engines_subscribed_through_tag": 0, + "total_subscribed_engines": 0, + "total_subscribed_organizations": 0 + } + }, + "addition_2days": { + "type": "integer", + "title": "Addition 2Days", + "default": 0 + }, + "addition_month": { + "type": "integer", + "title": "Addition Month", + "default": 0 + }, + "suppression_2days": { + "type": "integer", + "title": "Suppression 2Days", + "default": 0 + }, + "suppression_month": { + "type": "integer", + "title": "Suppression Month", + "default": 0 + }, + "change_2days_percentage": { + "type": "number", + "title": "Change 2Days Percentage", + "default": 0.0 + }, + "change_month_percentage": { + "type": "number", + "title": "Change Month Percentage", + "default": 0.0 + }, + "count": { + "type": "integer", + "title": "Count", + "default": 0 + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At" + } + }, + "additionalProperties": true, + "type": "object", + "title": "BlocklistStats" + }, + "BlocklistSubscriberEntity": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Subscriber entity id" + }, + "entity_type": { + "$ref": "#/components/schemas/SubscriberEntityType" + }, + "remediation": { + "type": "string", + "title": "Remediation", + "description": "Remediation" + } + }, + "type": "object", + "required": [ + "id", + "entity_type", + "remediation" + ], + "title": "BlocklistSubscriberEntity" + }, + "BlocklistSubscriberEntityPage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/BlocklistSubscriberEntity" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "BlocklistSubscriberEntityPage" + }, + "BlocklistSubscribersCount": { + "properties": { + "entity_type": { + "$ref": "#/components/schemas/SubscriberEntityType", + "description": "Subscriber entity type" + }, + "count": { + "type": "integer", + "title": "Count", + "description": "Subscriber entity count" + } + }, + "type": "object", + "required": [ + "entity_type", + "count" + ], + "title": "BlocklistSubscribersCount" + }, + "BlocklistSubscription": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "remediation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Remediation" + }, + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + } + }, + "type": "object", + "required": [ + "id", + "name", + "label" + ], + "title": "BlocklistSubscription" + }, + "BlocklistSubscriptionRequest": { + "properties": { + "ids": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Ids", + "description": "List of subscriber entity id" + }, + "entity_type": { + "$ref": "#/components/schemas/SubscriberEntityType" + }, + "remediation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Remediation", + "description": "Remediation" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "entity_type" + ], + "title": "BlocklistSubscriptionRequest" + }, + "BlocklistSubscriptionResponse": { + "properties": { + "updated": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Updated", + "description": "List of updated blocklist ids", + "examples": [ + "5f9d88b9e5c4f5b9a3d3e8b1" + ] + }, + "errors": { + "anyOf": [ + { + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Errors", + "description": "List of errors if any", + "examples": [ + { + "5f9d88b9e5c4f5b9a3d3e8b1": "error message" + } + ] + } + }, + "type": "object", + "required": [ + "updated", + "errors" + ], + "title": "BlocklistSubscriptionResponse" + }, + "BlocklistUpdateRequest": { + "properties": { + "label": { + "type": "string", + "title": "Label", + "description": "Blocklist human readable name" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Blocklist description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "Blocklist references" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Blocklist tags" + }, + "from_cti_query": { + "type": "string", + "title": "From Cti Query", + "description": "CTI query (doc link available soon)" + }, + "since": { + "type": "string", + "title": "Since", + "description": "Since duration for the CTI query (eg. 5m, 2h, 7d). Max is 30 days" + } + }, + "additionalProperties": false, + "type": "object", + "title": "BlocklistUpdateRequest" + }, + "BlocklistUsageStats": { + "properties": { + "engines_subscribed_directly": { + "type": "integer", + "title": "Engines Subscribed Directly", + "default": 0 + }, + "engines_subscribed_through_org": { + "type": "integer", + "title": "Engines Subscribed Through Org", + "default": 0 + }, + "engines_subscribed_through_tag": { + "type": "integer", + "title": "Engines Subscribed Through Tag", + "default": 0 + }, + "total_subscribed_engines": { + "type": "integer", + "title": "Total Subscribed Engines", + "default": 0 + }, + "total_subscribed_organizations": { + "type": "integer", + "title": "Total Subscribed Organizations", + "default": 0 + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At" + } + }, + "additionalProperties": true, + "type": "object", + "title": "BlocklistUsageStats" + }, + "Body_uploadBlocklistContent": { + "properties": { + "file": { + "type": "string", + "format": "binary", + "title": "File", + "description": "Blocklist file in txt format" + } + }, + "type": "object", + "required": [ + "file" + ], + "title": "Body_uploadBlocklistContent" + }, + "CVESubscription": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "CVE ID" + } + }, + "type": "object", + "required": [ + "id" + ], + "title": "CVESubscription" + }, + "ComputedMetrics": { + "properties": { + "saved": { + "$ref": "#/components/schemas/ComputedSavedMetrics", + "description": "estimated saved metrics" + }, + "dropped": { + "items": { + "$ref": "#/components/schemas/RemediationMetrics" + }, + "type": "array", + "title": "Dropped", + "description": "estimated dropped metrics", + "default": [] + }, + "prevented": { + "items": { + "$ref": "#/components/schemas/AttacksMetrics" + }, + "type": "array", + "title": "Prevented", + "description": "prevented attacks metrics", + "default": [] + } + }, + "type": "object", + "required": [ + "saved" + ], + "title": "ComputedMetrics" + }, + "ComputedSavedMetrics": { + "properties": { + "log_lines": { + "items": { + "$ref": "#/components/schemas/RemediationMetrics" + }, + "type": "array", + "title": "Log Lines", + "description": "estimated log lines saved", + "default": [] + }, + "storage": { + "items": { + "$ref": "#/components/schemas/RemediationMetrics" + }, + "type": "array", + "title": "Storage", + "description": "estimated storage saved", + "default": [] + }, + "egress_traffic": { + "items": { + "$ref": "#/components/schemas/RemediationMetrics" + }, + "type": "array", + "title": "Egress Traffic", + "description": "estimated egress traffic saved", + "default": [] + } + }, + "type": "object", + "title": "ComputedSavedMetrics" + }, + "CtiAs": { + "properties": { + "as_num": { + "type": "string", + "title": "As Num" + }, + "as_name": { + "type": "string", + "title": "As Name" + }, + "total_ips": { + "type": "integer", + "title": "Total Ips" + } + }, + "additionalProperties": true, + "type": "object", + "required": [ + "as_num", + "as_name", + "total_ips" + ], + "title": "CtiAs" + }, + "CtiBehavior": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + }, + "description": { + "type": "string", + "title": "Description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References" + }, + "total_ips": { + "type": "integer", + "title": "Total Ips" + } + }, + "additionalProperties": true, + "type": "object", + "required": [ + "name", + "label", + "description", + "references", + "total_ips" + ], + "title": "CtiBehavior" + }, + "CtiCategory": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + }, + "description": { + "type": "string", + "title": "Description" + }, + "total_ips": { + "type": "integer", + "title": "Total Ips" + } + }, + "additionalProperties": true, + "type": "object", + "required": [ + "name", + "label", + "description", + "total_ips" + ], + "title": "CtiCategory" + }, + "CtiCountry": { + "properties": { + "country_short": { + "type": "string", + "title": "Country Short" + }, + "total_ips": { + "type": "integer", + "title": "Total Ips" + } + }, + "additionalProperties": true, + "type": "object", + "required": [ + "country_short", + "total_ips" + ], + "title": "CtiCountry" + }, + "CtiIp": { + "properties": { + "ip": { + "type": "string", + "title": "Ip" + }, + "total_signals_1m": { + "type": "integer", + "title": "Total Signals 1M" + }, + "reputation": { + "type": "string", + "title": "Reputation", + "default": "unknown" + } + }, + "additionalProperties": true, + "type": "object", + "required": [ + "ip", + "total_signals_1m" + ], + "title": "CtiIp" + }, + "CtiScenario": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "label": { + "type": "string", + "title": "Label" + }, + "description": { + "type": "string", + "title": "Description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References" + }, + "total_ips": { + "type": "integer", + "title": "Total Ips" + } + }, + "additionalProperties": true, + "type": "object", + "required": [ + "name", + "label", + "description", + "references", + "total_ips" + ], + "title": "CtiScenario" + }, + "DecisionCreateRequest": { + "properties": { + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "uuid": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Uuid", + "description": "UUID of the decision" + }, + "id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Id", + "description": "ID of the decision" + }, + "duration": { + "type": "string", + "title": "Duration", + "description": "Duration of the decision" + }, + "origin": { + "type": "string", + "title": "Origin", + "description": "Origin of the decision" + }, + "scenario": { + "type": "string", + "title": "Scenario", + "description": "Scenario of the decision" + }, + "scope": { + "type": "string", + "title": "Scope", + "description": "Scope of the decision" + }, + "type": { + "type": "string", + "title": "Type", + "description": "Type of the decision" + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the decision" + }, + "country": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Country", + "description": "Country associated with the decision" + }, + "as_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "As Name", + "description": "AS name associated with the decision" + }, + "as_num": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "As Num", + "description": "AS number associated with the decision" + }, + "city": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "City", + "description": "City associated with the decision" + }, + "latitude": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Latitude", + "description": "Latitude associated with the decision" + }, + "longitude": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Longitude", + "description": "Longitude associated with the decision" + }, + "target": { + "$ref": "#/components/schemas/DecisionTargetModel", + "description": "Target of the decision" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "duration", + "origin", + "scenario", + "scope", + "type", + "value", + "target" + ], + "title": "DecisionCreateRequest" + }, + "DecisionCreateResponse": { + "properties": { + "uuid": { + "type": "string", + "title": "Uuid", + "description": "UUID of the created decision" + } + }, + "type": "object", + "required": [ + "uuid" + ], + "title": "DecisionCreateResponse" + }, + "DecisionResponse": { + "properties": { + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "uuid": { + "type": "string", + "title": "Uuid", + "description": "UUID of the decision" + }, + "id": { + "type": "integer", + "title": "Id", + "description": "ID of the decision" + }, + "duration": { + "type": "string", + "title": "Duration", + "description": "Duration of the decision" + }, + "origin": { + "type": "string", + "title": "Origin", + "description": "Origin of the decision" + }, + "scenario": { + "type": "string", + "title": "Scenario", + "description": "Scenario of the decision" + }, + "scope": { + "type": "string", + "title": "Scope", + "description": "Scope of the decision" + }, + "type": { + "type": "string", + "title": "Type", + "description": "Type of the decision" + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the decision" + }, + "country": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Country", + "description": "Country associated with the decision" + }, + "as_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "As Name", + "description": "AS name associated with the decision" + }, + "as_num": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "As Num", + "description": "AS number associated with the decision" + }, + "city": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "City", + "description": "City associated with the decision" + }, + "latitude": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Latitude", + "description": "Latitude associated with the decision" + }, + "longitude": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Longitude", + "description": "Longitude associated with the decision" + }, + "target": { + "$ref": "#/components/schemas/DecisionTargetModel", + "description": "Target of the decision" + } + }, + "type": "object", + "required": [ + "uuid", + "id", + "duration", + "origin", + "scenario", + "scope", + "type", + "value", + "target" + ], + "title": "DecisionResponse" + }, + "DecisionTargetModel": { + "properties": { + "type": { + "$ref": "#/components/schemas/DecisionTargetType", + "description": "Type of the decision target" + }, + "value": { + "type": "string", + "title": "Value", + "description": "Value of the decision target" + } + }, + "type": "object", + "required": [ + "type", + "value" + ], + "title": "DecisionTargetModel" + }, + "DecisionTargetType": { + "type": "string", + "enum": [ + "org", + "tag", + "entity" + ], + "title": "DecisionTargetType" + }, + "DecisionsGetResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/DecisionResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "DecisionsGetResponsePage" + }, + "DecisionsSortBy": { + "type": "string", + "enum": [ + "created_at", + "expire_at" + ], + "title": "DecisionsSortBy" + }, + "DecisionsSortOrder": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "title": "DecisionsSortOrder" + }, + "EntityType": { + "type": "string", + "enum": [ + "org", + "tag", + "engine", + "firewall_integration", + "remediation_component_integration", + "remediation_component", + "log_processor" + ], + "title": "EntityType" + }, + "FingerprintSubscription": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Fingerprint ID" + } + }, + "type": "object", + "required": [ + "id" + ], + "title": "FingerprintSubscription" + }, + "GetRemediationMetricsResponse": { + "properties": { + "raw": { + "$ref": "#/components/schemas/RawMetrics", + "description": "Raw metrics data" + }, + "computed": { + "$ref": "#/components/schemas/ComputedMetrics", + "description": "Computed metrics data" + } + }, + "type": "object", + "required": [ + "raw", + "computed" + ], + "title": "GetRemediationMetricsResponse" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array" + } + }, + "title": "HTTPValidationError", + "type": "object" + }, + "InfoResponse": { + "properties": { + "organization_id": { + "type": "string", + "title": "Organization Id", + "description": "The organization ID" + }, + "subscription_type": { + "type": "string", + "title": "Subscription Type", + "description": "The organization subscription type" + }, + "api_key_name": { + "type": "string", + "title": "Api Key Name", + "description": "The API key name that is used" + } + }, + "type": "object", + "required": [ + "organization_id", + "subscription_type", + "api_key_name" + ], + "title": "InfoResponse" + }, + "IntegrationCreateRequest": { + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name", + "description": "Name of the integration" + }, + "description": { + "type": "string", + "minLength": 1, + "title": "Description", + "description": "Description of the integration" + }, + "entity_type": { + "$ref": "#/components/schemas/IntegrationType", + "description": "Type of the integration" + }, + "output_format": { + "$ref": "#/components/schemas/OutputFormat", + "description": "Output format of the integration" + }, + "pull_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pull Limit", + "description": "Maximum number of items to pull" + }, + "enable_ip_aggregation": { + "type": "boolean", + "title": "Enable Ip Aggregation", + "description": "Whether to enable IP aggregation into ranges", + "default": false + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "name", + "entity_type", + "output_format" + ], + "title": "IntegrationCreateRequest" + }, + "IntegrationCreateResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the integration" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the integration. Should be unique within the organization" + }, + "organization_id": { + "type": "string", + "title": "Organization Id", + "description": "ID of the owner organization" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the integration" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the integration was created" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At", + "description": "Last time the integration was updated" + }, + "entity_type": { + "$ref": "#/components/schemas/IntegrationType", + "description": "Type of the integration" + }, + "output_format": { + "$ref": "#/components/schemas/OutputFormat", + "description": "Output format of the integration" + }, + "last_pull": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Pull", + "description": "Last time the integration pulled blocklists" + }, + "blocklists": { + "items": { + "$ref": "#/components/schemas/BlocklistSubscription" + }, + "type": "array", + "title": "Blocklists", + "description": "Blocklists that are subscribed by the integration" + }, + "cves": { + "items": { + "$ref": "#/components/schemas/CVESubscription" + }, + "type": "array", + "title": "Cves", + "description": "CVEs that are subscribed by the integration" + }, + "fingerprints": { + "items": { + "$ref": "#/components/schemas/FingerprintSubscription" + }, + "type": "array", + "title": "Fingerprints", + "description": "Fingerprints that are subscribed by the integration" + }, + "vendors": { + "items": { + "$ref": "#/components/schemas/VendorSubscription" + }, + "type": "array", + "title": "Vendors", + "description": "Vendors that are subscribed by the integration" + }, + "endpoint": { + "type": "string", + "maxLength": 2083, + "minLength": 1, + "format": "uri", + "title": "Endpoint", + "description": "Url that should be used by the firewall or the remediation component to fetch the integration's content" + }, + "stats": { + "$ref": "#/components/schemas/Stats", + "description": "Stats of the integration", + "default": { + "count": 0 + } + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the integration", + "default": [] + }, + "pull_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pull Limit", + "description": "Maximum number of items to pull" + }, + "enable_ip_aggregation": { + "type": "boolean", + "title": "Enable Ip Aggregation", + "description": "Whether to enable IP aggregation into ranges", + "default": false + }, + "credentials": { + "anyOf": [ + { + "$ref": "#/components/schemas/ApiKeyCredentials" + }, + { + "$ref": "#/components/schemas/BasicAuthCredentials" + } + ], + "title": "Credentials", + "description": "Credentials that were generated for the integration" + } + }, + "type": "object", + "required": [ + "id", + "name", + "organization_id", + "created_at", + "updated_at", + "entity_type", + "output_format", + "blocklists", + "cves", + "fingerprints", + "vendors", + "endpoint", + "credentials" + ], + "title": "IntegrationCreateResponse" + }, + "IntegrationGetResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the integration" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the integration. Should be unique within the organization" + }, + "organization_id": { + "type": "string", + "title": "Organization Id", + "description": "ID of the owner organization" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the integration" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the integration was created" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At", + "description": "Last time the integration was updated" + }, + "entity_type": { + "$ref": "#/components/schemas/IntegrationType", + "description": "Type of the integration" + }, + "output_format": { + "$ref": "#/components/schemas/OutputFormat", + "description": "Output format of the integration" + }, + "last_pull": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Pull", + "description": "Last time the integration pulled blocklists" + }, + "blocklists": { + "items": { + "$ref": "#/components/schemas/BlocklistSubscription" + }, + "type": "array", + "title": "Blocklists", + "description": "Blocklists that are subscribed by the integration" + }, + "cves": { + "items": { + "$ref": "#/components/schemas/CVESubscription" + }, + "type": "array", + "title": "Cves", + "description": "CVEs that are subscribed by the integration" + }, + "fingerprints": { + "items": { + "$ref": "#/components/schemas/FingerprintSubscription" + }, + "type": "array", + "title": "Fingerprints", + "description": "Fingerprints that are subscribed by the integration" + }, + "vendors": { + "items": { + "$ref": "#/components/schemas/VendorSubscription" + }, + "type": "array", + "title": "Vendors", + "description": "Vendors that are subscribed by the integration" + }, + "endpoint": { + "type": "string", + "maxLength": 2083, + "minLength": 1, + "format": "uri", + "title": "Endpoint", + "description": "Url that should be used by the firewall or the remediation component to fetch the integration's content" + }, + "stats": { + "$ref": "#/components/schemas/Stats", + "description": "Stats of the integration", + "default": { + "count": 0 + } + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the integration", + "default": [] + }, + "pull_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pull Limit", + "description": "Maximum number of items to pull" + }, + "enable_ip_aggregation": { + "type": "boolean", + "title": "Enable Ip Aggregation", + "description": "Whether to enable IP aggregation into ranges", + "default": false + } + }, + "type": "object", + "required": [ + "id", + "name", + "organization_id", + "created_at", + "updated_at", + "entity_type", + "output_format", + "blocklists", + "cves", + "fingerprints", + "vendors", + "endpoint" + ], + "title": "IntegrationGetResponse" + }, + "IntegrationGetResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IntegrationGetResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "IntegrationGetResponsePage" + }, + "IntegrationType": { + "type": "string", + "enum": [ + "firewall_integration", + "remediation_component_integration" + ], + "title": "IntegrationType" + }, + "IntegrationUpdateRequest": { + "properties": { + "name": { + "type": "string", + "minLength": 1, + "title": "Name", + "description": "New name" + }, + "description": { + "type": "string", + "minLength": 1, + "title": "Description", + "description": "New description" + }, + "output_format": { + "$ref": "#/components/schemas/OutputFormat", + "description": "New output format" + }, + "regenerate_credentials": { + "type": "boolean", + "title": "Regenerate Credentials", + "description": "Regenerate credentials for the integration" + }, + "pull_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pull Limit", + "description": "Maximum number of items to pull" + }, + "enable_ip_aggregation": { + "type": "boolean", + "title": "Enable Ip Aggregation", + "description": "Whether to enable IP aggregation into ranges", + "default": false + } + }, + "additionalProperties": false, + "type": "object", + "title": "IntegrationUpdateRequest" + }, + "IntegrationUpdateResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the integration" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the integration. Should be unique within the organization" + }, + "organization_id": { + "type": "string", + "title": "Organization Id", + "description": "ID of the owner organization" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the integration" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the integration was created" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At", + "description": "Last time the integration was updated" + }, + "entity_type": { + "$ref": "#/components/schemas/IntegrationType", + "description": "Type of the integration" + }, + "output_format": { + "$ref": "#/components/schemas/OutputFormat", + "description": "Output format of the integration" + }, + "last_pull": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Pull", + "description": "Last time the integration pulled blocklists" + }, + "blocklists": { + "items": { + "$ref": "#/components/schemas/BlocklistSubscription" + }, + "type": "array", + "title": "Blocklists", + "description": "Blocklists that are subscribed by the integration" + }, + "cves": { + "items": { + "$ref": "#/components/schemas/CVESubscription" + }, + "type": "array", + "title": "Cves", + "description": "CVEs that are subscribed by the integration" + }, + "fingerprints": { + "items": { + "$ref": "#/components/schemas/FingerprintSubscription" + }, + "type": "array", + "title": "Fingerprints", + "description": "Fingerprints that are subscribed by the integration" + }, + "vendors": { + "items": { + "$ref": "#/components/schemas/VendorSubscription" + }, + "type": "array", + "title": "Vendors", + "description": "Vendors that are subscribed by the integration" + }, + "endpoint": { + "type": "string", + "maxLength": 2083, + "minLength": 1, + "format": "uri", + "title": "Endpoint", + "description": "Url that should be used by the firewall or the remediation component to fetch the integration's content" + }, + "stats": { + "$ref": "#/components/schemas/Stats", + "description": "Stats of the integration", + "default": { + "count": 0 + } + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the integration", + "default": [] + }, + "pull_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pull Limit", + "description": "Maximum number of items to pull" + }, + "enable_ip_aggregation": { + "type": "boolean", + "title": "Enable Ip Aggregation", + "description": "Whether to enable IP aggregation into ranges", + "default": false + }, + "credentials": { + "anyOf": [ + { + "$ref": "#/components/schemas/ApiKeyCredentials" + }, + { + "$ref": "#/components/schemas/BasicAuthCredentials" + }, + { + "type": "null" + } + ], + "title": "Credentials", + "description": "Credentials for the integration" + } + }, + "type": "object", + "required": [ + "id", + "name", + "organization_id", + "created_at", + "updated_at", + "entity_type", + "output_format", + "blocklists", + "cves", + "fingerprints", + "vendors", + "endpoint" + ], + "title": "IntegrationUpdateResponse" + }, + "Links": { + "properties": { + "first": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "First", + "examples": [ + "/api/v1/users?limit=1&offset1" + ] + }, + "last": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last", + "examples": [ + "/api/v1/users?limit=1&offset1" + ] + }, + "self": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Self", + "examples": [ + "/api/v1/users?limit=1&offset1" + ] + }, + "next": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Next", + "examples": [ + "/api/v1/users?limit=1&offset1" + ] + }, + "prev": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Prev", + "examples": [ + "/api/v1/users?limit=1&offset1" + ] + } + }, + "type": "object", + "title": "Links" + }, + "MetricUnits": { + "type": "string", + "enum": [ + "byte", + "packet", + "request", + "ip", + "line", + "event" + ], + "title": "MetricUnits" + }, + "OriginMetrics": { + "properties": { + "origin": { + "anyOf": [ + { + "$ref": "#/components/schemas/BlocklistOrigin" + }, + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Origin", + "description": "Origin of the metric" + }, + "data": { + "items": { + "$ref": "#/components/schemas/RemediationMetricsData" + }, + "type": "array", + "title": "Data", + "description": "Data points" + } + }, + "type": "object", + "required": [ + "origin", + "data" + ], + "title": "OriginMetrics" + }, + "OutputFormat": { + "type": "string", + "enum": [ + "plain_text", + "f5", + "remediation_component", + "fortigate", + "paloalto", + "checkpoint", + "cisco", + "juniper", + "mikrotik", + "pfsense", + "opnsense", + "sophos" + ], + "title": "OutputFormat" + }, + "Permission": { + "type": "string", + "enum": [ + "read", + "write" + ], + "title": "Permission" + }, + "PricingTiers": { + "type": "string", + "enum": [ + "free", + "premium", + "platinum" + ], + "title": "PricingTiers" + }, + "PublicBlocklistResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Blocklist id" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Blocklist creation date" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At", + "description": "Blocklist update date" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Blocklist name, unique within the organization" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Blocklist human readable name" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Blocklist description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "Blocklist references", + "default": [] + }, + "is_private": { + "type": "boolean", + "title": "Is Private", + "description": "Private blocklist if True or public if False" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Classification tags", + "default": [] + }, + "pricing_tier": { + "$ref": "#/components/schemas/PricingTiers", + "description": "Pricing tier for Crowdsec blocklists only" + }, + "source": { + "$ref": "#/components/schemas/BlocklistSources", + "description": "Blocklist source" + }, + "stats": { + "$ref": "#/components/schemas/BlocklistStats", + "description": "Blocklist stats" + }, + "from_cti_query": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "From Cti Query", + "description": "CTI query from which the blocklist was created" + }, + "since": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Since", + "description": "Since duration for the CTI query (eg. 5m, 2h, 7d). Max is 30 days" + }, + "shared_with": { + "items": { + "$ref": "#/components/schemas/Share" + }, + "type": "array", + "title": "Shared With", + "description": "List of organizations shared with", + "default": [] + }, + "organization_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Organization Id", + "description": "Blocklists owner's organization id" + }, + "subscribers": { + "items": { + "$ref": "#/components/schemas/BlocklistSubscribersCount" + }, + "type": "array", + "title": "Subscribers", + "description": "List of subscribers to the blocklist. Only subscribers belonging to your organization are returned", + "default": [] + }, + "categories": { + "items": { + "$ref": "#/components/schemas/BlocklistCategory" + }, + "type": "array", + "title": "Categories", + "description": "List of categories for the blocklist", + "default": [] + } + }, + "type": "object", + "required": [ + "id", + "created_at", + "updated_at", + "name", + "description", + "is_private", + "pricing_tier", + "source", + "stats" + ], + "title": "PublicBlocklistResponse" + }, + "PublicBlocklistResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/PublicBlocklistResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "PublicBlocklistResponsePage" + }, + "RawMetrics": { + "properties": { + "dropped": { + "items": { + "$ref": "#/components/schemas/RemediationMetrics" + }, + "type": "array", + "title": "Dropped", + "description": "dropped metrics", + "default": [] + }, + "processed": { + "items": { + "$ref": "#/components/schemas/RemediationMetrics" + }, + "type": "array", + "title": "Processed", + "description": "processed metrics", + "default": [] + } + }, + "type": "object", + "title": "RawMetrics" + }, + "RemediationMetrics": { + "properties": { + "total": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "title": "Total", + "description": "Total value of the metric" + }, + "unit": { + "$ref": "#/components/schemas/MetricUnits", + "description": "Unit of the metric" + }, + "progression": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Progression", + "description": "Progression of the metric value from the previous period" + }, + "data": { + "items": { + "$ref": "#/components/schemas/OriginMetrics" + }, + "type": "array", + "title": "Data", + "description": "Data points per origin" + } + }, + "type": "object", + "required": [ + "total", + "unit", + "progression", + "data" + ], + "title": "RemediationMetrics" + }, + "RemediationMetricsData": { + "properties": { + "value": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "title": "Value", + "description": "Value of the metric" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp", + "description": "Timestamp of the metric" + } + }, + "type": "object", + "required": [ + "value", + "timestamp" + ], + "title": "RemediationMetricsData" + }, + "Share": { + "properties": { + "organization_id": { + "type": "string", + "title": "Organization Id" + }, + "permission": { + "$ref": "#/components/schemas/Permission" + } + }, + "type": "object", + "required": [ + "organization_id", + "permission" + ], + "title": "Share" + }, + "SourceInfo": { + "properties": { + "source_type": { + "$ref": "#/components/schemas/SourceType", + "description": "The source type that created the allowlist entry" + }, + "identifier": { + "type": "string", + "title": "Identifier", + "description": "The source identifier that created the allowlist entry" + } + }, + "type": "object", + "required": [ + "source_type", + "identifier" + ], + "title": "SourceInfo" + }, + "SourceType": { + "type": "string", + "enum": [ + "user", + "apikey" + ], + "title": "SourceType" + }, + "Stats": { + "properties": { + "count": { + "type": "integer", + "title": "Count", + "description": "Number of total blocklists items the integration will pull" + } + }, + "type": "object", + "required": [ + "count" + ], + "title": "Stats" + }, + "SubscriberEntityType": { + "type": "string", + "enum": [ + "org", + "tag", + "engine", + "firewall_integration", + "remediation_component_integration" + ], + "title": "SubscriberEntityType" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "title": "Location", + "type": "array" + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + }, + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError", + "type": "object" + }, + "VendorSubscription": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Vendor ID" + } + }, + "type": "object", + "required": [ + "id" + ], + "title": "VendorSubscription" + }, + "AppsecConfigIndex": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The YAML content of the item, in plaintext.", + "examples": [ + "type: leaky\n#debug: true\nname: crowdsecurity/vsftpd-bf\ndescription: \"Detect FTP bruteforce (vsftpd)\"\nfilter: evt.Meta.log_type == 'ftp_failed_auth'\nleakspeed: \"10s\"\ncapacity: 5\ngroupby: evt.Meta.source_ip\nblackhole: 5m\nlabels:\n confidence: 3\n spoofable: 0\n classification:\n - attack.T1110\n behavior: \"ftp:bruteforce\"\n label: \"VSFTPD Bruteforce\"\n remediation: true\n service: vsftpd" + ], + "title": "Content" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short, plaintext description of the item", + "title": "Description" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Classification labels for the item", + "examples": [ + { + "behavior": "ftp:bruteforce", + "classification": [ + "attack.T1110" + ], + "confidence": 3, + "label": "VSFTPD Bruteforce", + "remediation": true, + "service": "vsftpd", + "spoofable": 0 + } + ], + "title": "Labels" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relative path to the item's YAML content", + "examples": [ + "scenarios/crowdsecurity/vsftpd-bf.yaml" + ], + "title": "Path" + }, + "references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of references to external resources", + "title": "References" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current version of the collection", + "examples": [ + "0.2" + ], + "title": "Version" + }, + "versions": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/VersionDetail" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A dictionary where each key is a version number (e.g., '0.1', '0.2')", + "examples": [ + { + "0.1": { + "deprecated": false, + "digest": "3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1" + }, + "0.2": { + "deprecated": false, + "digest": "d1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91" + } + } + ], + "title": "Versions" + } + }, + "title": "AppsecConfigIndex", + "type": "object" + }, + "AppsecRuleIndex": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The YAML content of the item, in plaintext.", + "examples": [ + "type: leaky\n#debug: true\nname: crowdsecurity/vsftpd-bf\ndescription: \"Detect FTP bruteforce (vsftpd)\"\nfilter: evt.Meta.log_type == 'ftp_failed_auth'\nleakspeed: \"10s\"\ncapacity: 5\ngroupby: evt.Meta.source_ip\nblackhole: 5m\nlabels:\n confidence: 3\n spoofable: 0\n classification:\n - attack.T1110\n behavior: \"ftp:bruteforce\"\n label: \"VSFTPD Bruteforce\"\n remediation: true\n service: vsftpd" + ], + "title": "Content" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short, plaintext description of the item", + "title": "Description" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Classification labels for the item", + "examples": [ + { + "behavior": "ftp:bruteforce", + "classification": [ + "attack.T1110" + ], + "confidence": 3, + "label": "VSFTPD Bruteforce", + "remediation": true, + "service": "vsftpd", + "spoofable": 0 + } + ], + "title": "Labels" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relative path to the item's YAML content", + "examples": [ + "scenarios/crowdsecurity/vsftpd-bf.yaml" + ], + "title": "Path" + }, + "references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of references to external resources", + "title": "References" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current version of the collection", + "examples": [ + "0.2" + ], + "title": "Version" + }, + "versions": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/VersionDetail" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A dictionary where each key is a version number (e.g., '0.1', '0.2')", + "examples": [ + { + "0.1": { + "deprecated": false, + "digest": "3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1" + }, + "0.2": { + "deprecated": false, + "digest": "d1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91" + } + } + ], + "title": "Versions" + } + }, + "title": "AppsecRuleIndex", + "type": "object" + }, + "CollectionIndex": { + "properties": { + "appsec-configs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of appsec-configs", + "title": "Appsec-Configs" + }, + "appsec-rules": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of appsec-rules", + "title": "Appsec-Rules" + }, + "collections": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of collections", + "title": "Collections" + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The YAML content of the item, in plaintext.", + "examples": [ + "type: leaky\n#debug: true\nname: crowdsecurity/vsftpd-bf\ndescription: \"Detect FTP bruteforce (vsftpd)\"\nfilter: evt.Meta.log_type == 'ftp_failed_auth'\nleakspeed: \"10s\"\ncapacity: 5\ngroupby: evt.Meta.source_ip\nblackhole: 5m\nlabels:\n confidence: 3\n spoofable: 0\n classification:\n - attack.T1110\n behavior: \"ftp:bruteforce\"\n label: \"VSFTPD Bruteforce\"\n remediation: true\n service: vsftpd" + ], + "title": "Content" + }, + "contexts": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of contexts", + "title": "Contexts" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short, plaintext description of the item", + "title": "Description" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Classification labels for the item", + "examples": [ + { + "behavior": "ftp:bruteforce", + "classification": [ + "attack.T1110" + ], + "confidence": 3, + "label": "VSFTPD Bruteforce", + "remediation": true, + "service": "vsftpd", + "spoofable": 0 + } + ], + "title": "Labels" + }, + "parsers": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of parsers", + "title": "Parsers" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relative path to the item's YAML content", + "examples": [ + "scenarios/crowdsecurity/vsftpd-bf.yaml" + ], + "title": "Path" + }, + "postoverflows": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of postoverflows", + "title": "Postoverflows" + }, + "references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of references to external resources", + "title": "References" + }, + "scenarios": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of scenarios", + "title": "Scenarios" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current version of the collection", + "examples": [ + "0.2" + ], + "title": "Version" + }, + "versions": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/VersionDetail" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A dictionary where each key is a version number (e.g., '0.1', '0.2')", + "examples": [ + { + "0.1": { + "deprecated": false, + "digest": "3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1" + }, + "0.2": { + "deprecated": false, + "digest": "d1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91" + } + } + ], + "title": "Versions" + } + }, + "title": "CollectionIndex", + "type": "object" + }, + "ContextIndex": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The YAML content of the item, in plaintext.", + "examples": [ + "type: leaky\n#debug: true\nname: crowdsecurity/vsftpd-bf\ndescription: \"Detect FTP bruteforce (vsftpd)\"\nfilter: evt.Meta.log_type == 'ftp_failed_auth'\nleakspeed: \"10s\"\ncapacity: 5\ngroupby: evt.Meta.source_ip\nblackhole: 5m\nlabels:\n confidence: 3\n spoofable: 0\n classification:\n - attack.T1110\n behavior: \"ftp:bruteforce\"\n label: \"VSFTPD Bruteforce\"\n remediation: true\n service: vsftpd" + ], + "title": "Content" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short, plaintext description of the item", + "title": "Description" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Classification labels for the item", + "examples": [ + { + "behavior": "ftp:bruteforce", + "classification": [ + "attack.T1110" + ], + "confidence": 3, + "label": "VSFTPD Bruteforce", + "remediation": true, + "service": "vsftpd", + "spoofable": 0 + } + ], + "title": "Labels" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relative path to the item's YAML content", + "examples": [ + "scenarios/crowdsecurity/vsftpd-bf.yaml" + ], + "title": "Path" + }, + "references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of references to external resources", + "title": "References" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current version of the collection", + "examples": [ + "0.2" + ], + "title": "Version" + }, + "versions": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/VersionDetail" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A dictionary where each key is a version number (e.g., '0.1', '0.2')", + "examples": [ + { + "0.1": { + "deprecated": false, + "digest": "3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1" + }, + "0.2": { + "deprecated": false, + "digest": "d1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91" + } + } + ], + "title": "Versions" + } + }, + "title": "ContextIndex", + "type": "object" + }, + "Index": { + "description": "Index document served to crowdsec/cscli.", + "properties": { + "appsec-configs": { + "additionalProperties": { + "$ref": "#/components/schemas/AppsecConfigIndex" + }, + "title": "Appsec-Configs", + "type": "object" + }, + "appsec-rules": { + "additionalProperties": { + "$ref": "#/components/schemas/AppsecRuleIndex" + }, + "title": "Appsec-Rules", + "type": "object" + }, + "collections": { + "additionalProperties": { + "$ref": "#/components/schemas/CollectionIndex" + }, + "title": "Collections", + "type": "object" + }, + "contexts": { + "additionalProperties": { + "$ref": "#/components/schemas/ContextIndex" + }, + "title": "Contexts", + "type": "object" + }, + "parsers": { + "additionalProperties": { + "$ref": "#/components/schemas/ParserIndex" + }, + "title": "Parsers", + "type": "object" + }, + "postoverflows": { + "additionalProperties": { + "$ref": "#/components/schemas/PostoverflowIndex" + }, + "title": "Postoverflows", + "type": "object" + }, + "scenarios": { + "additionalProperties": { + "$ref": "#/components/schemas/ScenarioIndex" + }, + "title": "Scenarios", + "type": "object" + } + }, + "title": "Index", + "type": "object" + }, + "ParserIndex": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The YAML content of the item, in plaintext.", + "examples": [ + "type: leaky\n#debug: true\nname: crowdsecurity/vsftpd-bf\ndescription: \"Detect FTP bruteforce (vsftpd)\"\nfilter: evt.Meta.log_type == 'ftp_failed_auth'\nleakspeed: \"10s\"\ncapacity: 5\ngroupby: evt.Meta.source_ip\nblackhole: 5m\nlabels:\n confidence: 3\n spoofable: 0\n classification:\n - attack.T1110\n behavior: \"ftp:bruteforce\"\n label: \"VSFTPD Bruteforce\"\n remediation: true\n service: vsftpd" + ], + "title": "Content" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short, plaintext description of the item", + "title": "Description" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Classification labels for the item", + "examples": [ + { + "behavior": "ftp:bruteforce", + "classification": [ + "attack.T1110" + ], + "confidence": 3, + "label": "VSFTPD Bruteforce", + "remediation": true, + "service": "vsftpd", + "spoofable": 0 + } + ], + "title": "Labels" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relative path to the item's YAML content", + "examples": [ + "scenarios/crowdsecurity/vsftpd-bf.yaml" + ], + "title": "Path" + }, + "references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of references to external resources", + "title": "References" + }, + "stage": { + "description": "The stage of the parser", + "title": "Stage", + "type": "string" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current version of the collection", + "examples": [ + "0.2" + ], + "title": "Version" + }, + "versions": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/VersionDetail" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A dictionary where each key is a version number (e.g., '0.1', '0.2')", + "examples": [ + { + "0.1": { + "deprecated": false, + "digest": "3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1" + }, + "0.2": { + "deprecated": false, + "digest": "d1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91" + } + } + ], + "title": "Versions" + } + }, + "required": [ + "stage" + ], + "title": "ParserIndex", + "type": "object" + }, + "PostoverflowIndex": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The YAML content of the item, in plaintext.", + "examples": [ + "type: leaky\n#debug: true\nname: crowdsecurity/vsftpd-bf\ndescription: \"Detect FTP bruteforce (vsftpd)\"\nfilter: evt.Meta.log_type == 'ftp_failed_auth'\nleakspeed: \"10s\"\ncapacity: 5\ngroupby: evt.Meta.source_ip\nblackhole: 5m\nlabels:\n confidence: 3\n spoofable: 0\n classification:\n - attack.T1110\n behavior: \"ftp:bruteforce\"\n label: \"VSFTPD Bruteforce\"\n remediation: true\n service: vsftpd" + ], + "title": "Content" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short, plaintext description of the item", + "title": "Description" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Classification labels for the item", + "examples": [ + { + "behavior": "ftp:bruteforce", + "classification": [ + "attack.T1110" + ], + "confidence": 3, + "label": "VSFTPD Bruteforce", + "remediation": true, + "service": "vsftpd", + "spoofable": 0 + } + ], + "title": "Labels" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relative path to the item's YAML content", + "examples": [ + "scenarios/crowdsecurity/vsftpd-bf.yaml" + ], + "title": "Path" + }, + "references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of references to external resources", + "title": "References" + }, + "stage": { + "description": "The stage of the postoverflow", + "title": "Stage", + "type": "string" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current version of the collection", + "examples": [ + "0.2" + ], + "title": "Version" + }, + "versions": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/VersionDetail" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A dictionary where each key is a version number (e.g., '0.1', '0.2')", + "examples": [ + { + "0.1": { + "deprecated": false, + "digest": "3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1" + }, + "0.2": { + "deprecated": false, + "digest": "d1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91" + } + } + ], + "title": "Versions" + } + }, + "required": [ + "stage" + ], + "title": "PostoverflowIndex", + "type": "object" + }, + "ScenarioIndex": { + "properties": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The YAML content of the item, in plaintext.", + "examples": [ + "type: leaky\n#debug: true\nname: crowdsecurity/vsftpd-bf\ndescription: \"Detect FTP bruteforce (vsftpd)\"\nfilter: evt.Meta.log_type == 'ftp_failed_auth'\nleakspeed: \"10s\"\ncapacity: 5\ngroupby: evt.Meta.source_ip\nblackhole: 5m\nlabels:\n confidence: 3\n spoofable: 0\n classification:\n - attack.T1110\n behavior: \"ftp:bruteforce\"\n label: \"VSFTPD Bruteforce\"\n remediation: true\n service: vsftpd" + ], + "title": "Content" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "A short, plaintext description of the item", + "title": "Description" + }, + "labels": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "integer" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Classification labels for the item", + "examples": [ + { + "behavior": "ftp:bruteforce", + "classification": [ + "attack.T1110" + ], + "confidence": 3, + "label": "VSFTPD Bruteforce", + "remediation": true, + "service": "vsftpd", + "spoofable": 0 + } + ], + "title": "Labels" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Relative path to the item's YAML content", + "examples": [ + "scenarios/crowdsecurity/vsftpd-bf.yaml" + ], + "title": "Path" + }, + "references": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "List of references to external resources", + "title": "References" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Current version of the collection", + "examples": [ + "0.2" + ], + "title": "Version" + }, + "versions": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/components/schemas/VersionDetail" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A dictionary where each key is a version number (e.g., '0.1', '0.2')", + "examples": [ + { + "0.1": { + "deprecated": false, + "digest": "3591247988014705cf3a7e42388f0c87f9b86d3141268d996c5820ceab6364e1" + }, + "0.2": { + "deprecated": false, + "digest": "d1ddf4797250c1899a93ce634e6366e5deaaaf7508135056d17e9b09998ddf91" + } + } + ], + "title": "Versions" + } + }, + "title": "ScenarioIndex", + "type": "object" + }, + "VersionDetail": { + "properties": { + "deprecated": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": false, + "description": "Indicates whether this version is deprecated.", + "title": "Deprecated" + }, + "digest": { + "description": "The SHA256 digest of the versioned file.", + "examples": [ + "Detect FTP bruteforce (vsftpd)" + ], + "title": "Digest", + "type": "string" + } + }, + "required": [ + "digest" + ], + "title": "VersionDetail", + "type": "object" + }, + "AdjustmentScore": { + "properties": { + "total": { + "type": "integer", + "title": "Total", + "description": "Total score adjustment", + "default": 0 + }, + "recency": { + "type": "integer", + "title": "Recency", + "description": "Recency score adjustment", + "default": 0 + }, + "low_info": { + "type": "integer", + "title": "Low Info", + "description": "Low information score adjustment", + "default": 0 + } + }, + "type": "object", + "title": "AdjustmentScore" + }, + "AffectedComponent": { + "properties": { + "vendor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Vendor", + "description": "Vendor of the affected component" + }, + "product": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Product", + "description": "Product name of the affected component" + } + }, + "type": "object", + "title": "AffectedComponent", + "description": "Affected Component in a CVE" + }, + "AllowlistSubscription": { + "properties": { + "id": { + "type": "string", + "title": "Id" + } + }, + "type": "object", + "required": [ + "id" + ], + "title": "AllowlistSubscription" + }, + "AttackDetail": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Attack detail name" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Attack detail label" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Attack detail description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "Attack detail references" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description" + ], + "title": "AttackDetail" + }, + "Behavior": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Behavior name" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Behavior label" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Behavior description" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description" + ], + "title": "Behavior" + }, + "CVEEventOutput": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "date": { + "type": "string", + "title": "Date" + }, + "description": { + "type": "string", + "title": "Description" + }, + "label": { + "type": "string", + "title": "Label" + }, + "sorting_priority": { + "type": "integer", + "title": "Sorting Priority" + } + }, + "type": "object", + "required": [ + "name", + "date", + "description", + "label", + "sorting_priority" + ], + "title": "CVEEventOutput" + }, + "CVEExploitationPhase": { + "type": "string", + "enum": [ + "insufficient_data", + "early_exploitation", + "fresh_and_popular", + "targeted_exploitation", + "mass_exploitation", + "background_noise", + "unpopular", + "wearing_out", + "unclassified" + ], + "title": "CVEExploitationPhase" + }, + "CVEResponseBase": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the CVE" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the CVE" + }, + "title": { + "type": "string", + "title": "Title", + "description": "Title of the CVE" + }, + "affected_components": { + "items": { + "$ref": "#/components/schemas/AffectedComponent" + }, + "type": "array", + "title": "Affected Components", + "description": "List of affected components" + }, + "crowdsec_score": { + "type": "integer", + "maximum": 10.0, + "minimum": 0.0, + "title": "Crowdsec Score", + "description": "Live Exploit Tracker score of the CVE" + }, + "opportunity_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Opportunity Score", + "description": "Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5)", + "default": 0 + }, + "momentum_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Momentum Score", + "description": "Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5)", + "default": 0 + }, + "first_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "First Seen", + "description": "First seen date" + }, + "last_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Seen", + "description": "Last seen date" + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Number of unique IPs affected" + }, + "published_date": { + "type": "string", + "format": "date-time", + "title": "Published Date", + "description": "Published date of the CVE" + }, + "cvss_score": { + "anyOf": [ + { + "type": "number", + "maximum": 10.0, + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Cvss Score", + "description": "CVSS score of the CVE" + }, + "has_public_exploit": { + "type": "boolean", + "title": "Has Public Exploit", + "description": "Indicates if there is a public exploit for the CVE" + }, + "rule_release_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Rule Release Date", + "description": "Release date of the associated detection rule" + }, + "exploitation_phase": { + "$ref": "#/components/schemas/ExploitationPhase", + "description": "Current exploitation phase of the CVE" + }, + "adjustment_score": { + "anyOf": [ + { + "$ref": "#/components/schemas/AdjustmentScore" + }, + { + "type": "null" + } + ], + "description": "Score adjustments applied to the CVE score based on various factors" + }, + "threat_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThreatContext" + }, + { + "type": "null" + } + ], + "description": "Threat context (attacker/defender countries, industries, objectives)" + } + }, + "type": "object", + "required": [ + "id", + "name", + "title", + "affected_components", + "crowdsec_score", + "nb_ips", + "published_date", + "has_public_exploit", + "exploitation_phase" + ], + "title": "CVEResponseBase", + "description": "GET CVE ID Response" + }, + "CVEsubscription": { + "properties": { + "id": { + "type": "string", + "title": "Id" + } + }, + "type": "object", + "required": [ + "id" + ], + "title": "CVEsubscription" + }, + "CWE": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the CWE" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Label of the CWE" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the CWE" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description" + ], + "title": "CWE", + "description": "CWE Information" + }, + "Classification": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Classification name" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Classification label" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Classification description" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description" + ], + "title": "Classification" + }, + "Classifications": { + "properties": { + "false_positives": { + "items": { + "$ref": "#/components/schemas/Classification" + }, + "type": "array", + "title": "False Positives", + "description": "False positive classifications" + }, + "classifications": { + "items": { + "$ref": "#/components/schemas/Classification" + }, + "type": "array", + "title": "Classifications", + "description": "Main classifications" + } + }, + "type": "object", + "title": "Classifications" + }, + "ExploitationPhase": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the exploitation phase" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Label of the exploitation phase" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the exploitation phase" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description" + ], + "title": "ExploitationPhase" + }, + "ExploitationPhaseChangeEventItem": { + "properties": { + "cve_id": { + "type": "string", + "title": "Cve Id", + "description": "CVE identifier" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Event type name" + }, + "date": { + "type": "string", + "title": "Date", + "description": "Date of the phase change" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Human-readable event label" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Rendered event description" + }, + "previous_phase": { + "type": "string", + "title": "Previous Phase", + "description": "Previous exploitation phase label" + }, + "new_phase": { + "type": "string", + "title": "New Phase", + "description": "New exploitation phase label" + } + }, + "type": "object", + "required": [ + "cve_id", + "name", + "date", + "label", + "description", + "previous_phase", + "new_phase" + ], + "title": "ExploitationPhaseChangeEventItem" + }, + "ExploitationPhaseChangeEventsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/ExploitationPhaseChangeEventItem" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "ExploitationPhaseChangeEventsResponsePage" + }, + "FacetBucket": { + "properties": { + "value": { + "type": "string", + "title": "Value", + "description": "Facet value" + }, + "count": { + "type": "integer", + "minimum": 0.0, + "title": "Count", + "description": "Number of IPs matching this value" + } + }, + "type": "object", + "required": [ + "value", + "count" + ], + "title": "FacetBucket" + }, + "FingerprintEventOutput": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "date": { + "type": "string", + "title": "Date" + }, + "description": { + "type": "string", + "title": "Description" + }, + "label": { + "type": "string", + "title": "Label" + } + }, + "type": "object", + "required": [ + "name", + "date", + "description", + "label" + ], + "title": "FingerprintEventOutput" + }, + "FingerprintRuleResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Fingerprint rule identifier" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Fingerprint rule name" + }, + "title": { + "type": "string", + "title": "Title", + "description": "Fingerprint rule title" + }, + "affected_components": { + "items": { + "$ref": "#/components/schemas/AffectedComponent" + }, + "type": "array", + "title": "Affected Components", + "description": "List of affected components" + }, + "crowdsec_score": { + "type": "integer", + "maximum": 10.0, + "minimum": 0.0, + "title": "Crowdsec Score", + "description": "Live Exploit Tracker score for the fingerprint rule" + }, + "opportunity_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Opportunity Score", + "description": "Opportunity score", + "default": 0 + }, + "momentum_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Momentum Score", + "description": "Momentum score", + "default": 0 + }, + "first_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "First Seen", + "description": "First seen date" + }, + "last_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Seen", + "description": "Last seen date" + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Number of unique IPs observed" + }, + "rule_release_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Rule Release Date", + "description": "Release date of the fingerprint rule" + }, + "exploitation_phase": { + "$ref": "#/components/schemas/ExploitationPhase", + "description": "Current exploitation phase" + }, + "adjustment_score": { + "anyOf": [ + { + "$ref": "#/components/schemas/AdjustmentScore" + }, + { + "type": "null" + } + ], + "description": "Score adjustment details" + }, + "threat_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThreatContext" + }, + { + "type": "null" + } + ], + "description": "Threat context (attacker/defender countries, industries, objectives)" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the fingerprint rule" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Fingerprint rule description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "Reference links for the fingerprint rule" + }, + "crowdsec_analysis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Crowdsec Analysis", + "description": "CrowdSec analysis for this fingerprint rule" + }, + "events": { + "items": { + "$ref": "#/components/schemas/FingerprintEventOutput" + }, + "type": "array", + "title": "Events", + "description": "List of events related to the fingerprint rule" + } + }, + "type": "object", + "required": [ + "id", + "name", + "title", + "affected_components", + "crowdsec_score", + "nb_ips", + "exploitation_phase" + ], + "title": "FingerprintRuleResponse" + }, + "FingerprintRuleSummary": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Fingerprint rule identifier" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Fingerprint rule name" + }, + "title": { + "type": "string", + "title": "Title", + "description": "Fingerprint rule title" + }, + "affected_components": { + "items": { + "$ref": "#/components/schemas/AffectedComponent" + }, + "type": "array", + "title": "Affected Components", + "description": "List of affected components" + }, + "crowdsec_score": { + "type": "integer", + "maximum": 10.0, + "minimum": 0.0, + "title": "Crowdsec Score", + "description": "Live Exploit Tracker score for the fingerprint rule" + }, + "opportunity_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Opportunity Score", + "description": "Opportunity score", + "default": 0 + }, + "momentum_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Momentum Score", + "description": "Momentum score", + "default": 0 + }, + "first_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "First Seen", + "description": "First seen date" + }, + "last_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Seen", + "description": "Last seen date" + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Number of unique IPs observed" + }, + "rule_release_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Rule Release Date", + "description": "Release date of the fingerprint rule" + }, + "exploitation_phase": { + "$ref": "#/components/schemas/ExploitationPhase", + "description": "Current exploitation phase" + }, + "adjustment_score": { + "anyOf": [ + { + "$ref": "#/components/schemas/AdjustmentScore" + }, + { + "type": "null" + } + ], + "description": "Score adjustment details" + }, + "threat_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThreatContext" + }, + { + "type": "null" + } + ], + "description": "Threat context (attacker/defender countries, industries, objectives)" + } + }, + "type": "object", + "required": [ + "id", + "name", + "title", + "affected_components", + "crowdsec_score", + "nb_ips", + "exploitation_phase" + ], + "title": "FingerprintRuleSummary" + }, + "FingerprintTimelineItem": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp", + "description": "Timestamp of the timeline event" + }, + "count": { + "type": "integer", + "title": "Count", + "description": "Count of occurrences at the timestamp" + } + }, + "type": "object", + "required": [ + "timestamp", + "count" + ], + "title": "FingerprintTimelineItem" + }, + "GetCVEIPsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IPItem" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetCVEIPsResponsePage" + }, + "GetCVEProtectRulesResponse": { + "properties": { + "protect_rules": { + "items": { + "$ref": "#/components/schemas/ProtectRule" + }, + "type": "array", + "title": "Protect Rules", + "description": "Protection/detection rules associated with the CVE" + } + }, + "type": "object", + "title": "GetCVEProtectRulesResponse", + "description": "Response for the protect rules endpoint." + }, + "GetCVEResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the CVE" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the CVE" + }, + "title": { + "type": "string", + "title": "Title", + "description": "Title of the CVE" + }, + "affected_components": { + "items": { + "$ref": "#/components/schemas/AffectedComponent" + }, + "type": "array", + "title": "Affected Components", + "description": "List of affected components" + }, + "crowdsec_score": { + "type": "integer", + "maximum": 10.0, + "minimum": 0.0, + "title": "Crowdsec Score", + "description": "Live Exploit Tracker score of the CVE" + }, + "opportunity_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Opportunity Score", + "description": "Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5)", + "default": 0 + }, + "momentum_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Momentum Score", + "description": "Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5)", + "default": 0 + }, + "first_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "First Seen", + "description": "First seen date" + }, + "last_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Seen", + "description": "Last seen date" + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Number of unique IPs affected" + }, + "published_date": { + "type": "string", + "format": "date-time", + "title": "Published Date", + "description": "Published date of the CVE" + }, + "cvss_score": { + "anyOf": [ + { + "type": "number", + "maximum": 10.0, + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Cvss Score", + "description": "CVSS score of the CVE" + }, + "has_public_exploit": { + "type": "boolean", + "title": "Has Public Exploit", + "description": "Indicates if there is a public exploit for the CVE" + }, + "rule_release_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Rule Release Date", + "description": "Release date of the associated detection rule" + }, + "exploitation_phase": { + "$ref": "#/components/schemas/ExploitationPhase", + "description": "Current exploitation phase of the CVE" + }, + "adjustment_score": { + "anyOf": [ + { + "$ref": "#/components/schemas/AdjustmentScore" + }, + { + "type": "null" + } + ], + "description": "Score adjustments applied to the CVE score based on various factors" + }, + "threat_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThreatContext" + }, + { + "type": "null" + } + ], + "description": "Threat context (attacker/defender countries, industries, objectives)" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the CVE" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "List of references for the CVE" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the CVE" + }, + "crowdsec_analysis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Crowdsec Analysis", + "description": "CrowdSec analysis of the CVE" + }, + "cwes": { + "items": { + "$ref": "#/components/schemas/CWE" + }, + "type": "array", + "title": "Cwes", + "description": "List of CWEs associated with the CVE" + }, + "events": { + "items": { + "$ref": "#/components/schemas/CVEEventOutput" + }, + "type": "array", + "title": "Events", + "description": "List of events related to the CVE" + } + }, + "type": "object", + "required": [ + "id", + "name", + "title", + "affected_components", + "crowdsec_score", + "nb_ips", + "published_date", + "has_public_exploit", + "exploitation_phase", + "references", + "description", + "crowdsec_analysis", + "cwes" + ], + "title": "GetCVEResponse" + }, + "GetCVESubscribedIntegrationsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IntegrationResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetCVESubscribedIntegrationsResponsePage" + }, + "GetCVEsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/CVEResponseBase" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetCVEsResponsePage" + }, + "GetCVEsSortBy": { + "type": "string", + "enum": [ + "rule_release_date", + "trending", + "nb_ips", + "name", + "first_seen" + ], + "title": "GetCVEsSortBy" + }, + "GetCVEsSortOrder": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "title": "GetCVEsSortOrder" + }, + "GetFingerprintIPsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IPItem" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetFingerprintIPsResponsePage" + }, + "GetFingerprintRulesResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/FingerprintRuleSummary" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetFingerprintRulesResponsePage" + }, + "GetFingerprintSubscribedIntegrationsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IntegrationResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetFingerprintSubscribedIntegrationsResponsePage" + }, + "GetVendorIPsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IPItem" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetVendorIPsResponsePage" + }, + "GetVendorSubscribedIntegrationsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/IntegrationResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "GetVendorSubscribedIntegrationsResponsePage" + }, + "History": { + "properties": { + "first_seen": { + "type": "string", + "format": "date-time", + "title": "First Seen", + "description": "First seen timestamp" + }, + "last_seen": { + "type": "string", + "format": "date-time", + "title": "Last Seen", + "description": "Last seen timestamp" + }, + "full_age": { + "type": "integer", + "title": "Full Age", + "description": "Full age in days" + }, + "days_age": { + "type": "integer", + "title": "Days Age", + "description": "Days age" + } + }, + "type": "object", + "required": [ + "first_seen", + "last_seen", + "full_age", + "days_age" + ], + "title": "History" + }, + "IPItem": { + "properties": { + "ip": { + "type": "string", + "title": "Ip", + "description": "IP address" + }, + "reputation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reputation", + "description": "Reputation of the IP" + }, + "ip_range": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ip Range", + "description": "IP range" + }, + "ip_range_score": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ip Range Score", + "description": "IP range score" + }, + "ip_range_24": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ip Range 24", + "description": "IP range /24" + }, + "ip_range_24_reputation": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ip Range 24 Reputation", + "description": "IP range /24 reputation" + }, + "ip_range_24_score": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ip Range 24 Score", + "description": "IP range /24 score" + }, + "as_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "As Name", + "description": "AS name" + }, + "as_num": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "As Num", + "description": "AS number" + }, + "background_noise_score": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Background Noise Score", + "description": "Background noise score" + }, + "background_noise": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Background Noise", + "description": "Background noise level" + }, + "confidence": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Confidence", + "description": "Confidence level" + }, + "location": { + "anyOf": [ + { + "$ref": "#/components/schemas/Location" + }, + { + "type": "null" + } + ], + "description": "IP location information" + }, + "reverse_dns": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reverse Dns", + "description": "Reverse DNS" + }, + "behaviors": { + "items": { + "$ref": "#/components/schemas/Behavior" + }, + "type": "array", + "title": "Behaviors", + "description": "List of behaviors" + }, + "references": { + "items": { + "$ref": "#/components/schemas/Reference" + }, + "type": "array", + "title": "References", + "description": "List of references" + }, + "history": { + "anyOf": [ + { + "$ref": "#/components/schemas/History" + }, + { + "type": "null" + } + ], + "description": "Historical data" + }, + "classifications": { + "anyOf": [ + { + "$ref": "#/components/schemas/Classifications" + }, + { + "type": "null" + } + ], + "description": "Classification data" + }, + "mitre_techniques": { + "items": { + "$ref": "#/components/schemas/MitreTechnique" + }, + "type": "array", + "title": "Mitre Techniques", + "description": "MITRE techniques" + }, + "cves": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Cves", + "description": "List of CVEs" + }, + "attack_details": { + "items": { + "$ref": "#/components/schemas/AttackDetail" + }, + "type": "array", + "title": "Attack Details", + "description": "Attack details" + }, + "target_countries": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Target Countries", + "description": "Target countries" + }, + "scores": { + "anyOf": [ + { + "$ref": "#/components/schemas/Scores" + }, + { + "type": "null" + } + ], + "description": "Scoring information" + } + }, + "type": "object", + "required": [ + "ip" + ], + "title": "IPItem" + }, + "IntegrationResponse": { + "properties": { + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "default": [] + }, + "organization_id": { + "type": "string", + "title": "Organization Id" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At", + "description": "Time the integration was created" + }, + "entity_type": { + "$ref": "#/components/schemas/EntityType", + "description": "Type of the integration" + }, + "id": { + "type": "string", + "title": "Id", + "description": "ID of the integration" + }, + "blocklists": { + "items": { + "$ref": "#/components/schemas/BlocklistSubscription" + }, + "type": "array", + "title": "Blocklists", + "default": [] + }, + "allowlists": { + "items": { + "$ref": "#/components/schemas/AllowlistSubscription" + }, + "type": "array", + "title": "Allowlists", + "default": [] + }, + "cves": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/CVEsubscription" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Cves" + }, + "fingerprints": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/FingerprintSubscription" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Fingerprints" + }, + "vendors": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/VendorSubscription" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Vendors" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the integration" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At", + "description": "Last time the integration was updated" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Description of the integration" + }, + "output_format": { + "$ref": "#/components/schemas/OutputFormat", + "description": "Output format of the integration" + }, + "last_pull": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Pull", + "description": "Last time the integration pulled blocklists" + }, + "pull_limit": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Pull Limit", + "description": "Maximum number of items to pull" + }, + "enable_ip_aggregation": { + "type": "boolean", + "title": "Enable Ip Aggregation", + "description": "Whether to enable IP aggregation into ranges", + "default": false + } + }, + "type": "object", + "required": [ + "organization_id", + "entity_type", + "name", + "output_format" + ], + "title": "IntegrationResponse" + }, + "IntervalOptions": { + "type": "string", + "enum": [ + "hour", + "day", + "week" + ], + "title": "IntervalOptions" + }, + "IpsDetailsStats": { + "properties": { + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total", + "description": "Total number of matching IPs" + }, + "reputation": { + "items": { + "$ref": "#/components/schemas/FacetBucket" + }, + "type": "array", + "title": "Reputation", + "description": "IP count by reputation" + }, + "country": { + "items": { + "$ref": "#/components/schemas/FacetBucket" + }, + "type": "array", + "title": "Country", + "description": "IP count by country (top 5)" + }, + "as_name": { + "items": { + "$ref": "#/components/schemas/FacetBucket" + }, + "type": "array", + "title": "As Name", + "description": "IP count by AS name (top 5)" + }, + "cves": { + "items": { + "$ref": "#/components/schemas/FacetBucket" + }, + "type": "array", + "title": "Cves", + "description": "IP count by CVE (top 5)" + }, + "classifications": { + "items": { + "$ref": "#/components/schemas/FacetBucket" + }, + "type": "array", + "title": "Classifications", + "description": "IP count by classification (top 5)" + } + }, + "type": "object", + "required": [ + "total", + "reputation", + "country", + "as_name", + "cves", + "classifications" + ], + "title": "IpsDetailsStats" + }, + "Location": { + "properties": { + "country": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Country", + "description": "Country code" + }, + "city": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "City", + "description": "City name" + }, + "latitude": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Latitude", + "description": "Latitude coordinate" + }, + "longitude": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Longitude", + "description": "Longitude coordinate" + } + }, + "type": "object", + "title": "Location" + }, + "LookupImpactCVEItem": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the CVE" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Name of the CVE" + }, + "title": { + "type": "string", + "title": "Title", + "description": "Title of the CVE" + }, + "affected_components": { + "items": { + "$ref": "#/components/schemas/AffectedComponent" + }, + "type": "array", + "title": "Affected Components", + "description": "List of affected components" + }, + "crowdsec_score": { + "type": "integer", + "maximum": 10.0, + "minimum": 0.0, + "title": "Crowdsec Score", + "description": "Live Exploit Tracker score of the CVE" + }, + "opportunity_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Opportunity Score", + "description": "Opportunity score indicating if it's an opportunistic(0) or targeted(5) attack (between 0-5)", + "default": 0 + }, + "momentum_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Momentum Score", + "description": "Momentum score indicating the vulnerability's trendiness based on signal comparison with the previous month. Higher scores (4-5) indicate significantly more signals this month than last month's average, while lower scores (0-1) indicate declining activity (between 0-5)", + "default": 0 + }, + "first_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "First Seen", + "description": "First seen date" + }, + "last_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Seen", + "description": "Last seen date" + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Number of unique IPs affected" + }, + "published_date": { + "type": "string", + "format": "date-time", + "title": "Published Date", + "description": "Published date of the CVE" + }, + "cvss_score": { + "anyOf": [ + { + "type": "number", + "maximum": 10.0, + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Cvss Score", + "description": "CVSS score of the CVE" + }, + "has_public_exploit": { + "type": "boolean", + "title": "Has Public Exploit", + "description": "Indicates if there is a public exploit for the CVE" + }, + "rule_release_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Rule Release Date", + "description": "Release date of the associated detection rule" + }, + "exploitation_phase": { + "$ref": "#/components/schemas/ExploitationPhase", + "description": "Current exploitation phase of the CVE" + }, + "adjustment_score": { + "anyOf": [ + { + "$ref": "#/components/schemas/AdjustmentScore" + }, + { + "type": "null" + } + ], + "description": "Score adjustments applied to the CVE score based on various factors" + }, + "threat_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThreatContext" + }, + { + "type": "null" + } + ], + "description": "Threat context (attacker/defender countries, industries, objectives)" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the CVE" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "List of references for the CVE" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Description of the CVE" + }, + "crowdsec_analysis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Crowdsec Analysis", + "description": "CrowdSec analysis of the CVE" + }, + "cwes": { + "items": { + "$ref": "#/components/schemas/CWE" + }, + "type": "array", + "title": "Cwes", + "description": "List of CWEs associated with the CVE" + }, + "events": { + "items": { + "$ref": "#/components/schemas/CVEEventOutput" + }, + "type": "array", + "title": "Events", + "description": "List of events related to the CVE" + }, + "type": { + "type": "string", + "const": "cve", + "title": "Type", + "description": "Resource type", + "default": "cve" + } + }, + "type": "object", + "required": [ + "id", + "name", + "title", + "affected_components", + "crowdsec_score", + "nb_ips", + "published_date", + "has_public_exploit", + "exploitation_phase", + "references", + "description", + "crowdsec_analysis", + "cwes" + ], + "title": "LookupImpactCVEItem" + }, + "LookupImpactFingerprintItem": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Fingerprint rule identifier" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Fingerprint rule name" + }, + "title": { + "type": "string", + "title": "Title", + "description": "Fingerprint rule title" + }, + "affected_components": { + "items": { + "$ref": "#/components/schemas/AffectedComponent" + }, + "type": "array", + "title": "Affected Components", + "description": "List of affected components" + }, + "crowdsec_score": { + "type": "integer", + "maximum": 10.0, + "minimum": 0.0, + "title": "Crowdsec Score", + "description": "Live Exploit Tracker score for the fingerprint rule" + }, + "opportunity_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Opportunity Score", + "description": "Opportunity score", + "default": 0 + }, + "momentum_score": { + "type": "integer", + "maximum": 5.0, + "minimum": 0.0, + "title": "Momentum Score", + "description": "Momentum score", + "default": 0 + }, + "first_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "First Seen", + "description": "First seen date" + }, + "last_seen": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Seen", + "description": "Last seen date" + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Number of unique IPs observed" + }, + "rule_release_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Rule Release Date", + "description": "Release date of the fingerprint rule" + }, + "exploitation_phase": { + "$ref": "#/components/schemas/ExploitationPhase", + "description": "Current exploitation phase" + }, + "adjustment_score": { + "anyOf": [ + { + "$ref": "#/components/schemas/AdjustmentScore" + }, + { + "type": "null" + } + ], + "description": "Score adjustment details" + }, + "threat_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/ThreatContext" + }, + { + "type": "null" + } + ], + "description": "Threat context (attacker/defender countries, industries, objectives)" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the fingerprint rule" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description", + "description": "Fingerprint rule description" + }, + "references": { + "items": { + "type": "string" + }, + "type": "array", + "title": "References", + "description": "Reference links for the fingerprint rule" + }, + "crowdsec_analysis": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Crowdsec Analysis", + "description": "CrowdSec analysis for this fingerprint rule" + }, + "events": { + "items": { + "$ref": "#/components/schemas/FingerprintEventOutput" + }, + "type": "array", + "title": "Events", + "description": "List of events related to the fingerprint rule" + }, + "type": { + "type": "string", + "const": "fingerprint", + "title": "Type", + "description": "Resource type", + "default": "fingerprint" + } + }, + "type": "object", + "required": [ + "id", + "name", + "title", + "affected_components", + "crowdsec_score", + "nb_ips", + "exploitation_phase" + ], + "title": "LookupImpactFingerprintItem" + }, + "LookupImpactResponsePage": { + "properties": { + "items": { + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/LookupImpactCVEItem" + }, + { + "$ref": "#/components/schemas/LookupImpactFingerprintItem" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "cve": "#/components/schemas/LookupImpactCVEItem", + "fingerprint": "#/components/schemas/LookupImpactFingerprintItem" + } + } + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "LookupImpactResponsePage" + }, + "LookupListItemWithStats": { + "properties": { + "value": { + "type": "string", + "title": "Value", + "description": "Lookup entry value" + }, + "nb_cves": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Cves", + "description": "Number of CVEs", + "default": 0 + }, + "nb_fingerprints": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Fingerprints", + "description": "Number of fingerprint rules", + "default": 0 + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Total number of unique IPs targeting this entry", + "default": 0 + }, + "nb_ips_cves": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips Cves", + "description": "Number of IPs across CVEs", + "default": 0 + }, + "nb_ips_fingerprints": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips Fingerprints", + "description": "Number of IPs across fingerprint rules", + "default": 0 + }, + "latest_rule_release": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Latest Rule Release", + "description": "Most recent rule release date for this entry" + } + }, + "type": "object", + "required": [ + "value" + ], + "title": "LookupListItemWithStats" + }, + "LookupListWithStatsResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/LookupListItemWithStats" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0.0, + "title": "Total" + }, + "page": { + "type": "integer", + "minimum": 1.0, + "title": "Page" + }, + "size": { + "type": "integer", + "minimum": 1.0, + "title": "Size" + }, + "pages": { + "type": "integer", + "minimum": 0.0, + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true + } + }, + "type": "object", + "required": [ + "items", + "total", + "page", + "size", + "pages", + "links" + ], + "title": "LookupListWithStatsResponsePage" + }, + "MitreTechnique": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "MITRE technique ID" + }, + "label": { + "type": "string", + "title": "Label", + "description": "MITRE technique label" + }, + "description": { + "type": "string", + "title": "Description", + "description": "MITRE technique description" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description" + ], + "title": "MitreTechnique" + }, + "ProtectRule": { + "properties": { + "link": { + "type": "string", + "title": "Link", + "description": "URL to the rule source" + }, + "published_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Published Date", + "description": "Date the rule was published" + }, + "tags": { + "items": { + "$ref": "#/components/schemas/ProtectRuleTag" + }, + "type": "array", + "title": "Tags", + "description": "Tags associated with the rule" + }, + "name": { + "type": "string", + "title": "Name", + "description": "Rule name" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Human-readable rule label" + }, + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Content", + "description": "Rule content/definition" + } + }, + "type": "object", + "required": [ + "link", + "name", + "label" + ], + "title": "ProtectRule", + "description": "A protection/detection rule reference from vuln_scores." + }, + "ProtectRuleTag": { + "properties": { + "tag": { + "type": "string", + "title": "Tag", + "description": "Tag identifier" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Human-readable tag label" + } + }, + "type": "object", + "required": [ + "tag", + "label" + ], + "title": "ProtectRuleTag", + "description": "A tag on a protect rule reference." + }, + "Reference": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Reference name" + }, + "label": { + "type": "string", + "title": "Label", + "description": "Reference label" + }, + "description": { + "type": "string", + "title": "Description", + "description": "Reference description" + } + }, + "type": "object", + "required": [ + "name", + "label", + "description" + ], + "title": "Reference" + }, + "ScoreBreakdown": { + "properties": { + "aggressiveness": { + "type": "integer", + "title": "Aggressiveness", + "description": "Aggressiveness score" + }, + "threat": { + "type": "integer", + "title": "Threat", + "description": "Threat score" + }, + "trust": { + "type": "integer", + "title": "Trust", + "description": "Trust score" + }, + "anomaly": { + "type": "integer", + "title": "Anomaly", + "description": "Anomaly score" + }, + "total": { + "type": "integer", + "title": "Total", + "description": "Total score" + } + }, + "type": "object", + "required": [ + "aggressiveness", + "threat", + "trust", + "anomaly", + "total" + ], + "title": "ScoreBreakdown" + }, + "Scores": { + "properties": { + "overall": { + "$ref": "#/components/schemas/ScoreBreakdown", + "description": "Overall scores" + }, + "last_day": { + "$ref": "#/components/schemas/ScoreBreakdown", + "description": "Last day scores" + }, + "last_week": { + "$ref": "#/components/schemas/ScoreBreakdown", + "description": "Last week scores" + }, + "last_month": { + "$ref": "#/components/schemas/ScoreBreakdown", + "description": "Last month scores" + } + }, + "type": "object", + "required": [ + "overall", + "last_day", + "last_week", + "last_month" + ], + "title": "Scores" + }, + "SinceOptions": { + "type": "integer", + "enum": [ + 1, + 7, + 30 + ], + "title": "SinceOptions" + }, + "SubscribeCVEIntegrationRequest": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the integration to subscribe" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "name" + ], + "title": "SubscribeCVEIntegrationRequest" + }, + "SubscribeFingerprintIntegrationRequest": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the integration to subscribe" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "name" + ], + "title": "SubscribeFingerprintIntegrationRequest" + }, + "SubscribeVendorIntegrationRequest": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Name of the integration to subscribe" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "name" + ], + "title": "SubscribeVendorIntegrationRequest" + }, + "ThreatContext": { + "properties": { + "attacker_countries": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Attacker Countries", + "description": "Attacker country distribution (country code \u2192 count)" + }, + "defender_countries": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Defender Countries", + "description": "Defender country distribution (country code \u2192 count)" + }, + "industry_types": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Industry Types", + "description": "Industry type distribution (type \u2192 count)" + }, + "industry_risk_profiles": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Industry Risk Profiles", + "description": "Industry risk profile distribution (profile \u2192 count)" + }, + "attacker_objectives": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Attacker Objectives", + "description": "Attacker objective distribution (objective \u2192 count)" + } + }, + "type": "object", + "title": "ThreatContext" + }, + "TimelineItem": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp", + "description": "Timestamp of the timeline event" + }, + "count": { + "type": "integer", + "title": "Count", + "description": "Count of occurrences at the timestamp" + } + }, + "type": "object", + "required": [ + "timestamp", + "count" + ], + "title": "TimelineItem" + }, + "TopProductItem": { + "properties": { + "value": { + "type": "string", + "title": "Value", + "description": "Product name" + }, + "nb_ips_cves": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips Cves", + "description": "Number of IPs across CVEs", + "default": 0 + }, + "nb_ips_fingerprints": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips Fingerprints", + "description": "Number of IPs across fingerprint rules", + "default": 0 + } + }, + "type": "object", + "required": [ + "value" + ], + "title": "TopProductItem" + }, + "VendorSortBy": { + "type": "string", + "enum": [ + "value", + "nb_cves", + "nb_ips", + "latest_rule_release" + ], + "title": "VendorSortBy" + }, + "VendorStatsResponse": { + "properties": { + "value": { + "type": "string", + "title": "Value", + "description": "Vendor name" + }, + "nb_cves": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Cves", + "description": "Number of CVEs", + "default": 0 + }, + "nb_fingerprints": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Fingerprints", + "description": "Number of fingerprint rules", + "default": 0 + }, + "nb_ips": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips", + "description": "Total number of unique IPs targeting this vendor", + "default": 0 + }, + "nb_ips_cves": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips Cves", + "description": "Number of IPs across CVEs", + "default": 0 + }, + "nb_ips_fingerprints": { + "type": "integer", + "minimum": 0.0, + "title": "Nb Ips Fingerprints", + "description": "Number of IPs across fingerprint rules", + "default": 0 + }, + "top_products": { + "items": { + "$ref": "#/components/schemas/TopProductItem" + }, + "type": "array", + "title": "Top Products", + "description": "Top products for this vendor sorted by total IPs descending" + } + }, + "type": "object", + "required": [ + "value" + ], + "title": "VendorStatsResponse" + } + }, + "securitySchemes": { + "ApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "x-api-key", + "description": "If integration key is provided, can also work to get integration content" + }, + "BasicAuth": { + "type": "http", + "scheme": "basic", + "description": "Basic Auth for integration content endpoint only" + } + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "BasicAuth": [] + } + ] +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 8262bda..11a1680 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "crowdsec_service_api" -version = "1.87.2" +version = "v0.15.25" license = { text = "MIT" } authors = [ { name="crowdsec", email="info@crowdsec.net" } diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..edce21e --- /dev/null +++ b/uv.lock @@ -0,0 +1,337 @@ +version = 1 +revision = 3 +requires-python = ">=3.11" + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" }, +] + +[[package]] +name = "botocore" +version = "1.42.89" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/cc/e6be943efa9051bd15c2ee14077c2b10d6e27c9e9385fc43a03a5c4ed8b5/botocore-1.42.89.tar.gz", hash = "sha256:95ac52f472dad29942f3088b278ab493044516c16dbf9133c975af16527baa99", size = 15206290, upload-time = "2026-04-13T19:36:02.321Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/f1/90a7b8eda38b7c3a65ca7ee0075bdf310b6b471cb1b95fab6e8994323a50/botocore-1.42.89-py3-none-any.whl", hash = "sha256:d9b786c8d9db6473063b4cc5be0ba7e6a381082307bd6afb69d4216f9fa95f35", size = 14887287, upload-time = "2026-04-13T19:35:56.677Z" }, +] + +[[package]] +name = "certifi" +version = "2026.2.25" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, +] + +[[package]] +name = "crowdsec-service-api" +version = "0.15.25" +source = { editable = "." } +dependencies = [ + { name = "botocore" }, + { name = "httpx" }, + { name = "pydantic", extra = ["email", "timezone"] }, +] + +[package.metadata] +requires-dist = [ + { name = "botocore" }, + { name = "httpx", specifier = "==0.27.0" }, + { name = "pydantic", extras = ["email", "timezone"], specifier = ">=2.5.0,<3.0.0" }, +] + +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + +[[package]] +name = "email-validator" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, + { name = "sniffio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/3da5bdf4408b8b2800061c339f240c1802f2e82d55e50bd39c5a881f47f0/httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5", size = 126413, upload-time = "2024-02-21T13:07:52.434Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/7b/ddacf6dcebb42466abd03f368782142baa82e08fc0c1f8eaa05b4bae87d5/httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5", size = 75590, upload-time = "2024-02-21T13:07:50.455Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "jmespath" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/84/6b/69fd5c7194b21ebde0f8637e2a4ddc766ada29d472bfa6a5ca533d79549a/pydantic-2.13.0.tar.gz", hash = "sha256:b89b575b6e670ebf6e7448c01b41b244f471edd276cd0b6fe02e7e7aca320070", size = 843468, upload-time = "2026-04-13T10:51:35.571Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/d7/c3a52c61f5b7be648e919005820fbac33028c6149994cd64453f49951c17/pydantic-2.13.0-py3-none-any.whl", hash = "sha256:ab0078b90da5f3e2fd2e71e3d9b457ddcb35d0350854fbda93b451e28d56baaf", size = 471872, upload-time = "2026-04-13T10:51:33.343Z" }, +] + +[package.optional-dependencies] +email = [ + { name = "email-validator" }, +] +timezone = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6f/0a/9414cddf82eda3976b14048cc0fa8f5b5d1aecb0b22e1dcd2dbfe0e139b1/pydantic_core-2.46.0.tar.gz", hash = "sha256:82d2498c96be47b47e903e1378d1d0f770097ec56ea953322f39936a7cf34977", size = 471441, upload-time = "2026-04-13T09:06:33.813Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/43/9bc38d43a6a48794209e4eb6d61e9c68395f69b7949f66842854b0cd1344/pydantic_core-2.46.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0027da787ae711f7fbd5a76cb0bb8df526acba6c10c1e44581de1b838db10b7b", size = 2121004, upload-time = "2026-04-13T09:05:17.531Z" }, + { url = "https://files.pythonhosted.org/packages/8c/1d/f43342b7107939b305b5e4efeef7d54e267a5ef51515570a5c1d77726efb/pydantic_core-2.46.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:63e288fc18d7eaeef5f16c73e65c4fd0ad95b25e7e21d8a5da144977b35eb997", size = 1947505, upload-time = "2026-04-13T09:04:48.975Z" }, + { url = "https://files.pythonhosted.org/packages/4a/cd/ccf48cbbcaf0d99ba65969459ebfbf7037600b2cfdcca3062084dd83a008/pydantic_core-2.46.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:080a3bdc6807089a1fe1fbc076519cea287f1a964725731d80b49d8ecffaa217", size = 1973301, upload-time = "2026-04-13T09:05:42.149Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ff/a7bb1e7a762fb1f40ad5ef4e6a92c012864a017b7b1fdfb71cf91faa8b73/pydantic_core-2.46.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c065f1c3e54c3e79d909927a8cb48ccbc17b68733552161eba3e0628c38e5d19", size = 2042208, upload-time = "2026-04-13T09:05:32.591Z" }, + { url = "https://files.pythonhosted.org/packages/ea/64/d3f11c6f6ace71526f3b03646df95eaab3f21edd13e00daae3f20f4e5a09/pydantic_core-2.46.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7e2db58ab46cfe602d4255381cce515585998c3b6699d5b1f909f519bc44a5aa", size = 2229046, upload-time = "2026-04-13T09:04:18.59Z" }, + { url = "https://files.pythonhosted.org/packages/d0/64/93db9a63cce71630c58b376d63de498aa93cb341c72cd5f189b5c08f5c28/pydantic_core-2.46.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c660974890ec1e4c65cff93f5670a5f451039f65463e9f9c03ad49746b49fc78", size = 2292138, upload-time = "2026-04-13T09:04:13.816Z" }, + { url = "https://files.pythonhosted.org/packages/e9/96/936fccce22f1f2ae8b2b694de651c2c929847be5f701c927a0bb3b1eb679/pydantic_core-2.46.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3be91482a8db77377c902cca87697388a4fb68addeb3e943ac74f425201a099", size = 2093333, upload-time = "2026-04-13T09:05:15.729Z" }, + { url = "https://files.pythonhosted.org/packages/75/76/c325e7fda69d589e26e772272044fe704c7e525c47d0d32a74f8345ac657/pydantic_core-2.46.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:1c72de82115233112d70d07f26a48cf6996eb86f7e143423ec1a182148455a9d", size = 2138802, upload-time = "2026-04-13T09:03:51.142Z" }, + { url = "https://files.pythonhosted.org/packages/c0/6f/ccaa2ff7d53a017b66841e2d38edd1f38d19ae1a2d0c5efee17f2d432229/pydantic_core-2.46.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7904e58768cd79304b992868d7710bfc85dc6c7ed6163f0f68dbc1dcd72dc231", size = 2181358, upload-time = "2026-04-13T09:04:30.737Z" }, + { url = "https://files.pythonhosted.org/packages/6c/71/0c4b6303e92d63edcb81f5301695cdf70bb351775b4733eea65acdac8384/pydantic_core-2.46.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1af8d88718005f57bb4768f92f4ff16bf31a747d39dfc919b22211b84e72c053", size = 2183985, upload-time = "2026-04-13T09:04:06.792Z" }, + { url = "https://files.pythonhosted.org/packages/71/eb/f6bf255de38a4393aaa10bff224e882b630576bc26ebfb401e42bb965092/pydantic_core-2.46.0-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:a5b891301b02770a5852253f4b97f8bd192e5710067bc129e20d43db5403ede2", size = 2328559, upload-time = "2026-04-13T09:06:14.143Z" }, + { url = "https://files.pythonhosted.org/packages/f2/71/93895a1545f50823a24b21d7761c2bd1b1afea7a6ddc019787caec237361/pydantic_core-2.46.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:48b671fe59031fd9754c7384ac05b3ed47a0cccb7d4db0ec56121f0e6a541b90", size = 2367466, upload-time = "2026-04-13T09:05:59.613Z" }, + { url = "https://files.pythonhosted.org/packages/78/39/62331b3e71f41fb13d486621e2aec49900ba56567fb3a0ae5999fded0005/pydantic_core-2.46.0-cp311-cp311-win32.whl", hash = "sha256:0a52b7262b6cc67033823e9549a41bb77580ac299dc964baae4e9c182b2e335c", size = 1981367, upload-time = "2026-04-13T09:07:37.563Z" }, + { url = "https://files.pythonhosted.org/packages/9f/51/caac70958420e2d6115962f550676df59647c11f96a44c2fcb61662fcd16/pydantic_core-2.46.0-cp311-cp311-win_amd64.whl", hash = "sha256:4103fea1beeef6b3a9fed8515f27d4fa30c929a1973655adf8f454dc49ee0662", size = 2065942, upload-time = "2026-04-13T09:06:37.873Z" }, + { url = "https://files.pythonhosted.org/packages/b2/cf/576b2a4eb5500a1a5da485613b1ea8bc0d7279b27e0426801574b284ae65/pydantic_core-2.46.0-cp311-cp311-win_arm64.whl", hash = "sha256:3137cd88938adb8e567c5e938e486adc7e518ffc96b4ae1ec268e6a4275704d7", size = 2052532, upload-time = "2026-04-13T09:06:03.697Z" }, + { url = "https://files.pythonhosted.org/packages/a7/d2/206c72ad47071559142a35f71efc29eb16448a4a5ae9487230ab8e4e292b/pydantic_core-2.46.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:66ccedb02c934622612448489824955838a221b3a35875458970521ef17b2f9c", size = 2117060, upload-time = "2026-04-13T09:04:47.443Z" }, + { url = "https://files.pythonhosted.org/packages/17/2c/7a53b33f91c8b77e696b1a6aa3bed609bf9374bdc0f8dcda681bc7d922b8/pydantic_core-2.46.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a44f27f4d2788ef9876ec47a43739b118c5904d74f418f53398f6ced3bbcacf2", size = 1951802, upload-time = "2026-04-13T09:05:34.591Z" }, + { url = "https://files.pythonhosted.org/packages/fc/20/90e548c1f6d38800ef11c915881525770ce270d8e5e887563ff046a08674/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26a1032bcce6ca4b4670eb3f7d8195bd0a8b8f255f1307823e217ca3cfa7c27", size = 1976621, upload-time = "2026-04-13T09:04:03.909Z" }, + { url = "https://files.pythonhosted.org/packages/20/3c/9c5810ca70b60c623488cdd80f7e9ee1a0812df81e97098b64788719860f/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b8d1412f725060527e56675904b17a2d421dddcf861eecf7c75b9dda47921a4", size = 2056721, upload-time = "2026-04-13T09:04:40.992Z" }, + { url = "https://files.pythonhosted.org/packages/1a/a3/d6e5f4cdec84278431c75540f90838c9d0a4dfe9402a8f3902073660ff28/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc3d1569edd859cabaa476cabce9eecd05049a7966af7b4a33b541bfd4ca1104", size = 2239634, upload-time = "2026-04-13T09:03:52.478Z" }, + { url = "https://files.pythonhosted.org/packages/46/42/ef58aacf330d8de6e309d62469aa1f80e945eaf665929b4037ac1bfcebc1/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:38108976f2d8afaa8f5067fd1390a8c9f5cc580175407cda636e76bc76e88054", size = 2315739, upload-time = "2026-04-13T09:05:04.971Z" }, + { url = "https://files.pythonhosted.org/packages/8b/86/c63b12fafa2d86a515bfd1840b39c23a49302f02b653161bf9c3a0566c50/pydantic_core-2.46.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5a06d8ed01dad5575056b5187e5959b336793c6047920a3441ee5b03533836", size = 2098169, upload-time = "2026-04-13T09:07:27.151Z" }, + { url = "https://files.pythonhosted.org/packages/76/19/b5b33a2f6be4755b21a20434293c4364be255f4c1a108f125d101d4cc4ee/pydantic_core-2.46.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:04017ace142da9ce27cafd423a480872571b5c7e80382aec22f7d715ca8eb870", size = 2170830, upload-time = "2026-04-13T09:04:39.448Z" }, + { url = "https://files.pythonhosted.org/packages/99/ae/7559f99a29b7d440012ddb4da897359304988a881efaca912fd2f655652e/pydantic_core-2.46.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2629ad992ed1b1c012e6067f5ffafd3336fcb9b54569449fabb85621f1444ed3", size = 2203901, upload-time = "2026-04-13T09:04:01.048Z" }, + { url = "https://files.pythonhosted.org/packages/dd/0e/b0ef945a39aeb4ac58da316813e1106b7fbdfbf20ac141c1c27904355ac5/pydantic_core-2.46.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3068b1e7bd986aebc88f6859f8353e72072538dcf92a7fb9cf511a0f61c5e729", size = 2191789, upload-time = "2026-04-13T09:06:39.915Z" }, + { url = "https://files.pythonhosted.org/packages/90/f4/830484e07188c1236b013995818888ab93bab8fd88aa9689b1d8fd22220d/pydantic_core-2.46.0-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:1e366916ff69ff700aa9326601634e688581bc24c5b6b4f8738d809ec7d72611", size = 2344423, upload-time = "2026-04-13T09:05:12.252Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ba/e455c18cbdc333177af754e740be4fe9d1de173d65bbe534daf88da02ac0/pydantic_core-2.46.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:485a23e8f4618a1b8e23ac744180acde283fffe617f96923d25507d5cade62ec", size = 2384037, upload-time = "2026-04-13T09:06:24.503Z" }, + { url = "https://files.pythonhosted.org/packages/78/1f/b35d20d73144a41e78de0ae398e60fdd8bed91667daa1a5a92ab958551ba/pydantic_core-2.46.0-cp312-cp312-win32.whl", hash = "sha256:520940e1b702fe3b33525d0351777f25e9924f1818ca7956447dabacf2d339fd", size = 1967068, upload-time = "2026-04-13T09:05:23.374Z" }, + { url = "https://files.pythonhosted.org/packages/d1/84/4b6252e9606e8295647b848233cc4137ee0a04ebba8f0f9fb2977655b38c/pydantic_core-2.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:90d2048e0339fa365e5a66aefe760ddd3b3d0a45501e088bc5bc7f4ed9ff9571", size = 2071008, upload-time = "2026-04-13T09:05:21.392Z" }, + { url = "https://files.pythonhosted.org/packages/39/95/d08eb508d4d5560ccbd226ee5971e5ef9b749aba9b413c0c4ed6e406d4f6/pydantic_core-2.46.0-cp312-cp312-win_arm64.whl", hash = "sha256:a70247649b7dffe36648e8f34be5ce8c5fa0a27ff07b071ea780c20a738c05ce", size = 2036634, upload-time = "2026-04-13T09:05:48.299Z" }, + { url = "https://files.pythonhosted.org/packages/df/05/ab3b0742bad1d51822f1af0c4232208408902bdcfc47601f3b812e09e6c2/pydantic_core-2.46.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:a05900c37264c070c683c650cbca8f83d7cbb549719e645fcd81a24592eac788", size = 2116814, upload-time = "2026-04-13T09:04:12.41Z" }, + { url = "https://files.pythonhosted.org/packages/98/08/30b43d9569d69094a0899a199711c43aa58fce6ce80f6a8f7693673eb995/pydantic_core-2.46.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de8e482fd4f1e3f36c50c6aac46d044462615d8f12cfafc6bebeaa0909eea22", size = 1951867, upload-time = "2026-04-13T09:04:02.364Z" }, + { url = "https://files.pythonhosted.org/packages/db/a0/bf9a1ba34537c2ed3872a48195291138fdec8fe26c4009776f00d63cf0c8/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c525ecf8a4cdf198327b65030a7d081867ad8e60acb01a7214fff95cf9832d47", size = 1977040, upload-time = "2026-04-13T09:06:16.088Z" }, + { url = "https://files.pythonhosted.org/packages/71/70/0ba03c20e1e118219fc18c5417b008b7e880f0e3fb38560ec4465984d471/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f14581aeb12e61542ce73b9bfef2bca5439d65d9ab3efe1a4d8e346b61838f9b", size = 2055284, upload-time = "2026-04-13T09:05:25.125Z" }, + { url = "https://files.pythonhosted.org/packages/58/cf/1e320acefbde7fb7158a9e5def55e0adf9a4634636098ce28dc6b978e0d3/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c108067f2f7e190d0dbd81247d789ec41f9ea50ccd9265a3a46710796ac60530", size = 2238896, upload-time = "2026-04-13T09:05:01.345Z" }, + { url = "https://files.pythonhosted.org/packages/df/f5/ea8ba209756abe9eba891bb0ef3772b4c59a894eb9ad86cd5bd0dd4e3e52/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ac10967e9a7bb1b96697374513f9a1a90a59e2fb41566b5e00ee45392beac59", size = 2314353, upload-time = "2026-04-13T09:06:07.942Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f8/5885350203b72e96438eee7f94de0d8f0442f4627237ca8ef75de34db1cd/pydantic_core-2.46.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7897078fe8a13b73623c0955dfb2b3d2c9acb7177aac25144758c9e5a5265aaa", size = 2098522, upload-time = "2026-04-13T09:04:23.239Z" }, + { url = "https://files.pythonhosted.org/packages/bf/88/5930b0e828e371db5a556dd3189565417ddc3d8316bb001058168aadcf5f/pydantic_core-2.46.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:e69ce405510a419a082a78faed65bb4249cfb51232293cc675645c12f7379bf7", size = 2168757, upload-time = "2026-04-13T09:07:12.46Z" }, + { url = "https://files.pythonhosted.org/packages/da/75/63d563d3035a0548e721c38b5b69fd5626fdd51da0f09ff4467503915b82/pydantic_core-2.46.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd28d13eea0d8cf351dc1fe274b5070cc8e1cca2644381dee5f99de629e77cf3", size = 2202518, upload-time = "2026-04-13T09:05:44.418Z" }, + { url = "https://files.pythonhosted.org/packages/a7/53/1958eacbfddc41aadf5ae86dd85041bf054b675f34a2fa76385935f96070/pydantic_core-2.46.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:ee1547a6b8243e73dd10f585555e5a263395e55ce6dea618a078570a1e889aef", size = 2190148, upload-time = "2026-04-13T09:06:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/c7/17/098cc6d3595e4623186f2bc6604a6195eb182e126702a90517236391e9ce/pydantic_core-2.46.0-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:c3dc68dcf62db22a18ddfc3ad4960038f72b75908edc48ae014d7ac8b391d57a", size = 2342925, upload-time = "2026-04-13T09:04:17.286Z" }, + { url = "https://files.pythonhosted.org/packages/71/a7/abdb924620b1ac535c690b36ad5b8871f376104090f8842c08625cecf1d3/pydantic_core-2.46.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:004a2081c881abfcc6854a4623da6a09090a0d7c1398a6ae7133ca1256cee70b", size = 2383167, upload-time = "2026-04-13T09:04:52.643Z" }, + { url = "https://files.pythonhosted.org/packages/d7/c9/2ddd10f50e4b7350d2574629a0f53d8d4eb6573f9c19a6b43e6b1487a31d/pydantic_core-2.46.0-cp313-cp313-win32.whl", hash = "sha256:59d24ec8d5eaabad93097525a69d0f00f2667cb353eb6cda578b1cfff203ceef", size = 1965660, upload-time = "2026-04-13T09:06:05.877Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e7/1efc38ed6f2680c032bcefa0e3ebd496a8c77e92dfdb86b07d0f2fc632b1/pydantic_core-2.46.0-cp313-cp313-win_amd64.whl", hash = "sha256:71186dad5ac325c64d68fe0e654e15fd79802e7cc42bc6f0ff822d5ad8b1ab25", size = 2069563, upload-time = "2026-04-13T09:07:14.738Z" }, + { url = "https://files.pythonhosted.org/packages/c3/1e/a325b4989e742bf7e72ed35fa124bc611fd76539c9f8cd2a9a7854473533/pydantic_core-2.46.0-cp313-cp313-win_arm64.whl", hash = "sha256:8e4503f3213f723842c9a3b53955c88a9cfbd0b288cbd1c1ae933aebeec4a1b4", size = 2034966, upload-time = "2026-04-13T09:04:21.629Z" }, + { url = "https://files.pythonhosted.org/packages/36/3b/914891d384cdbf9a6f464eb13713baa22ea1e453d4da80fb7da522079370/pydantic_core-2.46.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:4fc801c290342350ffc82d77872054a934b2e24163727263362170c1db5416ca", size = 2113349, upload-time = "2026-04-13T09:04:59.407Z" }, + { url = "https://files.pythonhosted.org/packages/35/95/3a0c6f65e231709fb3463e32943c69d10285cb50203a2130a4732053a06d/pydantic_core-2.46.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0a36f2cc88170cc177930afcc633a8c15907ea68b59ac16bd180c2999d714940", size = 1949170, upload-time = "2026-04-13T09:06:09.935Z" }, + { url = "https://files.pythonhosted.org/packages/d1/63/d845c36a608469fe7bee226edeff0984c33dbfe7aecd755b0e7ab5a275c4/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a3912e0c568a1f99d4d6d3e41def40179d61424c0ca1c8c87c4877d7f6fd7fb", size = 1977914, upload-time = "2026-04-13T09:04:56.16Z" }, + { url = "https://files.pythonhosted.org/packages/08/6f/f2e7a7f85931fb31671f5378d1c7fc70606e4b36d59b1b48e1bd1ef5d916/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3534c3415ed1a19ab23096b628916a827f7858ec8db49ad5d7d1e44dc13c0d7b", size = 2050538, upload-time = "2026-04-13T09:05:06.789Z" }, + { url = "https://files.pythonhosted.org/packages/8c/97/f4aa7181dd9a16dd9059a99fc48fdab0c2aab68307283a5c04cf56de68c4/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21067396fc285609323a4db2f63a87570044abe0acddfcca8b135fc7948e3db7", size = 2236294, upload-time = "2026-04-13T09:07:03.2Z" }, + { url = "https://files.pythonhosted.org/packages/24/c1/6a5042fc32765c87101b500f394702890af04239c318b6002cfd627b710d/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2afd85b7be186e2fe7cdbb09a3d964bcc2042f65bbcc64ad800b3c7915032655", size = 2312954, upload-time = "2026-04-13T09:06:11.919Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e4/566101a561492ce8454f0844ca29c3b675a6b3a7b3ff577db85ed05c8c50/pydantic_core-2.46.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67e2c2e171b78db8154da602de72ffdc473c6ee51de8a9d80c0f1cd4051abfc7", size = 2102533, upload-time = "2026-04-13T09:06:58.664Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ac/adc11ee1646a5c4dd9abb09a00e7909e6dc25beddc0b1310ca734bb9b48e/pydantic_core-2.46.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c16ae1f3170267b1a37e16dba5c297bdf60c8b5657b147909ca8774ce7366644", size = 2169447, upload-time = "2026-04-13T09:04:11.143Z" }, + { url = "https://files.pythonhosted.org/packages/26/73/408e686b45b82d28ac19e8229e07282254dbee6a5d24c5c7cf3cf3716613/pydantic_core-2.46.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:133b69e1c1ba34d3702eed73f19f7f966928f9aa16663b55c2ebce0893cca42e", size = 2200672, upload-time = "2026-04-13T09:03:54.056Z" }, + { url = "https://files.pythonhosted.org/packages/0a/3b/807d5b035ec891b57b9079ce881f48263936c37bd0d154a056e7fd152afb/pydantic_core-2.46.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:15ed8e5bde505133d96b41702f31f06829c46b05488211a5b1c7877e11de5eb5", size = 2188293, upload-time = "2026-04-13T09:07:07.614Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ed/719b307516285099d1196c52769fdbe676fd677da007b9c349ae70b7226d/pydantic_core-2.46.0-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:8cfc29a1c66a7f0fcb36262e92f353dd0b9c4061d558fceb022e698a801cb8ae", size = 2335023, upload-time = "2026-04-13T09:04:05.176Z" }, + { url = "https://files.pythonhosted.org/packages/8d/90/8718e4ae98c4e8a7325afdc079be82be1e131d7a47cb6c098844a9531ffe/pydantic_core-2.46.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e1155708540f13845bf68d5ac511a55c76cfe2e057ed12b4bf3adac1581fc5c2", size = 2377155, upload-time = "2026-04-13T09:06:18.081Z" }, + { url = "https://files.pythonhosted.org/packages/dd/dc/7172789283b963f81da2fc92b186e22de55687019079f71c4d570822502b/pydantic_core-2.46.0-cp314-cp314-win32.whl", hash = "sha256:de5635a48df6b2eef161d10ea1bc2626153197333662ba4cd700ee7ec1aba7f5", size = 1963078, upload-time = "2026-04-13T09:05:30.615Z" }, + { url = "https://files.pythonhosted.org/packages/e0/69/03a7ea4b6264def3a44eabf577528bcec2f49468c5698b2044dea54dc07e/pydantic_core-2.46.0-cp314-cp314-win_amd64.whl", hash = "sha256:f07a5af60c5e7cf53dd1ff734228bd72d0dc9938e64a75b5bb308ca350d9681e", size = 2068439, upload-time = "2026-04-13T09:04:57.729Z" }, + { url = "https://files.pythonhosted.org/packages/f5/eb/1c3afcfdee2ab6634b802ab0a0f1966df4c8b630028ec56a1cb0a710dc58/pydantic_core-2.46.0-cp314-cp314-win_arm64.whl", hash = "sha256:e7a77eca3c7d5108ff509db20aae6f80d47c7ed7516d8b96c387aacc42f3ce0f", size = 2026470, upload-time = "2026-04-13T09:05:08.654Z" }, + { url = "https://files.pythonhosted.org/packages/5c/30/1177dde61b200785c4739665e3aa03a9d4b2c25d2d0408b07d585e633965/pydantic_core-2.46.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5e7cdd4398bee1aaeafe049ac366b0f887451d9ae418fd8785219c13fea2f928", size = 2107447, upload-time = "2026-04-13T09:05:46.314Z" }, + { url = "https://files.pythonhosted.org/packages/b1/60/4e0f61f99bdabbbc309d364a2791e1ba31e778a4935bc43391a7bdec0744/pydantic_core-2.46.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5c2c92d82808e27cef3f7ab3ed63d657d0c755e0dbe5b8a58342e37bdf09bd2e", size = 1926927, upload-time = "2026-04-13T09:06:20.371Z" }, + { url = "https://files.pythonhosted.org/packages/1d/d0/67f89a8269152c1d6eaa81f04e75a507372ebd8ca7382855a065222caa80/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bab80af91cd7014b45d1089303b5f844a9d91d7da60eabf3d5f9694b32a6655", size = 1966613, upload-time = "2026-04-13T09:07:05.389Z" }, + { url = "https://files.pythonhosted.org/packages/cd/07/8dfdc3edc78f29a80fb31f366c50203ec904cff6a4c923599bf50ac0d0ff/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1e49ffdb714bc990f00b39d1ad1d683033875b5af15582f60c1f34ad3eeccfaa", size = 2032902, upload-time = "2026-04-13T09:06:42.47Z" }, + { url = "https://files.pythonhosted.org/packages/b0/2a/111c5e8fe24f99c46bcad7d3a82a8f6dbc738066e2c72c04c71f827d8c78/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca877240e8dbdeef3a66f751dc41e5a74893767d510c22a22fc5c0199844f0ce", size = 2244456, upload-time = "2026-04-13T09:05:36.484Z" }, + { url = "https://files.pythonhosted.org/packages/6b/7c/cfc5d11c15a63ece26e148572c77cfbb2c7f08d315a7b63ef0fe0711d753/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87e6843f89ecd2f596d7294e33196c61343186255b9880c4f1b725fde8b0e20d", size = 2294535, upload-time = "2026-04-13T09:06:01.689Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2c/f0d744e3dab7bd026a3f4670a97a295157cff923a2666d30a15a70a7e3d0/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e20bc5add1dd9bc3b9a3600d40632e679376569098345500799a6ad7c5d46c72", size = 2104621, upload-time = "2026-04-13T09:04:34.388Z" }, + { url = "https://files.pythonhosted.org/packages/a7/64/e7cc4698dc024264d214b51d5a47a2404221b12060dd537d76f831b2120a/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:ee6ff79a5f0289d64a9d6696a3ce1f98f925b803dd538335a118231e26d6d827", size = 2130718, upload-time = "2026-04-13T09:04:26.23Z" }, + { url = "https://files.pythonhosted.org/packages/0b/a8/224e655fec21f7d4441438ad2ecaccb33b5a3876ce7bb2098c74a49efc14/pydantic_core-2.46.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:52d35cfb58c26323101c7065508d7bb69bb56338cda9ea47a7b32be581af055d", size = 2180738, upload-time = "2026-04-13T09:05:50.253Z" }, + { url = "https://files.pythonhosted.org/packages/32/7b/b3025618ed4c4e4cbaa9882731c19625db6669896b621760ea95bc1125ef/pydantic_core-2.46.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d14cc5a6f260fa78e124061eebc5769af6534fc837e9a62a47f09a2c341fa4ea", size = 2171222, upload-time = "2026-04-13T09:07:29.929Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e3/68170aa1d891920af09c1f2f34df61dc5ff3a746400027155523e3400e89/pydantic_core-2.46.0-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:4f7ff859d663b6635f6307a10803d07f0d09487e16c3d36b1744af51dbf948b2", size = 2320040, upload-time = "2026-04-13T09:06:35.732Z" }, + { url = "https://files.pythonhosted.org/packages/67/1b/5e65807001b84972476300c1f49aea2b4971b7e9fffb5c2654877dadd274/pydantic_core-2.46.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:8ef749be6ed0d69dba31902aaa8255a9bb269ae50c93888c4df242d8bb7acd9e", size = 2377062, upload-time = "2026-04-13T09:07:39.945Z" }, + { url = "https://files.pythonhosted.org/packages/75/03/48caa9dd5f28f7662bd52bff454d9a451f6b7e5e4af95e289e5e170749c9/pydantic_core-2.46.0-cp314-cp314t-win32.whl", hash = "sha256:d93ca72870133f86360e4bb0c78cd4e6ba2a0f9f3738a6486909ffc031463b32", size = 1951028, upload-time = "2026-04-13T09:04:20.224Z" }, + { url = "https://files.pythonhosted.org/packages/87/ed/e97ff55fe28c0e6e3cba641d622b15e071370b70e5f07c496b07b65db7c9/pydantic_core-2.46.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6ebb2668afd657e2127cb40f2ceb627dd78e74e9dfde14d9bf6cdd532a29ff59", size = 2048519, upload-time = "2026-04-13T09:05:10.464Z" }, + { url = "https://files.pythonhosted.org/packages/b6/51/e0db8267a287994546925f252e329eeae4121b1e77e76353418da5a3adf0/pydantic_core-2.46.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4864f5bbb7993845baf9209bae1669a8a76769296a018cb569ebda9dcb4241f5", size = 2026791, upload-time = "2026-04-13T09:04:37.724Z" }, + { url = "https://files.pythonhosted.org/packages/2d/f1/6731c2d6caf03efe822101edb4783eb3f212f34b7b005a34f039f67e76e1/pydantic_core-2.46.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:ce2e38e27de73ff6a0312a9e3304c398577c418d90bbde97f0ba1ee3ab7ac39f", size = 2121259, upload-time = "2026-04-13T09:07:34.845Z" }, + { url = "https://files.pythonhosted.org/packages/72/fd/ac34d4c92e739e37a040be9e7ea84d116afec5f983a7db856c27135fba77/pydantic_core-2.46.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:f0d34ba062396de0be7421e6e69c9a6821bf6dc73a0ab9959a48a5a6a1e24754", size = 1945798, upload-time = "2026-04-13T09:04:24.729Z" }, + { url = "https://files.pythonhosted.org/packages/b6/a4/f413a522c4047c46b109be6805a3095d35e5a4882fd5b4fdc0909693dfc0/pydantic_core-2.46.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4c0a12147b4026dd68789fb9f22f1a8769e457f9562783c181880848bbd6412", size = 1986062, upload-time = "2026-04-13T09:05:57.177Z" }, + { url = "https://files.pythonhosted.org/packages/91/2e/9760025ea8b0f49903c0ceebdfc2d8ef839da872426f2b03cae9de036a7c/pydantic_core-2.46.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a99896d9db56df901ab4a63cd6a36348a569cff8e05f049db35f4016a817a3d9", size = 2145344, upload-time = "2026-04-13T09:03:56.924Z" }, + { url = "https://files.pythonhosted.org/packages/74/0c/106ed5cc50393d90523f09adcc50d05e42e748eb107dc06aea971137f02d/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:bc0e2fefe384152d7da85b5c2fe8ce2bf24752f68a58e3f3ea42e28a29dfdeb2", size = 2104968, upload-time = "2026-04-13T09:06:26.967Z" }, + { url = "https://files.pythonhosted.org/packages/f5/71/b494cef3165e3413ee9bbbb5a9eedc9af0ea7b88d8638beef6c2061b110e/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:a2ab0e785548be1b4362a62c4004f9217598b7ee465f1f420fc2123e2a5b5b02", size = 1940442, upload-time = "2026-04-13T09:06:29.332Z" }, + { url = "https://files.pythonhosted.org/packages/7e/3e/a4d578c8216c443e26a1124f8c1e07c0654264ce5651143d3883d85ff140/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16d45aecb18b8cba1c68eeb17c2bb2d38627ceed04c5b30b882fc9134e01f187", size = 1999672, upload-time = "2026-04-13T09:04:42.798Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c1/9114560468685525a21770138382fd0cb849aaf351ff2c7b97f760d121e0/pydantic_core-2.46.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5078f6c377b002428e984259ac327ef8902aacae6c14b7de740dd4869a491501", size = 2154533, upload-time = "2026-04-13T09:04:50.868Z" }, + { url = "https://files.pythonhosted.org/packages/09/ed/fbd8127e4a19c4fdbb2f4983cf72c7b3534086df640c813c5c0ec4218177/pydantic_core-2.46.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:be3e04979ba4d68183f247202c7f4f483f35df57690b3f875c06340a1579b47c", size = 2119951, upload-time = "2026-04-13T09:04:35.923Z" }, + { url = "https://files.pythonhosted.org/packages/ec/77/df8711ebb45910412f90d75198430fa1120f5618336b71fa00303601c5a4/pydantic_core-2.46.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b1eae8d7d9b8c2a90b34d3d9014804dca534f7f40180197062634499412ea14e", size = 1953812, upload-time = "2026-04-13T09:05:40.293Z" }, + { url = "https://files.pythonhosted.org/packages/12/fe/14b35df69112bd812d6818a395eeab22eeaa2befc6f85bc54ed648430186/pydantic_core-2.46.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a95a2773680dd4b6b999d4eccdd1b577fd71c31739fb4849f6ada47eabb9c56", size = 2139585, upload-time = "2026-04-13T09:06:46.94Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f0/4fea4c14ebbdeb87e5f6edd2620735fcbd384865f06707fe229c021ce041/pydantic_core-2.46.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25988c3159bb097e06abfdf7b21b1fcaf90f187c74ca6c7bb842c1f72ce74fa8", size = 2179154, upload-time = "2026-04-13T09:04:15.639Z" }, + { url = "https://files.pythonhosted.org/packages/5c/36/6329aa79ba32b73560e6e453164fb29702b115fd3b2b650e796e1dc27862/pydantic_core-2.46.0-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:747d89bd691854c719a3381ba46b6124ef916ae85364c79e11db9c84995d8d03", size = 2182917, upload-time = "2026-04-13T09:07:24.483Z" }, + { url = "https://files.pythonhosted.org/packages/92/61/edbf7aea71052d410347846a2ea43394f74651bf6822b8fad8703ca00575/pydantic_core-2.46.0-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:909a7327b83ca93b372f7d48df0ebc7a975a5191eb0b6e024f503f4902c24124", size = 2327716, upload-time = "2026-04-13T09:06:31.681Z" }, + { url = "https://files.pythonhosted.org/packages/a4/11/aa5089b941e85294b1d5d526840b18f0d4464f842d43d8999ce50ef881c1/pydantic_core-2.46.0-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:2f7e6a3752378a69fadf3f5ee8bc5fa082f623703eec0f4e854b12c548322de0", size = 2365925, upload-time = "2026-04-13T09:05:38.338Z" }, + { url = "https://files.pythonhosted.org/packages/0c/75/e187b0ea247f71f2009d156df88b7d8449c52a38810c9a1bd55dd4871206/pydantic_core-2.46.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ef47ee0a3ac4c2bb25a083b3acafb171f65be4a0ac1e84edef79dd0016e25eaa", size = 2193856, upload-time = "2026-04-13T09:05:03.114Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/f5/cd531b2d15a671a40c0f66cf06bc3570a12cd56eef98960068ebbad1bf5a/tzdata-2026.1.tar.gz", hash = "sha256:67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98", size = 197639, upload-time = "2026-04-03T11:25:22.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/70/d460bd685a170790ec89317e9bd33047988e4bce507b831f5db771e142de/tzdata-2026.1-py2.py3-none-any.whl", hash = "sha256:4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9", size = 348952, upload-time = "2026-04-03T11:25:20.313Z" }, +] + +[[package]] +name = "urllib3" +version = "2.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, +]